spirv_std/
ray_tracing.rs

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