diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 4 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 6 | ||||
-rw-r--r-- | components/script/dom/gpubindgroup.rs | 58 | ||||
-rw-r--r-- | components/script/dom/gpubuffer.rs | 14 | ||||
-rw-r--r-- | components/script/dom/gpudevice.rs | 67 | ||||
-rw-r--r-- | components/script/dom/identityhub.rs | 22 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUBindGroup.webidl | 31 | ||||
-rw-r--r-- | components/script/dom/webidls/GPUDevice.webidl | 4 |
9 files changed, 201 insertions, 6 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index ffd4a4952d0..471d890c80b 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -152,7 +152,8 @@ use tendril::{StrTendril, TendrilSink}; use time::{Duration, Timespec, Tm}; use uuid::Uuid; use webgpu::{ - WebGPU, WebGPUAdapter, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, WebGPUPipelineLayout, + WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer, WebGPUDevice, + WebGPUPipelineLayout, }; use webrender_api::{DocumentId, ImageKey}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; @@ -532,6 +533,7 @@ unsafe_no_jsmanaged_fields!(WebGPU); unsafe_no_jsmanaged_fields!(WebGPUAdapter); unsafe_no_jsmanaged_fields!(WebGPUDevice); unsafe_no_jsmanaged_fields!(WebGPUBuffer); +unsafe_no_jsmanaged_fields!(WebGPUBindGroup); unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout); unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout); unsafe_no_jsmanaged_fields!(GPUBufferState); diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index f8427ffd083..aa0bfee1b79 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -98,7 +98,7 @@ use std::sync::Arc; use time::{get_time, Timespec}; use uuid::Uuid; use webgpu::wgpu::{ - id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, + id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, Backend, }; @@ -2105,6 +2105,10 @@ impl GlobalScope { self.gpu_id_hub.borrow_mut().create_adapter_ids() } + pub fn wgpu_create_bind_group_id(&self, backend: Backend) -> BindGroupId { + self.gpu_id_hub.borrow_mut().create_bind_group_id(backend) + } + pub fn wgpu_create_bind_group_layout_id(&self, backend: Backend) -> BindGroupLayoutId { self.gpu_id_hub .borrow_mut() diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs new file mode 100644 index 00000000000..c14ca7a23b5 --- /dev/null +++ b/components/script/dom/gpubindgroup.rs @@ -0,0 +1,58 @@ +/* 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::GPUBindGroupBinding::{ + GPUBindGroupBinding, GPUBindGroupMethods, +}; +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 std::cell::Cell; +use webgpu::WebGPUBindGroup; + +#[dom_struct] +pub struct GPUBindGroup { + reflector_: Reflector, + label: DomRefCell<Option<DOMString>>, + bind_group: WebGPUBindGroup, + valid: Cell<bool>, +} + +impl GPUBindGroup { + fn new_inherited(bind_group: WebGPUBindGroup, valid: bool) -> GPUBindGroup { + Self { + reflector_: Reflector::new(), + label: DomRefCell::new(None), + bind_group, + valid: Cell::new(valid), + } + } + + pub fn new( + global: &GlobalScope, + bind_group: WebGPUBindGroup, + valid: bool, + ) -> DomRoot<GPUBindGroup> { + reflect_dom_object( + Box::new(GPUBindGroup::new_inherited(bind_group, valid)), + global, + GPUBindGroupBinding::Wrap, + ) + } +} + +impl GPUBindGroupMethods for GPUBindGroup { + /// 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; + } +} diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index 160ef6cf79c..8cc9bc52249 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -79,6 +79,20 @@ impl GPUBuffer { } } +impl GPUBuffer { + pub fn id(&self) -> WebGPUBuffer { + self.buffer + } + + pub fn size(&self) -> GPUBufferSize { + self.size + } + + pub fn usage(&self) -> u32 { + self.usage + } +} + impl Drop for GPUBuffer { fn drop(&mut self) { self.Destroy() diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index de3efec8117..4c576c37e8b 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -6,6 +6,7 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupDescriptor; use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ GPUBindGroupLayoutBindings, GPUBindGroupLayoutDescriptor, GPUBindingType, }; @@ -18,6 +19,7 @@ use crate::dom::bindings::str::DOMString; 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; @@ -29,7 +31,10 @@ use js::jsval::{JSVal, ObjectValue}; use js::typedarray::{ArrayBuffer, CreateWith}; use std::collections::{HashMap, HashSet}; use std::ptr::{self, NonNull}; -use webgpu::wgpu::binding_model::{BindGroupLayoutBinding, BindingType, ShaderStage}; +use webgpu::wgpu::binding_model::{ + BindGroupBinding, BindGroupLayoutBinding, BindingResource, BindingType, BufferBinding, + ShaderStage, +}; use webgpu::wgpu::resource::{BufferDescriptor, BufferUsage}; use webgpu::{WebGPU, WebGPUBuffer, WebGPUDevice, WebGPURequest}; @@ -463,4 +468,64 @@ impl GPUDeviceMethods for GPUDevice { let pipeline_layout = receiver.recv().unwrap(); GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid) } + + /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup + fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot<GPUBindGroup> { + let alignment: u64 = 256; + let mut valid = descriptor.layout.bindings().len() == descriptor.bindings.len(); + + valid &= descriptor.bindings.iter().all(|bind| { + let buffer_size = bind.resource.buffer.size(); + let resource_size = bind.resource.size.unwrap_or(buffer_size); + let length = bind.resource.offset.checked_add(resource_size); + let usage = BufferUsage::from_bits(bind.resource.buffer.usage()).unwrap(); + + length.is_some() && + buffer_size >= length.unwrap() && // check buffer OOB + bind.resource.offset % alignment == 0 && // check alignment + bind.resource.offset < buffer_size && // on Vulkan offset must be less than size of buffer + descriptor.layout.bindings().iter().any(|layout_bind| { + let ty = match layout_bind.type_ { + GPUBindingType::Storage_buffer => BufferUsage::STORAGE, + // GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ, + GPUBindingType::Uniform_buffer => BufferUsage::UNIFORM, + _ => unimplemented!(), + }; + // binding must be present in layout + layout_bind.binding == bind.binding && + // binding must contain one buffer of its type + usage.contains(ty) + }) + }); + + let bindings = descriptor + .bindings + .iter() + .map(|bind| BindGroupBinding { + binding: bind.binding, + resource: BindingResource::Buffer(BufferBinding { + buffer: bind.resource.buffer.id().0, + offset: bind.resource.offset, + size: bind.resource.size.unwrap_or(bind.resource.buffer.size()), + }), + }) + .collect::<Vec<_>>(); + let (sender, receiver) = ipc::channel().unwrap(); + let id = self + .global() + .wgpu_create_bind_group_id(self.device.0.backend()); + self.channel + .0 + .send(WebGPURequest::CreateBindGroup( + sender, + self.device, + id, + descriptor.layout.id(), + bindings, + )) + .expect("Failed to create WebGPU PipelineLayout"); + + let bind_group = receiver.recv().unwrap(); + GPUBindGroup::new(&self.global(), bind_group, valid) + } } diff --git a/components/script/dom/identityhub.rs b/components/script/dom/identityhub.rs index d0999d1848d..311428893c0 100644 --- a/components/script/dom/identityhub.rs +++ b/components/script/dom/identityhub.rs @@ -5,7 +5,7 @@ use smallvec::SmallVec; use webgpu::wgpu::{ hub::IdentityManager, - id::{AdapterId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, + id::{AdapterId, BindGroupId, BindGroupLayoutId, BufferId, DeviceId, PipelineLayoutId}, Backend, }; @@ -14,6 +14,7 @@ pub struct IdentityHub { adapters: IdentityManager, devices: IdentityManager, buffers: IdentityManager, + bind_groups: IdentityManager, bind_group_layouts: IdentityManager, pipeline_layouts: IdentityManager, backend: Backend, @@ -25,6 +26,7 @@ impl IdentityHub { adapters: IdentityManager::default(), devices: IdentityManager::default(), buffers: IdentityManager::default(), + bind_groups: IdentityManager::default(), bind_group_layouts: IdentityManager::default(), pipeline_layouts: IdentityManager::default(), backend, @@ -43,6 +45,10 @@ impl IdentityHub { self.buffers.alloc(self.backend) } + fn create_bind_group_id(&mut self) -> BindGroupId { + self.bind_groups.alloc(self.backend) + } + fn create_bind_group_layout_id(&mut self) -> BindGroupLayoutId { self.bind_group_layouts.alloc(self.backend) } @@ -126,6 +132,20 @@ impl Identities { self.select(backend).create_buffer_id() } + 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(), + } + } + pub fn create_bind_group_layout_id(&mut self, backend: Backend) -> BindGroupLayoutId { self.select(backend).create_bind_group_layout_id() } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 2550eeda007..282d3b66d60 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -318,6 +318,7 @@ pub mod gamepadlist; pub mod globalscope; pub mod gpu; pub mod gpuadapter; +pub mod gpubindgroup; pub mod gpubindgrouplayout; pub mod gpubuffer; pub mod gpubufferusage; diff --git a/components/script/dom/webidls/GPUBindGroup.webidl b/components/script/dom/webidls/GPUBindGroup.webidl new file mode 100644 index 00000000000..537fda29a63 --- /dev/null +++ b/components/script/dom/webidls/GPUBindGroup.webidl @@ -0,0 +1,31 @@ +/* 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/#gpubindgrouplayout +[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] +interface GPUBindGroup { +}; +GPUBindGroup includes GPUObjectBase; + +dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase { + required GPUBindGroupLayout layout; + required sequence<GPUBindGroupBindings> bindings; +}; + +typedef /*(GPUSampler or GPUTextureView or*/ GPUBufferBindings/*)*/ GPUBindingResource; + +// Note: Servo codegen doesn't like the name `GPUBindGroupBinding` because it's already occupied +// dictionary GPUBindGroupBinding { +dictionary GPUBindGroupBindings { + required unsigned long binding; + required GPUBindingResource resource; +}; + +// Note: Servo codegen doesn't like the name `GPUBufferBinding` because it's already occupied +// dictionary GPUBufferBinding { +dictionary GPUBufferBindings { + required GPUBuffer buffer; + GPUBufferSize offset = 0; + GPUBufferSize size; +}; diff --git a/components/script/dom/webidls/GPUDevice.webidl b/components/script/dom/webidls/GPUDevice.webidl index 85e8a3ea633..1966c9b1e92 100644 --- a/components/script/dom/webidls/GPUDevice.webidl +++ b/components/script/dom/webidls/GPUDevice.webidl @@ -17,9 +17,9 @@ interface GPUDevice : EventTarget { GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor 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); GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); |