diff --git a/src/back/msl/mod.rs b/src/back/msl/mod.rs index 15af43abd1..5ef18730c9 100644 --- a/src/back/msl/mod.rs +++ b/src/back/msl/mod.rs @@ -141,6 +141,8 @@ pub enum Error { UnsupportedArrayOf(String), #[error("array of type '{0:?}' is not supported")] UnsupportedArrayOfType(Handle), + #[error("ray tracing is not supported prior to MSL 2.3")] + UnsupportedRayTracing, } #[derive(Clone, Debug, PartialEq, thiserror::Error)] diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index 060773fc0b..c960c9863c 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -1947,6 +1947,10 @@ impl Writer { } } crate::Expression::RayQueryGetIntersection { query, committed } => { + if context.lang_version < (2, 3) { + return Err(Error::UnsupportedRayTracing); + } + if !committed { unimplemented!() } @@ -2899,6 +2903,10 @@ impl Writer { self.write_barrier(crate::Barrier::WORK_GROUP, level)?; } crate::Statement::RayQuery { query, ref fun } => { + if context.expression.lang_version < (2, 3) { + return Err(Error::UnsupportedRayTracing); + } + match *fun { crate::RayQueryFunction::Initialize { acceleration_structure, @@ -3090,33 +3098,28 @@ impl Writer { // Work around Metal bug where `uint` is not available by default writeln!(self.out, "using {NAMESPACE}::uint;")?; - if module.types.iter().any(|(_, t)| match t.inner { - crate::TypeInner::RayQuery => true, - _ => false, - }) { - let tab = back::INDENT; - writeln!(self.out, "struct {RAY_QUERY_TYPE} {{")?; - let full_type = format!("{RT_NAMESPACE}::intersector<{RT_NAMESPACE}::instancing, {RT_NAMESPACE}::triangle_data, {RT_NAMESPACE}::world_space_data>"); - writeln!(self.out, "{tab}{full_type} {RAY_QUERY_FIELD_INTERSECTOR};")?; - writeln!( - self.out, - "{tab}{full_type}::result_type {RAY_QUERY_FIELD_INTERSECTION};" - )?; - writeln!(self.out, "{tab}bool {RAY_QUERY_FIELD_READY} = false;")?; - writeln!(self.out, "}};")?; - writeln!(self.out, "constexpr {NAMESPACE}::uint {RAY_QUERY_FUN_MAP_INTERSECTION}(const {RT_NAMESPACE}::intersection_type ty) {{")?; - let v_triangle = back::RayIntersectionType::Triangle as u32; - let v_bbox = back::RayIntersectionType::BoundingBox as u32; - writeln!( - self.out, - "{tab}return ty=={RT_NAMESPACE}::intersection_type::triangle ? {v_triangle} : " - )?; - writeln!( - self.out, - "{tab}{tab}ty=={RT_NAMESPACE}::intersection_type::bounding_box ? {v_bbox} : 0;" - )?; - writeln!(self.out, "}}")?; + for (_, ty) in module.types.iter() { + match ty.inner { + crate::TypeInner::AccelerationStructure | crate::TypeInner::RayQuery + if options.lang_version < (2, 3) => + { + return Err(Error::UnsupportedRayTracing); + } + crate::TypeInner::RayQuery => { + self.put_ray_query_type()?; + break; + } + _ => {} + } } + if module.special_types.ray_desc.is_some() + || module.special_types.ray_intersection.is_some() + { + if options.lang_version < (2, 3) { + return Err(Error::UnsupportedRayTracing); + } + } + if options .bounds_check_policies .contains(index::BoundsCheckPolicy::ReadZeroSkipWrite) @@ -3174,6 +3177,32 @@ impl Writer { Ok(()) } + fn put_ray_query_type(&mut self) -> BackendResult { + let tab = back::INDENT; + writeln!(self.out, "struct {RAY_QUERY_TYPE} {{")?; + let full_type = format!("{RT_NAMESPACE}::intersector<{RT_NAMESPACE}::instancing, {RT_NAMESPACE}::triangle_data, {RT_NAMESPACE}::world_space_data>"); + writeln!(self.out, "{tab}{full_type} {RAY_QUERY_FIELD_INTERSECTOR};")?; + writeln!( + self.out, + "{tab}{full_type}::result_type {RAY_QUERY_FIELD_INTERSECTION};" + )?; + writeln!(self.out, "{tab}bool {RAY_QUERY_FIELD_READY} = false;")?; + writeln!(self.out, "}};")?; + writeln!(self.out, "constexpr {NAMESPACE}::uint {RAY_QUERY_FUN_MAP_INTERSECTION}(const {RT_NAMESPACE}::intersection_type ty) {{")?; + let v_triangle = back::RayIntersectionType::Triangle as u32; + let v_bbox = back::RayIntersectionType::BoundingBox as u32; + writeln!( + self.out, + "{tab}return ty=={RT_NAMESPACE}::intersection_type::triangle ? {v_triangle} : " + )?; + writeln!( + self.out, + "{tab}{tab}ty=={RT_NAMESPACE}::intersection_type::bounding_box ? {v_bbox} : 0;" + )?; + writeln!(self.out, "}}")?; + Ok(()) + } + fn write_type_defs(&mut self, module: &crate::Module) -> BackendResult { for (handle, ty) in module.types.iter() { if !ty.needs_alias() { diff --git a/tests/in/ray-query.param.ron b/tests/in/ray-query.param.ron index c400db8c64..6823e3ede4 100644 --- a/tests/in/ray-query.param.ron +++ b/tests/in/ray-query.param.ron @@ -4,7 +4,7 @@ version: (1, 4), ), msl: ( - lang_version: (2, 4), + lang_version: (2, 3), spirv_cross_compatibility: false, fake_missing_bindings: true, zero_initialize_workgroup_memory: false, diff --git a/tests/out/msl/ray-query.msl b/tests/out/msl/ray-query.msl index 0d4560f313..028a1939db 100644 --- a/tests/out/msl/ray-query.msl +++ b/tests/out/msl/ray-query.msl @@ -1,4 +1,4 @@ -// language: metal2.4 +// language: metal2.3 #include #include