From 7956e8a0f0bceec91847853de8149a2b54c70cd3 Mon Sep 17 00:00:00 2001 From: Erin Power Date: Wed, 31 Mar 2021 15:33:56 +0200 Subject: [PATCH] Add support for SPV_KHR_ray_query --- crates/rustc_codegen_spirv/src/abi.rs | 1 + crates/rustc_codegen_spirv/src/attr.rs | 1 + .../src/builder/builder_methods.rs | 2 + .../src/builder/spirv_asm.rs | 1 + .../src/codegen_cx/constant.rs | 1 + .../src/codegen_cx/type_.rs | 1 + crates/rustc_codegen_spirv/src/spirv_type.rs | 6 + .../src/spirv_type_constraints.rs | 5 +- crates/rustc_codegen_spirv/src/symbols.rs | 4 + crates/spirv-std/src/ray_tracing.rs | 490 ++++++++++++++++++ ...query_get_intersection_barycentrics_khr.rs | 15 + ...y_query_get_intersection_front_face_khr.rs | 15 + ...ery_get_intersection_geometry_index_khr.rs | 15 + ..._intersection_instance_custom_index_khr.rs | 15 + ..._query_get_intersection_instance_id_khr.rs | 15 + ..._shader_binding_table_record_offset_khr.rs | 15 + .../arch/ray_query_get_intersection_t_khr.rs | 15 + .../ray_query_get_intersection_type_khr.rs | 15 + tests/ui/arch/ray_query_get_ray_t_min_khr.rs | 15 + tests/ui/arch/ray_query_initialize_khr.rs | 28 + tests/ui/arch/ray_query_proceed_khr.rs | 15 + tests/ui/arch/ray_query_terminate_khr.rs | 15 + 22 files changed, 704 insertions(+), 1 deletion(-) create mode 100644 tests/ui/arch/ray_query_get_intersection_barycentrics_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_front_face_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_geometry_index_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_instance_custom_index_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_instance_id_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_shader_binding_table_record_offset_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_t_khr.rs create mode 100644 tests/ui/arch/ray_query_get_intersection_type_khr.rs create mode 100644 tests/ui/arch/ray_query_get_ray_t_min_khr.rs create mode 100644 tests/ui/arch/ray_query_initialize_khr.rs create mode 100644 tests/ui/arch/ray_query_proceed_khr.rs create mode 100644 tests/ui/arch/ray_query_terminate_khr.rs diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index 3aaa9bd4f8..bd71990a2e 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -791,6 +791,7 @@ fn trans_intrinsic_type<'tcx>( IntrinsicType::AccelerationStructureKhr => { Ok(SpirvType::AccelerationStructureKhr.def(span, cx)) } + IntrinsicType::RayQueryKhr => Ok(SpirvType::RayQueryKhr.def(span, cx)), IntrinsicType::SampledImage => { // see SpirvType::sizeof if ty.size != Size::from_bytes(4) { diff --git a/crates/rustc_codegen_spirv/src/attr.rs b/crates/rustc_codegen_spirv/src/attr.rs index 75d86053cd..267c2709d5 100644 --- a/crates/rustc_codegen_spirv/src/attr.rs +++ b/crates/rustc_codegen_spirv/src/attr.rs @@ -73,6 +73,7 @@ pub enum IntrinsicType { Sampler, AccelerationStructureKhr, SampledImage, + RayQueryKhr, } // NOTE(eddyb) when adding new `#[spirv(...)]` attributes, the tests found inside diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 3081976df8..2b5a3ce6b4 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -239,6 +239,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { SpirvType::AccelerationStructureKhr => { self.fatal("cannot memset acceleration structure") } + SpirvType::RayQueryKhr => self.fatal("cannot memset ray query"), } } @@ -299,6 +300,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { SpirvType::AccelerationStructureKhr => { self.fatal("cannot memset acceleration structure") } + SpirvType::RayQueryKhr => self.fatal("cannot memset ray query"), } } diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 2e0d9d644b..f1fa7632d6 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -312,6 +312,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { image_type: inst.operands[0].unwrap_id_ref(), } .def(self.span(), self), + Op::TypeRayQueryKHR => SpirvType::RayQueryKhr.def(self.span(), self), Op::Variable if inst.operands[0].unwrap_storage_class() != StorageClass::Function => { // OpVariable with Function storage class should be emitted inside the function, // however, all other OpVariables should appear in the global scope instead. diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index b6d8f3228d..d493a24b8c 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -534,6 +534,7 @@ impl<'tcx> CodegenCx<'tcx> { .tcx .sess .fatal("Cannot create a constant acceleration structure"), + SpirvType::RayQueryKhr => self.tcx.sess.fatal("Cannot create a constant ray query"), } } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index 4424a5f6c1..0a42a50e60 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -179,6 +179,7 @@ impl<'tcx> BaseTypeMethods<'tcx> for CodegenCx<'tcx> { | SpirvType::Sampler | SpirvType::SampledImage { .. } | SpirvType::AccelerationStructureKhr + | SpirvType::RayQueryKhr => TypeKind::Token, } } diff --git a/crates/rustc_codegen_spirv/src/spirv_type.rs b/crates/rustc_codegen_spirv/src/spirv_type.rs index 49cc32ddf6..1581328017 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type.rs @@ -87,6 +87,7 @@ pub enum SpirvType { }, AccelerationStructureKhr, + RayQueryKhr, } impl SpirvType { @@ -251,6 +252,7 @@ impl SpirvType { ), Self::Sampler => cx.emit_global().type_sampler(), Self::AccelerationStructureKhr => cx.emit_global().type_acceleration_structure_khr(), + Self::RayQueryKhr => cx.emit_global().type_ray_query_khr(), Self::SampledImage { image_type } => cx.emit_global().type_sampled_image(image_type), Self::InterfaceBlock { inner_type } => { @@ -352,6 +354,7 @@ impl SpirvType { Self::Pointer { .. } => cx.tcx.data_layout.pointer_size, Self::Image { .. } | Self::AccelerationStructureKhr + | Self::RayQueryKhr | Self::Sampler | Self::SampledImage { .. } => Size::from_bytes(4), @@ -383,6 +386,7 @@ impl SpirvType { Self::Pointer { .. } => cx.tcx.data_layout.pointer_align.abi, Self::Image { .. } | Self::AccelerationStructureKhr + | Self::RayQueryKhr | Self::Sampler | Self::SampledImage { .. } => Align::from_bytes(4).unwrap(), @@ -529,6 +533,7 @@ impl fmt::Debug for SpirvTypePrinter<'_, '_> { .field("inner_type", &self.cx.debug_type(inner_type)) .finish(), SpirvType::AccelerationStructureKhr => f.debug_struct("AccelerationStructure").finish(), + SpirvType::RayQueryKhr => f.debug_struct("RayQuery").finish(), }; { let mut debug_stack = DEBUG_STACK.lock().unwrap(); @@ -684,6 +689,7 @@ impl SpirvTypePrinter<'_, '_> { f.write_str(" }") } SpirvType::AccelerationStructureKhr => f.write_str("AccelerationStructureKhr"), + SpirvType::RayQueryKhr => f.write_str("RayQuery"), } } } diff --git a/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs b/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs index 7de8e1d700..c1da95a86e 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs @@ -811,7 +811,10 @@ pub fn instruction_signatures(op: Op) -> Option<&'static [InstSig<'static>]> { | Op::RayQueryGetWorldRayDirectionKHR | Op::RayQueryGetWorldRayOriginKHR | Op::RayQueryGetIntersectionObjectToWorldKHR - | Op::RayQueryGetIntersectionWorldToObjectKHR => reserved!(SPV_KHR_ray_query), + | Op::RayQueryGetIntersectionWorldToObjectKHR => { + // NOTE(eddyb) we actually use these despite not being in the standard yet. + // reserved!(SPV_KHR_ray_query) + } // Instructions not present in current SPIR-V specification // SPV_INTEL_function_pointers diff --git a/crates/rustc_codegen_spirv/src/symbols.rs b/crates/rustc_codegen_spirv/src/symbols.rs index abaccb5c55..401fe7aa07 100644 --- a/crates/rustc_codegen_spirv/src/symbols.rs +++ b/crates/rustc_codegen_spirv/src/symbols.rs @@ -321,6 +321,10 @@ impl Symbols { "acceleration_structure", SpirvAttribute::IntrinsicType(IntrinsicType::AccelerationStructureKhr), ), + ( + "ray_query", + SpirvAttribute::IntrinsicType(IntrinsicType::RayQueryKhr), + ), ("block", SpirvAttribute::Block), ("flat", SpirvAttribute::Flat), ("invariant", SpirvAttribute::Invariant), diff --git a/crates/spirv-std/src/ray_tracing.rs b/crates/spirv-std/src/ray_tracing.rs index 14ce58efaa..77cf0f87de 100644 --- a/crates/spirv-std/src/ray_tracing.rs +++ b/crates/spirv-std/src/ray_tracing.rs @@ -159,3 +159,493 @@ bitflags::bitflags! { const SKIP_AABBS = 512; } } + +/// A ray query type which is an opaque object representing a ray traversal. +#[spirv(ray_query)] +pub struct RayQuery { + _private: u32, +} + +/// Constructs an uninitialized ray query variable. Using the syntax +/// `let (mut)? `. Where `name` is the name of the ray query variable. +#[macro_export] +macro_rules! ray_query { + (let $name:ident) => { + $crate::ray_query!(@inner $name) + }; + (let mut $name:ident) => { + $crate::ray_query!(@inner $name, mut) + }; + (@inner $name:ident $(, $mut:tt)?) => { + #[allow(deprecated)] + let $name : *mut RayQuery; + let $($mut)? $name = unsafe { + asm! { + "%ray_query = OpTypeRayQueryKHR", + "%ray_query_ptr = OpTypePointer Generic %ray_query", + "{name} = OpVariable %ray_query_ptr Function", + name = out(reg) $name, + } + + &$($mut)? *$name + }; + } +} + +impl RayQuery { + /// Initialize a ray query object, defining parameters of traversal. After this + /// call, a new ray trace can be performed with [`Self::proceed`]. Any + /// previous traversal state stored in the object is lost. + /// + /// - `ray_query` is a pointer to the ray query to initialize. + /// - `acceleration_structure` is the descriptor for the acceleration structure + /// to trace into. + /// - `ray_flags` contains one or more of the Ray Flag values. + /// - `cull_mask` is the mask to test against the instance mask. Only the 8 + /// least-significant bits of `cull_mask` are used by this instruction - other + /// bits are ignored. + /// - `ray_origin`, `ray_tmin`, `ray_direction`, and `ray_tmax` control the + /// basic parameters of the ray to be traced. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryInitializeKHR")] + #[inline] + #[allow(clippy::too_many_arguments)] + pub unsafe fn initialize( + &mut self, + acceleration_structure: &AccelerationStructure, + ray_flags: RayFlags, + cull_mask: u32, + ray_origin: impl Vector, + ray_tmin: f32, + ray_direction: impl Vector, + ray_tmax: f32, + ) { + asm! { + "%origin = OpLoad _ {ray_origin}", + "%direction = OpLoad _ {ray_direction}", + "OpRayQueryInitializeKHR \ + {ray_query} \ + {acceleration_structure} \ + {ray_flags} \ + {cull_mask} \ + %origin \ + {ray_tmin} \ + %direction \ + {ray_tmax}", + ray_query = in(reg) self, + acceleration_structure = in(reg) acceleration_structure, + ray_flags = in(reg) ray_flags.bits(), + cull_mask = in(reg) cull_mask, + ray_origin = in(reg) &ray_origin, + ray_tmin = in(reg) ray_tmin, + ray_direction = in(reg) &ray_direction, + ray_tmax = in(reg) ray_tmax, + } + } + + /// Allow traversal to proceed. Returns `true` if traversal is incomplete, + /// and `false` when it has completed. A previous call to [`Self::proceed`] + /// with the same ray query object must not have already returned `false`. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryProceedKHR")] + #[inline] + pub unsafe fn proceed(&self) -> bool { + let result: u32; + + asm!{ + "%u32 = OpTypeInt 32 0", + "%bool = OpTypeBool", + "%u32_0 = OpConstant %u32 0", + "%u32_1 = OpConstant %u32 1", + "%result = OpRayQueryProceedKHR %bool {ray_query}", + "{result} = OpSelect %u32 %result %u32_0 %u32_1", + ray_query = in(reg) self, + result = out(reg) result, + } + + result != 0 + } + + /// Terminates further execution of a ray query; further calls to + /// [`Self::proceed`] will return `false`.The value returned by any prior + /// execution of [`Self::proceed`] with the same ray query object must have + /// been true. Refer to the client API specification for more details. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryTerminateKHR")] + #[inline] + pub unsafe fn terminate(&self) { + asm!("OpRayQueryTerminateKHR {}", in(reg) self) + } + + /// Returns the type of the current candidate or committed intersection. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionTypeKHR")] + #[inline] + pub unsafe fn get_intersection_type(&self) -> u32 { + let mut result = 0; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Returns the "Ray Tmin" value used by the ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetRayTMinKHR")] + #[inline] + pub unsafe fn get_ray_t_min(&self) -> f32 { + let mut result = 0.0; + + asm! { + "%f32 = OpTypeFloat 32", + "%result = OpRayQueryGetRayTMinKHR %f32 {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } + + result + } + + /// Returns the "Ray Flags" value used by the ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetRayFlagsKHR")] + #[inline] + pub unsafe fn get_ray_flags(&self) -> RayFlags { + let mut result = 0; + + asm! { + "%u32 = OpTypeInt 32 0", + "%result = OpRayQueryGetRayFlagsKHR %u32 {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } + + RayFlags::from_bits_truncate(result) + } + + /// Gets the "T" value for the current or previous intersection considered + /// in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionTKHR")] + #[inline] + pub unsafe fn get_intersection_t(&self) -> f32 { + let mut result = 0.0; + + asm! { + "%f32 = OpTypeFloat 32", + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionTKHR %f32 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the custom index of the instance for the current intersection + /// considered in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionInstanceCustomIndexKHR")] + #[inline] + pub unsafe fn get_intersection_instance_custom_index(&self) -> u32 { + let mut result = 0; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the id of the instance for the current intersection considered in a + /// ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionInstanceIdKHR")] + #[inline] + pub unsafe fn get_intersection_instance_id(&self) -> u32 { + let mut result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = out(reg) result, + } + + result + } + + /// Gets the shader binding table record offset for the current intersection + /// considered in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR")] + #[inline] + pub unsafe fn get_intersection_shader_binding_table_record_offset( + &self, + ) -> u32 { + let mut result = 0; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the geometry index for the current intersection considered in a + /// ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionGeometryIndexKHR")] + #[inline] + pub unsafe fn get_intersection_geometry_index(&self) -> u32 { + let mut result = 0; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the primitive index for the current intersection considered in a + /// ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionPrimitiveIndexKHR")] + #[inline] + pub unsafe fn get_intersection_primitive_index(&self) -> u32 { + let mut result = 0; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the second and third barycentric coordinates of the current + /// intersection considered in a ray query against the primitive it hit. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionBarycentricsKHR")] + #[inline] + pub unsafe fn get_intersection_barycentrics, const INTERSECTION: u32>( + &self, + ) -> V { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x2 = OpTypeVector %f32 2", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionBarycentricsKHR %f32x2 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Returns whether the current intersection considered in a ray query was with + /// the front face (`true`) or back face (`false`) of a primitive. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionFrontFaceKHR")] + #[inline] + pub unsafe fn get_intersection_front_face(&self) -> bool { + let mut result = 0u8; + + asm! { + "%u8 = OpTypeInt 8 0", + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionFrontFaceKHR %u8 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result != 0 + } + + /// Returns whether a candidate intersection considered in a ray query was with + /// an opaque AABB (Axis Aligned Bounding Box) or not. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR")] + #[inline] + pub unsafe fn get_intersection_candidate_aabb_opaque(&self) -> bool { + let mut result = 0u8; + + asm! { + "%u8 = OpTypeInt 8 0", + "%result = OpRayQueryGetIntersectionCandidateAABBOpaqueKHR %u8 {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } + + result != 0 + } + + /// Gets the object-space ray direction for the current intersection considered + /// in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionObjectRayDirectionKHR")] + #[inline] + pub unsafe fn get_intersection_object_ray_direction< + V: Vector, + const INTERSECTION: u32, + >( + &self, + ) -> V { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR %f32x3 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the object-space ray origin for the current intersection considered in + /// a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionObjectRayOriginKHR")] + #[inline] + pub unsafe fn get_intersection_object_ray_origin, const INTERSECTION: u32>( + &self, + ) -> V { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetIntersectionObjectRayOriginKHR %f32x3 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the world-space direction for the ray traced in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetWorldRayDirectionKHR")] + #[inline] + pub unsafe fn get_world_ray_direction, const INTERSECTION: u32>(&self) -> V { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetWorldRayDirectionKHR %f32x3 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets the world-space origin for the ray traced in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetWorldRayOriginKHR")] + #[inline] + pub unsafe fn get_world_ray_origin, const INTERSECTION: u32>(&self) -> V { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetWorldRayOriginKHR %f32x3 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } + + /// Gets a matrix that transforms values to world-space from the object-space of + /// the current intersection considered in a ray query. + #[spirv_std_macros::gpu_only] + #[doc(alias = "OpRayQueryGetIntersectionObjectToWorldKHR")] + #[inline] + pub unsafe fn get_intersection_object_to_world, const INTERSECTION: u32>( + &self, + ) -> V { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%intersection = OpConstant %u32 {intersection}", + "%result = OpRayQueryGetWorldRayOriginKHR %f32x3 {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + intersection = const INTERSECTION, + result = in(reg) &mut result, + } + + result + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_barycentrics_khr.rs b/tests/ui/arch/ray_query_get_intersection_barycentrics_khr.rs new file mode 100644 index 0000000000..7ce9cab77e --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_barycentrics_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let barycentric_coords: glam::Vec2 = handle.get_intersection_barycentrics::<_, 5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_front_face_khr.rs b/tests/ui/arch/ray_query_get_intersection_front_face_khr.rs new file mode 100644 index 0000000000..552d7ed228 --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_front_face_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + assert!(handle.get_intersection_front_face::<5>()); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_geometry_index_khr.rs b/tests/ui/arch/ray_query_get_intersection_geometry_index_khr.rs new file mode 100644 index 0000000000..acf1c53948 --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_geometry_index_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let t = handle.get_intersection_geometry_index::<5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_instance_custom_index_khr.rs b/tests/ui/arch/ray_query_get_intersection_instance_custom_index_khr.rs new file mode 100644 index 0000000000..e68adb29bb --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_instance_custom_index_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let index = handle.get_intersection_instance_custom_index::<5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_instance_id_khr.rs b/tests/ui/arch/ray_query_get_intersection_instance_id_khr.rs new file mode 100644 index 0000000000..6d1fcc14ba --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_instance_id_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let id = handle.get_intersection_instance_id::<5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_shader_binding_table_record_offset_khr.rs b/tests/ui/arch/ray_query_get_intersection_shader_binding_table_record_offset_khr.rs new file mode 100644 index 0000000000..15eee3cb8b --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_shader_binding_table_record_offset_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let offset = handle.get_intersection_shader_binding_table_record_offset::<5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_t_khr.rs b/tests/ui/arch/ray_query_get_intersection_t_khr.rs new file mode 100644 index 0000000000..7e1bff6a9d --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_t_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let t = handle.get_intersection_t::<5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_intersection_type_khr.rs b/tests/ui/arch/ray_query_get_intersection_type_khr.rs new file mode 100644 index 0000000000..5d8e9dd446 --- /dev/null +++ b/tests/ui/arch/ray_query_get_intersection_type_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + handle.get_intersection_type::<5>(); + } +} diff --git a/tests/ui/arch/ray_query_get_ray_t_min_khr.rs b/tests/ui/arch/ray_query_get_ray_t_min_khr.rs new file mode 100644 index 0000000000..2a9e014673 --- /dev/null +++ b/tests/ui/arch/ray_query_get_ray_t_min_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + let tmin = handle.get_ray_t_min(); + } +} diff --git a/tests/ui/arch/ray_query_initialize_khr.rs b/tests/ui/arch/ray_query_initialize_khr.rs new file mode 100644 index 0000000000..6b1bb352f8 --- /dev/null +++ b/tests/ui/arch/ray_query_initialize_khr.rs @@ -0,0 +1,28 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +// Rustfmt eats long attributes +#[rustfmt::skip] +pub fn main( + #[spirv(descriptor_set = 0, binding = 0)] acceleration_structure: &AccelerationStructure, + #[spirv(ray_payload)] payload: &mut Vec3, +) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut ray_query); + + ray_query.initialize( + acceleration_structure, + RayFlags::NONE, + 0, + glam::vec3(1.0, 2.0, 3.0), + 0.5, + glam::vec3(3.0, 2.0, 1.0), + 1.0, + ); + } +} diff --git a/tests/ui/arch/ray_query_proceed_khr.rs b/tests/ui/arch/ray_query_proceed_khr.rs new file mode 100644 index 0000000000..725cf31589 --- /dev/null +++ b/tests/ui/arch/ray_query_proceed_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + assert!(handle.proceed()); + } +} diff --git a/tests/ui/arch/ray_query_terminate_khr.rs b/tests/ui/arch/ray_query_terminate_khr.rs new file mode 100644 index 0000000000..66d6e084be --- /dev/null +++ b/tests/ui/arch/ray_query_terminate_khr.rs @@ -0,0 +1,15 @@ +// build-pass + +use glam::Vec3; +use spirv_std::ray_tracing::{AccelerationStructure, RayFlags, RayQuery}; + +#[spirv(fragment)] +pub fn main(#[spirv(descriptor_set = 0, binding = 0)] accel: &AccelerationStructure) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_query""#); + asm!("OpCapability RayQueryKHR"); + spirv_std::ray_query!(let mut handle); + handle.initialize(accel, RayFlags::NONE, 0, Vec3::ZERO, 0.0, Vec3::ZERO, 0.0); + handle.terminate(); + } +}