spirv_std/
ray_tracing.rs

1//! Ray-tracing data types
2
3// NOTE(eddyb) "&-masking with zero", likely due to `NONE = 0` in `bitflags!`.
4#![allow(clippy::bad_bit_mask)]
5
6use crate::vector::Vector;
7#[cfg(target_arch = "spirv")]
8use core::arch::asm;
9
10/// An acceleration structure type which is an opaque reference to an
11/// acceleration structure handle as defined in the client API specification.
12#[spirv(acceleration_structure)]
13#[derive(Copy, Clone)]
14// HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation.
15#[repr(C)]
16pub struct AccelerationStructure {
17    // HACK(eddyb) avoids the layout becoming ZST (and being elided in one way
18    // or another, before `#[spirv(acceleration_structure)]` can special-case it).
19    _anti_zst_padding: core::mem::MaybeUninit<u32>,
20}
21
22impl AccelerationStructure {
23    /// Converts a 64-bit integer into an [`AccelerationStructure`].
24    /// # Safety
25    /// The 64-bit integer must point to a valid acceleration structure.
26    #[spirv_std_macros::gpu_only]
27    #[doc(alias = "OpConvertUToAccelerationStructureKHR")]
28    #[inline]
29    pub unsafe fn from_u64(id: u64) -> AccelerationStructure {
30        unsafe {
31            // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
32            let mut result_slot = core::mem::MaybeUninit::uninit();
33            asm! {
34                "%ret = OpTypeAccelerationStructureKHR",
35                "%result = OpConvertUToAccelerationStructureKHR %ret {id}",
36                "OpStore {result_slot} %result",
37                id = in(reg) id,
38                result_slot = in(reg) result_slot.as_mut_ptr(),
39            }
40            result_slot.assume_init()
41        }
42    }
43
44    /// Converts a vector of two 32 bit integers into an [`AccelerationStructure`].
45    /// # Safety
46    /// The combination must point to a valid acceleration structure.
47    #[spirv_std_macros::gpu_only]
48    #[doc(alias = "OpConvertUToAccelerationStructureKHR")]
49    #[inline]
50    pub unsafe fn from_vec(id: impl Vector<u32, 2>) -> AccelerationStructure {
51        unsafe {
52            // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this.
53            let mut result_slot = core::mem::MaybeUninit::uninit();
54            asm! {
55                "%ret = OpTypeAccelerationStructureKHR",
56                "%id = OpLoad _ {id}",
57                "%result = OpConvertUToAccelerationStructureKHR %ret %id",
58                "OpStore {result_slot} %result",
59                id = in(reg) &id,
60                result_slot = in(reg) result_slot.as_mut_ptr(),
61            }
62            result_slot.assume_init()
63        }
64    }
65
66    #[spirv_std_macros::gpu_only]
67    /// Trace a ray into the acceleration structure.
68    ///
69    /// - `structure` is the descriptor for the acceleration structure to trace into.
70    /// - `ray_flags` contains one or more of the Ray Flag values.
71    /// - `cull_mask` is the mask to test against the instance mask. Only the 8
72    ///   least-significant bits of are used by this instruction - other bits
73    ///   are ignored.
74    /// - `sbt_offset` and `sbt_stride` control indexing into the SBT (Shader
75    ///   Binding Table) for hit shaders called from this trace. Only the 4
76    ///   least-significant bits of `sbt_offset` and `sbt_stride` are used by this
77    ///   instruction - other bits are ignored.
78    /// - `miss_index` is the index of the miss shader to be called from this
79    ///   trace call. Only the 16 least-significant bits are used by this
80    ///   instruction - other bits are ignored.
81    /// - `ray_origin`, `ray_tmin`, `ray_direction`, and `ray_tmax` control the
82    ///   basic parameters of the ray to be traced.
83    ///
84    /// - `payload` is a pointer to the ray payload structure to use for this trace.
85    ///   `payload` must have a storage class of `ray_payload`
86    ///   or `incoming_ray_payload`.
87    ///
88    /// This instruction is allowed only in `ray_generation`, `closest_hit` and
89    /// `miss` execution models.
90    ///
91    /// This instruction is a shader call instruction which may invoke shaders with
92    /// the `intersection`, `any_hit`, `closest_hit`, and `miss`
93    /// execution models.
94    #[doc(alias = "OpTraceRayKHR")]
95    #[inline]
96    #[allow(clippy::too_many_arguments)]
97    pub unsafe fn trace_ray<T>(
98        &self,
99        ray_flags: RayFlags,
100        cull_mask: i32,
101        sbt_offset: i32,
102        sbt_stride: i32,
103        miss_index: i32,
104        ray_origin: impl Vector<f32, 3>,
105        ray_tmin: f32,
106        ray_direction: impl Vector<f32, 3>,
107        ray_tmax: f32,
108        payload: &mut T,
109    ) {
110        unsafe {
111            asm! {
112                "%acceleration_structure = OpLoad _ {acceleration_structure}",
113                "%ray_origin = OpLoad _ {ray_origin}",
114                "%ray_direction = OpLoad _ {ray_direction}",
115                "OpTraceRayKHR \
116                %acceleration_structure \
117                {ray_flags} \
118                {cull_mask} \
119                {sbt_offset} \
120                {sbt_stride} \
121                {miss_index} \
122                %ray_origin \
123                {ray_tmin} \
124                %ray_direction \
125                {ray_tmax} \
126                {payload}",
127                acceleration_structure = in(reg) self,
128                ray_flags = in(reg) ray_flags.bits(),
129                cull_mask = in(reg) cull_mask,
130                sbt_offset = in(reg) sbt_offset,
131                sbt_stride = in(reg) sbt_stride,
132                miss_index = in(reg) miss_index,
133                ray_origin = in(reg) &ray_origin,
134                ray_tmin = in(reg) ray_tmin,
135                ray_direction = in(reg) &ray_direction,
136                ray_tmax = in(reg) ray_tmax,
137                payload = in(reg) payload,
138            }
139        }
140    }
141}
142
143bitflags::bitflags! {
144    /// Flags controlling the properties of an OpTraceRayKHR instruction.
145    /// Despite being a mask and allowing multiple bits to be combined, it is
146    /// invalid for more than one of these four bits to be set: `OPAQUE`,
147    /// `NO_OPAQUE`, `CULL_OPAQUE`, `CULL_NO_OPAQUE`, only one of
148    /// `CULL_BACK_FACING_TRIANGLES` and `CULL_FRONT_FACING_TRIANGLES` may
149    /// be set.
150    #[repr(transparent)]
151    #[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
152    pub struct RayFlags: u32 {
153        /// No flags specified.
154        const NONE = 0;
155        /// Force all intersections with the trace to be opaque.
156        const OPAQUE = 1;
157        /// Force all intersections with the trace to be non-opaque.
158        const NO_OPAQUE = 2;
159        /// Accept the first hit discovered.
160        const TERMINATE_ON_FIRST_HIT = 4;
161        /// Do not execute a closest hit shader.
162        const SKIP_CLOSEST_HIT_SHADER = 8;
163        /// Do not intersect with the back face of triangles.
164        const CULL_BACK_FACING_TRIANGLES = 16;
165        /// Do not intersect with the front face of triangles.
166        const CULL_FRONT_FACING_TRIANGLES = 32;
167        /// Do not intersect with opaque geometry.
168        const CULL_OPAQUE = 64;
169        /// Do not intersect with non-opaque geometry.
170        const CULL_NO_OPAQUE = 128;
171        /// Do not intersect with any triangle geometries.
172        const SKIP_TRIANGLES = 256;
173        /// Do not intersect with any AABB (Axis Aligned Bounding Box) geometries.
174        const SKIP_AABBS = 512;
175    }
176}
177
178/// Describes the type of the intersection which is currently the candidate in a ray query,
179/// returned by [`RayQuery::get_candidate_intersection_type`].
180#[repr(u32)]
181#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
182#[allow(clippy::upper_case_acronyms)]
183pub enum CandidateIntersection {
184    /// A potential intersection with a triangle is being considered.
185    Triangle = 0,
186    /// A potential intersection with an axis-aligned bounding box is being considered.
187    AABB = 1,
188}
189
190/// Describes the type of the intersection currently committed in a ray query, returned by
191/// [`RayQuery::get_committed_intersection_type`].
192#[repr(u32)]
193#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
194pub enum CommittedIntersection {
195    /// No intersection is committed.
196    None = 0,
197    /// An intersection with a triangle has been committed.
198    Triangle = 1,
199    /// A user-generated intersection has been committed.
200    Generated = 2,
201}
202
203/// A ray query type which is an opaque object representing a ray traversal.
204#[spirv(ray_query)]
205// HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation.
206#[repr(C)]
207// HACK(eddyb) false positive due to `rustc` not understanding e.g. `ray_query!`.
208#[allow(dead_code)]
209pub struct RayQuery {
210    // HACK(eddyb) avoids the layout becoming ZST (and being elided in one way
211    // or another, before `#[spirv(ray_query)]` can special-case it).
212    _anti_zst_padding: core::mem::MaybeUninit<u32>,
213}
214
215/// Constructs an uninitialized ray query variable. Using the syntax
216/// `let (mut)? <name>`. Where `name` is the name of the ray query variable.
217#[macro_export]
218macro_rules! ray_query {
219    (let $name:ident) => {
220        $crate::ray_query!(@inner $name)
221    };
222    (let mut $name:ident) => {
223        $crate::ray_query!(@inner $name, mut)
224    };
225    (@inner $name:ident $(, $mut:tt)?) => {
226        let $name: &$($mut)? RayQuery = unsafe {
227            let $name : *mut RayQuery;
228            ::core::arch::asm! {
229                "%ray_query = OpTypeRayQueryKHR",
230                "%ray_query_ptr = OpTypePointer Generic %ray_query",
231                "{name} = OpVariable %ray_query_ptr Function",
232                name = out(reg) $name,
233            }
234
235            &$($mut)? *$name
236        };
237    }
238}
239
240impl RayQuery {
241    /// Initialize a ray query object, defining parameters of traversal. After this
242    /// call, a new ray trace can be performed with [`Self::proceed`]. Any
243    /// previous traversal state stored in the object is lost.
244    ///
245    /// - `ray_query` is a pointer to the ray query to initialize.
246    /// - `acceleration_structure` is the descriptor for the acceleration structure
247    ///   to trace into.
248    /// - `ray_flags` contains one or more of the Ray Flag values.
249    /// - `cull_mask` is the mask to test against the instance mask.  Only the 8
250    ///   least-significant bits of `cull_mask` are used by this instruction - other
251    ///   bits are ignored.
252    /// - `ray_origin`, `ray_tmin`, `ray_direction`, and `ray_tmax` control the
253    ///   basic parameters of the ray to be traced.
254    #[spirv_std_macros::gpu_only]
255    #[doc(alias = "OpRayQueryInitializeKHR")]
256    #[inline]
257    #[allow(clippy::too_many_arguments)]
258    pub unsafe fn initialize(
259        &mut self,
260        acceleration_structure: &AccelerationStructure,
261        ray_flags: RayFlags,
262        cull_mask: u32,
263        ray_origin: impl Vector<f32, 3>,
264        ray_tmin: f32,
265        ray_direction: impl Vector<f32, 3>,
266        ray_tmax: f32,
267    ) {
268        unsafe {
269            asm! {
270                "%acceleration_structure = OpLoad _ {acceleration_structure}",
271                "%origin = OpLoad _ {ray_origin}",
272                "%direction = OpLoad _ {ray_direction}",
273                "OpRayQueryInitializeKHR \
274                    {ray_query} \
275                    %acceleration_structure \
276                    {ray_flags} \
277                    {cull_mask} \
278                    %origin \
279                    {ray_tmin} \
280                    %direction \
281                    {ray_tmax}",
282                ray_query = in(reg) self,
283                acceleration_structure = in(reg) acceleration_structure,
284                ray_flags = in(reg) ray_flags.bits(),
285                cull_mask = in(reg) cull_mask,
286                ray_origin = in(reg) &ray_origin,
287                ray_tmin = in(reg) ray_tmin,
288                ray_direction = in(reg) &ray_direction,
289                ray_tmax = in(reg) ray_tmax,
290            }
291        }
292    }
293
294    /// Allow traversal to proceed. Returns `true` if traversal is incomplete,
295    /// and `false` when it has completed. A previous call to [`Self::proceed`]
296    /// with the same ray query object must not have already returned `false`.
297    #[spirv_std_macros::gpu_only]
298    #[doc(alias = "OpRayQueryProceedKHR")]
299    #[inline]
300    pub unsafe fn proceed(&self) -> bool {
301        unsafe {
302            let mut result = false;
303
304            asm! {
305                "%bool = OpTypeBool",
306                "%result = OpRayQueryProceedKHR %bool {ray_query}",
307                "OpStore {result} %result",
308                ray_query = in(reg) self,
309                result = in(reg) &mut result,
310            }
311
312            result
313        }
314    }
315
316    /// Terminates further execution of a ray query; further calls to
317    /// [`Self::proceed`] will return `false`. The value returned by any prior
318    /// execution of [`Self::proceed`] with the same ray query object must have
319    /// been true.
320    #[spirv_std_macros::gpu_only]
321    #[doc(alias = "OpRayQueryTerminateKHR")]
322    #[inline]
323    pub unsafe fn terminate(&self) {
324        unsafe { asm!("OpRayQueryTerminateKHR {}", in(reg) self) }
325    }
326
327    /// Confirms a triangle intersection to be included in the determination
328    /// of the closest hit for a ray query.
329    ///
330    /// [`Self::proceed()`] must have been called on this object, and it must
331    /// have returned true. The current intersection candidate must have a
332    /// [`Self::get_candidate_intersection_type()`] of
333    /// [`CandidateIntersection::Triangle`].
334    #[spirv_std_macros::gpu_only]
335    #[doc(alias = "OpRayQueryConfirmIntersectionKHR")]
336    #[inline]
337    pub unsafe fn confirm_intersection(&self) {
338        unsafe { asm!("OpRayQueryConfirmIntersectionKHR {}", in(reg) self) }
339    }
340
341    /// Returns the type of the current candidate intersection.
342    ///
343    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
344    #[spirv_std_macros::gpu_only]
345    #[doc(alias = "OpRayQueryGetIntersectionTypeKHR")]
346    #[inline]
347    pub unsafe fn get_candidate_intersection_type(&self) -> CandidateIntersection {
348        unsafe {
349            let result: u32;
350
351            asm! {
352                "%u32 = OpTypeInt 32 0",
353                "%intersection = OpConstant %u32 0",
354                "{result} = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection",
355                ray_query = in(reg) self,
356                result = out(reg) result,
357            }
358
359            match result {
360                0 => CandidateIntersection::Triangle,
361                1 => CandidateIntersection::AABB,
362                _ => CandidateIntersection::Triangle,
363            }
364        }
365    }
366
367    /// Returns the type of the current candidate intersection.
368    #[spirv_std_macros::gpu_only]
369    #[doc(alias = "OpRayQueryGetIntersectionTypeKHR")]
370    #[inline]
371    pub unsafe fn get_committed_intersection_type(&self) -> CommittedIntersection {
372        unsafe {
373            let result: u32;
374
375            asm! {
376                "%u32 = OpTypeInt 32 0",
377                "%intersection = OpConstant %u32 1",
378                "{result} = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection",
379                ray_query = in(reg) self,
380                result = out(reg) result,
381            }
382
383            match result {
384                0 => CommittedIntersection::None,
385                1 => CommittedIntersection::Triangle,
386                2 => CommittedIntersection::Generated,
387                _ => CommittedIntersection::None,
388            }
389        }
390    }
391
392    /// Returns the "Ray Tmin" value used by the ray query.
393    #[spirv_std_macros::gpu_only]
394    #[doc(alias = "OpRayQueryGetRayTMinKHR")]
395    #[inline]
396    pub unsafe fn get_ray_t_min(&self) -> f32 {
397        unsafe {
398            let result;
399
400            asm! {
401                "%f32 = OpTypeFloat 32",
402                "{result} = OpRayQueryGetRayTMinKHR %f32 {ray_query}",
403                ray_query = in(reg) self,
404                result = out(reg) result,
405            }
406
407            result
408        }
409    }
410
411    /// Returns the "Ray Flags" value used by the ray query.
412    #[spirv_std_macros::gpu_only]
413    #[doc(alias = "OpRayQueryGetRayFlagsKHR")]
414    #[inline]
415    pub unsafe fn get_ray_flags(&self) -> RayFlags {
416        unsafe {
417            let result;
418
419            asm! {
420                "{result} = OpRayQueryGetRayFlagsKHR typeof{result} {ray_query}",
421                ray_query = in(reg) self,
422                result = out(reg) result,
423            }
424
425            RayFlags::from_bits_truncate(result)
426        }
427    }
428
429    /// Gets the "T" value for the current or previous intersection considered
430    /// in a ray query.
431    ///
432    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
433    /// The current intersection candidate must have a [`Self::get_candidate_intersection_type()`]
434    /// of [`CandidateIntersection::Triangle`].
435    #[spirv_std_macros::gpu_only]
436    #[doc(alias = "OpRayQueryGetIntersectionTKHR")]
437    #[inline]
438    pub unsafe fn get_candidate_intersection_t(&self) -> f32 {
439        unsafe {
440            let result;
441
442            asm! {
443                "%u32 = OpTypeInt 32 0",
444                "%intersection = OpConstant %u32 0",
445                "{result} = OpRayQueryGetIntersectionTKHR typeof{result} {ray_query} %intersection",
446                ray_query = in(reg) self,
447                result = out(reg) result,
448            }
449
450            result
451        }
452    }
453
454    /// Gets the "T" value for the current or previous intersection considered
455    /// in a ray query.
456    ///
457    /// There must be a current committed intersection.
458    ///
459    /// TODO: Improve docs. Can't right now due to
460    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
461    #[spirv_std_macros::gpu_only]
462    #[doc(alias = "OpRayQueryGetIntersectionTKHR")]
463    #[inline]
464    pub unsafe fn get_committed_intersection_t(&self) -> f32 {
465        unsafe {
466            let result;
467
468            asm! {
469                "%u32 = OpTypeInt 32 0",
470                "%intersection = OpConstant %u32 1",
471                "{result} = OpRayQueryGetIntersectionTKHR typeof{result} {ray_query} %intersection",
472                ray_query = in(reg) self,
473                result = out(reg) result,
474            }
475
476            result
477        }
478    }
479
480    /// Gets the custom index of the instance for the current intersection
481    /// considered in a ray query.
482    ///
483    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
484    #[spirv_std_macros::gpu_only]
485    #[doc(alias = "OpRayQueryGetIntersectionInstanceCustomIndexKHR")]
486    #[inline]
487    pub unsafe fn get_candidate_intersection_instance_custom_index(&self) -> u32 {
488        unsafe {
489            let result;
490
491            asm! {
492                "%u32 = OpTypeInt 32 0",
493                "%intersection = OpConstant %u32 0",
494                "{result} = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection",
495                ray_query = in(reg) self,
496                result = out(reg) result,
497            }
498
499            result
500        }
501    }
502
503    /// Gets the custom index of the instance for the current intersection
504    /// considered in a ray query.
505    ///
506    /// There must be a current committed intersection.
507    ///
508    /// TODO: Improve docs. Can't right now due to
509    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
510    #[spirv_std_macros::gpu_only]
511    #[doc(alias = "OpRayQueryGetIntersectionInstanceCustomIndexKHR")]
512    #[inline]
513    pub unsafe fn get_committed_intersection_instance_custom_index(&self) -> u32 {
514        unsafe {
515            let result;
516
517            asm! {
518                "%u32 = OpTypeInt 32 0",
519                "%intersection = OpConstant %u32 1",
520                "{result} = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection",
521                ray_query = in(reg) self,
522                result = out(reg) result,
523            }
524
525            result
526        }
527    }
528
529    /// Gets the id of the instance for the current intersection considered in a
530    /// ray query.
531    ///
532    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
533    #[spirv_std_macros::gpu_only]
534    #[doc(alias = "OpRayQueryGetIntersectionInstanceIdKHR")]
535    #[inline]
536    pub unsafe fn get_candidate_intersection_instance_id(&self) -> u32 {
537        unsafe {
538            let result;
539
540            asm! {
541                "%u32 = OpTypeInt 32 0",
542                "%intersection = OpConstant %u32 0",
543                "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection",
544                ray_query = in(reg) self,
545                result = out(reg) result,
546            }
547
548            result
549        }
550    }
551
552    /// Gets the id of the instance for the current intersection considered in a
553    /// ray query.
554    ///
555    /// There must be a current committed intersection.
556    ///
557    /// TODO: Improve docs. Can't right now due to
558    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
559    #[spirv_std_macros::gpu_only]
560    #[doc(alias = "OpRayQueryGetIntersectionInstanceIdKHR")]
561    #[inline]
562    pub unsafe fn get_committed_intersection_instance_id(&self) -> u32 {
563        unsafe {
564            let result;
565
566            asm! {
567                "%u32 = OpTypeInt 32 0",
568                "%intersection = OpConstant %u32 1",
569                "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection",
570                ray_query = in(reg) self,
571                result = out(reg) result,
572            }
573
574            result
575        }
576    }
577
578    /// Gets the shader binding table record offset for the current intersection
579    /// considered in a ray query.
580    ///
581    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
582    #[spirv_std_macros::gpu_only]
583    #[doc(alias = "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR")]
584    #[inline]
585    pub unsafe fn get_candidate_intersection_shader_binding_table_record_offset(&self) -> u32 {
586        unsafe {
587            let result;
588
589            asm! {
590                "%u32 = OpTypeInt 32 0",
591                "%intersection = OpConstant %u32 0",
592                "{result} = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection",
593                ray_query = in(reg) self,
594                result = out(reg) result,
595            }
596
597            result
598        }
599    }
600
601    /// Gets the shader binding table record offset for the current intersection
602    /// considered in a ray query.
603    ///
604    /// There must be a current committed intersection.
605    ///
606    /// TODO: Improve docs. Can't right now due to
607    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
608    #[spirv_std_macros::gpu_only]
609    #[doc(alias = "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR")]
610    #[inline]
611    pub unsafe fn get_committed_intersection_shader_binding_table_record_offset(&self) -> u32 {
612        unsafe {
613            let result;
614
615            asm! {
616                "%u32 = OpTypeInt 32 0",
617                "%intersection = OpConstant %u32 1",
618                "{result} = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection",
619                ray_query = in(reg) self,
620                result = out(reg) result,
621            }
622
623            result
624        }
625    }
626
627    /// Gets the geometry index for the current intersection considered in a
628    /// ray query.
629    ///
630    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
631    #[spirv_std_macros::gpu_only]
632    #[doc(alias = "OpRayQueryGetIntersectionGeometryIndexKHR")]
633    #[inline]
634    pub unsafe fn get_candidate_intersection_geometry_index(&self) -> u32 {
635        unsafe {
636            let result;
637
638            asm! {
639                "%u32 = OpTypeInt 32 0",
640                "%intersection = OpConstant %u32 0",
641                "{result} = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection",
642                ray_query = in(reg) self,
643                result = out(reg) result,
644            }
645
646            result
647        }
648    }
649
650    /// Gets the geometry index for the current intersection considered in a
651    /// ray query.
652    ///
653    /// There must be a current committed intersection.
654    ///
655    /// TODO: Improve docs. Can't right now due to
656    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
657    #[spirv_std_macros::gpu_only]
658    #[doc(alias = "OpRayQueryGetIntersectionGeometryIndexKHR")]
659    #[inline]
660    pub unsafe fn get_committed_intersection_geometry_index(&self) -> u32 {
661        unsafe {
662            let result;
663
664            asm! {
665                "%u32 = OpTypeInt 32 0",
666                "%intersection = OpConstant %u32 1",
667                "{result} = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection",
668                ray_query = in(reg) self,
669                result = out(reg) result,
670            }
671
672            result
673        }
674    }
675
676    /// Gets the primitive index for the current intersection considered in a
677    /// ray query.
678    ///
679    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
680    #[spirv_std_macros::gpu_only]
681    #[doc(alias = "OpRayQueryGetIntersectionPrimitiveIndexKHR")]
682    #[inline]
683    pub unsafe fn get_candidate_intersection_primitive_index(&self) -> u32 {
684        unsafe {
685            let result;
686
687            asm! {
688                "%u32 = OpTypeInt 32 0",
689                "%intersection = OpConstant %u32 0",
690                "{result} = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection",
691                ray_query = in(reg) self,
692                result = out(reg) result,
693            }
694
695            result
696        }
697    }
698
699    /// Gets the primitive index for the current intersection considered in a
700    /// ray query.
701    ///
702    /// There must be a current committed intersection.
703    ///
704    /// TODO: Improve docs. Can't right now due to
705    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
706    #[spirv_std_macros::gpu_only]
707    #[doc(alias = "OpRayQueryGetIntersectionPrimitiveIndexKHR")]
708    #[inline]
709    pub unsafe fn get_committed_intersection_primitive_index(&self) -> u32 {
710        unsafe {
711            let result;
712
713            asm! {
714                "%u32 = OpTypeInt 32 0",
715                "%intersection = OpConstant %u32 1",
716                "{result} = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection",
717                ray_query = in(reg) self,
718                result = out(reg) result,
719            }
720
721            result
722        }
723    }
724
725    /// Gets the second and third barycentric coordinates of the current
726    /// intersection considered in a ray query against the primitive it hit.
727    ///
728    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
729    /// The current intersection candidate must have a [`Self::get_candidate_intersection_type()`]
730    /// of [`CandidateIntersection::Triangle`].
731    #[spirv_std_macros::gpu_only]
732    #[doc(alias = "OpRayQueryGetIntersectionBarycentricsKHR")]
733    #[inline]
734    pub unsafe fn get_candidate_intersection_barycentrics<V: Vector<f32, 2>>(&self) -> V {
735        unsafe {
736            let mut result = Default::default();
737
738            asm! {
739                "%u32 = OpTypeInt 32 0",
740                "%intersection = OpConstant %u32 0",
741                "%result = OpRayQueryGetIntersectionBarycentricsKHR typeof*{result} {ray_query} %intersection",
742                "OpStore {result} %result",
743                ray_query = in(reg) self,
744                result = in(reg) &mut result,
745            }
746
747            result
748        }
749    }
750
751    /// Gets the second and third barycentric coordinates of the current
752    /// intersection considered in a ray query against the primitive it hit.
753    ///
754    /// There must be a current committed intersection. Its
755    /// [`Self::get_committed_intersection_type()`] must be [`CommittedIntersection::Triangle`].
756    ///
757    /// TODO: Improve docs. Can't right now due to
758    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
759    #[spirv_std_macros::gpu_only]
760    #[doc(alias = "OpRayQueryGetIntersectionBarycentricsKHR")]
761    #[inline]
762    pub unsafe fn get_committed_intersection_barycentrics<V: Vector<f32, 2>>(&self) -> V {
763        unsafe {
764            let mut result = Default::default();
765
766            asm! {
767                "%u32 = OpTypeInt 32 0",
768                "%intersection = OpConstant %u32 1",
769                "%result = OpRayQueryGetIntersectionBarycentricsKHR typeof*{result} {ray_query} %intersection",
770                "OpStore {result} %result",
771                ray_query = in(reg) self,
772                result = in(reg) &mut result,
773            }
774
775            result
776        }
777    }
778
779    /// Returns whether the current intersection considered in a ray query was with
780    /// the front face (`true`) or back face (`false`) of a primitive.
781    ///
782    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
783    /// The current intersection candidate must have a [`Self::get_candidate_intersection_type()`]
784    /// of [`CandidateIntersection::Triangle`].
785    #[spirv_std_macros::gpu_only]
786    #[doc(alias = "OpRayQueryGetIntersectionFrontFaceKHR")]
787    #[inline]
788    pub unsafe fn get_candidate_intersection_front_face(&self) -> bool {
789        unsafe {
790            let mut result = false;
791
792            asm! {
793                "%bool = OpTypeBool",
794                "%u32 = OpTypeInt 32 0",
795                "%intersection = OpConstant %u32 0",
796                "%result = OpRayQueryGetIntersectionFrontFaceKHR %bool {ray_query} %intersection",
797                "OpStore {result} %result",
798                ray_query = in(reg) self,
799                result = in(reg) &mut result,
800            }
801
802            result
803        }
804    }
805
806    /// Returns whether the current intersection considered in a ray query was with
807    /// the front face (`true`) or back face (`false`) of a primitive.
808    ///
809    /// There must be a current committed intersection. Its
810    /// [`Self::get_committed_intersection_type()`] must be [`CommittedIntersection::Triangle`].
811    ///
812    /// TODO: Improve docs. Can't right now due to
813    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
814    #[spirv_std_macros::gpu_only]
815    #[doc(alias = "OpRayQueryGetIntersectionFrontFaceKHR")]
816    #[inline]
817    pub unsafe fn get_committed_intersection_front_face(&self) -> bool {
818        unsafe {
819            let mut result = false;
820
821            asm! {
822                "%bool = OpTypeBool",
823                "%u32 = OpTypeInt 32 0",
824                "%intersection = OpConstant %u32 1",
825                "%result = OpRayQueryGetIntersectionFrontFaceKHR %bool {ray_query} %intersection",
826                "OpStore {result} %result",
827                ray_query = in(reg) self,
828                result = in(reg) &mut result,
829            }
830
831            result
832        }
833    }
834
835    /// Returns whether a candidate intersection considered in a ray query was with
836    /// an opaque AABB (Axis Aligned Bounding Box) or not.
837    #[spirv_std_macros::gpu_only]
838    #[doc(alias = "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR")]
839    #[inline]
840    pub unsafe fn get_intersection_candidate_aabb_opaque(&self) -> bool {
841        unsafe {
842            let mut result = false;
843
844            asm! {
845                "%bool = OpTypeBool",
846                "%result = OpRayQueryGetIntersectionCandidateAABBOpaqueKHR %bool {ray_query}",
847                "OpStore {result} %result",
848                ray_query = in(reg) self,
849                result = in(reg) &mut result,
850            }
851
852            result
853        }
854    }
855
856    /// Gets the object-space ray direction for the current intersection considered
857    /// in a ray query.
858    ///
859    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
860    #[spirv_std_macros::gpu_only]
861    #[doc(alias = "OpRayQueryGetIntersectionObjectRayDirectionKHR")]
862    #[inline]
863    pub unsafe fn get_candidate_intersection_object_ray_direction<V: Vector<f32, 3>>(&self) -> V {
864        unsafe {
865            let mut result = Default::default();
866
867            asm! {
868                "%u32 = OpTypeInt 32 0",
869                "%intersection = OpConstant %u32 0",
870                "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR typeof*{result} {ray_query} %intersection",
871                "OpStore {result} %result",
872                ray_query = in(reg) self,
873                result = in(reg) &mut result,
874            }
875
876            result
877        }
878    }
879
880    /// Gets the object-space ray direction for the current intersection considered
881    /// in a ray query.
882    ///
883    /// There must be a current committed intersection.
884    ///
885    /// TODO: Improve docs. Can't right now due to
886    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
887    #[spirv_std_macros::gpu_only]
888    #[doc(alias = "OpRayQueryGetIntersectionObjectRayDirectionKHR")]
889    #[inline]
890    pub unsafe fn get_committed_intersection_object_ray_direction<V: Vector<f32, 3>>(&self) -> V {
891        unsafe {
892            let mut result = Default::default();
893
894            asm! {
895                "%u32 = OpTypeInt 32 0",
896                "%intersection = OpConstant %u32 1",
897                "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR typeof*{result} {ray_query} %intersection",
898                "OpStore {result} %result",
899                ray_query = in(reg) self,
900                result = in(reg) &mut result,
901            }
902
903            result
904        }
905    }
906
907    /// Gets the object-space ray origin for the current intersection considered in
908    /// a ray query.
909    ///
910    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
911    #[spirv_std_macros::gpu_only]
912    #[doc(alias = "OpRayQueryGetIntersectionObjectRayOriginKHR")]
913    #[inline]
914    pub unsafe fn get_candidate_intersection_object_ray_origin<V: Vector<f32, 3>>(&self) -> V {
915        unsafe {
916            let mut result = Default::default();
917
918            asm! {
919                "%u32 = OpTypeInt 32 0",
920                "%intersection = OpConstant %u32 0",
921                "%result = OpRayQueryGetIntersectionObjectRayOriginKHR typeof*{result} {ray_query} %intersection",
922                "OpStore {result} %result",
923                ray_query = in(reg) self,
924                result = in(reg) &mut result,
925            }
926
927            result
928        }
929    }
930
931    /// Gets the object-space ray origin for the current intersection considered in
932    /// a ray query.
933    ///
934    /// There must be a current committed intersection.
935    ///
936    /// TODO: Improve docs. Can't right now due to
937    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
938    #[spirv_std_macros::gpu_only]
939    #[doc(alias = "OpRayQueryGetIntersectionObjectRayOriginKHR")]
940    #[inline]
941    pub unsafe fn get_committed_intersection_object_ray_origin<V: Vector<f32, 3>>(&self) -> V {
942        unsafe {
943            let mut result = Default::default();
944
945            asm! {
946                "%u32 = OpTypeInt 32 0",
947                "%intersection = OpConstant %u32 1",
948                "%result = OpRayQueryGetIntersectionObjectRayOriginKHR typeof*{result} {ray_query} %intersection",
949                "OpStore {result} %result",
950                ray_query = in(reg) self,
951                result = in(reg) &mut result,
952            }
953
954            result
955        }
956    }
957
958    /// Gets the world-space direction for the ray traced in a ray query.
959    #[spirv_std_macros::gpu_only]
960    #[doc(alias = "OpRayQueryGetWorldRayDirectionKHR")]
961    #[inline]
962    pub unsafe fn get_world_ray_direction<V: Vector<f32, 3>>(&self) -> V {
963        unsafe {
964            let mut result = Default::default();
965
966            asm! {
967                "%u32 = OpTypeInt 32 0",
968                "%result = OpRayQueryGetWorldRayDirectionKHR typeof*{result} {ray_query}",
969                "OpStore {result} %result",
970                ray_query = in(reg) self,
971                result = in(reg) &mut result,
972            }
973
974            result
975        }
976    }
977
978    /// Gets the world-space origin for the ray traced in a ray query.
979    #[spirv_std_macros::gpu_only]
980    #[doc(alias = "OpRayQueryGetWorldRayOriginKHR")]
981    #[inline]
982    pub unsafe fn get_world_ray_origin<V: Vector<f32, 3>>(&self) -> V {
983        unsafe {
984            let mut result = Default::default();
985
986            asm! {
987                "%u32 = OpTypeInt 32 0",
988                "%result = OpRayQueryGetWorldRayOriginKHR typeof*{result} {ray_query}",
989                "OpStore {result} %result",
990                ray_query = in(reg) self,
991                result = in(reg) &mut result,
992            }
993
994            result
995        }
996    }
997
998    /// Gets a matrix that transforms values to world-space from the object-space of
999    /// the current intersection considered in a ray query.
1000    ///
1001    /// [`Self::proceed()`] must have been called on this object, and it must have returned true.
1002    #[spirv_std_macros::gpu_only]
1003    #[doc(alias = "OpRayQueryGetIntersectionObjectToWorldKHR")]
1004    #[inline]
1005    pub unsafe fn get_candidate_intersection_object_to_world<V: Vector<f32, 3>>(&self) -> [V; 4] {
1006        unsafe {
1007            let mut result = Default::default();
1008
1009            asm! {
1010                "%u32 = OpTypeInt 32 0",
1011                "%f32 = OpTypeFloat 32",
1012                "%f32x3 = OpTypeVector %f32 3",
1013                "%f32x3x4 = OpTypeMatrix %f32x3 4",
1014                "%intersection = OpConstant %u32 0",
1015                "%matrix = OpRayQueryGetIntersectionObjectToWorldKHR %f32x3x4 {ray_query} %intersection",
1016                "%col0 = OpCompositeExtract %f32x3 %matrix 0",
1017                "%col1 = OpCompositeExtract %f32x3 %matrix 1",
1018                "%col2 = OpCompositeExtract %f32x3 %matrix 2",
1019                "%col3 = OpCompositeExtract %f32x3 %matrix 3",
1020                "%result = OpCompositeConstruct typeof*{result} %col0 %col1 %col2 %col3",
1021                "OpStore {result} %result",
1022                ray_query = in(reg) self,
1023                result = in(reg) &mut result,
1024            }
1025
1026            result
1027        }
1028    }
1029
1030    /// Gets a matrix that transforms values to world-space from the object-space of
1031    /// the current intersection considered in a ray query.
1032    ///
1033    /// There must be a current committed intersection.
1034    ///
1035    /// TODO: Improve docs. Can't right now due to
1036    /// <https://github.com/KhronosGroup/SPIRV-Registry/issues/128>
1037    #[spirv_std_macros::gpu_only]
1038    #[doc(alias = "OpRayQueryGetIntersectionObjectToWorldKHR")]
1039    #[inline]
1040    pub unsafe fn get_committed_intersection_object_to_world<V: Vector<f32, 3>>(&self) -> [V; 4] {
1041        unsafe {
1042            let mut result = Default::default();
1043
1044            asm! {
1045                "%u32 = OpTypeInt 32 0",
1046                "%f32 = OpTypeFloat 32",
1047                "%f32x3 = OpTypeVector %f32 3",
1048                "%f32x3x4 = OpTypeMatrix %f32x3 4",
1049                "%intersection = OpConstant %u32 1",
1050                "%matrix = OpRayQueryGetIntersectionObjectToWorldKHR %f32x3x4 {ray_query} %intersection",
1051                "%col0 = OpCompositeExtract %f32x3 %matrix 0",
1052                "%col1 = OpCompositeExtract %f32x3 %matrix 1",
1053                "%col2 = OpCompositeExtract %f32x3 %matrix 2",
1054                "%col3 = OpCompositeExtract %f32x3 %matrix 3",
1055                "%result = OpCompositeConstruct typeof*{result} %col0 %col1 %col2 %col3",
1056                "OpStore {result} %result",
1057                ray_query = in(reg) self,
1058                result = in(reg) &mut result,
1059            }
1060
1061            result
1062        }
1063    }
1064}