From 9ab308310bb36fef59b85bb4a7d85166ca5874de Mon Sep 17 00:00:00 2001 From: Erin Power Date: Wed, 31 Mar 2021 11:13:02 +0200 Subject: [PATCH] Add support for SPV_KHR_ray_tracing --- Cargo.lock | 23 +-- crates/rustc_codegen_spirv/Cargo.toml | 2 +- crates/rustc_codegen_spirv/src/abi.rs | 3 + crates/rustc_codegen_spirv/src/attr.rs | 1 + .../src/builder/builder_methods.rs | 6 + .../src/codegen_cx/constant.rs | 4 + .../src/codegen_cx/type_.rs | 8 +- .../src/linker/new_structurizer.rs | 7 +- .../src/linker/simple_passes.rs | 7 +- crates/rustc_codegen_spirv/src/spirv_type.rs | 16 +- .../src/spirv_type_constraints.rs | 6 +- crates/rustc_codegen_spirv/src/symbols.rs | 45 ++--- crates/spirv-std/src/arch.rs | 2 + crates/spirv-std/src/arch/ray_tracing.rs | 174 ++++++++++++++++++ crates/spirv-std/src/lib.rs | 1 + crates/spirv-std/src/ray_tracing.rs | 9 + ...convert_u_to_acceleration_structure_khr.rs | 23 +++ tests/ui/arch/ignore_intersection_khr.rs | 10 + tests/ui/arch/report_intersection_khr.rs | 10 + tests/ui/arch/terminate_ray_khr.rs | 10 + tests/ui/arch/trace_ray_khr.rs | 28 +++ .../sample_gradient.rs | 4 +- 22 files changed, 353 insertions(+), 46 deletions(-) create mode 100644 crates/spirv-std/src/arch/ray_tracing.rs create mode 100644 crates/spirv-std/src/ray_tracing.rs create mode 100644 tests/ui/arch/convert_u_to_acceleration_structure_khr.rs create mode 100644 tests/ui/arch/ignore_intersection_khr.rs create mode 100644 tests/ui/arch/report_intersection_khr.rs create mode 100644 tests/ui/arch/terminate_ray_khr.rs create mode 100644 tests/ui/arch/trace_ray_khr.rs diff --git a/Cargo.lock b/Cargo.lock index e36d4bdca6..247f6e72c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1311,9 +1311,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" +checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" [[package]] name = "libloading" @@ -1899,9 +1899,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] @@ -2077,12 +2077,12 @@ dependencies = [ [[package]] name = "rspirv" version = "0.7.0" -source = "git+https://github.com/gfx-rs/rspirv.git?rev=ee1e913#ee1e9135845409b2a096d880286c865c4e2ac3d6" +source = "git+https://github.com/gfx-rs/rspirv.git?rev=719cf08#719cf08e4af0436242707479e3509add5ec3d514" dependencies = [ "derive_more", "fxhash", "num-traits", - "spirv_headers 1.5.0 (git+https://github.com/gfx-rs/rspirv.git?rev=ee1e913)", + "spirv_headers 1.5.0 (git+https://github.com/gfx-rs/rspirv.git?rev=719cf08)", ] [[package]] @@ -2394,7 +2394,7 @@ dependencies = [ [[package]] name = "spirv_headers" version = "1.5.0" -source = "git+https://github.com/gfx-rs/rspirv.git?rev=ee1e913#ee1e9135845409b2a096d880286c865c4e2ac3d6" +source = "git+https://github.com/gfx-rs/rspirv.git?rev=719cf08#719cf08e4af0436242707479e3509add5ec3d514" dependencies = [ "bitflags", "num-traits", @@ -2484,9 +2484,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.67" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663" dependencies = [ "proc-macro2", "quote", @@ -2926,9 +2926,9 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c60007fc3748278a36b458d96f86105f43aa5f0e412b15a5f934950d61ec26a9" +checksum = "79a0a0a63fac9492cfaf6e7e4bdf9729c128f1e94124b9e4cbc4004b8cb6d1d8" dependencies = [ "arrayvec", "js-sys", @@ -2936,6 +2936,7 @@ dependencies = [ "parking_lot", "raw-window-handle", "smallvec", + "syn", "tracing", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/crates/rustc_codegen_spirv/Cargo.toml b/crates/rustc_codegen_spirv/Cargo.toml index 6651279ff1..a71107b686 100644 --- a/crates/rustc_codegen_spirv/Cargo.toml +++ b/crates/rustc_codegen_spirv/Cargo.toml @@ -37,7 +37,7 @@ syn = { version = "1", features = ["visit", "visit-mut"] } # Normal dependencies. bimap = "0.6" indexmap = "1.6.0" -rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "ee1e913" } +rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "719cf08" } rustc-demangle = "0.1.18" sanitize-filename = "0.3" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index afaf928f95..1c841ec397 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -825,6 +825,9 @@ fn trans_intrinsic_type<'tcx>( } Ok(SpirvType::Sampler.def(span, cx)) } + IntrinsicType::AccelerationStructureKhr => { + Ok(SpirvType::AccelerationStructureKhr.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 43f2b782ab..812c9be515 100644 --- a/crates/rustc_codegen_spirv/src/attr.rs +++ b/crates/rustc_codegen_spirv/src/attr.rs @@ -71,6 +71,7 @@ pub enum IntrinsicType { access_qualifier: Option, }, Sampler, + AccelerationStructureKhr, SampledImage, } diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 192a63544d..3ad83944d6 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -232,6 +232,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { SpirvType::Image { .. } => self.fatal("cannot memset image"), SpirvType::Sampler => self.fatal("cannot memset sampler"), SpirvType::SampledImage { .. } => self.fatal("cannot memset sampled image"), + SpirvType::AccelerationStructureKhr => { + self.fatal("cannot memset acceleration structure") + } } } @@ -288,6 +291,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { SpirvType::Image { .. } => self.fatal("cannot memset image"), SpirvType::Sampler => self.fatal("cannot memset sampler"), SpirvType::SampledImage { .. } => self.fatal("cannot memset sampled image"), + SpirvType::AccelerationStructureKhr => { + self.fatal("cannot memset acceleration structure") + } } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 99a353f402..ae14ece394 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -524,6 +524,10 @@ impl<'tcx> CodegenCx<'tcx> { .tcx .sess .fatal("Cannot create a constant sampled image value"), + SpirvType::AccelerationStructureKhr => self + .tcx + .sess + .fatal("Cannot create a constant acceleration structure"), } } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index eb45cc3ba6..0ea15db945 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -174,9 +174,11 @@ impl<'tcx> BaseTypeMethods<'tcx> for CodegenCx<'tcx> { SpirvType::Function { .. } => TypeKind::Function, // HACK(eddyb) this is probably the closest `TypeKind` (which is still // very much LLVM-specific, sadly) has to offer to "resource handle". - SpirvType::Image { .. } | - SpirvType::Sampler | - SpirvType::SampledImage { .. } => TypeKind::Token, + | SpirvType::Image { .. } + | SpirvType::Sampler + | SpirvType::SampledImage { .. } + | SpirvType::AccelerationStructureKhr + => TypeKind::Token, } } fn type_ptr_to(&self, ty: Self::Type) -> Self::Type { diff --git a/crates/rustc_codegen_spirv/src/linker/new_structurizer.rs b/crates/rustc_codegen_spirv/src/linker/new_structurizer.rs index d36a2b175c..09a6b26141 100644 --- a/crates/rustc_codegen_spirv/src/linker/new_structurizer.rs +++ b/crates/rustc_codegen_spirv/src/linker/new_structurizer.rs @@ -168,7 +168,12 @@ impl Structurizer<'_> { let block_id = self.func.blocks()[block].label_id().unwrap(); let terminator = self.func.blocks()[block].instructions.last().unwrap(); let mut region = match terminator.class.opcode { - Op::Return | Op::ReturnValue | Op::Kill | Op::Unreachable => Region { + Op::Return + | Op::ReturnValue + | Op::Kill + | Op::IgnoreIntersectionKHR + | Op::TerminateRayKHR + | Op::Unreachable => Region { merge: block, merge_id: block_id, exits: indexmap! {}, diff --git a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs index 70eed5d48a..d91199f821 100644 --- a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs +++ b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs @@ -98,7 +98,12 @@ pub fn outgoing_edges(block: &Block) -> Vec { .map(|op| op.unwrap_id_ref()), ) .collect(), - Op::Return | Op::ReturnValue | Op::Kill | Op::Unreachable => Vec::new(), + Op::Return + | Op::ReturnValue + | Op::Kill + | Op::Unreachable + | Op::IgnoreIntersectionKHR + | Op::TerminateRayKHR => Vec::new(), _ => panic!("Invalid block terminator: {:?}", terminator), } } diff --git a/crates/rustc_codegen_spirv/src/spirv_type.rs b/crates/rustc_codegen_spirv/src/spirv_type.rs index 098147ed3c..c195d52765 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type.rs @@ -80,6 +80,7 @@ pub enum SpirvType { SampledImage { image_type: Word, }, + AccelerationStructureKhr, } impl SpirvType { @@ -247,6 +248,7 @@ impl SpirvType { access_qualifier, ), Self::Sampler => cx.emit_global().type_sampler(), + Self::AccelerationStructureKhr => cx.emit_global().type_acceleration_structure_khr(), Self::SampledImage { image_type } => cx.emit_global().type_sampled_image(image_type), }; cx.type_cache.def(result, self); @@ -320,7 +322,8 @@ impl SpirvType { Self::Void | Self::Opaque { .. } | Self::RuntimeArray { .. } - | Self::Function { .. } => return None, + | Self::Function { .. } + | Self::AccelerationStructureKhr => return None, Self::Bool => Size::from_bytes(1), Self::Integer(width, _) | Self::Float(width) => Size::from_bits(width), @@ -340,9 +343,10 @@ impl SpirvType { pub fn alignof<'tcx>(&self, cx: &CodegenCx<'tcx>) -> Align { match *self { // Types that have no concept of size or alignment. - Self::Void | Self::Opaque { .. } | Self::Function { .. } => { - Align::from_bytes(0).unwrap() - } + Self::Void + | Self::Opaque { .. } + | Self::Function { .. } + | Self::AccelerationStructureKhr => Align::from_bytes(0).unwrap(), Self::Bool => Align::from_bytes(1).unwrap(), Self::Integer(width, _) | Self::Float(width) => Align::from_bits(width as u64).unwrap(), @@ -499,6 +503,9 @@ impl fmt::Debug for SpirvTypePrinter<'_, '_> { .field("id", &self.id) .field("image_type", &self.cx.debug_type(image_type)) .finish(), + SpirvType::AccelerationStructureKhr => { + f.debug_struct("AccelerationStructureKhr").finish() + } }; { let mut debug_stack = DEBUG_STACK.lock().unwrap(); @@ -654,6 +661,7 @@ impl SpirvTypePrinter<'_, '_> { .debug_struct("SampledImage") .field("image_type", &self.cx.debug_type(image_type)) .finish(), + SpirvType::AccelerationStructureKhr => f.write_str("AccelerationStructureKhr"), } } } diff --git a/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs b/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs index 17edcdc84f..5519a77759 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type_constraints.rs @@ -727,7 +727,7 @@ pub fn instruction_signatures(op: Op) -> Option<&'static [InstSig<'static>]> { | Op::ExecuteCallableKHR | Op::ConvertUToAccelerationStructureKHR | Op::IgnoreIntersectionKHR - | Op::TerminateRayKHR => reserved!(SPV_KHR_ray_tracing), + | Op::TerminateRayKHR => {} // SPV_KHR_ray_query Op::TypeRayQueryKHR | Op::RayQueryInitializeKHR @@ -735,7 +735,7 @@ pub fn instruction_signatures(op: Op) -> Option<&'static [InstSig<'static>]> { | Op::RayQueryGenerateIntersectionKHR | Op::RayQueryConfirmIntersectionKHR | Op::RayQueryProceedKHR - | Op::RayQueryGetIntersectionTypeKHR => reserved!(SPV_KHR_ray_query), + | Op::RayQueryGetIntersectionTypeKHR => {} // SPV_AMD_shader_fragment_mask Op::FragmentMaskFetchAMD | Op::FragmentFetchAMD => reserved!(SPV_AMD_shader_fragment_mask), // SPV_KHR_shader_clock @@ -748,7 +748,7 @@ pub fn instruction_signatures(op: Op) -> Option<&'static [InstSig<'static>]> { | Op::TerminateRayNV | Op::TraceNV | Op::TypeAccelerationStructureNV - | Op::ExecuteCallableNV => reserved!(SPV_NV_ray_tracing), + | Op::ExecuteCallableNV => {} // SPV_NV_cooperative_matrix Op::TypeCooperativeMatrixNV | Op::CooperativeMatrixLoadNV diff --git a/crates/rustc_codegen_spirv/src/symbols.rs b/crates/rustc_codegen_spirv/src/symbols.rs index af99e12ae7..71bab257f2 100644 --- a/crates/rustc_codegen_spirv/src/symbols.rs +++ b/crates/rustc_codegen_spirv/src/symbols.rs @@ -129,21 +129,20 @@ const BUILTINS: &[(&str, BuiltIn)] = { ("bary_coord_no_persp_nv", BaryCoordNoPerspNV), ("frag_size_ext", FragSizeEXT), ("frag_invocation_count_ext", FragInvocationCountEXT), - ("launch_id_nv", LaunchIdNV), - ("launch_size_nv", LaunchSizeNV), - ("world_ray_origin_nv", WorldRayOriginNV), - ("world_ray_direction_nv", WorldRayDirectionNV), - ("object_ray_origin_nv", ObjectRayOriginNV), - ("object_ray_direction_nv", ObjectRayDirectionNV), - ("ray_tmin_nv", RayTminNV), - ("ray_tmax_nv", RayTmaxNV), - ("instance_custom_index_nv", InstanceCustomIndexNV), - ("object_to_world_nv", ObjectToWorldNV), - ("world_to_object_nv", WorldToObjectNV), - ("hit_t_nv", HitTNV), - ("hit_kind_nv", HitKindNV), - ("incoming_ray_flags_nv", IncomingRayFlagsNV), - ("ray_geometry_index_khr", RayGeometryIndexKHR), + ("launch_id_khr", BuiltIn::LaunchIdKHR), + ("launch_size_khr", BuiltIn::LaunchSizeKHR), + ("instance_custom_index_khr", BuiltIn::InstanceCustomIndexKHR), + ("ray_geometry_index_khr", BuiltIn::RayGeometryIndexKHR), + ("world_ray_origin_khr", BuiltIn::WorldRayOriginKHR), + ("world_ray_direction_khr", BuiltIn::WorldRayDirectionKHR), + ("object_ray_origin_khr", BuiltIn::ObjectRayOriginKHR), + ("object_ray_direction_khr", BuiltIn::ObjectRayDirectionKHR), + ("ray_tmin_khr", BuiltIn::RayTminKHR), + ("ray_tmax_khr", BuiltIn::RayTmaxKHR), + ("object_to_world_khr", BuiltIn::ObjectToWorldKHR), + ("world_to_object_khr", BuiltIn::WorldToObjectKHR), + ("hit_kind_khr", BuiltIn::HitKindKHR), + ("incoming_ray_flags_khr", BuiltIn::IncomingRayFlagsKHR), ("warps_per_sm_nv", WarpsPerSMNV), ("sm_count_nv", SMCountNV), ("warp_id_nv", WarpIDNV), @@ -198,12 +197,12 @@ const EXECUTION_MODELS: &[(&str, ExecutionModel)] = { ("kernel", Kernel), ("task_nv", TaskNV), ("mesh_nv", MeshNV), - ("ray_generation_nv", RayGenerationNV), - ("intersection_nv", IntersectionNV), - ("any_hit_nv", AnyHitNV), - ("closest_hit_nv", ClosestHitNV), - ("miss_nv", MissNV), - ("callable_nv", CallableNV), + ("ray_generation_khr", RayGenerationNV), + ("intersection_khr", IntersectionNV), + ("any_hit_khr", AnyHitNV), + ("closest_hit_khr", ClosestHitNV), + ("miss_khr", MissNV), + ("callable_khr", CallableNV), ] }; @@ -334,6 +333,10 @@ impl Symbols { "sampler", SpirvAttribute::IntrinsicType(IntrinsicType::Sampler), ), + ( + "acceleration_structure_khr", + SpirvAttribute::IntrinsicType(IntrinsicType::AccelerationStructureKhr), + ), ("block", SpirvAttribute::Block), ("flat", SpirvAttribute::Flat), ("invariant", SpirvAttribute::Invariant), diff --git a/crates/spirv-std/src/arch.rs b/crates/spirv-std/src/arch.rs index 49b3a096aa..6044043c23 100644 --- a/crates/spirv-std/src/arch.rs +++ b/crates/spirv-std/src/arch.rs @@ -8,10 +8,12 @@ use crate::{scalar::Scalar, vector::Vector}; mod arithmetic; mod derivative; mod primitive; +mod ray_tracing; pub use arithmetic::*; pub use derivative::*; pub use primitive::*; +pub use ray_tracing::*; /// Result is true if any component of `vector` is true, otherwise result is /// false. diff --git a/crates/spirv-std/src/arch/ray_tracing.rs b/crates/spirv-std/src/arch/ray_tracing.rs new file mode 100644 index 0000000000..e3a30c2ebd --- /dev/null +++ b/crates/spirv-std/src/arch/ray_tracing.rs @@ -0,0 +1,174 @@ +use crate::{ray_tracing::*, vector::Vector}; + +/// Converts a 64-bit integer into an [`AccelerationStructureKHR`]. +/// # Safety +/// The 64-bit integer must point to a valid acceleration structure. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpConvertUToAccelerationStructureKHR")] +#[inline] +pub unsafe fn convert_u_to_acceleration_structure_khr(id: u64) -> AccelerationStructureKhr { + // Since we can't represent an uninitalized opaque type in Rust at the + // moment, we need to create and return the acceleration structure entirely + // in assembly. + asm! { + "%ret = OpTypeAccelerationStructureKHR", + "%result = OpConvertUToAccelerationStructureKHR %ret {id}", + "OpReturnValue %result", + "%blah = OpLabel", + id = in(reg) id, + } + loop {} +} + +/// Trace a ray into the acceleration structure. +/// +/// - `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 are used by this instruction - other bits +/// are ignored. +/// - `sbt_offset` and `sbt_stride` control indexing into the SBT (Shader +/// Binding Table) for hit shaders called from this trace. Only the 4 +/// least-significant bits of `sbt_offset` and `sbt_stride` are used by this +/// instruction - other bits are ignored. +/// - `miss_index` is the index of the miss shader to be called from this +/// trace call. Only the 16 least-significant bits 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. +/// +/// - `payload` is a pointer to the ray payload structure to use for this trace. +/// `payload` must have a storage class of `ray_payload_khr` +/// or `incoming_ray_payload_khr`. +/// +/// This instruction is allowed only in `ray_generation_khr`, `closest_hit_khr` and +/// `miss_khr` execution models. +/// +/// This instruction is a shader call instruction which may invoke shaders with +/// the `intersection_khr`, `any_hit_khr`, `closest_hit_khr`, and `miss_khr` +/// execution models. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpTraceRayKHR")] +#[inline] +#[allow(clippy::too_many_arguments)] +pub unsafe fn trace_ray_khr( + acceleration_structure: AccelerationStructureKhr, + ray_flags: i32, + cull_mask: i32, + sbt_offset: i32, + sbt_stride: i32, + miss_index: i32, + ray_origin: impl Vector, + ray_tmin: f32, + ray_direction: impl Vector, + ray_tmax: f32, + payload: &mut T, +) { + asm! { + "OpTraceRayKHR \ + {acceleration_structure} \ + {ray_flags} \ + {cull_mask} \ + {sbt_offset} \ + {sbt_stride} \ + {miss_index} \ + {ray_origin} \ + {ray_tmin} \ + {ray_direction} \ + {ray_tmax} \ + {payload}", + acceleration_structure = in(reg) &acceleration_structure, + ray_flags = in(reg) ray_flags, + cull_mask = in(reg) cull_mask, + sbt_offset = in(reg) sbt_offset, + sbt_stride = in(reg) sbt_stride, + miss_index = in(reg) miss_index, + ray_origin = in(reg) &ray_origin, + ray_tmin = in(reg) ray_tmin, + ray_direction = in(reg) &ray_direction, + ray_tmax = in(reg) ray_tmax, + payload = in(reg) payload, + } +} + +/// Reports an intersection back to the traversal infrastructure. +/// +/// If the intersection occurred within the current ray interval, the +/// intersection confirmation is performed (see the API specification for more +/// details). If the value of Hit falls outside the current ray interval, the +/// hit is rejected. +/// +/// Returns True if the hit was accepted by the ray interval and the intersection was confirmed. Returns False otherwise. +/// +/// - `hit` is the floating point parametric value along ray for the intersection. +/// - `hit_kind` is the integer hit kind reported back to other shaders and +/// accessible by the `hit kind` builtin. +/// +/// This instruction is allowed only in IntersectionKHR execution model. +/// +/// This instruction is a shader call instruction which may invoke shaders with +/// the `any_hit_khr` execution model. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpReportIntersectionKHR")] +#[inline] +pub unsafe fn report_intersection_khr(hit: f32, hit_kind: u32) -> bool { + let mut result: u8 = 0; + + asm! { + "%bool = OpTypeBool", + "%u8 = OpTypeInt 8 0", + "%result = OpReportIntersectionKHR %u8 {hit} {hit_kind}", + "OpStore {result} %result", + result = in(reg) &mut result, + hit = in(reg) hit, + hit_kind = in(reg) hit_kind, + }; + + result != 0 +} + +/// Ignores the current potential intersection, terminating the invocation that +/// executes it, and continues the ray traversal. This instruction is allowed +/// only in `any_hit_khr` execution model. This instruction must be the last +/// instruction in a block. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpIgnoreIntersectionKHR")] +#[inline] +pub unsafe fn ignore_intersection_khr() { + asm!("OpIgnoreIntersectionKHR", "%unused = OpLabel") +} + +/// Terminates the invocation that executes it, stops the ray traversal, accepts +/// the current hit, and invokes the `closest_hit_khr` execution model +/// (if active). This instruction is allowed only in the `any_hit_khr` +/// execution model. This instruction must be the last instruction in a block. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpTerminateRayKHR")] +#[inline] +pub unsafe fn terminate_ray_khr() { + asm!("OpTerminateRayKHR", "%unused = OpLabel") +} + +/// Invoke a callable shader. +/// +/// - `INDEX` is the index into the SBT table to select callable shader +/// to execute. +/// - `data` is a pointer to the callable data to pass into the called shader. +/// `data` must have a storage class of `callable_data_khr` +/// or `incoming_callable_data_khr`. +/// +/// This instruction is allowed only in `ray_generation_khr`, `closest_hit_khr`, +/// `miss_khr` and `callable_khr` execution models. +/// +/// This instruction is a shader call instruction which will invoke a shader +/// with the `callable_khr` execution model. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpExecuteCallableKHR")] +#[inline] +pub unsafe fn execute_callable_khr(data: &T) { + asm! { + "OpExecuteCallableKHR {id} {data}", + id = const ID, + data = in(reg) data, + }; +} diff --git a/crates/spirv-std/src/lib.rs b/crates/spirv-std/src/lib.rs index ed904e8555..8bdb344a3b 100644 --- a/crates/spirv-std/src/lib.rs +++ b/crates/spirv-std/src/lib.rs @@ -72,6 +72,7 @@ pub extern crate spirv_std_macros as macros; pub mod arch; pub mod float; pub mod integer; +pub mod ray_tracing; pub mod scalar; pub(crate) mod sealed; mod textures; diff --git a/crates/spirv-std/src/ray_tracing.rs b/crates/spirv-std/src/ray_tracing.rs new file mode 100644 index 0000000000..65a3625f41 --- /dev/null +++ b/crates/spirv-std/src/ray_tracing.rs @@ -0,0 +1,9 @@ +//! Ray-tracing data types + +/// An acceleration structure type which is an opaque reference to an +/// acceleration structure handle as defined in the client API specification. +#[spirv(acceleration_structure_khr)] +#[derive(Copy, Clone)] +pub struct AccelerationStructureKhr { + pub(crate) _private: u32, +} diff --git a/tests/ui/arch/convert_u_to_acceleration_structure_khr.rs b/tests/ui/arch/convert_u_to_acceleration_structure_khr.rs new file mode 100644 index 0000000000..d3b33cf075 --- /dev/null +++ b/tests/ui/arch/convert_u_to_acceleration_structure_khr.rs @@ -0,0 +1,23 @@ +// build-pass + +#[spirv(ray_generation_khr)] +pub fn main(#[spirv(ray_payload_khr)] payload: &mut glam::Vec3) { + unsafe { + let handle = spirv_std::arch::convert_u_to_acceleration_structure_khr(0xffff_ffff); + asm!(r#"OpExtension "SPV_KHR_ray_tracing""#); + asm!("OpCapability RayTracingKHR"); + spirv_std::arch::trace_ray_khr( + handle, + 0, + 0, + 0, + 0, + 0, + glam::vec3(1.0, 2.0, 3.0), + 0.5, + glam::vec3(3.0, 2.0, 1.0), + 1.0, + payload, + ); + } +} diff --git a/tests/ui/arch/ignore_intersection_khr.rs b/tests/ui/arch/ignore_intersection_khr.rs new file mode 100644 index 0000000000..f5057f971f --- /dev/null +++ b/tests/ui/arch/ignore_intersection_khr.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(any_hit_khr)] +pub fn main() { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_tracing""#); + asm!("OpCapability RayTracingKHR"); + spirv_std::arch::ignore_intersection_khr(); + } +} diff --git a/tests/ui/arch/report_intersection_khr.rs b/tests/ui/arch/report_intersection_khr.rs new file mode 100644 index 0000000000..09ef97a634 --- /dev/null +++ b/tests/ui/arch/report_intersection_khr.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(intersection_khr)] +pub fn main() { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_tracing""#); + asm!("OpCapability RayTracingKHR"); + spirv_std::arch::report_intersection_khr(2.0, 4); + } +} diff --git a/tests/ui/arch/terminate_ray_khr.rs b/tests/ui/arch/terminate_ray_khr.rs new file mode 100644 index 0000000000..d914bdb036 --- /dev/null +++ b/tests/ui/arch/terminate_ray_khr.rs @@ -0,0 +1,10 @@ +// build-pass + +#[spirv(any_hit_khr)] +pub fn main() { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_tracing""#); + asm!("OpCapability RayTracingKHR"); + spirv_std::arch::terminate_ray_khr(); + } +} diff --git a/tests/ui/arch/trace_ray_khr.rs b/tests/ui/arch/trace_ray_khr.rs new file mode 100644 index 0000000000..88abae0c94 --- /dev/null +++ b/tests/ui/arch/trace_ray_khr.rs @@ -0,0 +1,28 @@ +// build-pass + +#[spirv(ray_generation_khr)] +// Rustfmt will eat long attributes (https://github.com/rust-lang/rustfmt/issues/4579) +#[rustfmt::skip] +pub fn main( + #[spirv(uniform_constant, descriptor_set = 0, binding = 0)] + acceleration_structure: &spirv_std::ray_tracing::AccelerationStructureKhr, + #[spirv(ray_payload_khr)] payload: &mut glam::Vec3, +) { + unsafe { + asm!(r#"OpExtension "SPV_KHR_ray_tracing""#); + asm!("OpCapability RayTracingKHR"); + spirv_std::arch::trace_ray_khr( + *acceleration_structure, + 0, + 0, + 0, + 0, + 0, + glam::vec3(1.0, 2.0, 3.0), + 0.5, + glam::vec3(3.0, 2.0, 1.0), + 1.0, + payload, + ); + } +} diff --git a/tests/ui/image/sample_depth_reference_with_project_coordinate/sample_gradient.rs b/tests/ui/image/sample_depth_reference_with_project_coordinate/sample_gradient.rs index a458b06f11..0b16026713 100644 --- a/tests/ui/image/sample_depth_reference_with_project_coordinate/sample_gradient.rs +++ b/tests/ui/image/sample_depth_reference_with_project_coordinate/sample_gradient.rs @@ -12,5 +12,7 @@ pub fn main( let v2_dx = glam::Vec2::new(0.0, 1.0); let v2_dy = glam::Vec2::new(0.0, 1.0); let v3 = glam::Vec3A::new(0.0, 0.0, 1.0); - *output = image.sample_depth_reference_with_project_coordinate_by_gradient(*sampler, v3, 1.0, v2_dx, v2_dy); + *output = image.sample_depth_reference_with_project_coordinate_by_gradient( + *sampler, v3, 1.0, v2_dx, v2_dy, + ); }