New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of GPUComputePipeline #25700
Changes from all commits
File filter...
Jump to…
| @@ -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, ComputePipelineId, DeviceId, | ||
| PipelineLayoutId, ShaderModuleId, | ||
| }, | ||
| Backend, | ||
| }; | ||
|
|
||
| @@ -2128,6 +2131,17 @@ 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) | ||
| } | ||
| pub fn wgpu_create_compute_pipeline_id(&self, backend: Backend) -> ComputePipelineId { | ||
| self.gpu_id_hub | ||
kvark
Member
|
||
| .borrow_mut() | ||
| .create_compute_pipeline_id(backend) | ||
| } | ||
| } | ||
|
|
||
| fn timestamp_in_ms(time: Timespec) -> u64 { | ||
| @@ -0,0 +1,55 @@ | ||
| /* 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::GPUComputePipelineBinding::{ | ||
| GPUComputePipelineBinding, GPUComputePipelineMethods, | ||
| }; | ||
| use crate::dom::bindings::reflector::reflect_dom_object; | ||
| use crate::dom::bindings::reflector::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::WebGPUComputePipeline; | ||
|
|
||
| #[dom_struct] | ||
| pub struct GPUComputePipeline { | ||
| reflector_: Reflector, | ||
| label: DomRefCell<Option<DOMString>>, | ||
| compute_pipeline: WebGPUComputePipeline, | ||
| } | ||
|
|
||
| impl GPUComputePipeline { | ||
| fn new_inherited(compute_pipeline: WebGPUComputePipeline) -> GPUComputePipeline { | ||
| Self { | ||
| reflector_: Reflector::new(), | ||
| label: DomRefCell::new(None), | ||
| compute_pipeline, | ||
| } | ||
| } | ||
|
|
||
| pub fn new( | ||
| global: &GlobalScope, | ||
| compute_pipeline: WebGPUComputePipeline, | ||
| ) -> DomRoot<GPUComputePipeline> { | ||
| reflect_dom_object( | ||
| Box::new(GPUComputePipeline::new_inherited(compute_pipeline)), | ||
| global, | ||
| GPUComputePipelineBinding::Wrap, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| impl GPUComputePipelineMethods for GPUComputePipeline { | ||
| /// 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; | ||
| } | ||
| } |
| @@ -11,18 +11,24 @@ use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ | ||
| GPUBindGroupLayoutBindings, GPUBindGroupLayoutDescriptor, GPUBindingType, | ||
| }; | ||
| use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; | ||
| use crate::dom::bindings::codegen::Bindings::GPUComputePipelineBinding::GPUComputePipelineDescriptor; | ||
| 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::gpucomputepipeline::GPUComputePipeline; | ||
| 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 +529,64 @@ 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(); | ||
kvark
Member
|
||
| GPUShaderModule::new(&self.global(), shader_module) | ||
| } | ||
|
|
||
| /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcomputepipeline | ||
| fn CreateComputePipeline( | ||
| &self, | ||
| descriptor: &GPUComputePipelineDescriptor, | ||
| ) -> DomRoot<GPUComputePipeline> { | ||
| let pipeline = descriptor.parent.layout.id(); | ||
| let program = descriptor.computeStage.module.id(); | ||
| let entry_point = descriptor.computeStage.entryPoint.to_string(); | ||
| let id = self | ||
| .global() | ||
| .wgpu_create_compute_pipeline_id(self.device.0.backend()); | ||
| let (sender, receiver) = ipc::channel().unwrap(); | ||
| self.channel | ||
| .0 | ||
| .send(WebGPURequest::CreateComputePipeline( | ||
| sender, | ||
| self.device, | ||
| id, | ||
| pipeline.0, | ||
| program.0, | ||
| entry_point, | ||
| )) | ||
| .expect("Failed to create WebGPU ComputePipeline"); | ||
|
|
||
| let compute_pipeline = receiver.recv().unwrap(); | ||
| GPUComputePipeline::new(&self.global(), compute_pipeline) | ||
| } | ||
| } | ||
| @@ -0,0 +1,60 @@ | ||
| /* 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 GPUShaderModule { | ||
| pub fn id(&self) -> WebGPUShaderModule { | ||
| self.shader_module | ||
| } | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
| } |
| @@ -0,0 +1,22 @@ | ||
| /* 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/#gpucomputepipeline | ||
| [Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] | ||
| interface GPUComputePipeline { | ||
| }; | ||
| GPUComputePipeline includes GPUObjectBase; | ||
|
|
||
| dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase { | ||
| required GPUPipelineLayout layout; | ||
| }; | ||
|
|
||
| dictionary GPUProgrammableStageDescriptor { | ||
| required GPUShaderModule module; | ||
| required DOMString entryPoint; | ||
| }; | ||
|
|
||
| dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase { | ||
| required GPUProgrammableStageDescriptor computeStage; | ||
| }; |
nit: perhaps it would be simpler to just have a function returning
&mut GpuIdHuband let the users call the methods appropriately?