diff --git a/src/proc/mod.rs b/src/proc/mod.rs index 101d8e1c16..5dec4285bf 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -58,18 +58,18 @@ impl From for super::ScalarKind { } } -impl crate::ScalarValue { - pub fn scalar_kind(&self) -> crate::ScalarKind { +impl super::ScalarValue { + pub fn scalar_kind(&self) -> super::ScalarKind { match *self { - Self::Uint(_) => crate::ScalarKind::Uint, - Self::Sint(_) => crate::ScalarKind::Sint, - Self::Float(_) => crate::ScalarKind::Float, - Self::Bool(_) => crate::ScalarKind::Bool, + Self::Uint(_) => super::ScalarKind::Uint, + Self::Sint(_) => super::ScalarKind::Sint, + Self::Float(_) => super::ScalarKind::Float, + Self::Bool(_) => super::ScalarKind::Bool, } } } -impl crate::TypeInner { +impl super::TypeInner { pub fn scalar_kind(&self) -> Option { match *self { super::TypeInner::Scalar { kind, .. } | super::TypeInner::Vector { kind, .. } => { @@ -81,7 +81,7 @@ impl crate::TypeInner { } } -impl crate::MathFunction { +impl super::MathFunction { pub fn argument_count(&self) -> usize { match *self { // comparison diff --git a/src/proc/validator.rs b/src/proc/validator.rs index 4aca857e17..01e2bae606 100644 --- a/src/proc/validator.rs +++ b/src/proc/validator.rs @@ -227,6 +227,30 @@ fn storage_usage(access: crate::StorageAccess) -> crate::GlobalUse { storage_usage } +fn built_in_usage(built_in: crate::BuiltIn) -> (crate::ShaderStage, crate::GlobalUse) { + use crate::{BuiltIn as Bi, GlobalUse as Gu, ShaderStage as Ss}; + match built_in { + Bi::BaseInstance => (Ss::Vertex, Gu::LOAD), + Bi::BaseVertex => (Ss::Vertex, Gu::LOAD), + Bi::ClipDistance => (Ss::Vertex, Gu::STORE), + Bi::InstanceIndex => (Ss::Vertex, Gu::LOAD), + Bi::PointSize => (Ss::Vertex, Gu::STORE), + Bi::Position => (Ss::Vertex, Gu::STORE), + Bi::VertexIndex => (Ss::Vertex, Gu::LOAD), + Bi::FragCoord => (Ss::Fragment, Gu::LOAD), + Bi::FragDepth => (Ss::Fragment, Gu::LOAD), + Bi::FrontFacing => (Ss::Fragment, Gu::LOAD), + Bi::SampleIndex => (Ss::Fragment, Gu::LOAD), + Bi::SampleMaskIn => (Ss::Fragment, Gu::LOAD), + Bi::SampleMaskOut => (Ss::Fragment, Gu::STORE), + Bi::GlobalInvocationId => (Ss::Compute, Gu::LOAD), + Bi::LocalInvocationId => (Ss::Compute, Gu::LOAD), + Bi::LocalInvocationIndex => (Ss::Compute, Gu::LOAD), + Bi::WorkGroupId => (Ss::Compute, Gu::LOAD), + Bi::WorkGroupSize => (Ss::Compute, Gu::LOAD), + } +} + impl Validator { /// Construct a new validator instance. pub fn new() -> Self { @@ -497,22 +521,14 @@ impl Validator { crate::StorageClass::Function => unreachable!(), crate::StorageClass::Input => { match var.binding { - Some(crate::Binding::BuiltIn(built_in)) => match (stage, built_in) { - (crate::ShaderStage::Vertex, crate::BuiltIn::BaseInstance) - | (crate::ShaderStage::Vertex, crate::BuiltIn::BaseVertex) - | (crate::ShaderStage::Vertex, crate::BuiltIn::InstanceIndex) - | (crate::ShaderStage::Vertex, crate::BuiltIn::VertexIndex) - | (crate::ShaderStage::Fragment, crate::BuiltIn::FragCoord) - | (crate::ShaderStage::Fragment, crate::BuiltIn::FrontFacing) - | (crate::ShaderStage::Fragment, crate::BuiltIn::SampleIndex) - | (crate::ShaderStage::Fragment, crate::BuiltIn::SampleMaskIn) - | (crate::ShaderStage::Compute, crate::BuiltIn::GlobalInvocationId) - | (crate::ShaderStage::Compute, crate::BuiltIn::LocalInvocationId) - | (crate::ShaderStage::Compute, crate::BuiltIn::LocalInvocationIndex) - | (crate::ShaderStage::Compute, crate::BuiltIn::WorkGroupId) - | (crate::ShaderStage::Compute, crate::BuiltIn::WorkGroupSize) => (), - _ => return Err(EntryPointError::InvalidBuiltIn(built_in)), - }, + Some(crate::Binding::BuiltIn(built_in)) => { + let (allowed_stage, allowed_usage) = built_in_usage(built_in); + if allowed_stage != stage + || !allowed_usage.contains(crate::GlobalUse::LOAD) + { + return Err(EntryPointError::InvalidBuiltIn(built_in)); + } + } Some(crate::Binding::Location(loc)) => { if !self.location_in_mask.insert(loc as usize) { return Err(EntryPointError::BindingCollision(var_handle)); @@ -525,14 +541,14 @@ impl Validator { } crate::StorageClass::Output => { match var.binding { - Some(crate::Binding::BuiltIn(built_in)) => match (stage, built_in) { - (crate::ShaderStage::Vertex, crate::BuiltIn::Position) - | (crate::ShaderStage::Vertex, crate::BuiltIn::PointSize) - | (crate::ShaderStage::Vertex, crate::BuiltIn::ClipDistance) - | (crate::ShaderStage::Fragment, crate::BuiltIn::FragDepth) - | (crate::ShaderStage::Fragment, crate::BuiltIn::SampleMaskOut) => (), - _ => return Err(EntryPointError::InvalidBuiltIn(built_in)), - }, + Some(crate::Binding::BuiltIn(built_in)) => { + let (allowed_stage, allowed_usage) = built_in_usage(built_in); + if allowed_stage != stage + || !allowed_usage.contains(crate::GlobalUse::STORE) + { + return Err(EntryPointError::InvalidBuiltIn(built_in)); + } + } Some(crate::Binding::Location(loc)) => { if !self.location_out_mask.insert(loc as usize) { return Err(EntryPointError::BindingCollision(var_handle));