Skip to content

Commit

Permalink
Initial implementation of GPUShaderModule
Browse files Browse the repository at this point in the history
Added WebIDL bindings for `GPUShaderModule`.
Implemented the `createShaderModule` function of `GPUDevice`.
  • Loading branch information
Istvan Miklos committed Feb 11, 2020
1 parent 5f55cd5 commit a8621c4
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 17 deletions.
3 changes: 2 additions & 1 deletion components/script/dom/bindings/trace.rs
Expand Up @@ -153,7 +153,7 @@ use time::{Duration, Timespec, Tm};
use uuid::Uuid;
use webgpu::{
WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice,
WebGPUPipelineLayout,
WebGPUPipelineLayout, WebGPUShaderModule,
};
use webrender_api::{DocumentId, ImageKey};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
Expand Down Expand Up @@ -536,6 +536,7 @@ unsafe_no_jsmanaged_fields!(WebGPUBuffer);
unsafe_no_jsmanaged_fields!(WebGPUBindGroup);
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(GPUBufferState);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
Expand Down
11 changes: 10 additions & 1 deletion components/script/dom/globalscope.rs
Expand Up @@ -98,7 +98,10 @@ use std::sync::Arc;
use time::{get_time, Timespec};
use uuid::Uuid;
use webgpu::wgpu::{
id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId,
ShaderModuleId,
},
Backend,
};

Expand Down Expand Up @@ -2128,6 +2131,12 @@ impl GlobalScope {
.borrow_mut()
.create_pipeline_layout_id(backend)
}

pub fn wgpu_create_shader_module_id(&self, backend: Backend) -> ShaderModuleId {
self.gpu_id_hub
.borrow_mut()
.create_shader_module_id(backend)
}
}

fn timestamp_in_ms(time: Timespec) -> u64 {
Expand Down
33 changes: 32 additions & 1 deletion components/script/dom/gpudevice.rs
Expand Up @@ -13,16 +13,20 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::GPUShaderModuleDescriptor;
use crate::dom::bindings::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::gpubindgroup::GPUBindGroup;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpupipelinelayout::GPUPipelineLayout;
use crate::dom::gpushadermodule::GPUShaderModule;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use ipc_channel::ipc;
Expand Down Expand Up @@ -523,9 +527,36 @@ impl GPUDeviceMethods for GPUDevice {
descriptor.layout.id(),
bindings,
))
.expect("Failed to create WebGPU PipelineLayout");
.expect("Failed to create WebGPU BindGroup");

let bind_group = receiver.recv().unwrap();
GPUBindGroup::new(&self.global(), bind_group, valid)
}

/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule
fn CreateShaderModule(
&self,
descriptor: RootedTraceableBox<GPUShaderModuleDescriptor>,
) -> DomRoot<GPUShaderModule> {
let (sender, receiver) = ipc::channel().unwrap();
let program: Vec<u32> = match &descriptor.code {
Uint32Array(program) => program.to_vec(),
String(program) => program.chars().map(|c| c as u32).collect::<Vec<u32>>(),
};
let id = self
.global()
.wgpu_create_shader_module_id(self.device.0.backend());
self.channel
.0
.send(WebGPURequest::CreateShaderModule(
sender,
self.device,
id,
program,
))
.expect("Failed to create WebGPU ShaderModule");

let shader_module = receiver.recv().unwrap();
GPUShaderModule::new(&self.global(), shader_module)
}
}
54 changes: 54 additions & 0 deletions components/script/dom/gpushadermodule.rs
@@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUShaderModuleBinding::{
self, GPUShaderModuleMethods,
};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use webgpu::WebGPUShaderModule;

#[dom_struct]
pub struct GPUShaderModule {
reflector_: Reflector,
label: DomRefCell<Option<DOMString>>,
shader_module: WebGPUShaderModule,
}

impl GPUShaderModule {
fn new_inherited(shader_module: WebGPUShaderModule) -> GPUShaderModule {
Self {
reflector_: Reflector::new(),
label: DomRefCell::new(None),
shader_module,
}
}

pub fn new(
global: &GlobalScope,
shader_module: WebGPUShaderModule,
) -> DomRoot<GPUShaderModule> {
reflect_dom_object(
Box::new(GPUShaderModule::new_inherited(shader_module)),
global,
GPUShaderModuleBinding::Wrap,
)
}
}

impl GPUShaderModuleMethods for GPUShaderModule {
/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn GetLabel(&self) -> Option<DOMString> {
self.label.borrow().clone()
}

/// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label
fn SetLabel(&self, value: Option<DOMString>) {
*self.label.borrow_mut() = value;
}
}
27 changes: 15 additions & 12 deletions components/script/dom/identityhub.rs
Expand Up @@ -5,7 +5,10 @@
use smallvec::SmallVec;
use webgpu::wgpu::{
hub::IdentityManager,
id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId},
id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId,
ShaderModuleId,
},
Backend,
};

