From a8621c4ed9d87f6d168fd9b70e0cf501a4033632 Mon Sep 17 00:00:00 2001 From: Istvan Miklos Date: Wed, 29 Jan 2020 11:15:18 +0100 Subject: [PATCH] Initial implementation of GPUShaderModule Added WebIDL bindings for `GPUShaderModule`. Implemented the `createShaderModule` function of `GPUDevice`. --- components/script/dom/bindings/trace.rs | 3 +- components/script/dom/globalscope.rs | 11 +++- components/script/dom/gpudevice.rs | 33 +++++++++++- components/script/dom/gpushadermodule.rs | 54 +++++++++++++++++++ components/script/dom/identityhub.rs | 27 +++++----- components/script/dom/mod.rs | 1 + .../script/dom/webidls/GPUDevice.webidl | 4 +- .../script/dom/webidls/GPUShaderModule.webidl | 15 ++++++ components/webgpu/lib.rs | 25 +++++++++ 9 files changed, 156 insertions(+), 17 deletions(-) create mode 100644 components/script/dom/gpushadermodule.rs create mode 100644 components/script/dom/webidls/GPUShaderModule.webidl diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 471d890c80bd..e58d9d8968fc 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -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}; @@ -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); diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index aa0bfee1b790..0656a982cc90 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -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, }; @@ -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 { diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 4c576c37e8b4..428552173a3b 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -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::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; @@ -23,6 +26,7 @@ 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; @@ -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, + ) -> DomRoot { + let (sender, receiver) = ipc::channel().unwrap(); + let program: Vec = match &descriptor.code { + Uint32Array(program) => program.to_vec(), + String(program) => program.chars().map(|c| c as u32).collect::>(), + }; + 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) + } } diff --git a/components/script/dom/gpushadermodule.rs b/components/script/dom/gpushadermodule.rs new file mode 100644 index 000000000000..215a0efc1000 --- /dev/null +++ b/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>, + 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 { + 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 { + self.label.borrow().clone() + } + + /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label + fn SetLabel(&self, value: Option) { + *self.label.borrow_mut() = value; + } +} diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs index 311428893c06..c260cfc5b2ec 100644 --- a/components/script/dom/identityhub.rs +++ b/components/script/dom/identityhub.rs @@ -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, }; @@ -17,6 +20,7 @@ pub struct IdentityHub { bind_groups: IdentityManager, bind_group_layouts: IdentityManager, pipeline_layouts: IdentityManager, + shader_modules: IdentityManager, backend: Backend, } @@ -29,6 +33,7 @@ impl IdentityHub { bind_groups: IdentityManager::default(), bind_group_layouts: IdentityManager::default(), pipeline_layouts: IdentityManager::default(), + shader_modules: IdentityManager::default(), backend, } } @@ -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)] @@ -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 { @@ -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() + } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index c1a1ab72354c..59a60040ab3f 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -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; diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl index 1966c9b1e924..0c83a1ca5ccb 100644 --- a/components/script/dom/webidls/GPUDevice.webidl +++ b/components/script/dom/webidls/GPUDevice.webidl @@ -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 = {}); diff --git a/components/script/dom/webidls/GPUShaderModule.webidl b/components/script/dom/webidls/GPUShaderModule.webidl new file mode 100644 index 000000000000..0fdfc7c0327e --- /dev/null +++ b/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; +}; diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index e3548a158ca6..583ccb340d83 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -65,6 +65,12 @@ pub enum WebGPURequest { wgpu::id::PipelineLayoutId, Vec, ), + CreateShaderModule( + IpcSender, + WebGPUDevice, + wgpu::id::ShaderModuleId, + Vec, + ), UnmapBuffer(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) => { self.deinit(); if let Err(e) = sender.send(()) { @@ -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);