diff --git a/naga/src/front/wgsl/parse/mod.rs b/naga/src/front/wgsl/parse/mod.rs index 93b9343324..50d1072757 100644 --- a/naga/src/front/wgsl/parse/mod.rs +++ b/naga/src/front/wgsl/parse/mod.rs @@ -655,6 +655,14 @@ impl Parser { ctx: &mut ExpressionContext<'a, '_, '_>, ) -> Result>, Error<'a>> { self.push_rule_span(Rule::PrimaryExpr, lexer); + const fn literal_ray_flag<'b>(flag: crate::RayFlag) -> ast::Expression<'b> { + ast::Expression::Literal(ast::Literal::Number(Number::U32(flag.bits()))) + } + const fn literal_ray_intersection<'b>( + intersection: crate::RayQueryIntersection, + ) -> ast::Expression<'b> { + ast::Expression::Literal(ast::Literal::Number(Number::U32(intersection.bits()))) + } let expr = match lexer.peek() { (Token::Paren('('), _) => { @@ -687,15 +695,63 @@ impl Parser { } (Token::Word("RAY_FLAG_NONE"), _) => { let _ = lexer.next(); - ast::Expression::Literal(ast::Literal::Number(Number::U32(0))) + literal_ray_flag(crate::RayFlag::empty()) + } + (Token::Word("RAY_FLAG_FORCE_OPAQUE"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::FORCE_OPAQUE) + } + (Token::Word("RAY_FLAG_FORCE_NO_OPAQUE"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::FORCE_NO_OPAQUE) } (Token::Word("RAY_FLAG_TERMINATE_ON_FIRST_HIT"), _) => { let _ = lexer.next(); - ast::Expression::Literal(ast::Literal::Number(Number::U32(4))) + literal_ray_flag(crate::RayFlag::TERMINATE_ON_FIRST_HIT) + } + (Token::Word("RAY_FLAG_SKIP_CLOSEST_HIT_SHADER"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::SKIP_CLOSEST_HIT_SHADER) + } + (Token::Word("RAY_FLAG_CULL_BACK_FACING"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::CULL_BACK_FACING) + } + (Token::Word("RAY_FLAG_CULL_FRONT_FACING"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::CULL_FRONT_FACING) + } + (Token::Word("RAY_FLAG_CULL_OPAQUE"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::CULL_OPAQUE) + } + (Token::Word("RAY_FLAG_CULL_NO_OPAQUE"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::CULL_NO_OPAQUE) + } + (Token::Word("RAY_FLAG_SKIP_TRIANGLES"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::SKIP_TRIANGLES) + } + (Token::Word("RAY_FLAG_SKIP_AABBS"), _) => { + let _ = lexer.next(); + literal_ray_flag(crate::RayFlag::SKIP_AABBS) } (Token::Word("RAY_QUERY_INTERSECTION_NONE"), _) => { let _ = lexer.next(); - ast::Expression::Literal(ast::Literal::Number(Number::U32(0))) + literal_ray_intersection(crate::RayQueryIntersection::empty()) + } + (Token::Word("RAY_QUERY_INTERSECTION_TRIANGLE"), _) => { + let _ = lexer.next(); + literal_ray_intersection(crate::RayQueryIntersection::TRIANGLE) + } + (Token::Word("RAY_QUERY_INTERSECTION_GENERATED"), _) => { + let _ = lexer.next(); + literal_ray_intersection(crate::RayQueryIntersection::GENERATED) + } + (Token::Word("RAY_QUERY_INTERSECTION_AABB"), _) => { + let _ = lexer.next(); + literal_ray_intersection(crate::RayQueryIntersection::AABB) } (Token::Word(word), span) => { let start = lexer.start_byte_offset(); diff --git a/naga/src/lib.rs b/naga/src/lib.rs index c69542ab05..0bbf857d0b 100644 --- a/naga/src/lib.rs +++ b/naga/src/lib.rs @@ -2295,3 +2295,56 @@ pub struct Module { /// validation. pub diagnostic_filter_leaf: Option>, } + +bitflags::bitflags! { + /// Ray flags used when casting rays. + /// Matching vulkan constants can be found in + /// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/ray_common/ray_flags_section.txt + #[cfg_attr(feature = "serialize", derive(Serialize))] + #[cfg_attr(feature = "deserialize", derive(Deserialize))] + #[cfg_attr(feature = "arbitrary", derive(Arbitrary))] + #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct RayFlag: u32 { + /// Force all intersections to be treated as opaque. + const FORCE_OPAQUE = 0x1; + /// Force all intersections to be treated as non-opaque. + const FORCE_NO_OPAQUE = 0x2; + /// Stop traversal after the first hit. + const TERMINATE_ON_FIRST_HIT = 0x4; + /// Don't execute the closest hit shader. + const SKIP_CLOSEST_HIT_SHADER = 0x8; + /// Cull back facing geometry. + const CULL_BACK_FACING = 0x10; + /// Cull front facing geometry. + const CULL_FRONT_FACING = 0x20; + /// Cull opaque geometry. + const CULL_OPAQUE = 0x40; + /// Cull non-opaque geometry. + const CULL_NO_OPAQUE = 0x80; + /// Skip triangular geometry. + const SKIP_TRIANGLES = 0x100; + /// Skip axis-aligned bounding boxes. + const SKIP_AABBS = 0x200; + } +} + +bitflags::bitflags! { + /// Type of a ray query intersection. + /// Matching vulkan constants can be found in + /// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/SPV_KHR_ray_query.asciidoc + #[cfg_attr(feature = "serialize", derive(Serialize))] + #[cfg_attr(feature = "deserialize", derive(Deserialize))] + #[cfg_attr(feature = "arbitrary", derive(Arbitrary))] + #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] + pub struct RayQueryIntersection: u32 { + /// Intersecting with triangles.. + /// Matches RayQueryCommittedIntersectionTriangleKHR and RayQueryCandidateIntersectionTriangleKHR. + const TRIANGLE = 0x1; + /// Intersecting with generated primitives. + /// Matches RayQueryCommittedIntersectionGeneratedKHR. + const GENERATED = 0x2; + /// Intersecting with Axis Aligned Bounding Boxes. + /// Matches RayQueryCandidateIntersectionAABBKHR. + const AABB = 0x4; + } +} diff --git a/naga/tests/in/ray-query.wgsl b/naga/tests/in/ray-query.wgsl index 0af8c7c95f..ea38e65c17 100644 --- a/naga/tests/in/ray-query.wgsl +++ b/naga/tests/in/ray-query.wgsl @@ -1,7 +1,7 @@ /* let RAY_FLAG_NONE = 0x00u; -let RAY_FLAG_OPAQUE = 0x01u; -let RAY_FLAG_NO_OPAQUE = 0x02u; +let RAY_FLAG_FORCE_OPAQUE = 0x01u; +let RAY_FLAG_FORCE_NO_OPAQUE = 0x02u; let RAY_FLAG_TERMINATE_ON_FIRST_HIT = 0x04u; let RAY_FLAG_SKIP_CLOSEST_HIT_SHADER = 0x08u; let RAY_FLAG_CULL_BACK_FACING = 0x10u;