diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index f13c3c7577..ad7c208519 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -2367,11 +2367,40 @@ impl> Parser { crate::StorageAccess::empty() }; + let ty = match binding { + // SPIR-V only cares about some of the built-in types being integer. + // Naga requires them to be strictly unsigned, so we have to patch it. + Some(crate::Binding::BuiltIn(built_in)) => { + let scalar_kind = module.types[lookup_type.handle].inner.scalar_kind(); + let needs_uint = match built_in { + crate::BuiltIn::BaseInstance + | crate::BuiltIn::BaseVertex + | crate::BuiltIn::InstanceIndex + | crate::BuiltIn::SampleIndex + | crate::BuiltIn::VertexIndex => true, + _ => false, + }; + if needs_uint && scalar_kind == Some(crate::ScalarKind::Sint) { + log::warn!("Treating {:?} as unsigned", built_in); + module.types.fetch_or_append(crate::Type { + name: None, + inner: crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + width: 4, + }, + }) + } else { + lookup_type.handle + } + } + _ => lookup_type.handle, + }; + let var = crate::GlobalVariable { name: dec.name, class, binding, - ty: lookup_type.handle, + ty, init, interpolation: dec.interpolation, storage_access, diff --git a/test-data/spv/quad.vert.spv b/test-data/spv/quad.vert.spv new file mode 100644 index 0000000000..ea22e0c6c8 Binary files /dev/null and b/test-data/spv/quad.vert.spv differ diff --git a/tests/convert.rs b/tests/convert.rs index 2946613750..593f9b433e 100644 --- a/tests/convert.rs +++ b/tests/convert.rs @@ -173,7 +173,7 @@ fn convert_boids() { #[cfg(feature = "spv-in")] #[test] -fn convert_cube() { +fn convert_cube_spv() { let mut validator = naga::proc::Validator::new(); let vs = load_spv("cube.vert.spv"); validator.validate(&vs).unwrap(); @@ -232,6 +232,25 @@ fn convert_cube() { } } +#[cfg(feature = "spv-in")] +#[test] +fn convert_quad_spv() { + let mut validator = naga::proc::Validator::new(); + // check that integer `gl_VertexIndex` is treated as unsigned + let vs = load_spv("quad.vert.spv"); + validator.validate(&vs).unwrap(); + #[cfg(feature = "msl-out")] + { + use naga::back::msl; + let options = msl::Options { + lang_version: (1, 0), + spirv_cross_compatibility: false, + binding_map: msl::BindingMap::default(), + }; + msl::write_string(&vs, &options).unwrap(); + } +} + #[cfg(feature = "glsl-in")] #[test] #[ignore]