From 00b3f785c4d4bb4da9d883128d9dc18e0406ad71 Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Tue, 2 Jun 2020 15:36:08 +0530 Subject: [PATCH 1/3] Add GPUSampler and GPUTextureView to BindingResource Add validation for BindGroups --- components/script/dom/gpubindgroup.rs | 57 ++- components/script/dom/gpubindgrouplayout.rs | 15 +- components/script/dom/gpubuffer.rs | 2 +- components/script/dom/gpucommandencoder.rs | 4 +- components/script/dom/gpudevice.rs | 422 +++++++++++++++--- components/script/dom/gpusampler.rs | 14 + components/script/dom/gputexture.rs | 73 ++- components/script/dom/gputextureview.rs | 70 ++- .../script/dom/webidls/GPUAdapter.webidl | 17 +- .../script/dom/webidls/GPUBindGroup.webidl | 6 +- .../dom/webidls/GPUBindGroupLayout.webidl | 18 +- components/webgpu/lib.rs | 16 +- 12 files changed, 591 insertions(+), 123 deletions(-) diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs index 4767d28d0f1..53b005fd7f0 100644 --- a/components/script/dom/gpubindgroup.rs +++ b/components/script/dom/gpubindgroup.rs @@ -3,36 +3,81 @@ * 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::GPUBindGroupMethods; +use crate::dom::bindings::codegen::Bindings::GPUBindGroupBinding::{ + GPUBindGroupEntry, 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 crate::dom::gpubuffer::GPUBuffer; +use crate::dom::gputextureview::TextureSubresource; use dom_struct::dom_struct; use std::cell::Cell; -use webgpu::WebGPUBindGroup; +use std::collections::HashMap; +use webgpu::{WebGPUBindGroup, WebGPUDevice}; #[dom_struct] pub struct GPUBindGroup { reflector_: Reflector, label: DomRefCell>, 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, } impl GPUBindGroup { - fn new_inherited(bind_group: WebGPUBindGroup, valid: bool) -> Self { + fn new_inherited( + bind_group: WebGPUBindGroup, + device: WebGPUDevice, + valid: bool, + entries: Vec, + layout: &GPUBindGroupLayout, + used_buffers: HashMap, u32>, + used_textures: HashMap, + ) -> Self { Self { reflector_: Reflector::new(), label: DomRefCell::new(None), bind_group, + 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, } } - pub fn new(global: &GlobalScope, bind_group: WebGPUBindGroup, valid: bool) -> DomRoot { + pub fn new( + global: &GlobalScope, + 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, valid)), + Box::new(GPUBindGroup::new_inherited( + bind_group, + device, + valid, + entries, + layout, + used_buffers, + used_textures, + )), global, ) } diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs index 8c141256261..aadc75557b2 100644 --- a/components/script/dom/gpubindgrouplayout.rs +++ b/components/script/dom/gpubindgrouplayout.rs @@ -12,6 +12,7 @@ use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use dom_struct::dom_struct; use std::cell::Cell; +use std::collections::HashMap; use webgpu::{WebGPU, WebGPUBindGroupLayout}; #[dom_struct] @@ -20,7 +21,7 @@ pub struct GPUBindGroupLayout { label: DomRefCell>, bind_group_layout: WebGPUBindGroupLayout, #[ignore_malloc_size_of = "defined in webgpu"] - bindings: Vec, + entry_map: HashMap, #[ignore_malloc_size_of = "defined in webgpu"] channel: WebGPU, valid: Cell, @@ -30,7 +31,7 @@ impl GPUBindGroupLayout { fn new_inherited( channel: WebGPU, bind_group_layout: WebGPUBindGroupLayout, - bindings: Vec, + entry_map: HashMap, valid: bool, ) -> Self { Self { @@ -38,7 +39,7 @@ impl GPUBindGroupLayout { channel, label: DomRefCell::new(None), bind_group_layout, - bindings, + entry_map, valid: Cell::new(valid), } } @@ -47,14 +48,14 @@ impl GPUBindGroupLayout { global: &GlobalScope, channel: WebGPU, bind_group_layout: WebGPUBindGroupLayout, - bindings: Vec, + entry_map: HashMap, valid: bool, ) -> DomRoot { reflect_dom_object( Box::new(GPUBindGroupLayout::new_inherited( channel, bind_group_layout, - bindings, + entry_map, valid, )), global, @@ -71,8 +72,8 @@ impl GPUBindGroupLayout { self.bind_group_layout } - pub fn bindings(&self) -> &[GPUBindGroupLayoutEntry] { - &self.bindings + pub fn entries(&self) -> &HashMap { + &self.entry_map } } 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/gpudevice.rs b/components/script/dom/gpudevice.rs index fbbfa541761..dbbc6470849 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -6,11 +6,14 @@ 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, GPUBindGroupEntry, 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, @@ -29,6 +32,7 @@ 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}; @@ -49,13 +53,14 @@ 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::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::{HashMap, HashSet}; +use std::collections::{hash_map::Entry, HashMap, HashSet}; use std::ptr::{self, NonNull}; use webgpu::wgpu::binding_model::{ BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BufferBinding, @@ -153,6 +158,81 @@ impl GPUDevice { ) } } + + fn validate_texture_view_binding( + &self, + texture_view: &GPUTextureView, + binding: &GPUBindGroupLayoutEntry, + ) -> bool { + let mut valid = if let Some(d) = binding.viewDimension { + texture_view.descriptor().dimension.unwrap() == d + } else { + false + }; + let view_component = get_component_from_format(texture_view.descriptor().format.unwrap()); + valid &= if let Some(c) = binding.textureComponentType { + view_component == c + } else { + false + }; + valid &= if binding.multisampled { + texture_view.texture().sample_count() > 1 + } else { + texture_view.texture().sample_count() == 1 + }; + valid &= match binding.type_ { + GPUBindingType::Sampled_texture => { + match wgt::TextureUsage::from_bits(texture_view.texture().usage()) { + Some(u) => u.contains(wgt::TextureUsage::SAMPLED), + None => false, + } + }, + GPUBindingType::Readonly_storage_texture | + GPUBindingType::Writeonly_storage_texture => { + match wgt::TextureUsage::from_bits(texture_view.texture().usage()) { + Some(u) => u.contains(wgt::TextureUsage::STORAGE), + None => false, + } + }, + _ => false, + }; + valid + } + + fn validate_buffer_binding( + &self, + buffer_bind: &GPUBufferBindings, + binding: &GPUBindGroupLayoutEntry, + ) -> bool { + let mut valid = match binding.type_ { + GPUBindingType::Uniform_buffer => { + match wgt::BufferUsage::from_bits(buffer_bind.buffer.usage()) { + Some(u) => { + let v = if let Some(s) = buffer_bind.size { + s <= GPULimits::empty().maxUniformBufferBindingSize.into() + } else { + true + }; + v && u.contains(wgt::BufferUsage::UNIFORM) + }, + None => false, + } + }, + GPUBindingType::Storage_buffer | GPUBindingType::Readonly_storage_buffer => { + match wgt::BufferUsage::from_bits(buffer_bind.buffer.usage()) { + Some(u) => u.contains(wgt::BufferUsage::STORAGE), + None => false, + } + }, + _ => false, + }; + valid &= if let Some(s) = buffer_bind.size { + buffer_bind.offset + s <= buffer_bind.buffer.size() && buffer_bind.offset > 0 + } else { + buffer_bind.offset > 0 && buffer_bind.offset < buffer_bind.buffer.size() + }; + valid + } } impl GPUDeviceMethods for GPUDevice { @@ -303,11 +383,10 @@ impl GPUDeviceMethods for GPUDevice { 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, @@ -324,6 +403,10 @@ impl GPUDeviceMethods for GPUDevice { if bind.hasDynamicOffset { max_dynamic_uniform_buffers_per_pipeline_layout -= 1; }; + valid &= bind.viewDimension.is_none() && + bind.textureComponentType.is_none() && + !bind.multisampled && + bind.storageTextureFormat.is_none(); BindingType::UniformBuffer }, GPUBindingType::Storage_buffer => { @@ -333,6 +416,11 @@ impl GPUDeviceMethods for GPUDevice { if bind.hasDynamicOffset { max_dynamic_storage_buffers_per_pipeline_layout -= 1; }; + valid &= bind.viewDimension.is_none() && + !visibility.contains(wgt::ShaderStage::VERTEX) && + bind.textureComponentType.is_none() && + !bind.multisampled && + bind.storageTextureFormat.is_none(); BindingType::StorageBuffer }, GPUBindingType::Readonly_storage_buffer => { @@ -342,44 +430,59 @@ impl GPUDeviceMethods for GPUDevice { if bind.hasDynamicOffset { max_dynamic_storage_buffers_per_pipeline_layout -= 1; }; + valid &= bind.viewDimension.is_none() && + bind.textureComponentType.is_none() && + !bind.multisampled && + bind.storageTextureFormat.is_none(); BindingType::ReadonlyStorageBuffer }, 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 - }; + valid &= !bind.hasDynamicOffset && bind.storageTextureFormat.is_none(); BindingType::SampledTexture }, 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 - }; + valid &= !bind.hasDynamicOffset && + bind.textureComponentType.is_none() && + !bind.multisampled; BindingType::ReadonlyStorageTexture }, 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 - }; + valid &= !bind.hasDynamicOffset && + bind.textureComponentType.is_none() && + !bind.multisampled; BindingType::WriteonlyStorageTexture }, GPUBindingType::Sampler => { if let Some(limit) = validation_map.get_mut(&visibility) { limit.max_samplers_per_shader_stage -= 1; } - if bind.hasDynamicOffset { - valid = false - }; + valid &= !bind.hasDynamicOffset && + bind.viewDimension.is_none() && + bind.textureComponentType.is_none() && + !bind.multisampled && + bind.storageTextureFormat.is_none(); BindingType::Sampler }, + GPUBindingType::Comparison_sampler => { + if let Some(limit) = validation_map.get_mut(&visibility) { + limit.max_samplers_per_shader_stage -= 1; + } + valid &= !bind.hasDynamicOffset && + bind.viewDimension.is_none() && + bind.textureComponentType.is_none() && + !bind.multisampled && + bind.storageTextureFormat.is_none(); + BindingType::ComparisonSampler + }, }; BindGroupLayoutEntry { @@ -388,22 +491,30 @@ impl GPUDeviceMethods for GPUDevice { 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, + 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: convert_texture_view_dimension(bind.viewDimension), + view_dimension: bind + .viewDimension + .map_or(wgt::TextureViewDimension::D2, |v| { + convert_texture_view_dimension(v) + }), } }) .collect::>(); // bindings are unique - valid &= storeBindings.len() == bindings.len(); + valid &= storeBindings.len() == entries.len(); // Ensure that values do not exceed the max limit for each ShaderStage. valid &= validation_map.values().all(|stage| { @@ -428,26 +539,28 @@ impl GPUDeviceMethods for GPUDevice { .send(WebGPURequest::CreateBindGroupLayout { device_id: self.device.0, bind_group_layout_id, - bindings: bindings.clone(), + entries: entries.clone(), }) .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::>(); + let mut binds = HashMap::new(); + descriptor.entries.iter().for_each(|bind| { + binds.insert( + bind.binding, + 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, + }, + ); + }); GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid) } @@ -471,7 +584,7 @@ impl GPUDeviceMethods for GPUDevice { bind_group_layouts.push(id); bgl_ids.push(id.0); } - each.bindings().iter().for_each(|bind| { + each.entries().values().for_each(|bind| { match bind.type_ { GPUBindingType::Uniform_buffer => { if bind.hasDynamicOffset { @@ -518,10 +631,11 @@ 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.bindings().len() == descriptor.entries.len(); + //let alignment: u64 = 256; + let mut valid = descriptor.layout.is_valid() && + descriptor.layout.entries().len() == descriptor.entries.len(); - valid &= descriptor.entries.iter().all(|bind| { + /*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); @@ -531,32 +645,149 @@ impl GPUDeviceMethods for GPUDevice { 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, + 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 => wgt::BufferUsage::UNIFORM, + GPUBindingType::Uniform_buffer => usage.contains(wgt::BufferUsage::UNIFORM), + GPUBindingType::Sampler => bind.resource _ => unimplemented!(), }; // binding must be present in layout - layout_bind.binding == bind.binding && - // binding must contain one buffer of its type - usage.contains(ty) + 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) + { + match layout_bind.type_ { + GPUBindingType::Sampler => match bind.resource { + GPUBindingResource::GPUSampler(ref s) => s.is_valid() && !s.compare(), + _ => false, + }, + GPUBindingType::Comparison_sampler => match bind.resource { + 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::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 + }, + _ => false, + }, + GPUBindingType::Uniform_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 + } }); - let bindings = descriptor + valid &= bindings.len() == descriptor.entries.len(); + + 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()), - ), - }), + 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 + }, + }) + }, + }, }) .collect::>(); @@ -571,12 +802,44 @@ 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 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, valid) + GPUBindGroup::new( + &self.global(), + bind_group, + self.device, + valid, + desc_entries, + &*descriptor.layout, + used_buffers, + used_textures, + ) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createshadermodule @@ -1094,3 +1357,46 @@ fn convert_texture_size_to_wgt(size: &GPUExtent3DDict) -> wgt::Extent3d { depth: size.depth, } } + +fn get_component_from_format(format: GPUTextureFormat) -> GPUTextureComponentType { + match format { + GPUTextureFormat::R8unorm | + GPUTextureFormat::R8snorm | + GPUTextureFormat::R16float | + GPUTextureFormat::Rg8unorm | + GPUTextureFormat::Rg8snorm | + GPUTextureFormat::R32float | + GPUTextureFormat::Rg16float | + GPUTextureFormat::Rgba8unorm | + GPUTextureFormat::Rgba8unorm_srgb | + GPUTextureFormat::Rgba8snorm | + GPUTextureFormat::Bgra8unorm | + GPUTextureFormat::Bgra8unorm_srgb | + GPUTextureFormat::Rgb10a2unorm | + GPUTextureFormat::Rg11b10float | + GPUTextureFormat::Rg32float | + GPUTextureFormat::Rgba16float | + GPUTextureFormat::Rgba32float | + GPUTextureFormat::Depth32float | + GPUTextureFormat::Depth24plus | + GPUTextureFormat::Depth24plus_stencil8 => GPUTextureComponentType::Float, + GPUTextureFormat::R8uint | + GPUTextureFormat::R16uint | + GPUTextureFormat::Rg8uint | + GPUTextureFormat::R32uint | + GPUTextureFormat::Rg16uint | + GPUTextureFormat::Rgba8uint | + GPUTextureFormat::Rg32uint | + GPUTextureFormat::Rgba16uint | + GPUTextureFormat::Rgba32uint => GPUTextureComponentType::Uint, + GPUTextureFormat::R8sint | + GPUTextureFormat::R16sint | + GPUTextureFormat::Rg8sint | + GPUTextureFormat::R32sint | + GPUTextureFormat::Rg16sint | + GPUTextureFormat::Rgba8sint | + GPUTextureFormat::Rg32sint | + GPUTextureFormat::Rgba16sint | + GPUTextureFormat::Rgba32sint => GPUTextureComponentType::Sint, + } +} diff --git a/components/script/dom/gpusampler.rs b/components/script/dom/gpusampler.rs index db85f60e9b6..488d3df1d05 100644 --- a/components/script/dom/gpusampler.rs +++ b/components/script/dom/gpusampler.rs @@ -64,6 +64,20 @@ impl GPUSampler { } } +impl GPUSampler { + pub fn id(&self) -> WebGPUSampler { + self.sampler + } + + pub fn is_valid(&self) -> bool { + self.valid.get() + } + + pub fn compare(&self) -> bool { + self.compare_enable + } +} + 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..54b5610ae48 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -3,11 +3,12 @@ * 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, }; 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; @@ -107,6 +108,14 @@ impl GPUTexture { pub fn id(&self) -> WebGPUTexture { self.texture } + + pub fn sample_count(&self) -> u32 { + self.sample_count + } + + pub fn usage(&self) -> u32 { + self.texture_usage + } } impl GPUTextureMethods for GPUTexture { @@ -122,23 +131,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 +189,32 @@ impl GPUTextureMethods for GPUTexture { let texture_view = WebGPUTextureView(texture_view_id); - GPUTextureView::new(&self.global(), texture_view, self.device, true) + 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) } /// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs index f3bb4209708..e1c14ef1cd5 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -3,43 +3,85 @@ * 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::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 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, label: DomRefCell>, texture_view: WebGPUTextureView, - device: WebGPUDevice, + texture: Dom, valid: Cell, + #[ignore_malloc_size_of = "defined in webgpu"] + descriptor: GPUTextureViewDescriptor, } impl GPUTextureView { - fn new_inherited(texture_view: WebGPUTextureView, device: WebGPUDevice, valid: bool) -> Self { + fn new_inherited( + texture_view: WebGPUTextureView, + texture: &GPUTexture, + valid: bool, + descriptor: GPUTextureViewDescriptor, + ) -> GPUTextureView { Self { reflector_: Reflector::new(), - device, + texture: Dom::from_ref(texture), label: DomRefCell::new(None), texture_view, valid: Cell::new(valid), + descriptor, } } pub fn new( global: &GlobalScope, texture_view: WebGPUTextureView, - device: WebGPUDevice, + texture: &GPUTexture, valid: bool, - ) -> DomRoot { + descriptor: GPUTextureViewDescriptor, + ) -> DomRoot { reflect_dom_object( - Box::new(GPUTextureView::new_inherited(texture_view, device, valid)), + Box::new(GPUTextureView::new_inherited( + texture_view, + texture, + valid, + descriptor, + )), global, ) } @@ -49,6 +91,18 @@ impl GPUTextureView { pub fn id(&self) -> WebGPUTextureView { self.texture_view } + + pub fn is_valid(&self) -> bool { + self.valid.get() + } + + pub fn descriptor(&self) -> &GPUTextureViewDescriptor { + &self.descriptor + } + + pub fn texture(&self) -> &GPUTexture { + &*self.texture + } } 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..32ae601440e 100644 --- a/components/script/dom/webidls/GPUBindGroupLayout.webidl +++ b/components/script/dom/webidls/GPUBindGroupLayout.webidl @@ -16,11 +16,19 @@ dictionary GPUBindGroupLayoutEntry { required GPUIndex32 binding; required GPUShaderStageFlags visibility; required GPUBindingType type; - GPUTextureViewDimension viewDimension = "2d"; - GPUTextureComponentType textureComponentType = "float"; - GPUTextureFormat storageTextureFormat; - boolean multisampled = false; + + // Used for uniform buffer and storage buffer bindings. boolean hasDynamicOffset = false; + + // Used for sampled texture and storage texture bindings. + GPUTextureViewDimension viewDimension; + + // Used for sampled texture bindings. + GPUTextureComponentType textureComponentType; + boolean multisampled = false; + + // Used for storage texture bindings. + GPUTextureFormat storageTextureFormat; }; enum GPUBindingType { @@ -31,5 +39,5 @@ enum GPUBindingType { "sampled-texture", "readonly-storage-texture", "writeonly-storage-texture", - //"comparison-sampler", + "comparison-sampler", }; diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index 9f04b2bd58b..45a7e453364 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -73,12 +73,12 @@ pub enum WebGPURequest { device_id: id::DeviceId, bind_group_id: id::BindGroupId, bind_group_layout_id: id::BindGroupLayoutId, - bindings: Vec, + entries: Vec, }, CreateBindGroupLayout { device_id: id::DeviceId, bind_group_layout_id: id::BindGroupLayoutId, - bindings: Vec, + entries: Vec, }, CreateBuffer { device_id: id::DeviceId, @@ -334,13 +334,13 @@ impl WGPU { device_id, bind_group_id, bind_group_layout_id, - bindings, + entries, } => { let global = &self.global; let descriptor = BindGroupDescriptor { layout: bind_group_layout_id, - entries: bindings.as_ptr(), - entries_length: bindings.len(), + entries: entries.as_ptr(), + entries_length: entries.len(), label: ptr::null(), }; let _ = gfx_select!(bind_group_id => @@ -349,12 +349,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(), + entries: entries.as_ptr(), + entries_length: entries.len(), label: ptr::null(), }; let _ = gfx_select!(bind_group_layout_id => From 48ef306bd3f1c9abbd1437e7a8f2b21b7b307a04 Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Fri, 19 Jun 2020 00:52:16 +0530 Subject: [PATCH 2/3] Update wgpu-core and wgpu-types --- Cargo.lock | 23 +- components/script/dom/bindings/trace.rs | 10 +- components/script/dom/gpuadapter.rs | 2 + components/script/dom/gpubindgroup.rs | 31 +- .../script/dom/gpucomputepassencoder.rs | 3 +- components/script/dom/gpudevice.rs | 349 +++++++----------- components/script/dom/gpurenderpassencoder.rs | 11 +- components/script/dom/gpusampler.rs | 8 +- components/script/dom/gputexture.rs | 28 +- components/script/dom/gputextureview.rs | 56 +-- .../dom/webidls/GPUBindGroupLayout.webidl | 13 +- components/webgpu/identity.rs | 6 +- components/webgpu/lib.rs | 70 ++-- 13 files changed, 244 insertions(+), 366 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d019836592f..57acbec56fb 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 01cbde4bcfa..c42acc83de4 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 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 53b005fd7f0..8965952051c 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 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/gpudevice.rs b/components/script/dom/gpudevice.rs index dbbc6470849..136a194c7df 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 { + 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::SAMPLED); - }, - Entry::Occupied(mut o) => { - *o.get_mut() += GPUTextureUsageConstants::SAMPLED; - }, - } - } - } t.is_valid() && self.validate_texture_view_binding(t, layout_bind) }, _ => false, }, - 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 - }, - _ => 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) + .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 + }, + }) + }, }, - 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 - }, - }) - }, - }, + ) }) .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 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 488d3df1d05..2c15d89b0fc 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 54b5610ae48..59e97e43317 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 e1c14ef1cd5..c5334e9b7ec 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 32ae601440e..6413afa6032 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 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 45a7e453364..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, - 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 )); From f973099020ca162bc139866e2742d2983a3f7856 Mon Sep 17 00:00:00 2001 From: Kunal Mohan Date: Fri, 19 Jun 2020 21:35:30 +0530 Subject: [PATCH 3/3] Remove validation for GPUBindGroup, GPUBindGroupLayout, GPUPipelineLayout --- components/script/dom/gpubindgrouplayout.rs | 33 +- components/script/dom/gpucomputepipeline.rs | 13 +- components/script/dom/gpudevice.rs | 523 +++----------------- components/script/dom/gpupipelinelayout.rs | 17 +- components/script/dom/gpusampler.rs | 4 - components/script/dom/gputexture.rs | 10 +- components/script/dom/gputextureview.rs | 33 +- 7 files changed, 102 insertions(+), 531 deletions(-) diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs index aadc75557b2..216058a89a0 100644 --- a/components/script/dom/gpubindgrouplayout.rs +++ b/components/script/dom/gpubindgrouplayout.rs @@ -3,61 +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 std::collections::HashMap; -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"] - entry_map: HashMap, - #[ignore_malloc_size_of = "defined in webgpu"] - channel: WebGPU, valid: Cell, } impl GPUBindGroupLayout { - fn new_inherited( - channel: WebGPU, - bind_group_layout: WebGPUBindGroupLayout, - entry_map: HashMap, - 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, - entry_map, valid: Cell::new(valid), } } pub fn new( global: &GlobalScope, - channel: WebGPU, bind_group_layout: WebGPUBindGroupLayout, - entry_map: HashMap, valid: bool, ) -> DomRoot { reflect_dom_object( - Box::new(GPUBindGroupLayout::new_inherited( - channel, - bind_group_layout, - entry_map, - valid, - )), + Box::new(GPUBindGroupLayout::new_inherited(bind_group_layout, valid)), global, ) } @@ -71,10 +50,6 @@ impl GPUBindGroupLayout { pub fn id(&self) -> WebGPUBindGroupLayout { self.bind_group_layout } - - pub fn entries(&self) -> &HashMap { - &self.entry_map - } } impl GPUBindGroupLayoutMethods for GPUBindGroupLayout { 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 136a194c7df..b67c6e696e3 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -5,12 +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, GPUBindingResource, GPUBufferBindings, + 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; @@ -51,18 +50,16 @@ 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; 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::{HashMap, HashSet}; use std::num::NonZeroU64; use std::ptr::{self, NonNull}; use webgpu::wgpu::binding_model::BufferBinding; -use webgpu::{self, wgpu, wgt, WebGPU, WebGPUBindings, WebGPURequest}; +use webgpu::{self, wgt, WebGPU, WebGPUBindings, WebGPURequest}; #[dom_struct] pub struct GPUDevice { @@ -155,86 +152,6 @@ impl GPUDevice { ) } } - - fn validate_texture_view_binding( - &self, - texture_view: &GPUTextureView, - binding: &GPUBindGroupLayoutEntry, - ) -> bool { - let mut valid = if let Some(d) = binding.viewDimension { - texture_view.dimension() == d - } else { - false - }; - let view_component = get_component_from_format(texture_view.format()); - valid &= if let Some(c) = binding.textureComponentType { - view_component == c - } else { - false - }; - valid &= if binding.multisampled { - texture_view.texture().sample_count() > 1 - } else { - texture_view.texture().sample_count() == 1 - }; - valid &= match binding.type_ { - GPUBindingType::Sampled_texture => { - match wgt::TextureUsage::from_bits(texture_view.texture().usage()) { - Some(u) => u.contains(wgt::TextureUsage::SAMPLED), - None => false, - } - }, - GPUBindingType::Readonly_storage_texture | - GPUBindingType::Writeonly_storage_texture => { - 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, - }; - valid - } - - fn validate_buffer_binding( - &self, - buffer_bind: &GPUBufferBindings, - binding: &GPUBindGroupLayoutEntry, - ) -> bool { - let mut valid = match binding.type_ { - GPUBindingType::Uniform_buffer => { - match wgt::BufferUsage::from_bits(buffer_bind.buffer.usage()) { - Some(u) => { - let v = if let Some(s) = buffer_bind.size { - s <= GPULimits::empty().maxUniformBufferBindingSize.into() - } else { - true - }; - v && u.contains(wgt::BufferUsage::UNIFORM) - }, - None => false, - } - }, - GPUBindingType::Storage_buffer | GPUBindingType::Readonly_storage_buffer => { - match wgt::BufferUsage::from_bits(buffer_bind.buffer.usage()) { - Some(u) => u.contains(wgt::BufferUsage::STORAGE), - None => false, - } - }, - _ => false, - }; - valid &= if let Some(s) = buffer_bind.size { - 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 < buffer_bind.buffer.size() && - buffer_bind.buffer.size() - buffer_bind.offset >= binding.minBufferBindingSize - }; - valid - } } impl GPUDeviceMethods for GPUDevice { @@ -356,210 +273,86 @@ 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 entries = descriptor .entries .iter() .map(|bind| { - 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; - }; - valid &= bind.viewDimension.is_none() && - bind.textureComponentType.is_none() && - !bind.multisampled && - bind.storageTextureFormat.is_none(); - wgt::BindingType::UniformBuffer { - dynamic: bind.hasDynamicOffset, - min_binding_size: if bind.minBufferBindingSize == 0 { - None - } else { - Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap()) - }, - } + 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; - }; - valid &= bind.viewDimension.is_none() && - !visibility.contains(wgt::ShaderStage::VERTEX) && - bind.textureComponentType.is_none() && - !bind.multisampled && - bind.storageTextureFormat.is_none(); - wgt::BindingType::StorageBuffer { - dynamic: bind.hasDynamicOffset, - min_binding_size: if bind.minBufferBindingSize == 0 { - None - } else { - Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap()) - }, - readonly: false, - } + 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; - }; - valid &= bind.viewDimension.is_none() && - bind.textureComponentType.is_none() && - !bind.multisampled && - bind.storageTextureFormat.is_none(); - wgt::BindingType::StorageBuffer { - dynamic: bind.hasDynamicOffset, - min_binding_size: if bind.minBufferBindingSize == 0 { - None - } else { - Some(NonZeroU64::new(bind.minBufferBindingSize).unwrap()) - }, - readonly: true, - } + 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; - } - 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::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; - } - valid &= !bind.hasDynamicOffset && - bind.textureComponentType.is_none() && - !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::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; - } - valid &= !bind.hasDynamicOffset && - bind.textureComponentType.is_none() && - !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) { - limit.max_samplers_per_shader_stage -= 1; - } - valid &= !bind.hasDynamicOffset && - bind.viewDimension.is_none() && - bind.textureComponentType.is_none() && - !bind.multisampled && - bind.storageTextureFormat.is_none() && - bind.minBufferBindingSize == 0; - wgt::BindingType::Sampler { comparison: false } + 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 => wgt::BindingType::Sampler { comparison: false }, GPUBindingType::Comparison_sampler => { - if let Some(limit) = validation_map.get_mut(&visibility) { - limit.max_samplers_per_shader_stage -= 1; - } - valid &= !bind.hasDynamicOffset && - bind.viewDimension.is_none() && - bind.textureComponentType.is_none() && - !bind.multisampled && - bind.storageTextureFormat.is_none() && - bind.minBufferBindingSize == 0; wgt::BindingType::Sampler { comparison: true } }, }; @@ -568,22 +361,6 @@ impl GPUDeviceMethods for GPUDevice { }) .collect::>(); - // bindings are unique - valid &= storeBindings.len() == entries.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; - let bind_group_layout_id = self .global() .wgpu_id_hub() @@ -600,25 +377,7 @@ impl GPUDeviceMethods for GPUDevice { let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); - let mut binds = HashMap::new(); - descriptor.entries.iter().for_each(|bind| { - binds.insert( - bind.binding, - 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, - minBufferBindingSize: bind.minBufferBindingSize, - }, - ); - }); - - GPUBindGroupLayout::new(&self.global(), self.channel.clone(), bgl, binds, valid) + GPUBindGroupLayout::new(&self.global(), bgl, true) } /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout @@ -626,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.entries().values().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() @@ -682,51 +407,12 @@ 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 mut valid = descriptor.layout.is_valid() && - descriptor.layout.entries().len() == descriptor.entries.len(); - - let mut bindings = HashSet::new(); - valid &= descriptor.entries.iter().all(|bind| { - bindings.insert(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(), - _ => false, - }, - GPUBindingType::Comparison_sampler => match bind.resource { - GPUBindingResource::GPUSampler(ref s) => s.is_valid() && s.compare(), - _ => false, - }, - GPUBindingType::Sampled_texture | - GPUBindingType::Readonly_storage_texture | - GPUBindingType::Writeonly_storage_texture => match bind.resource { - GPUBindingResource::GPUTextureView(ref t) => { - t.is_valid() && self.validate_texture_view_binding(t, layout_bind) - }, - _ => false, - }, - GPUBindingType::Uniform_buffer | - GPUBindingType::Storage_buffer | - GPUBindingType::Readonly_storage_buffer => match bind.resource { - GPUBindingResource::GPUBufferBindings(ref b) => { - b.buffer.is_valid() && self.validate_buffer_binding(b, layout_bind) - }, - _ => false, - }, - } - } else { - false - } - }); - - valid &= bindings.len() == descriptor.entries.len(); - + let mut valid = descriptor.layout.is_valid(); let entries = descriptor .entries .iter() @@ -734,11 +420,16 @@ impl GPUDeviceMethods for GPUDevice { ( bind.binding, match bind.resource { - GPUBindingResource::GPUSampler(ref s) => WebGPUBindings::Sampler(s.id().0), + 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, @@ -811,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(); @@ -832,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 @@ -961,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 { @@ -1007,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::>(); @@ -1288,46 +972,3 @@ fn convert_texture_size_to_wgt(size: &GPUExtent3DDict) -> wgt::Extent3d { depth: size.depth, } } - -fn get_component_from_format(format: GPUTextureFormat) -> GPUTextureComponentType { - match format { - GPUTextureFormat::R8unorm | - GPUTextureFormat::R8snorm | - GPUTextureFormat::R16float | - GPUTextureFormat::Rg8unorm | - GPUTextureFormat::Rg8snorm | - GPUTextureFormat::R32float | - GPUTextureFormat::Rg16float | - GPUTextureFormat::Rgba8unorm | - GPUTextureFormat::Rgba8unorm_srgb | - GPUTextureFormat::Rgba8snorm | - GPUTextureFormat::Bgra8unorm | - GPUTextureFormat::Bgra8unorm_srgb | - GPUTextureFormat::Rgb10a2unorm | - GPUTextureFormat::Rg11b10float | - GPUTextureFormat::Rg32float | - GPUTextureFormat::Rgba16float | - GPUTextureFormat::Rgba32float | - GPUTextureFormat::Depth32float | - GPUTextureFormat::Depth24plus | - GPUTextureFormat::Depth24plus_stencil8 => GPUTextureComponentType::Float, - GPUTextureFormat::R8uint | - GPUTextureFormat::R16uint | - GPUTextureFormat::Rg8uint | - GPUTextureFormat::R32uint | - GPUTextureFormat::Rg16uint | - GPUTextureFormat::Rgba8uint | - GPUTextureFormat::Rg32uint | - GPUTextureFormat::Rgba16uint | - GPUTextureFormat::Rgba32uint => GPUTextureComponentType::Uint, - GPUTextureFormat::R8sint | - GPUTextureFormat::R16sint | - GPUTextureFormat::Rg8sint | - GPUTextureFormat::R32sint | - GPUTextureFormat::Rg16sint | - GPUTextureFormat::Rgba8sint | - GPUTextureFormat::Rg32sint | - GPUTextureFormat::Rgba16sint | - GPUTextureFormat::Rgba32sint => GPUTextureComponentType::Sint, - } -} 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/gpusampler.rs b/components/script/dom/gpusampler.rs index 2c15d89b0fc..97e6c1dc37f 100644 --- a/components/script/dom/gpusampler.rs +++ b/components/script/dom/gpusampler.rs @@ -66,10 +66,6 @@ impl GPUSampler { pub fn is_valid(&self) -> bool { self.valid.get() } - - pub fn compare(&self) -> bool { - self.compare_enable - } } impl GPUSamplerMethods for GPUSampler { diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index 59e97e43317..6bf4892887a 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -107,14 +107,6 @@ impl GPUTexture { pub fn id(&self) -> WebGPUTexture { self.texture } - - pub fn sample_count(&self) -> u32 { - self.sample_count - } - - pub fn usage(&self) -> u32 { - self.texture_usage - } } impl GPUTextureMethods for GPUTexture { @@ -188,7 +180,7 @@ impl GPUTextureMethods for GPUTexture { let texture_view = WebGPUTextureView(texture_view_id); - GPUTextureView::new(&self.global(), texture_view, &self, true, dimension, format) + 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 c5334e9b7ec..06cb5a0ddbf 100644 --- a/components/script/dom/gputextureview.rs +++ b/components/script/dom/gputextureview.rs @@ -3,10 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::GPUTextureFormat; -use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::{ - GPUTextureViewDimension, GPUTextureViewMethods, -}; +use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::GPUTextureViewMethods; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; @@ -23,8 +20,6 @@ pub struct GPUTextureView { texture_view: WebGPUTextureView, texture: Dom, valid: Cell, - dimension: GPUTextureViewDimension, - format: GPUTextureFormat, } impl GPUTextureView { @@ -32,8 +27,6 @@ impl GPUTextureView { texture_view: WebGPUTextureView, texture: &GPUTexture, valid: bool, - dimension: GPUTextureViewDimension, - format: GPUTextureFormat, ) -> GPUTextureView { Self { reflector_: Reflector::new(), @@ -41,8 +34,6 @@ impl GPUTextureView { label: DomRefCell::new(None), texture_view, valid: Cell::new(valid), - dimension, - format, } } @@ -51,17 +42,9 @@ impl GPUTextureView { texture_view: WebGPUTextureView, texture: &GPUTexture, valid: bool, - dimension: GPUTextureViewDimension, - format: GPUTextureFormat, ) -> DomRoot { reflect_dom_object( - Box::new(GPUTextureView::new_inherited( - texture_view, - texture, - valid, - dimension, - format, - )), + Box::new(GPUTextureView::new_inherited(texture_view, texture, valid)), global, ) } @@ -75,18 +58,6 @@ impl GPUTextureView { pub fn is_valid(&self) -> bool { self.valid.get() } - - pub fn dimension(&self) -> GPUTextureViewDimension { - self.dimension - } - - pub fn format(&self) -> GPUTextureFormat { - self.format - } - - pub fn texture(&self) -> &GPUTexture { - &*self.texture - } } impl GPUTextureViewMethods for GPUTextureView {