Initial implementation of GPUShaderModule

Added WebIDL bindings for `GPUShaderModule`.
Implemented the `createShaderModule` function of `GPUDevice`.
This commit is contained in:
Istvan Miklos 2020-01-29 11:15:18 +01:00
parent 5f55cd5d71
commit a8621c4ed9
9 changed files with 156 additions and 17 deletions

View file

@ -153,7 +153,7 @@ use time::{Duration, Timespec, Tm};
use uuid::Uuid; use uuid::Uuid;
use webgpu::{ use webgpu::{
WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice,
WebGPUPipelineLayout, WebGPUPipelineLayout, WebGPUShaderModule,
}; };
use webrender_api::{DocumentId, ImageKey}; use webrender_api::{DocumentId, ImageKey};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
@ -536,6 +536,7 @@ unsafe_no_jsmanaged_fields!(WebGPUBuffer);
unsafe_no_jsmanaged_fields!(WebGPUBindGroup); unsafe_no_jsmanaged_fields!(WebGPUBindGroup);
unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout); unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout); unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(GPUBufferState); unsafe_no_jsmanaged_fields!(GPUBufferState);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId); unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList); unsafe_no_jsmanaged_fields!(MediaList);

View file

@ -98,7 +98,10 @@ use std::sync::Arc;
use time::{get_time, Timespec}; use time::{get_time, Timespec};
use uuid::Uuid; use uuid::Uuid;
use webgpu::wgpu::{ use webgpu::wgpu::{
id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId,
ShaderModuleId,
},
Backend, Backend,
}; };
@ -2128,6 +2131,12 @@ impl GlobalScope {
.borrow_mut() .borrow_mut()
.create_pipeline_layout_id(backend) .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 { fn timestamp_in_ms(time: Timespec) -> u64 {

View file

@ -13,9 +13,12 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor;
use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods}; use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{self, GPUDeviceMethods};
use crate::dom::bindings::codegen::Bindings::GPUPipelineLayoutBinding::GPUPipelineLayoutDescriptor; 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::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter; use crate::dom::gpuadapter::GPUAdapter;
@ -23,6 +26,7 @@ use crate::dom::gpubindgroup::GPUBindGroup;
use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout;
use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState}; use crate::dom::gpubuffer::{GPUBuffer, GPUBufferState};
use crate::dom::gpupipelinelayout::GPUPipelineLayout; use crate::dom::gpupipelinelayout::GPUPipelineLayout;
use crate::dom::gpushadermodule::GPUShaderModule;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc; use ipc_channel::ipc;
@ -523,9 +527,36 @@ impl GPUDeviceMethods for GPUDevice {
descriptor.layout.id(), descriptor.layout.id(),
bindings, bindings,
)) ))
.expect("Failed to create WebGPU PipelineLayout"); .expect("Failed to create WebGPU BindGroup");
let bind_group = receiver.recv().unwrap(); let bind_group = receiver.recv().unwrap();
GPUBindGroup::new(&self.global(), bind_group, valid) 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)
}
} }

View file

@ -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;
}
}

View file

@ -5,7 +5,10 @@
use smallvec::SmallVec; use smallvec::SmallVec;
use webgpu::wgpu::{ use webgpu::wgpu::{
hub::IdentityManager, hub::IdentityManager,
id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, id::{
AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId,
ShaderModuleId,
},
Backend, Backend,
}; };
@ -17,6 +20,7 @@ pub struct IdentityHub {
bind_groups: IdentityManager, bind_groups: IdentityManager,
bind_group_layouts: IdentityManager, bind_group_layouts: IdentityManager,
pipeline_layouts: IdentityManager, pipeline_layouts: IdentityManager,
shader_modules: IdentityManager,
backend: Backend, backend: Backend,
} }
@ -29,6 +33,7 @@ impl IdentityHub {
bind_groups: IdentityManager::default(), bind_groups: IdentityManager::default(),
bind_group_layouts: IdentityManager::default(), bind_group_layouts: IdentityManager::default(),
pipeline_layouts: IdentityManager::default(), pipeline_layouts: IdentityManager::default(),
shader_modules: IdentityManager::default(),
backend, backend,
} }
} }
@ -56,6 +61,10 @@ impl IdentityHub {
fn create_pipeline_layout_id(&mut self) -> PipelineLayoutId { fn create_pipeline_layout_id(&mut self) -> PipelineLayoutId {
self.pipeline_layouts.alloc(self.backend) self.pipeline_layouts.alloc(self.backend)
} }
fn create_shader_module_id(&mut self) -> ShaderModuleId {
self.shader_modules.alloc(self.backend)
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -133,17 +142,7 @@ impl Identities {
} }
pub fn create_bind_group_id(&mut self, backend: Backend) -> BindGroupId { pub fn create_bind_group_id(&mut self, backend: Backend) -> BindGroupId {
match backend { self.select(backend).create_bind_group_id()
#[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(),
}
} }
pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId { pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId {
@ -153,4 +152,8 @@ impl Identities {
pub fn create_pipeline_layout_id(&mut self, backend: Backend) -> PipelineLayoutId { pub fn create_pipeline_layout_id(&mut self, backend: Backend) -> PipelineLayoutId {
self.select(backend).create_pipeline_layout_id() 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()
}
} }

View file

@ -324,6 +324,7 @@ pub mod gpubuffer;
pub mod gpubufferusage; pub mod gpubufferusage;
pub mod gpudevice; pub mod gpudevice;
pub mod gpupipelinelayout; pub mod gpupipelinelayout;
pub mod gpushadermodule;
pub mod gpushaderstage; pub mod gpushaderstage;
pub mod hashchangeevent; pub mod hashchangeevent;
pub mod headers; pub mod headers;

View file

@ -19,8 +19,8 @@ interface GPUDevice : EventTarget {
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
/*GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); /*GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {}); GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});

View file

@ -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;
};

View file

@ -65,6 +65,12 @@ pub enum WebGPURequest {
wgpu::id::PipelineLayoutId, wgpu::id::PipelineLayoutId,
Vec<wgpu::id::BindGroupLayoutId>, Vec<wgpu::id::BindGroupLayoutId>,
), ),
CreateShaderModule(
IpcSender<WebGPUShaderModule>,
WebGPUDevice,
wgpu::id::ShaderModuleId,
Vec<u32>,
),
UnmapBuffer(WebGPUBuffer), UnmapBuffer(WebGPUBuffer),
DestroyBuffer(WebGPUBuffer), DestroyBuffer(WebGPUBuffer),
} }
@ -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) => { WebGPURequest::Exit(sender) => {
self.deinit(); self.deinit();
if let Err(e) = sender.send(()) { if let Err(e) = sender.send(()) {
@ -319,3 +343,4 @@ webgpu_resource!(WebGPUBuffer, wgpu::id::BufferId);
webgpu_resource!(WebGPUBindGroup, wgpu::id::BindGroupId); webgpu_resource!(WebGPUBindGroup, wgpu::id::BindGroupId);
webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId); webgpu_resource!(WebGPUBindGroupLayout, wgpu::id::BindGroupLayoutId);
webgpu_resource!(WebGPUPipelineLayout, wgpu::id::PipelineLayoutId); webgpu_resource!(WebGPUPipelineLayout, wgpu::id::PipelineLayoutId);
webgpu_resource!(WebGPUShaderModule, wgpu::id::ShaderModuleId);