mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Remove validation for GPUBindGroup, GPUBindGroupLayout, GPUPipelineLayout
This commit is contained in:
parent
48ef306bd3
commit
f973099020
7 changed files with 102 additions and 531 deletions
|
@ -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<Option<DOMString>>,
|
||||
bind_group_layout: WebGPUBindGroupLayout,
|
||||
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||
entry_map: HashMap<u32, GPUBindGroupLayoutEntry>,
|
||||
#[ignore_malloc_size_of = "defined in webgpu"]
|
||||
channel: WebGPU,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GPUBindGroupLayout {
|
||||
fn new_inherited(
|
||||
channel: WebGPU,
|
||||
bind_group_layout: WebGPUBindGroupLayout,
|
||||
entry_map: HashMap<u32, GPUBindGroupLayoutEntry>,
|
||||
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<u32, GPUBindGroupLayoutEntry>,
|
||||
valid: bool,
|
||||
) -> DomRoot<Self> {
|
||||
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<u32, GPUBindGroupLayoutEntry> {
|
||||
&self.entry_map
|
||||
}
|
||||
}
|
||||
|
||||
impl GPUBindGroupLayoutMethods for GPUBindGroupLayout {
|
||||
|
|
|
@ -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<Option<DOMString>>,
|
||||
compute_pipeline: WebGPUComputePipeline,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
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<Self> {
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
compute_pipeline: WebGPUComputePipeline,
|
||||
valid: bool,
|
||||
) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUComputePipeline::new_inherited(compute_pipeline)),
|
||||
Box::new(GPUComputePipeline::new_inherited(compute_pipeline, valid)),
|
||||
global,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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<GPUBindGroupLayout> {
|
||||
#[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::<Vec<_>>();
|
||||
|
||||
// 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<GPUPipelineLayout> {
|
||||
// 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<GPUBindGroup> {
|
||||
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<GPUComputePipeline> {
|
||||
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<GPURenderPipeline> {
|
||||
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::<ArrayVec<_>>();
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<WebGPUBindGroupLayout>,
|
||||
label: DomRefCell<Option<DOMString>>,
|
||||
pipeline_layout: WebGPUPipelineLayout,
|
||||
valid: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GPUPipelineLayout {
|
||||
fn new_inherited(
|
||||
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
|
||||
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<WebGPUBindGroupLayout>,
|
||||
pipeline_layout: WebGPUPipelineLayout,
|
||||
valid: bool,
|
||||
) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(GPUPipelineLayout::new_inherited(
|
||||
bind_group_layouts,
|
||||
pipeline_layout,
|
||||
valid,
|
||||
)),
|
||||
Box::new(GPUPipelineLayout::new_inherited(pipeline_layout, valid)),
|
||||
global,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<GPUTexture>,
|
||||
valid: Cell<bool>,
|
||||
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<GPUTextureView> {
|
||||
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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue