diff --git a/Cargo.lock b/Cargo.lock index d019836592ff..57acbec56fbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1785,9 +1785,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", @@ -1813,9 +1813,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", @@ -1840,9 +1840,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", @@ -1870,9 +1870,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", @@ -1881,8 +1881,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", @@ -6531,7 +6530,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", @@ -6560,7 +6559,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 01cbde4bcfaa..c42acc83de43 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -164,10 +164,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; @@ -578,7 +578,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 7947a0693352..e510afce17df 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 53b005fd7f05..8965952051c9 100644 --- a/components/script/dom/gpubindgroup.rs +++ b/components/script/dom/gpubindgroup.rs @@ -3,19 +3,14 @@ * 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::{ - GPUBindGroupEntry, GPUBindGroupMethods, -}; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::GPUBindGroupMethods; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use crate::dom::gpubindgrouplayout::GPUBindGroupLayout; -use crate::dom::gpubuffer::GPUBuffer; -use crate::dom::gputextureview::TextureSubresource; use dom_struct::dom_struct; use std::cell::Cell; -use std::collections::HashMap; use webgpu::{WebGPUBindGroup, WebGPUDevice}; #[dom_struct] @@ -25,10 +20,6 @@ pub struct GPUBindGroup { bind_group: WebGPUBindGroup, device: WebGPUDevice, layout: Dom, - #[ignore_malloc_size_of = "defined in webgpu"] - entries: Vec, - used_buffers: HashMap, u32>, - used_textures: HashMap, valid: Cell, } @@ -37,10 +28,7 @@ impl GPUBindGroup { bind_group: WebGPUBindGroup, device: WebGPUDevice, valid: bool, - entries: Vec, layout: &GPUBindGroupLayout, - used_buffers: HashMap, u32>, - used_textures: HashMap, ) -> Self { Self { reflector_: Reflector::new(), @@ -49,12 +37,6 @@ impl GPUBindGroup { device, valid: Cell::new(valid), layout: Dom::from_ref(layout), - entries, - used_buffers: used_buffers - .into_iter() - .map(|(key, value)| (Dom::from_ref(&*key), value)) - .collect(), - used_textures, } } @@ -63,20 +45,11 @@ impl GPUBindGroup { bind_group: WebGPUBindGroup, device: WebGPUDevice, valid: bool, - entries: Vec, layout: &GPUBindGroupLayout, - used_buffers: HashMap, u32>, - used_textures: HashMap, ) -> DomRoot { reflect_dom_object( Box::new(GPUBindGroup::new_inherited( - bind_group, - device, - valid, - entries, - layout, - used_buffers, - used_textures, + bind_group, device, valid, layout, )), global, ) diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs index f202cc37038d..68fb641bd25a 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/gpudevice.rs b/components/script/dom/gpudevice.rs index dbbc64708495..136a194c7df7 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -7,13 +7,12 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::GPULimits; use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::{ - GPUBindGroupDescriptor, GPUBindGroupEntry, GPUBindingResource, GPUBufferBindings, + GPUBindGroupDescriptor, GPUBindingResource, GPUBufferBindings, }; use crate::dom::bindings::codegen::Bindings::GPUBindGroupLayoutBinding::{ GPUBindGroupLayoutDescriptor, GPUBindGroupLayoutEntry, GPUBindingType, }; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::GPUBufferDescriptor; -use crate::dom::bindings::codegen::Bindings::GPUBufferUsageBinding::GPUBufferUsageConstants; use crate::dom::bindings::codegen::Bindings::GPUComputePipelineBinding::GPUComputePipelineDescriptor; use crate::dom::bindings::codegen::Bindings::GPUDeviceBinding::{ GPUCommandEncoderDescriptor, GPUDeviceMethods, @@ -32,7 +31,6 @@ use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{ GPUExtent3D, GPUExtent3DDict, GPUTextureComponentType, GPUTextureDescriptor, GPUTextureDimension, GPUTextureFormat, }; -use crate::dom::bindings::codegen::Bindings::GPUTextureUsageBinding::GPUTextureUsageConstants; use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewDimension; use crate::dom::bindings::codegen::UnionTypes::Uint32ArrayOrString::{String, Uint32Array}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; @@ -53,19 +51,18 @@ use crate::dom::gpurenderpipeline::GPURenderPipeline; use crate::dom::gpusampler::GPUSampler; use crate::dom::gpushadermodule::GPUShaderModule; use crate::dom::gputexture::GPUTexture; -use crate::dom::gputextureview::{GPUTextureView, TextureSubresource}; +use crate::dom::gputextureview::GPUTextureView; use crate::script_runtime::JSContext as SafeJSContext; use arrayvec::ArrayVec; use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use js::jsval::{JSVal, ObjectValue}; use js::typedarray::{ArrayBuffer, CreateWith}; -use std::collections::{hash_map::Entry, HashMap, HashSet}; +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, wgpu, wgt, WebGPU, WebGPUBindings, WebGPURequest}; #[dom_struct] pub struct GPUDevice { @@ -165,11 +162,11 @@ impl GPUDevice { binding: &GPUBindGroupLayoutEntry, ) -> bool { let mut valid = if let Some(d) = binding.viewDimension { - texture_view.descriptor().dimension.unwrap() == d + texture_view.dimension() == d } else { false }; - let view_component = get_component_from_format(texture_view.descriptor().format.unwrap()); + let view_component = get_component_from_format(texture_view.format()); valid &= if let Some(c) = binding.textureComponentType { view_component == c } else { @@ -189,10 +186,11 @@ impl GPUDevice { }, GPUBindingType::Readonly_storage_texture | GPUBindingType::Writeonly_storage_texture => { - match wgt::TextureUsage::from_bits(texture_view.texture().usage()) { + let v = match wgt::TextureUsage::from_bits(texture_view.texture().usage()) { Some(u) => u.contains(wgt::TextureUsage::STORAGE), None => false, - } + }; + v && Some(texture_view.format()) == binding.storageTextureFormat }, _ => false, }; @@ -227,9 +225,13 @@ impl GPUDevice { _ => false, }; valid &= if let Some(s) = buffer_bind.size { - buffer_bind.offset + s <= buffer_bind.buffer.size() && buffer_bind.offset > 0 + buffer_bind.offset + s <= buffer_bind.buffer.size() && + buffer_bind.offset + s >= binding.minBufferBindingSize && + buffer_bind.offset > 0 && + buffer_bind.offset.checked_add(s).is_some() } else { - buffer_bind.offset > 0 && buffer_bind.offset < buffer_bind.buffer.size() + buffer_bind.offset < buffer_bind.buffer.size() && + buffer_bind.buffer.size() - buffer_bind.offset >= binding.minBufferBindingSize }; valid } @@ -407,7 +409,14 @@ impl GPUDeviceMethods for GPUDevice { bind.textureComponentType.is_none() && !bind.multisampled && bind.storageTextureFormat.is_none(); - BindingType::UniformBuffer + 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) { @@ -421,7 +430,15 @@ impl GPUDeviceMethods for GPUDevice { bind.textureComponentType.is_none() && !bind.multisampled && bind.storageTextureFormat.is_none(); - BindingType::StorageBuffer + 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) { @@ -434,14 +451,46 @@ impl GPUDeviceMethods for GPUDevice { bind.textureComponentType.is_none() && !bind.multisampled && bind.storageTextureFormat.is_none(); - BindingType::ReadonlyStorageBuffer + 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; } - valid &= !bind.hasDynamicOffset && bind.storageTextureFormat.is_none(); - BindingType::SampledTexture + valid &= !bind.hasDynamicOffset && + bind.storageTextureFormat.is_none() && + bind.minBufferBindingSize == 0; + 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) { @@ -449,8 +498,22 @@ impl GPUDeviceMethods for GPUDevice { } valid &= !bind.hasDynamicOffset && bind.textureComponentType.is_none() && - !bind.multisampled; - BindingType::ReadonlyStorageTexture + !bind.multisampled && + bind.minBufferBindingSize == 0 && + bind.storageTextureFormat.is_some(); + 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) { @@ -458,8 +521,22 @@ impl GPUDeviceMethods for GPUDevice { } valid &= !bind.hasDynamicOffset && bind.textureComponentType.is_none() && - !bind.multisampled; - BindingType::WriteonlyStorageTexture + !bind.multisampled && + bind.minBufferBindingSize == 0 && + bind.storageTextureFormat.is_some(); + 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) { @@ -469,8 +546,9 @@ impl GPUDeviceMethods for GPUDevice { bind.viewDimension.is_none() && bind.textureComponentType.is_none() && !bind.multisampled && - bind.storageTextureFormat.is_none(); - BindingType::Sampler + bind.storageTextureFormat.is_none() && + bind.minBufferBindingSize == 0; + wgt::BindingType::Sampler { comparison: false } }, GPUBindingType::Comparison_sampler => { if let Some(limit) = validation_map.get_mut(&visibility) { @@ -480,38 +558,15 @@ impl GPUDeviceMethods for GPUDevice { bind.viewDimension.is_none() && bind.textureComponentType.is_none() && !bind.multisampled && - bind.storageTextureFormat.is_none(); - BindingType::ComparisonSampler + bind.storageTextureFormat.is_none() && + bind.minBufferBindingSize == 0; + wgt::BindingType::Sampler { comparison: true } }, }; - BindGroupLayoutEntry { - binding: bind.binding, - visibility, - ty, - has_dynamic_offset: bind.hasDynamicOffset, - multisampled: bind.multisampled, - texture_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 - }, - storage_texture_format: match bind.storageTextureFormat { - Some(s) => convert_texture_format(s), - None => wgt::TextureFormat::Bgra8UnormSrgb, - }, - view_dimension: bind - .viewDimension - .map_or(wgt::TextureViewDimension::D2, |v| { - convert_texture_view_dimension(v) - }), - } + wgt::BindGroupLayoutEntry::new(bind.binding, visibility, ty) }) - .collect::>(); + .collect::>(); // bindings are unique valid &= storeBindings.len() == entries.len(); @@ -539,7 +594,7 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateBindGroupLayout { device_id: self.device.0, bind_group_layout_id, - entries: entries.clone(), + entries, }) .expect("Failed to create WebGPU BindGroupLayout"); @@ -558,6 +613,7 @@ impl GPUDeviceMethods for GPUDevice { viewDimension: bind.viewDimension, textureComponentType: bind.textureComponentType, storageTextureFormat: bind.storageTextureFormat, + minBufferBindingSize: bind.minBufferBindingSize, }, ); }); @@ -631,43 +687,13 @@ impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbindgroup fn CreateBindGroup(&self, descriptor: &GPUBindGroupDescriptor) -> DomRoot { - //let alignment: u64 = 256; let mut valid = descriptor.layout.is_valid() && descriptor.layout.entries().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.entries().iter().any(|layout_bind| { - match layout_bind.type_ { - GPUBindingType::Storage_buffer => usage.contains(wgt::BufferUsage::STORAGE), - // GPUBindingType::Readonly_storage_buffer => BufferUsage::STORAGE_READ, - GPUBindingType::Uniform_buffer => usage.contains(wgt::BufferUsage::UNIFORM), - GPUBindingType::Sampler => bind.resource - _ => unimplemented!(), - }; - // binding must be present in layout - layout_bind.binding == bind.binding - }) - });*/ let mut bindings = HashSet::new(); - let mut used_buffers = HashMap::new(); - let mut used_textures = HashMap::new(); valid &= descriptor.entries.iter().all(|bind| { bindings.insert(bind.binding); - if let Some(layout_bind) = descriptor - .layout - .entries() - .values() - .find(|lb| lb.binding == bind.binding) - { + if let Some(layout_bind) = descriptor.layout.entries().get(&bind.binding) { match layout_bind.type_ { GPUBindingType::Sampler => match bind.resource { GPUBindingResource::GPUSampler(ref s) => s.is_valid() && !s.compare(), @@ -677,87 +703,22 @@ impl GPUDeviceMethods for GPUDevice { GPUBindingResource::GPUSampler(ref s) => s.is_valid() && s.compare(), _ => false, }, - GPUBindingType::Sampled_texture => match bind.resource { - GPUBindingResource::GPUTextureView(ref t) => { - let desc = t.descriptor(); - for i in desc.baseMipLevel..desc.mipLevelCount { - for j in desc.baseArrayLayer..desc.arrayLayerCount { - let subresource = TextureSubresource { - texture: DomRoot::from_ref(t.texture()), - mipmap_level: i, - array_layer: j, - }; - match used_textures.entry(subresource) { - Entry::Vacant(v) => { - v.insert(GPUTextureUsageConstants::SAMPLED); - }, - Entry::Occupied(mut o) => { - *o.get_mut() += GPUTextureUsageConstants::SAMPLED; - }, - } - } - } - t.is_valid() && self.validate_texture_view_binding(t, layout_bind) - }, - _ => false, - }, + GPUBindingType::Sampled_texture | GPUBindingType::Readonly_storage_texture | GPUBindingType::Writeonly_storage_texture => match bind.resource { GPUBindingResource::GPUTextureView(ref t) => { - let desc = t.descriptor(); - for i in desc.baseMipLevel..desc.mipLevelCount { - for j in desc.baseArrayLayer..desc.arrayLayerCount { - let subresource = TextureSubresource { - texture: DomRoot::from_ref(t.texture()), - mipmap_level: i, - array_layer: j, - }; - match used_textures.entry(subresource) { - Entry::Vacant(v) => { - v.insert(GPUTextureUsageConstants::STORAGE); - }, - Entry::Occupied(mut o) => { - *o.get_mut() += GPUTextureUsageConstants::STORAGE; - }, - } - } - } - t.is_valid() && - self.validate_texture_view_binding(t, layout_bind) && - t.descriptor().format == layout_bind.storageTextureFormat + t.is_valid() && self.validate_texture_view_binding(t, layout_bind) }, _ => false, }, - GPUBindingType::Uniform_buffer => match bind.resource { + GPUBindingType::Uniform_buffer | + GPUBindingType::Storage_buffer | + GPUBindingType::Readonly_storage_buffer => match bind.resource { GPUBindingResource::GPUBufferBindings(ref b) => { - match used_buffers.entry(DomRoot::from_ref(&*b.buffer)) { - Entry::Vacant(v) => { - v.insert(GPUBufferUsageConstants::UNIFORM); - }, - Entry::Occupied(mut o) => { - *o.get_mut() += GPUBufferUsageConstants::UNIFORM; - }, - } b.buffer.is_valid() && self.validate_buffer_binding(b, layout_bind) }, _ => false, }, - GPUBindingType::Storage_buffer | GPUBindingType::Readonly_storage_buffer => { - match bind.resource { - GPUBindingResource::GPUBufferBindings(ref b) => { - match used_buffers.entry(DomRoot::from_ref(&*b.buffer)) { - Entry::Vacant(v) => { - v.insert(GPUBufferUsageConstants::STORAGE); - }, - Entry::Occupied(mut o) => { - *o.get_mut() += GPUBufferUsageConstants::STORAGE; - }, - } - b.buffer.is_valid() && self.validate_buffer_binding(b, layout_bind) - }, - _ => false, - } - }, } } else { false @@ -769,25 +730,27 @@ impl GPUDeviceMethods for GPUDevice { let entries = descriptor .entries .iter() - .map(|bind| BindGroupEntry { - binding: bind.binding, - resource: match bind.resource { - GPUBindingResource::GPUSampler(ref s) => BindingResource::Sampler(s.id().0), - GPUBindingResource::GPUTextureView(ref t) => { - BindingResource::TextureView(t.id().0) - }, - GPUBindingResource::GPUBufferBindings(ref b) => { - BindingResource::Buffer(BufferBinding { - buffer: b.buffer.id().0, - offset: b.offset, - size: if let Some(s) = b.size { - wgt::BufferSize(s) - } else { - wgt::BufferSize::WHOLE - }, - }) + .map(|bind| { + ( + bind.binding, + match bind.resource { + GPUBindingResource::GPUSampler(ref s) => WebGPUBindings::Sampler(s.id().0), + GPUBindingResource::GPUTextureView(ref t) => { + WebGPUBindings::TextureView(t.id().0) + }, + GPUBindingResource::GPUBufferBindings(ref b) => { + 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::>(); @@ -806,39 +769,13 @@ impl GPUDeviceMethods for GPUDevice { }) .expect("Failed to create WebGPU BindGroup"); - let desc_entries = descriptor - .entries - .iter() - .map(|bind| GPUBindGroupEntry { - binding: bind.binding, - resource: match bind.resource { - GPUBindingResource::GPUSampler(ref s) => { - GPUBindingResource::GPUSampler(DomRoot::from_ref(&*s)) - }, - GPUBindingResource::GPUTextureView(ref t) => { - GPUBindingResource::GPUTextureView(DomRoot::from_ref(&*t)) - }, - GPUBindingResource::GPUBufferBindings(ref b) => { - GPUBindingResource::GPUBufferBindings(GPUBufferBindings { - buffer: DomRoot::from_ref(&*b.buffer), - offset: b.offset, - size: b.size, - }) - }, - }, - }) - .collect::>(); - let bind_group = webgpu::WebGPUBindGroup(bind_group_id); GPUBindGroup::new( &self.global(), bind_group, self.device, valid, - desc_entries, &*descriptor.layout, - used_buffers, - used_textures, ) } @@ -1003,6 +940,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 @@ -1015,14 +953,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 diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs index a74d1f86c8e6..a2d223b6f5d4 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 488d3df1d05c..2c15d89b0fc0 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, diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 54b5610ae480..59e97e433170 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::GPUObjectBaseBinding::GPUObjectDescriptorBase; use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{ GPUExtent3DDict, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods, }; @@ -189,32 +188,7 @@ impl GPUTextureMethods for GPUTexture { let texture_view = WebGPUTextureView(texture_view_id); - let desc = GPUTextureViewDescriptor { - parent: GPUObjectDescriptorBase { - label: descriptor - .parent - .label - .as_ref() - .map(|l| l.as_ref().map(|u| u.clone())), - }, - arrayLayerCount: if descriptor.arrayLayerCount == 0 { - self.texture_size.depth - descriptor.baseArrayLayer - } else { - descriptor.arrayLayerCount - }, - aspect: descriptor.aspect, - baseArrayLayer: descriptor.baseArrayLayer, - baseMipLevel: descriptor.baseMipLevel, - dimension: Some(dimension), - format: Some(descriptor.format.unwrap_or(self.format)), - mipLevelCount: if descriptor.mipLevelCount == 0 { - self.mip_level_count - descriptor.baseMipLevel - } else { - descriptor.mipLevelCount - }, - }; - - GPUTextureView::new(&self.global(), texture_view, &self, true, desc) + GPUTextureView::new(&self.global(), texture_view, &self, true, dimension, format) } /// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs index e1c14ef1cd59..c5334e9b7ec5 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -3,8 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewDescriptor; -use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewMethods; +use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUTextureFormat; +use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::{ + GPUTextureViewDimension, GPUTextureViewMethods, +}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; @@ -12,34 +14,8 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::gputexture::GPUTexture; use dom_struct::dom_struct; use std::cell::Cell; -use std::hash::{Hash, Hasher}; use webgpu::WebGPUTextureView; -#[derive(MallocSizeOf, JSTraceable)] -pub struct TextureSubresource { - pub texture: DomRoot, - pub mipmap_level: u32, - pub array_layer: u32, -} - -impl PartialEq for TextureSubresource { - fn eq(&self, other: &Self) -> bool { - self.texture.id().0 == other.texture.id().0 && - self.mipmap_level == other.mipmap_level && - self.array_layer == other.array_layer - } -} - -impl Eq for TextureSubresource {} - -impl Hash for TextureSubresource { - fn hash(&self, state: &mut H) { - self.texture.id().0.hash(state); - self.mipmap_level.hash(state); - self.array_layer.hash(state); - } -} - #[dom_struct] pub struct GPUTextureView { reflector_: Reflector, @@ -47,8 +23,8 @@ pub struct GPUTextureView { texture_view: WebGPUTextureView, texture: Dom, valid: Cell, - #[ignore_malloc_size_of = "defined in webgpu"] - descriptor: GPUTextureViewDescriptor, + dimension: GPUTextureViewDimension, + format: GPUTextureFormat, } impl GPUTextureView { @@ -56,7 +32,8 @@ impl GPUTextureView { texture_view: WebGPUTextureView, texture: &GPUTexture, valid: bool, - descriptor: GPUTextureViewDescriptor, + dimension: GPUTextureViewDimension, + format: GPUTextureFormat, ) -> GPUTextureView { Self { reflector_: Reflector::new(), @@ -64,7 +41,8 @@ impl GPUTextureView { label: DomRefCell::new(None), texture_view, valid: Cell::new(valid), - descriptor, + dimension, + format, } } @@ -73,14 +51,16 @@ impl GPUTextureView { texture_view: WebGPUTextureView, texture: &GPUTexture, valid: bool, - descriptor: GPUTextureViewDescriptor, + dimension: GPUTextureViewDimension, + format: GPUTextureFormat, ) -> DomRoot { reflect_dom_object( Box::new(GPUTextureView::new_inherited( texture_view, texture, valid, - descriptor, + dimension, + format, )), global, ) @@ -96,8 +76,12 @@ impl GPUTextureView { self.valid.get() } - pub fn descriptor(&self) -> &GPUTextureViewDescriptor { - &self.descriptor + pub fn dimension(&self) -> GPUTextureViewDimension { + self.dimension + } + + pub fn format(&self) -> GPUTextureFormat { + self.format } pub fn texture(&self) -> &GPUTexture { diff --git a/components/script/dom/webidls/GPUBindGroupLayout.webidl b/components/script/dom/webidls/GPUBindGroupLayout.webidl index 32ae601440e3..6413afa60324 100644 --- a/components/script/dom/webidls/GPUBindGroupLayout.webidl +++ b/components/script/dom/webidls/GPUBindGroupLayout.webidl @@ -16,18 +16,11 @@ dictionary GPUBindGroupLayoutEntry { required GPUIndex32 binding; required GPUShaderStageFlags visibility; required GPUBindingType type; - - // Used for uniform buffer and storage buffer bindings. boolean hasDynamicOffset = false; - - // Used for sampled texture and storage texture bindings. + GPUSize64 minBufferBindingSize = 0; GPUTextureViewDimension viewDimension; - - // Used for sampled texture bindings. GPUTextureComponentType textureComponentType; boolean multisampled = false; - - // Used for storage texture bindings. GPUTextureFormat storageTextureFormat; }; @@ -36,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 2b40ff5a9bcb..9ed149eb1524 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 45a7e4533647..800a248a4a6a 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, - entries: Vec, + entries: Vec<(u32, WebGPUBindings)>, }, CreateBindGroupLayout { device_id: id::DeviceId, bind_group_layout_id: id::BindGroupLayoutId, - entries: 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, - entries, + 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: entries.as_ptr(), - entries_length: entries.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)); @@ -352,10 +370,9 @@ impl WGPU { entries, } => { let global = &self.global; - let descriptor = BindGroupLayoutDescriptor { - entries: entries.as_ptr(), - entries_length: entries.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 ));