Expand All @@ -17,6 +20,7 @@ pub struct IdentityHub {
bind_groups: IdentityManager,
bind_group_layouts: IdentityManager,
pipeline_layouts: IdentityManager,
shader_modules: IdentityManager,
backend: Backend,
}

Expand All @@ -29,6 +33,7 @@ impl IdentityHub {
bind_groups: IdentityManager::default(),
bind_group_layouts: IdentityManager::default(),
pipeline_layouts: IdentityManager::default(),
shader_modules: IdentityManager::default(),
backend,
}
}
Expand Down Expand Up @@ -56,6 +61,10 @@ impl IdentityHub {
fn create_pipeline_layout_id(&mut self) -> PipelineLayoutId {
self.pipeline_layouts.alloc(self.backend)
}

fn create_shader_module_id(&mut self) -> ShaderModuleId {
self.shader_modules.alloc(self.backend)
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -133,17 +142,7 @@ impl Identities {
}

pub fn create_bind_group_id(&mut self, backend: Backend) -> BindGroupId {
match backend {
#[cfg(any(target_os = "linux", target_os = "windows"))]
Backend::Vulkan => self.vk_hub.create_bind_group_id(),
#[cfg(target_os = "windows")]
Backend::Dx12 => self.dx12_hub.create_bind_group_id(),
#[cfg(target_os = "windows")]
Backend::Dx11 => self.dx11_hub.create_bind_group_id(),
#[cfg(any(target_os = "ios", target_os = "macos"))]
Backend::Metal => self.metal_hub.create_bind_group_id(),
_ => self.dummy_hub.create_bind_group_id(),
}
self.select(backend).create_bind_group_id()
}

pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId {
Expand All @@ -153,4 +152,8 @@ impl Identities {
pub fn create_pipeline_layout_id(&mut self, backend: Backend) -> PipelineLayoutId {
self.select(backend).create_pipeline_layout_id()
}

pub fn create_shader_module_id(&mut self, backend: Backend) -> ShaderModuleId {
self.select(backend).create_shader_module_id()
}
}
1 change: 1 addition & 0 deletions components/script/dom/mod.rs
Expand Up @@ -324,6 +324,7 @@ pub mod gpubuffer;
pub mod gpubufferusage;
pub mod gpudevice;
pub mod gpupipelinelayout;
pub mod gpushadermodule;
pub mod gpushaderstage;
pub mod hashchangeevent;
pub mod headers;
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/webidls/GPUDevice.webidl
Expand Up @@ -19,8 +19,8 @@ interface GPUDevice : EventTarget {
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);

/*GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
/*GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
Expand Down
15 changes: 15 additions & 0 deletions components/script/dom/webidls/GPUShaderModule.webidl
@@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

// https://gpuweb.github.io/gpuweb/#gpushadermodule
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
interface GPUShaderModule {
};
GPUShaderModule includes GPUObjectBase;

typedef (Uint32Array or DOMString) GPUShaderCode;

dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase {
required GPUShaderCode code;
};
25 changes: 25 additions & 0 deletions components/webgpu/lib.rs
Expand Up @@ -65,6 +65,12 @@ pub enum WebGPURequest {
wgpu::id::PipelineLayoutId,
Vec<wgpu::id::BindGroupLayoutId>,
),
CreateShaderModule(
IpcSender<WebGPUShaderModule>,
WebGPUDevice,
wgpu::id::ShaderModuleId,
Vec<u32>,
),
UnmapBuffer(WebGPUBuffer),
DestroyBuffer(WebGPUBuffer),
}
Expand Down Expand Up @@ -286,6 +292,24 @@ impl WGPU {
)
}
},
WebGPURequest::CreateShaderModule(sender, device, id, program) => {
let global = &self.global;
let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
code: wgpu_core::U32Array {
bytes: program.as_ptr(),
length: program.len(),
},
};
let sm_id = gfx_select!(id => global.device_create_shader_module(device.0, &descriptor, id));
let shader_module = WebGPUShaderModule(sm_id);

if let Err(e) = sender.send(shader_module) {
warn!(
"Failed to send response to WebGPURequest::CreateShaderModule ({})",
e
)
}
},
WebGPURequest::Exit(sender) => {
self.deinit();
if let Err(e) = sender.send(()) {
Expand Down Expand Up @@ -319,3 +343,4 @@ webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
webgpu_resource!(WebGPUBindGroup, wgpu::id::BindGroupId);
webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId);
webgpu_resource!(WebGPUPipelineLayout, wgpu::id::PipelineLayoutId);
webgpu_resource!(WebGPUShaderModule, wgpu::id::ShaderModuleId);

0 comments on commit a8621c4

Please sign in to comment.