diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
commit | 40a355a42d4a9444dc753c04c6608dade2f06a23 (patch) | |
tree | 871fc667d2de662f171103ce5ec067014ef85e61 /third_party/rust/wgpu-core/src/validation.rs | |
parent | Adding upstream version 124.0.1. (diff) | |
download | firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.tar.xz firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.zip |
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wgpu-core/src/validation.rs')
-rw-r--r-- | third_party/rust/wgpu-core/src/validation.rs | 115 |
1 files changed, 99 insertions, 16 deletions
diff --git a/third_party/rust/wgpu-core/src/validation.rs b/third_party/rust/wgpu-core/src/validation.rs index a0947ae83f..e4846c4000 100644 --- a/third_party/rust/wgpu-core/src/validation.rs +++ b/third_party/rust/wgpu-core/src/validation.rs @@ -1,4 +1,8 @@ -use crate::{device::bgl, FastHashMap, FastHashSet}; +use crate::{ + device::bgl, + id::{markers::Buffer, Id}, + FastHashMap, FastHashSet, +}; use arrayvec::ArrayVec; use std::{collections::hash_map::Entry, fmt}; use thiserror::Error; @@ -134,8 +138,11 @@ pub struct Interface { } #[derive(Clone, Debug, Error)] -#[error("Buffer usage is {actual:?} which does not contain required usage {expected:?}")] +#[error( + "Usage flags {actual:?} for buffer {id:?} do not contain required usage flags {expected:?}" +)] pub struct MissingBufferUsageError { + pub(crate) id: Id<Buffer>, pub(crate) actual: wgt::BufferUsages, pub(crate) expected: wgt::BufferUsages, } @@ -143,11 +150,16 @@ pub struct MissingBufferUsageError { /// Checks that the given buffer usage contains the required buffer usage, /// returns an error otherwise. pub fn check_buffer_usage( + id: Id<Buffer>, actual: wgt::BufferUsages, expected: wgt::BufferUsages, ) -> Result<(), MissingBufferUsageError> { if !actual.contains(expected) { - Err(MissingBufferUsageError { actual, expected }) + Err(MissingBufferUsageError { + id, + actual, + expected, + }) } else { Ok(()) } @@ -271,6 +283,16 @@ pub enum StageError { }, #[error("Location[{location}] is provided by the previous stage output but is not consumed as input by this stage.")] InputNotConsumed { location: wgt::ShaderLocation }, + #[error( + "Unable to select an entry point: no entry point was found in the provided shader module" + )] + NoEntryPointFound, + #[error( + "Unable to select an entry point: \ + multiple entry points were found in the provided shader module, \ + but no entry point was specified" + )] + MultipleEntryPointsFound, } fn map_storage_format_to_naga(format: wgt::TextureFormat) -> Option<naga::StorageFormat> { @@ -892,9 +914,15 @@ impl Interface { class, }, naga::TypeInner::Sampler { comparison } => ResourceType::Sampler { comparison }, - naga::TypeInner::Array { stride, .. } => ResourceType::Buffer { - size: wgt::BufferSize::new(stride as u64).unwrap(), - }, + naga::TypeInner::Array { stride, size, .. } => { + let size = match size { + naga::ArraySize::Constant(size) => size.get() * stride, + naga::ArraySize::Dynamic => stride, + }; + ResourceType::Buffer { + size: wgt::BufferSize::new(size as u64).unwrap(), + } + } ref other => ResourceType::Buffer { size: wgt::BufferSize::new(other.size(module.to_ctx()) as u64).unwrap(), }, @@ -953,6 +981,37 @@ impl Interface { } } + pub fn finalize_entry_point_name( + &self, + stage_bit: wgt::ShaderStages, + entry_point_name: Option<&str>, + ) -> Result<String, StageError> { + let stage = Self::shader_stage_from_stage_bit(stage_bit); + entry_point_name + .map(|ep| ep.to_string()) + .map(Ok) + .unwrap_or_else(|| { + let mut entry_points = self + .entry_points + .keys() + .filter_map(|(ep_stage, name)| (ep_stage == &stage).then_some(name)); + let first = entry_points.next().ok_or(StageError::NoEntryPointFound)?; + if entry_points.next().is_some() { + return Err(StageError::MultipleEntryPointsFound); + } + Ok(first.clone()) + }) + } + + pub(crate) fn shader_stage_from_stage_bit(stage_bit: wgt::ShaderStages) -> naga::ShaderStage { + match stage_bit { + wgt::ShaderStages::VERTEX => naga::ShaderStage::Vertex, + wgt::ShaderStages::FRAGMENT => naga::ShaderStage::Fragment, + wgt::ShaderStages::COMPUTE => naga::ShaderStage::Compute, + _ => unreachable!(), + } + } + pub fn check_stage( &self, layouts: &mut BindingLayoutSource<'_>, @@ -964,17 +1023,13 @@ impl Interface { ) -> Result<StageIo, StageError> { // Since a shader module can have multiple entry points with the same name, // we need to look for one with the right execution model. - let shader_stage = match stage_bit { - wgt::ShaderStages::VERTEX => naga::ShaderStage::Vertex, - wgt::ShaderStages::FRAGMENT => naga::ShaderStage::Fragment, - wgt::ShaderStages::COMPUTE => naga::ShaderStage::Compute, - _ => unreachable!(), - }; + let shader_stage = Self::shader_stage_from_stage_bit(stage_bit); let pair = (shader_stage, entry_point_name.to_string()); - let entry_point = self - .entry_points - .get(&pair) - .ok_or(StageError::MissingEntryPoint(pair.1))?; + let entry_point = match self.entry_points.get(&pair) { + Some(some) => some, + None => return Err(StageError::MissingEntryPoint(pair.1)), + }; + let (_stage, entry_point_name) = pair; // check resources visibility for &handle in entry_point.resources.iter() { @@ -1246,3 +1301,31 @@ impl Interface { .map(|ep| ep.dual_source_blending) } } + +// https://gpuweb.github.io/gpuweb/#abstract-opdef-calculating-color-attachment-bytes-per-sample +pub fn validate_color_attachment_bytes_per_sample( + attachment_formats: impl Iterator<Item = Option<wgt::TextureFormat>>, + limit: u32, +) -> Result<(), u32> { + let mut total_bytes_per_sample = 0; + for format in attachment_formats { + let Some(format) = format else { + continue; + }; + + let byte_cost = format.target_pixel_byte_cost().unwrap(); + let alignment = format.target_component_alignment().unwrap(); + + let rem = total_bytes_per_sample % alignment; + if rem != 0 { + total_bytes_per_sample += alignment - rem; + } + total_bytes_per_sample += byte_cost; + } + + if total_bytes_per_sample > limit { + return Err(total_bytes_per_sample); + } + + Ok(()) +} |