diff --git a/cli/src/main.rs b/cli/src/main.rs index 707f95f065..efaf5959bc 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -317,12 +317,23 @@ fn run() -> Result<(), Box> { _ => return Err(CliError("Unknown input file extension").into()), }; + // Decide which capabilities our output formats can support. + let validation_caps = + output_paths + .iter() + .fold(naga::valid::Capabilities::all(), |caps, path| { + use naga::valid::Capabilities as C; + let missing = match Path::new(path).extension().and_then(|ex| ex.to_str()) { + Some("wgsl") => C::CLIP_DISTANCE | C::CULL_DISTANCE, + Some("metal") => C::CULL_DISTANCE, + _ => C::empty(), + }; + caps & !missing + }); + // validate the IR - let info = match naga::valid::Validator::new( - params.validation_flags, - naga::valid::Capabilities::all(), - ) - .validate(&module) + let info = match naga::valid::Validator::new(params.validation_flags, validation_caps) + .validate(&module) { Ok(info) => Some(info), Err(error) => { diff --git a/src/valid/interface.rs b/src/valid/interface.rs index 91c121dced..bee57e877b 100644 --- a/src/valid/interface.rs +++ b/src/valid/interface.rs @@ -135,6 +135,16 @@ impl VaryingContext<'_> { } self.built_ins.insert(canonical); + let required = match built_in { + Bi::ClipDistance => Capabilities::CLIP_DISTANCE, + Bi::CullDistance => Capabilities::CULL_DISTANCE, + Bi::PrimitiveIndex => Capabilities::PRIMITIVE_INDEX, + _ => Capabilities::empty(), + }; + if !self.capabilities.contains(required) { + return Err(VaryingError::UnsupportedCapability(required)); + } + let width = 4; let (visible, type_good) = match built_in { Bi::BaseInstance | Bi::BaseVertex | Bi::InstanceIndex | Bi::VertexIndex => ( @@ -206,21 +216,14 @@ impl VaryingContext<'_> { width: crate::BOOL_WIDTH, }, ), - Bi::PrimitiveIndex => { - if !self.capabilities.contains(Capabilities::PRIMITIVE_INDEX) { - return Err(VaryingError::UnsupportedCapability( - Capabilities::PRIMITIVE_INDEX, - )); - } - ( - self.stage == St::Fragment && !self.output, - *ty_inner - == Ti::Scalar { - kind: Sk::Uint, - width, - }, - ) - } + Bi::PrimitiveIndex => ( + self.stage == St::Fragment && !self.output, + *ty_inner + == Ti::Scalar { + kind: Sk::Uint, + width, + }, + ), Bi::SampleIndex => ( self.stage == St::Fragment && !self.output, *ty_inner diff --git a/src/valid/mod.rs b/src/valid/mod.rs index 29ef658db2..60178bb47e 100644 --- a/src/valid/mod.rs +++ b/src/valid/mod.rs @@ -82,11 +82,11 @@ bitflags::bitflags! { #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pub struct Capabilities: u8 { - /// Support for `AddressSpace:PushConstant`. + /// Support for [`AddressSpace:PushConstant`]. const PUSH_CONSTANT = 0x1; /// Float values with width = 8. const FLOAT64 = 0x2; - /// Support for `Builtin:PrimitiveIndex`. + /// Support for [`Builtin:PrimitiveIndex`]. const PRIMITIVE_INDEX = 0x4; /// Support for non-uniform indexing of sampled textures and storage buffer arrays. const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 0x8; @@ -94,6 +94,10 @@ bitflags::bitflags! { const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 0x10; /// Support for non-uniform indexing of samplers. const SAMPLER_NON_UNIFORM_INDEXING = 0x20; + /// Support for [`Builtin::ClipDistance`]. + const CLIP_DISTANCE = 0x40; + /// Support for [`Builtin::CullDistance`]. + const CULL_DISTANCE = 0x80; } }