diff --git a/Cargo.lock b/Cargo.lock index 9346961bc16..d7f0fdd62a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1787,9 +1787,9 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69af46bd4fc5479cc7d90bf77ccee0da5dd88d4d27b87986a582f9eec97d02d4" +checksum = "6e1a979a793023717bcaa7511c8cbb449bab550c093737c98674a659a2bbaf73" dependencies = [ "bitflags", "d3d12", @@ -1815,9 +1815,9 @@ dependencies = [ [[package]] name = "gfx-backend-metal" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205f3ca8e74ed814ea2c0206d47d8925077673cab2e21f9b12d48ff781cf87ee" +checksum = "412a1e0e53e9e325a7c2e0316f1a4e8a14cbe8d8bfb5f030bc3895692f8a8254" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -1842,9 +1842,9 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ff36feae801fa23d29acd74082603a0145a697a23595757dd4e78828ab33da" +checksum = "04af900c2597587b35e801e9d3f91fd8078cc06067421a22caa640ad2b1bc53e" dependencies = [ "arrayvec 0.5.1", "ash", @@ -1872,9 +1872,9 @@ dependencies = [ [[package]] name = "gfx-hal" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc96180204064c9493e0fe4a9efeb721e0ac59fe8e1906d0c659142a93114fb1" +checksum = "f13e8fd6aaa8f50146b9519999432e097da43466749d8863c53409322c705339" dependencies = [ "bitflags", "raw-window-handle", @@ -1883,8 +1883,7 @@ dependencies = [ [[package]] name = "gfx-memory" version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2eed6cda674d9cd4d92229102dbd544292124533d236904f987e9afab456137" +source = "git+https://github.com/gfx-rs/gfx-extras?rev=438353c3f75368c12024ad2fc03cbeb15f351fd9#438353c3f75368c12024ad2fc03cbeb15f351fd9" dependencies = [ "fxhash", "gfx-hal", @@ -6563,7 +6562,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#ac9587e9ced5b043abad68e260cb8c9e812cffb5" +source = "git+https://github.com/gfx-rs/wgpu#fc2dd481b2713cd0eda6ffa540faeaf7418fd051" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -6592,7 +6591,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#ac9587e9ced5b043abad68e260cb8c9e812cffb5" +source = "git+https://github.com/gfx-rs/wgpu#fc2dd481b2713cd0eda6ffa540faeaf7418fd051" dependencies = [ "bitflags", "peek-poke 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 9d7b385adc3..6208a7bc1ba 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -165,10 +165,10 @@ use tendril::{StrTendril, TendrilSink}; use time::{Duration, Timespec, Tm}; use uuid::Uuid; use webgpu::{ - wgpu::command::RawPass, WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, - WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice, - WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule, - WebGPUTexture, WebGPUTextureView, + wgpu::command::RawPass, wgpu::id, WebGPU, WebGPUAdapter, WebGPUBindGroup, + WebGPUBindGroupLayout, WebGPUBuffer, WebGPUCommandBuffer, WebGPUCommandEncoder, + WebGPUComputePipeline, WebGPUDevice, WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, + WebGPUSampler, WebGPUShaderModule, WebGPUTexture, WebGPUTextureView, }; use webrender_api::{DocumentId, ExternalImageId, ImageKey}; use webxr_api::SwapChainId as WebXRSwapChainId; @@ -581,7 +581,7 @@ unsafe_no_jsmanaged_fields!(WebGPUContextId); unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer); unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder); unsafe_no_jsmanaged_fields!(WebGPUDevice); -unsafe_no_jsmanaged_fields!(Option); +unsafe_no_jsmanaged_fields!(Option>); unsafe_no_jsmanaged_fields!(GPUBufferState); unsafe_no_jsmanaged_fields!(GPUCommandEncoderState); unsafe_no_jsmanaged_fields!(WebXRSwapChainId); diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs index 7947a069335..e510afce17d 100644 --- a/components/script/dom/gpuadapter.rs +++ b/components/script/dom/gpuadapter.rs @@ -84,7 +84,9 @@ impl GPUAdapterMethods for GPUAdapter { extensions: wgt::Extensions::empty(), limits: wgt::Limits { max_bind_groups: descriptor.limits.maxBindGroups, + ..Default::default() }, + shader_validation: true, }; let id = self .global() diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs index 4767d28d0f1..8965952051c 100644 --- a/components/script/dom/gpubindgroup.rs +++ b/components/script/dom/gpubindgroup.rs @@ -5,34 +5,52 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupMethods; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; use dom_struct::dom_struct; use std::cell::Cell; -use webgpu::WebGPUBindGroup; +use webgpu::{WebGPUBindGroup, WebGPUDevice}; #[dom_struct] pub struct GPUBindGroup { reflector_: Reflector, label: DomRefCell>, bind_group: WebGPUBindGroup, + device: WebGPUDevice, + layout: Dom, valid: Cell, } impl GPUBindGroup { - fn new_inherited(bind_group: WebGPUBindGroup, valid: bool) -> Self { + fn new_inherited( + bind_group: WebGPUBindGroup, + device: WebGPUDevice, + valid: bool, + layout: &GPUBindGroupLayout, + ) -> Self { Self { reflector_: Reflector::new(), label: DomRefCell::new(None), bind_group, + device, valid: Cell::new(valid), + layout: Dom::from_ref(layout), } } - pub fn new(global: &GlobalScope, bind_group: WebGPUBindGroup, valid: bool) -> DomRoot { + pub fn new( + global: &GlobalScope, + bind_group: WebGPUBindGroup, + device: WebGPUDevice, + valid: bool, + layout: &GPUBindGroupLayout, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUBindGroup::new_inherited(bind_group, valid)), + Box::new(GPUBindGroup::new_inherited( + bind_group, device, valid, layout, + )), global, ) } diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs index 8c141256261..216058a89a0 100644 --- a/components/script/dom/gpubindgrouplayout.rs +++ b/components/script/dom/gpubindgrouplayout.rs @@ -3,60 +3,40 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ - GPUBindGroupLayoutEntry, GPUBindGroupLayoutMethods, -}; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::GPUBindGroupLayoutMethods; 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::{WebGPU, WebGPUBindGroupLayout}; +use webgpu::WebGPUBindGroupLayout; #[dom_struct] pub struct GPUBindGroupLayout { reflector_: Reflector, label: DomRefCell>, bind_group_layout: WebGPUBindGroupLayout, - #[ignore_malloc_size_of = "defined in webgpu"] - bindings: Vec, - #[ignore_malloc_size_of = "defined in webgpu"] - channel: WebGPU, valid: Cell, } impl GPUBindGroupLayout { - fn new_inherited( - channel: WebGPU, - bind_group_layout: WebGPUBindGroupLayout, - bindings: Vec, - valid: bool, - ) -> Self { + fn new_inherited(bind_group_layout: WebGPUBindGroupLayout, valid: bool) -> Self { Self { reflector_: Reflector::new(), - channel, label: DomRefCell::new(None), bind_group_layout, - bindings, valid: Cell::new(valid), } } pub fn new( global: &GlobalScope, - channel: WebGPU, bind_group_layout: WebGPUBindGroupLayout, - bindings: Vec, valid: bool, ) -> DomRoot { reflect_dom_object( - Box::new(GPUBindGroupLayout::new_inherited( - channel, - bind_group_layout, - bindings, - valid, - )), + Box::new(GPUBindGroupLayout::new_inherited(bind_group_layout, valid)), global, ) } @@ -70,10 +50,6 @@ impl GPUBindGroupLayout { pub fn id(&self) -> WebGPUBindGroupLayout { self.bind_group_layout } - - pub fn bindings(&self) -> &[GPUBindGroupLayoutEntry] { - &self.bindings - } } impl GPUBindGroupLayoutMethods for GPUBindGroupLayout { diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs index 1c756dae15f..a23a30a4b11 100644 --- a/components/script/dom/gpubuffer.rs +++ b/components/script/dom/gpubuffer.rs @@ -110,7 +110,7 @@ impl GPUBuffer { self.state.borrow() } - pub fn valid(&self) -> bool { + pub fn is_valid(&self) -> bool { self.valid.get() } } diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs index d0ba2dc8624..0615492dec6 100644 --- a/components/script/dom/gpucommandencoder.rs +++ b/components/script/dom/gpucommandencoder.rs @@ -240,8 +240,8 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder { None => false, }; valid &= (*self.state.borrow() == GPUCommandEncoderState::Open) && - source.valid() && - destination.valid() & + source.is_valid() && + destination.is_valid() & !(size & BUFFER_COPY_ALIGN_MASK == 0) & !(source_offset & BUFFER_COPY_ALIGN_MASK == 0) & !(destination_offset & BUFFER_COPY_ALIGN_MASK == 0) & diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs index f202cc37038..68fb641bd25 100644 --- a/components/script/dom/gpucomputepassencoder.rs +++ b/components/script/dom/gpucomputepassencoder.rs @@ -22,6 +22,7 @@ use webgpu::{ }, RawPass, }, + wgpu::id, WebGPU, WebGPURequest, }; @@ -32,7 +33,7 @@ pub struct GPUComputePassEncoder { channel: WebGPU, label: DomRefCell>, #[ignore_malloc_size_of = "defined in wgpu-core"] - raw_pass: DomRefCell>, + raw_pass: DomRefCell>>, command_encoder: Dom, } diff --git a/components/script/dom/gpucomputepipeline.rs b/components/script/dom/gpucomputepipeline.rs index e96697c95a2..cd5fac795d7 100644 --- a/components/script/dom/gpucomputepipeline.rs +++ b/components/script/dom/gpucomputepipeline.rs @@ -10,6 +10,7 @@ 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::WebGPUComputePipeline; #[dom_struct] @@ -17,20 +18,26 @@ pub struct GPUComputePipeline { reflector_: Reflector, label: DomRefCell>, compute_pipeline: WebGPUComputePipeline, + valid: Cell, } impl GPUComputePipeline { - fn new_inherited(compute_pipeline: WebGPUComputePipeline) -> Self { + fn new_inherited(compute_pipeline: WebGPUComputePipeline, valid: bool) -> Self { Self { reflector_: Reflector::new(), label: DomRefCell::new(None), compute_pipeline, + valid: Cell::new(valid), } } - pub fn new(global: &GlobalScope, compute_pipeline: WebGPUComputePipeline) -> DomRoot { + pub fn new( + global: &GlobalScope, + compute_pipeline: WebGPUComputePipeline, + valid: bool, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUComputePipeline::new_inherited(compute_pipeline)), + Box::new(GPUComputePipeline::new_inherited(compute_pipeline, valid)), global, ) } diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index fbbfa541761..b67c6e696e3 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -5,10 +5,11 @@ #![allow(unsafe_code)] 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::GPUBindGroupBinding::{ + GPUBindGroupDescriptor, GPUBindingResource, +}; use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ - GPUBindGroupLayoutDescriptor, GPUBindGroupLayoutEntry, GPUBindingType, + GPUBindGroupLayoutDescriptor, GPUBindingType, }; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; use crate::dom::bindings::codegen::Bindings::GPUComputePipelineBinding::GPUComputePipelineDescriptor; @@ -55,12 +56,10 @@ use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use js::jsval::{JSVal, ObjectValue}; use js::typedarray::{ArrayBuffer, CreateWith}; -use std::collections::{HashMap, HashSet}; +use std::num::NonZeroU64; use std::ptr::{self, NonNull}; -use webgpu::wgpu::binding_model::{ - BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding, -}; -use webgpu::{self, wgpu, wgt, WebGPU, WebGPURequest}; +use webgpu::wgpu::binding_model::BufferBinding; +use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest}; #[dom_struct] pub struct GPUDevice { @@ -274,149 +273,93 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUBindGroupLayoutDescriptor, ) -> DomRoot { - #[derive(Clone)] - struct MaxLimits { - max_uniform_buffers_per_shader_stage: i32, - max_storage_buffers_per_shader_stage: i32, - max_sampled_textures_per_shader_stage: i32, - max_storage_textures_per_shader_stage: i32, - max_samplers_per_shader_stage: i32, - } - let mut storeBindings = HashSet::new(); - // TODO: We should have these limits on device creation - let limits = GPULimits::empty(); - - let mut validation_map = HashMap::new(); - let maxLimits = MaxLimits { - max_uniform_buffers_per_shader_stage: limits.maxUniformBuffersPerShaderStage as i32, - max_storage_buffers_per_shader_stage: limits.maxStorageBuffersPerShaderStage as i32, - max_sampled_textures_per_shader_stage: limits.maxSampledTexturesPerShaderStage as i32, - max_storage_textures_per_shader_stage: limits.maxStorageTexturesPerShaderStage as i32, - max_samplers_per_shader_stage: limits.maxSamplersPerShaderStage as i32, - }; - validation_map.insert(wgt::ShaderStage::VERTEX, maxLimits.clone()); - validation_map.insert(wgt::ShaderStage::FRAGMENT, maxLimits.clone()); - validation_map.insert(wgt::ShaderStage::COMPUTE, maxLimits.clone()); - let mut max_dynamic_uniform_buffers_per_pipeline_layout = - limits.maxDynamicUniformBuffersPerPipelineLayout as i32; - let mut max_dynamic_storage_buffers_per_pipeline_layout = - limits.maxDynamicStorageBuffersPerPipelineLayout as i32; - let mut valid = true; - - let bindings = descriptor + let entries = descriptor .entries .iter() .map(|bind| { - // TODO: binding must be >= 0 - storeBindings.insert(bind.binding); let visibility = match wgt::ShaderStage::from_bits(bind.visibility) { Some(visibility) => visibility, - None => { - valid = false; - wgt::ShaderStage::from_bits(0).unwrap() - }, + None => wgt::ShaderStage::from_bits(0).unwrap(), }; let ty = match bind.type_ { - GPUBindingType::Uniform_buffer => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_uniform_buffers_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - max_dynamic_uniform_buffers_per_pipeline_layout -= 1; - }; - BindingType::UniformBuffer + GPUBindingType::Uniform_buffer => wgt::BindingType::UniformBuffer { + dynamic: bind.hasDynamicOffset, + min_binding_size: if bind.minBufferBindingSize == 0 { + None + } else { + Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap()) + }, }, - GPUBindingType::Storage_buffer => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_storage_buffers_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - max_dynamic_storage_buffers_per_pipeline_layout -= 1; - }; - BindingType::StorageBuffer + GPUBindingType::Storage_buffer => wgt::BindingType::StorageBuffer { + dynamic: bind.hasDynamicOffset, + min_binding_size: if bind.minBufferBindingSize == 0 { + None + } else { + Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap()) + }, + readonly: false, }, - GPUBindingType::Readonly_storage_buffer => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_storage_buffers_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - max_dynamic_storage_buffers_per_pipeline_layout -= 1; - }; - BindingType::ReadonlyStorageBuffer + GPUBindingType::Readonly_storage_buffer => wgt::BindingType::StorageBuffer { + dynamic: bind.hasDynamicOffset, + min_binding_size: if bind.minBufferBindingSize == 0 { + None + } else { + Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap()) + }, + readonly: true, }, - GPUBindingType::Sampled_texture => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_sampled_textures_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - valid = false - }; - BindingType::SampledTexture + GPUBindingType::Sampled_texture => wgt::BindingType::SampledTexture { + dimension: bind + .viewDimension + .map_or(wgt::TextureViewDimension::D2, |v| { + convert_texture_view_dimension(v) + }), + component_type: if let Some(c) = bind.textureComponentType { + match c { + GPUTextureComponentType::Float => wgt::TextureComponentType::Float, + GPUTextureComponentType::Sint => wgt::TextureComponentType::Sint, + GPUTextureComponentType::Uint => wgt::TextureComponentType::Uint, + } + } else { + wgt::TextureComponentType::Float + }, + multisampled: bind.multisampled, }, - GPUBindingType::Readonly_storage_texture => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_storage_textures_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - valid = false - }; - BindingType::ReadonlyStorageTexture + GPUBindingType::Readonly_storage_texture => wgt::BindingType::StorageTexture { + dimension: bind + .viewDimension + .map_or(wgt::TextureViewDimension::D2, |v| { + convert_texture_view_dimension(v) + }), + format: bind + .storageTextureFormat + .map_or(wgt::TextureFormat::Bgra8UnormSrgb, |f| { + convert_texture_format(f) + }), + readonly: true, }, - GPUBindingType::Writeonly_storage_texture => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_storage_textures_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - valid = false - }; - BindingType::WriteonlyStorageTexture + GPUBindingType::Writeonly_storage_texture => wgt::BindingType::StorageTexture { + dimension: bind + .viewDimension + .map_or(wgt::TextureViewDimension::D2, |v| { + convert_texture_view_dimension(v) + }), + format: bind + .storageTextureFormat + .map_or(wgt::TextureFormat::Bgra8UnormSrgb, |f| { + convert_texture_format(f) + }), + readonly: true, }, - GPUBindingType::Sampler => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_samplers_per_shader_stage -= 1; - } - if bind.hasDynamicOffset { - valid = false - }; - BindingType::Sampler + GPUBindingType::Sampler => wgt::BindingType::Sampler { comparison: false }, + GPUBindingType::Comparison_sampler => { + wgt::BindingType::Sampler { comparison: true } }, }; - BindGroupLayoutEntry { - binding: bind.binding, - visibility, - ty, - has_dynamic_offset: bind.hasDynamicOffset, - multisampled: bind.multisampled, - texture_component_type: match bind.textureComponentType { - GPUTextureComponentType::Float => wgt::TextureComponentType::Float, - GPUTextureComponentType::Sint => wgt::TextureComponentType::Sint, - GPUTextureComponentType::Uint => wgt::TextureComponentType::Uint, - }, - storage_texture_format: match bind.storageTextureFormat { - Some(s) => convert_texture_format(s), - None => wgt::TextureFormat::Bgra8UnormSrgb, - }, - view_dimension: convert_texture_view_dimension(bind.viewDimension), - } + wgt::BindGroupLayoutEntry::new(bind.binding, visibility, ty) }) - .collect::>(); - - // bindings are unique - valid &= storeBindings.len() == bindings.len(); - - // Ensure that values do not exceed the max limit for each ShaderStage. - valid &= validation_map.values().all(|stage| { - stage.max_uniform_buffers_per_shader_stage >= 0 && - stage.max_storage_buffers_per_shader_stage >= 0 && - stage.max_sampled_textures_per_shader_stage >= 0 && - stage.max_storage_textures_per_shader_stage >= 0 && - stage.max_samplers_per_shader_stage >= 0 - }); - - // DynamicValues does not exceed the max limit for the pipeline - valid &= max_dynamic_uniform_buffers_per_pipeline_layout >= 0 && - max_dynamic_storage_buffers_per_pipeline_layout >= 0; + .collect::>(); let bind_group_layout_id = self .global() @@ -428,28 +371,13 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateBindGroupLayout { device_id: self.device.0, bind_group_layout_id, - bindings: bindings.clone(), + entries, }) .expect("Failed to create WebGPU BindGroupLayout"); let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); - let binds = descriptor - .entries - .iter() - .map(|bind| GPUBindGroupLayoutEntry { - binding: bind.binding, - hasDynamicOffset: bind.hasDynamicOffset, - multisampled: bind.multisampled, - type_: bind.type_, - visibility: bind.visibility, - viewDimension: bind.viewDimension, - textureComponentType: bind.textureComponentType, - storageTextureFormat: bind.storageTextureFormat, - }) - .collect::>(); - - GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid) + GPUBindGroupLayout::new(&self.global(), bgl, true) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout @@ -457,47 +385,13 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUPipelineLayoutDescriptor, ) -> DomRoot { - // TODO: We should have these limits on device creation - let limits = GPULimits::empty(); - let mut bind_group_layouts = Vec::new(); let mut bgl_ids = Vec::new(); - let mut max_dynamic_uniform_buffers_per_pipeline_layout = - limits.maxDynamicUniformBuffersPerPipelineLayout as i32; - let mut max_dynamic_storage_buffers_per_pipeline_layout = - limits.maxDynamicStorageBuffersPerPipelineLayout as i32; descriptor.bindGroupLayouts.iter().for_each(|each| { if each.is_valid() { - let id = each.id(); - bind_group_layouts.push(id); - bgl_ids.push(id.0); + bgl_ids.push(each.id().0); } - each.bindings().iter().for_each(|bind| { - match bind.type_ { - GPUBindingType::Uniform_buffer => { - if bind.hasDynamicOffset { - max_dynamic_uniform_buffers_per_pipeline_layout -= 1; - }; - }, - GPUBindingType::Storage_buffer => { - if bind.hasDynamicOffset { - max_dynamic_storage_buffers_per_pipeline_layout -= 1; - }; - }, - GPUBindingType::Readonly_storage_buffer => { - if bind.hasDynamicOffset { - max_dynamic_storage_buffers_per_pipeline_layout -= 1; - }; - }, - _ => {}, - }; - }); }); - let valid = descriptor.bindGroupLayouts.len() <= limits.maxBindGroups as usize && - descriptor.bindGroupLayouts.len() == bind_group_layouts.len() && - max_dynamic_uniform_buffers_per_pipeline_layout >= 0 && - max_dynamic_storage_buffers_per_pipeline_layout >= 0; - let pipeline_layout_id = self .global() .wgpu_id_hub() @@ -513,50 +407,41 @@ impl GPUDeviceMethods for GPUDevice { .expect("Failed to create WebGPU PipelineLayout"); let pipeline_layout = webgpu::WebGPUPipelineLayout(pipeline_layout_id); - GPUPipelineLayout::new(&self.global(), bind_group_layouts, pipeline_layout, valid) + GPUPipelineLayout::new(&self.global(), pipeline_layout, true) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot { - let alignment: u64 = 256; - let mut valid = descriptor.layout.bindings().len() == descriptor.entries.len(); - - valid &= descriptor.entries.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 = wgt::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 => wgt::BufferUsage::STORAGE, - // GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ, - GPUBindingType::Uniform_buffer => wgt::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 + let mut valid = descriptor.layout.is_valid(); + let entries = descriptor .entries .iter() - .map(|bind| BindGroupEntry { - binding: bind.binding, - resource: BindingResource::Buffer(BufferBinding { - buffer: bind.resource.buffer.id().0, - offset: bind.resource.offset, - size: wgt::BufferSize( - bind.resource.size.unwrap_or(bind.resource.buffer.size()), - ), - }), + .map(|bind| { + ( + bind.binding, + match bind.resource { + GPUBindingResource::GPUSampler(ref s) => { + valid &= s.is_valid(); + WebGPUBindings::Sampler(s.id().0) + }, + GPUBindingResource::GPUTextureView(ref t) => { + valid &= t.is_valid(); + WebGPUBindings::TextureView(t.id().0) + }, + GPUBindingResource::GPUBufferBindings(ref b) => { + valid &= b.buffer.is_valid(); + WebGPUBindings::Buffer(BufferBinding { + buffer_id: b.buffer.id().0, + offset: b.offset, + size: if let Some(s) = b.size { + wgt::BufferSize(s) + } else { + wgt::BufferSize::WHOLE + }, + }) + }, + }, + ) }) .collect::>(); @@ -571,12 +456,18 @@ impl GPUDeviceMethods for GPUDevice { device_id: self.device.0, bind_group_id, bind_group_layout_id: descriptor.layout.id().0, - bindings, + entries, }) .expect("Failed to create WebGPU BindGroup"); let bind_group = webgpu::WebGPUBindGroup(bind_group_id); - GPUBindGroup::new(&self.global(), bind_group, valid) + GPUBindGroup::new( + &self.global(), + bind_group, + self.device, + valid, + &*descriptor.layout, + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule @@ -611,6 +502,7 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUComputePipelineDescriptor, ) -> DomRoot { + let valid = descriptor.parent.layout.is_valid(); let pipeline = descriptor.parent.layout.id(); let program = descriptor.computeStage.module.id(); let entry_point = descriptor.computeStage.entryPoint.to_string(); @@ -632,7 +524,7 @@ impl GPUDeviceMethods for GPUDevice { .expect("Failed to create WebGPU ComputePipeline"); let compute_pipeline = webgpu::WebGPUComputePipeline(compute_pipeline_id); - GPUComputePipeline::new(&self.global(), compute_pipeline) + GPUComputePipeline::new(&self.global(), compute_pipeline, valid) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder @@ -740,6 +632,7 @@ impl GPUDeviceMethods for GPUDevice { lod_max_clamp: *descriptor.lodMaxClamp, compare: descriptor.compare.map(|c| convert_compare_function(c)), anisotropy_clamp: None, + ..Default::default() }; self.channel .0 @@ -752,14 +645,7 @@ impl GPUDeviceMethods for GPUDevice { let sampler = webgpu::WebGPUSampler(sampler_id); - GPUSampler::new( - &self.global(), - self.channel.clone(), - self.device, - compare_enable, - sampler, - true, - ) + GPUSampler::new(&self.global(), self.device, compare_enable, sampler, true) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipeline @@ -767,12 +653,7 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPURenderPipelineDescriptor, ) -> DomRoot { - let mut valid = descriptor.parent.layout.is_valid(); - valid &= descriptor.colorStates.len() <= wgpu::device::MAX_COLOR_TARGETS; - if descriptor.alphaToCoverageEnabled { - valid &= descriptor.sampleCount > 1; - } - + let valid = descriptor.parent.layout.is_valid(); let vertex_module = descriptor.vertexStage.module.id().0; let vertex_entry_point = descriptor.vertexStage.entryPoint.to_string(); let (fragment_module, fragment_entry_point) = match descriptor.fragmentStage { @@ -813,10 +694,7 @@ impl GPUDeviceMethods for GPUDevice { color_blend: convert_blend_descriptor(&state.colorBlend), write_mask: match wgt::ColorWrite::from_bits(state.writeMask) { Some(mask) => mask, - None => { - valid = false; - wgt::ColorWrite::empty() - }, + None => wgt::ColorWrite::empty(), }, }) .collect::>(); diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs index af665ba8c41..a331456b14f 100644 --- a/components/script/dom/gpupipelinelayout.rs +++ b/components/script/dom/gpupipelinelayout.rs @@ -10,26 +10,20 @@ use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use dom_struct::dom_struct; use std::cell::Cell; -use webgpu::{WebGPUBindGroupLayout, WebGPUPipelineLayout}; +use webgpu::WebGPUPipelineLayout; #[dom_struct] pub struct GPUPipelineLayout { reflector_: Reflector, - bind_group_layouts: Vec, label: DomRefCell>, pipeline_layout: WebGPUPipelineLayout, valid: Cell, } impl GPUPipelineLayout { - fn new_inherited( - bind_group_layouts: Vec, - pipeline_layout: WebGPUPipelineLayout, - valid: bool, - ) -> Self { + fn new_inherited(pipeline_layout: WebGPUPipelineLayout, valid: bool) -> Self { Self { reflector_: Reflector::new(), - bind_group_layouts, label: DomRefCell::new(None), pipeline_layout, valid: Cell::new(valid), @@ -38,16 +32,11 @@ impl GPUPipelineLayout { pub fn new( global: &GlobalScope, - bind_group_layouts: Vec, pipeline_layout: WebGPUPipelineLayout, valid: bool, ) -> DomRoot { reflect_dom_object( - Box::new(GPUPipelineLayout::new_inherited( - bind_group_layouts, - pipeline_layout, - valid, - )), + Box::new(GPUPipelineLayout::new_inherited(pipeline_layout, valid)), global, ) } diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs index a74d1f86c8e..a2d223b6f5d 100644 --- a/components/script/dom/gpurenderpassencoder.rs +++ b/components/script/dom/gpurenderpassencoder.rs @@ -19,6 +19,7 @@ use crate::dom::gpurenderpipeline::GPURenderPipeline; use dom_struct::dom_struct; use webgpu::{ wgpu::command::{render_ffi as wgpu_render, RawPass}, + wgpu::id, wgt, WebGPU, WebGPURequest, }; @@ -29,12 +30,16 @@ pub struct GPURenderPassEncoder { channel: WebGPU, label: DomRefCell>, #[ignore_malloc_size_of = "defined in wgpu-core"] - raw_pass: DomRefCell>, + raw_pass: DomRefCell>>, command_encoder: Dom, } impl GPURenderPassEncoder { - fn new_inherited(channel: WebGPU, raw_pass: RawPass, parent: &GPUCommandEncoder) -> Self { + fn new_inherited( + channel: WebGPU, + raw_pass: RawPass, + parent: &GPUCommandEncoder, + ) -> Self { Self { channel, reflector_: Reflector::new(), @@ -47,7 +52,7 @@ impl GPURenderPassEncoder { pub fn new( global: &GlobalScope, channel: WebGPU, - raw_pass: RawPass, + raw_pass: RawPass, parent: &GPUCommandEncoder, ) -> DomRoot { reflect_dom_object( diff --git a/components/script/dom/gpusampler.rs b/components/script/dom/gpusampler.rs index db85f60e9b6..97e6c1dc37f 100644 --- a/components/script/dom/gpusampler.rs +++ b/components/script/dom/gpusampler.rs @@ -10,13 +10,11 @@ use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use dom_struct::dom_struct; use std::cell::Cell; -use webgpu::{WebGPU, WebGPUDevice, WebGPUSampler}; +use webgpu::{WebGPUDevice, WebGPUSampler}; #[dom_struct] pub struct GPUSampler { reflector_: Reflector, - #[ignore_malloc_size_of = "channels are hard"] - channel: WebGPU, label: DomRefCell>, device: WebGPUDevice, compare_enable: bool, @@ -26,7 +24,6 @@ pub struct GPUSampler { impl GPUSampler { fn new_inherited( - channel: WebGPU, device: WebGPUDevice, compare_enable: bool, sampler: WebGPUSampler, @@ -34,7 +31,6 @@ impl GPUSampler { ) -> Self { Self { reflector_: Reflector::new(), - channel, label: DomRefCell::new(None), valid: Cell::new(valid), device, @@ -45,7 +41,6 @@ impl GPUSampler { pub fn new( global: &GlobalScope, - channel: WebGPU, device: WebGPUDevice, compare_enable: bool, sampler: WebGPUSampler, @@ -53,7 +48,6 @@ impl GPUSampler { ) -> DomRoot { reflect_dom_object( Box::new(GPUSampler::new_inherited( - channel, device, compare_enable, sampler, @@ -64,6 +58,16 @@ impl GPUSampler { } } +impl GPUSampler { + pub fn id(&self) -> WebGPUSampler { + self.sampler + } + + pub fn is_valid(&self) -> bool { + self.valid.get() + } +} + impl GPUSamplerMethods for GPUSampler { /// https://gpuweb.github.io/gpuweb/#dom-gpuobjectbase-label fn GetLabel(&self) -> Option { diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 48060efa666..6bf4892887a 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -7,7 +7,7 @@ use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{ GPUExtent3DDict, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods, }; use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::{ - GPUTextureAspect, GPUTextureViewDescriptor, + GPUTextureAspect, GPUTextureViewDescriptor, GPUTextureViewDimension, }; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::DomRoot; @@ -122,23 +122,28 @@ impl GPUTextureMethods for GPUTexture { /// https://gpuweb.github.io/gpuweb/#dom-gputexture-createview fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot { + let dimension = if let Some(d) = descriptor.dimension { + d + } else { + match self.dimension { + GPUTextureDimension::_1d => GPUTextureViewDimension::_1d, + GPUTextureDimension::_2d => { + if self.texture_size.depth > 1 && descriptor.arrayLayerCount == 0 { + GPUTextureViewDimension::_2d_array + } else { + GPUTextureViewDimension::_2d + } + }, + GPUTextureDimension::_3d => GPUTextureViewDimension::_3d, + } + }; + + let format = descriptor.format.unwrap_or(self.format); + let desc = wgt::TextureViewDescriptor { label: Default::default(), - format: convert_texture_format(descriptor.format.unwrap_or(self.format)), - dimension: match descriptor.dimension { - Some(d) => convert_texture_view_dimension(d), - None => match self.dimension { - GPUTextureDimension::_1d => wgt::TextureViewDimension::D1, - GPUTextureDimension::_2d => { - if self.texture_size.depth > 1 && descriptor.arrayLayerCount == 0 { - wgt::TextureViewDimension::D2Array - } else { - wgt::TextureViewDimension::D2 - } - }, - GPUTextureDimension::_3d => wgt::TextureViewDimension::D3, - }, - }, + format: convert_texture_format(format), + dimension: convert_texture_view_dimension(dimension), aspect: match descriptor.aspect { GPUTextureAspect::All => wgt::TextureAspect::All, GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly, @@ -175,7 +180,7 @@ impl GPUTextureMethods for GPUTexture { let texture_view = WebGPUTextureView(texture_view_id); - GPUTextureView::new(&self.global(), texture_view, self.device, true) + GPUTextureView::new(&self.global(), texture_view, &self, self.valid.get()) } /// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs index f3bb4209708..06cb5a0ddbf 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -5,27 +5,32 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewMethods; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; +use crate::dom::gputexture::GPUTexture; use dom_struct::dom_struct; use std::cell::Cell; -use webgpu::{WebGPUDevice, WebGPUTextureView}; +use webgpu::WebGPUTextureView; #[dom_struct] pub struct GPUTextureView { reflector_: Reflector, label: DomRefCell>, texture_view: WebGPUTextureView, - device: WebGPUDevice, + texture: Dom, valid: Cell, } impl GPUTextureView { - fn new_inherited(texture_view: WebGPUTextureView, device: WebGPUDevice, valid: bool) -> Self { + fn new_inherited( + texture_view: WebGPUTextureView, + texture: &GPUTexture, + valid: bool, + ) -> GPUTextureView { Self { reflector_: Reflector::new(), - device, + texture: Dom::from_ref(texture), label: DomRefCell::new(None), texture_view, valid: Cell::new(valid), @@ -35,11 +40,11 @@ impl GPUTextureView { pub fn new( global: &GlobalScope, texture_view: WebGPUTextureView, - device: WebGPUDevice, + texture: &GPUTexture, valid: bool, - ) -> DomRoot { + ) -> DomRoot { reflect_dom_object( - Box::new(GPUTextureView::new_inherited(texture_view, device, valid)), + Box::new(GPUTextureView::new_inherited(texture_view, texture, valid)), global, ) } @@ -49,6 +54,10 @@ impl GPUTextureView { pub fn id(&self) -> WebGPUTextureView { self.texture_view } + + pub fn is_valid(&self) -> bool { + self.valid.get() + } } impl GPUTextureViewMethods for GPUTextureView { diff --git a/components/script/dom/webidls/GPUAdapter.webidl b/components/script/dom/webidls/GPUAdapter.webidl index 8d2e34f4a57..7fc2e8438f5 100644 --- a/components/script/dom/webidls/GPUAdapter.webidl +++ b/components/script/dom/webidls/GPUAdapter.webidl @@ -24,12 +24,13 @@ enum GPUExtensionName { }; dictionary GPULimits { - unsigned long maxBindGroups = 4; - unsigned long maxDynamicUniformBuffersPerPipelineLayout = 8; - unsigned long maxDynamicStorageBuffersPerPipelineLayout = 4; - unsigned long maxSampledTexturesPerShaderStage = 16; - unsigned long maxSamplersPerShaderStage = 16; - unsigned long maxStorageBuffersPerShaderStage = 4; - unsigned long maxStorageTexturesPerShaderStage = 4; - unsigned long maxUniformBuffersPerShaderStage = 12; + GPUSize32 maxBindGroups = 4; + GPUSize32 maxDynamicUniformBuffersPerPipelineLayout = 8; + GPUSize32 maxDynamicStorageBuffersPerPipelineLayout = 4; + GPUSize32 maxSampledTexturesPerShaderStage = 16; + GPUSize32 maxSamplersPerShaderStage = 16; + GPUSize32 maxStorageBuffersPerShaderStage = 4; + GPUSize32 maxStorageTexturesPerShaderStage = 4; + GPUSize32 maxUniformBuffersPerShaderStage = 12; + GPUSize32 maxUniformBufferBindingSize = 16384; }; diff --git a/components/script/dom/webidls/GPUBindGroup.webidl b/components/script/dom/webidls/GPUBindGroup.webidl index f905755d6fb..7bfa023acba 100644 --- a/components/script/dom/webidls/GPUBindGroup.webidl +++ b/components/script/dom/webidls/GPUBindGroup.webidl @@ -3,7 +3,7 @@ * 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"] +[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] interface GPUBindGroup { }; GPUBindGroup includes GPUObjectBase; @@ -13,10 +13,10 @@ dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase { required sequence entries; }; -typedef /*(GPUSampler or GPUTextureView or*/ GPUBufferBindings/*)*/ GPUBindingResource; +typedef (GPUSampler or GPUTextureView or GPUBufferBindings) GPUBindingResource; dictionary GPUBindGroupEntry { - required unsigned long binding; + required GPUIndex32 binding; required GPUBindingResource resource; }; diff --git a/components/script/dom/webidls/GPUBindGroupLayout.webidl b/components/script/dom/webidls/GPUBindGroupLayout.webidl index 8b2d63a84ff..6413afa6032 100644 --- a/components/script/dom/webidls/GPUBindGroupLayout.webidl +++ b/components/script/dom/webidls/GPUBindGroupLayout.webidl @@ -16,11 +16,12 @@ dictionary GPUBindGroupLayoutEntry { required GPUIndex32 binding; required GPUShaderStageFlags visibility; required GPUBindingType type; - GPUTextureViewDimension viewDimension = "2d"; - GPUTextureComponentType textureComponentType = "float"; - GPUTextureFormat storageTextureFormat; - boolean multisampled = false; boolean hasDynamicOffset = false; + GPUSize64 minBufferBindingSize = 0; + GPUTextureViewDimension viewDimension; + GPUTextureComponentType textureComponentType; + boolean multisampled = false; + GPUTextureFormat storageTextureFormat; }; enum GPUBindingType { @@ -28,8 +29,8 @@ enum GPUBindingType { "storage-buffer", "readonly-storage-buffer", "sampler", + "comparison-sampler", "sampled-texture", "readonly-storage-texture", - "writeonly-storage-texture", - //"comparison-sampler", + "writeonly-storage-texture" }; diff --git a/components/webgpu/identity.rs b/components/webgpu/identity.rs index 2b40ff5a9bc..9ed149eb152 100644 --- a/components/webgpu/identity.rs +++ b/components/webgpu/identity.rs @@ -8,8 +8,8 @@ use wgpu::{ hub::{GlobalIdentityHandlerFactory, IdentityHandler, IdentityHandlerFactory}, id::{ AdapterId, BindGroupId, BindGroupLayoutId, BufferId, CommandBufferId, ComputePipelineId, - DeviceId, PipelineLayoutId, RenderPipelineId, SamplerId, ShaderModuleId, SurfaceId, - SwapChainId, TextureId, TextureViewId, TypedId, + DeviceId, PipelineLayoutId, RenderBundleId, RenderPipelineId, SamplerId, ShaderModuleId, + SurfaceId, SwapChainId, TextureId, TextureViewId, TypedId, }, }; use wgt::Backend; @@ -31,6 +31,7 @@ pub enum WebGPUMsg { FreeSampler(SamplerId), FreeSurface(SurfaceId), FreeShaderModule(ShaderModuleId), + FreeRenderBundle(RenderBundleId), Exit, } @@ -73,6 +74,7 @@ impl_identity_handler!(BufferId, "buffer", WebGPUMsg::FreeBuffer); impl_identity_handler!(BindGroupId, "bind_group", WebGPUMsg::FreeBindGroup); impl_identity_handler!(SwapChainId, "swap_chain", WebGPUMsg::FreeSwapChain); impl_identity_handler!(ShaderModuleId, "shader_module", WebGPUMsg::FreeShaderModule); +impl_identity_handler!(RenderBundleId, "render_bundle", WebGPUMsg::FreeRenderBundle); impl_identity_handler!( RenderPipelineId, "render_pipeline", diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 9f04b2bd58b..800a248a4a6 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -28,9 +28,7 @@ use webrender_traits::{ WebrenderImageSource, }; use wgpu::{ - binding_model::{ - BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, - }, + binding_model::{BindGroupDescriptor, BindGroupEntry, BindingResource, BufferBinding}, command::{BufferCopyView, TextureCopyView}, device::HostMap, id, @@ -73,12 +71,12 @@ pub enum WebGPURequest { device_id: id::DeviceId, bind_group_id: id::BindGroupId, bind_group_layout_id: id::BindGroupLayoutId, - bindings: Vec, + entries: Vec<(u32, WebGPUBindings)>, }, CreateBindGroupLayout { device_id: id::DeviceId, bind_group_layout_id: id::BindGroupLayoutId, - bindings: Vec, + entries: Vec, }, CreateBuffer { device_id: id::DeviceId, @@ -195,6 +193,13 @@ pub enum WebGPURequest { }, } +#[derive(Debug, Deserialize, Serialize)] +pub enum WebGPUBindings { + Buffer(BufferBinding), + Sampler(id::SamplerId), + TextureView(id::TextureViewId), +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct WebGPU(pub IpcSender); @@ -334,14 +339,27 @@ impl WGPU { device_id, bind_group_id, bind_group_layout_id, - bindings, + mut entries, } => { let global = &self.global; + let bindings = entries + .drain(..) + .map(|(bind, res)| { + let resource = match res { + WebGPUBindings::Sampler(s) => BindingResource::Sampler(s), + WebGPUBindings::TextureView(t) => BindingResource::TextureView(t), + WebGPUBindings::Buffer(b) => BindingResource::Buffer(b), + }; + BindGroupEntry { + binding: bind, + resource, + } + }) + .collect::>(); let descriptor = BindGroupDescriptor { + label: None, layout: bind_group_layout_id, - entries: bindings.as_ptr(), - entries_length: bindings.len(), - label: ptr::null(), + bindings: bindings.as_slice(), }; let _ = gfx_select!(bind_group_id => global.device_create_bind_group(device_id, &descriptor, bind_group_id)); @@ -349,13 +367,12 @@ impl WGPU { WebGPURequest::CreateBindGroupLayout { device_id, bind_group_layout_id, - bindings, + entries, } => { let global = &self.global; - let descriptor = BindGroupLayoutDescriptor { - entries: bindings.as_ptr(), - entries_length: bindings.len(), - label: ptr::null(), + let descriptor = wgt::BindGroupLayoutDescriptor { + bindings: entries.as_slice(), + label: None, }; let _ = gfx_select!(bind_group_layout_id => global.device_create_bind_group_layout(device_id, &descriptor, bind_group_layout_id)); @@ -375,18 +392,9 @@ impl WGPU { command_encoder_id, } => { let global = &self.global; + let desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; let _ = gfx_select!(command_encoder_id => - global.device_create_command_encoder(device_id, &Default::default(), command_encoder_id)); - }, - WebGPURequest::CreateContext(sender) => { - let id = self - .external_images - .lock() - .expect("Lock poisoned?") - .next_id(WebrenderImageHandlerType::WebGPU); - if let Err(e) = sender.send(id) { - warn!("Failed to send ExternalImageId to new context ({})", e); - }; + global.device_create_command_encoder(device_id, &desc, command_encoder_id)); }, WebGPURequest::CreateComputePipeline { device_id, @@ -407,6 +415,16 @@ impl WGPU { let _ = gfx_select!(compute_pipeline_id => global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); }, + WebGPURequest::CreateContext(sender) => { + let id = self + .external_images + .lock() + .expect("Lock poisoned?") + .next_id(WebrenderImageHandlerType::WebGPU); + if let Err(e) = sender.send(id) { + warn!("Failed to send ExternalImageId to new context ({})", e); + }; + }, WebGPURequest::CreatePipelineLayout { device_id, pipeline_layout_id, @@ -631,6 +649,7 @@ impl WGPU { } => { let adapter_id = match self.global.pick_adapter( &options, + wgt::UnsafeExtensions::disallow(), wgpu::instance::AdapterInputs::IdSet(&ids, |id| id.backend()), ) { Some(id) => id, @@ -749,9 +768,10 @@ impl WGPU { } let buffer_size = (size.height as u32 * buffer_stride) as wgt::BufferAddress; + let comm_desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; let _ = gfx_select!(encoder_id => global.device_create_command_encoder( device_id, - &wgt::CommandEncoderDescriptor::default(), + &comm_desc, encoder_id ));