mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
Add support for SPV_KHR_ray_tracing (#563)
* Add support for SPV_KHR_ray_tracing * Update spirv_type_constraints.rs * Update spirv_type_constraints.rs * Update spirv_type_constraints.rs
This commit is contained in:
parent
bb7adc912f
commit
a42a9f20e1
43
Cargo.lock
generated
43
Cargo.lock
generated
@ -531,9 +531,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
@ -853,9 +853,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
|
||||
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -868,9 +868,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@ -878,15 +878,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
|
||||
checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@ -895,27 +895,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
||||
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
||||
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -2078,12 +2078,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]]
|
||||
@ -2348,6 +2348,7 @@ dependencies = [
|
||||
name = "spirv-std"
|
||||
version = "0.4.0-alpha.5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
"spirv-std-macros",
|
||||
]
|
||||
@ -2395,7 +2396,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",
|
||||
|
@ -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"] }
|
||||
|
@ -788,6 +788,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) {
|
||||
|
@ -71,6 +71,7 @@ pub enum IntrinsicType {
|
||||
access_qualifier: Option<AccessQualifier>,
|
||||
},
|
||||
Sampler,
|
||||
AccelerationStructureKhr,
|
||||
SampledImage,
|
||||
}
|
||||
|
||||
|
@ -236,6 +236,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
SpirvType::Sampler => self.fatal("cannot memset sampler"),
|
||||
SpirvType::SampledImage { .. } => self.fatal("cannot memset sampled image"),
|
||||
SpirvType::InterfaceBlock { .. } => self.fatal("cannot memset interface block"),
|
||||
SpirvType::AccelerationStructureKhr => {
|
||||
self.fatal("cannot memset acceleration structure")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,6 +296,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
SpirvType::Sampler => self.fatal("cannot memset sampler"),
|
||||
SpirvType::SampledImage { .. } => self.fatal("cannot memset sampled image"),
|
||||
SpirvType::InterfaceBlock { .. } => self.fatal("cannot memset interface block"),
|
||||
SpirvType::AccelerationStructureKhr => {
|
||||
self.fatal("cannot memset acceleration structure")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,6 +530,10 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create a constant interface block value"),
|
||||
SpirvType::AccelerationStructureKhr => self
|
||||
.tcx
|
||||
.sess
|
||||
.fatal("Cannot create a constant acceleration structure"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,10 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
let spirv_ty = self.layout_of(value_ty).spirv_type(hir_param.ty_span, self);
|
||||
// Some types automatically specify a storage class. Compute that here.
|
||||
let inferred_storage_class_from_ty = match self.lookup_type(spirv_ty) {
|
||||
SpirvType::Image { .. } | SpirvType::Sampler | SpirvType::SampledImage { .. } => {
|
||||
SpirvType::Image { .. }
|
||||
| SpirvType::Sampler
|
||||
| SpirvType::SampledImage { .. }
|
||||
| SpirvType::AccelerationStructureKhr => {
|
||||
if is_ref {
|
||||
Some(StorageClass::UniformConstant)
|
||||
} else {
|
||||
|
@ -175,9 +175,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 {
|
||||
|
@ -118,8 +118,9 @@ struct Region {
|
||||
/// After structurizing a region, all paths through it must lead to a single
|
||||
/// "merge" block (i.e. `merge` post-dominates the entire region).
|
||||
/// The `merge` block must be terminated by one of `OpReturn`, `OpReturnValue`,
|
||||
/// `OpKill`, or `OpUnreachable`. If `exits` isn't empty, `merge` will
|
||||
/// receive an `OpBranch` from its parent region (to an outer merge block).
|
||||
/// `OpKill`, `OpIgnoreIntersectionKHR`, `OpTerminateRayKHR` or
|
||||
/// `OpUnreachable`. If `exits` isn't empty, `merge` will receive an
|
||||
/// `OpBranch` from its parent region (to an outer merge block).
|
||||
merge: BlockIdx,
|
||||
merge_id: BlockId,
|
||||
|
||||
@ -168,7 +169,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! {},
|
||||
|
@ -86,7 +86,12 @@ pub fn outgoing_edges(block: &Block) -> impl Iterator<Item = Word> + '_ {
|
||||
Op::Branch => (0..1).step_by(1),
|
||||
Op::BranchConditional => (1..3).step_by(1),
|
||||
Op::Switch => (1..terminator.operands.len()).step_by(2),
|
||||
Op::Return | Op::ReturnValue | Op::Kill | Op::Unreachable => (0..0).step_by(1),
|
||||
Op::Return
|
||||
| Op::ReturnValue
|
||||
| Op::Kill
|
||||
| Op::Unreachable
|
||||
| Op::IgnoreIntersectionKHR
|
||||
| Op::TerminateRayKHR => (0..0).step_by(1),
|
||||
_ => panic!("Invalid block terminator: {:?}", terminator),
|
||||
};
|
||||
operand_indices.map(move |i| terminator.operands[i].unwrap_id_ref())
|
||||
|
@ -85,6 +85,8 @@ pub enum SpirvType {
|
||||
InterfaceBlock {
|
||||
inner_type: Word,
|
||||
},
|
||||
|
||||
AccelerationStructureKhr,
|
||||
}
|
||||
|
||||
impl SpirvType {
|
||||
@ -248,6 +250,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),
|
||||
|
||||
Self::InterfaceBlock { inner_type } => {
|
||||
@ -347,7 +350,10 @@ impl SpirvType {
|
||||
cx.lookup_type(element).sizeof(cx)? * cx.builder.lookup_const_u64(count).unwrap()
|
||||
}
|
||||
Self::Pointer { .. } => cx.tcx.data_layout.pointer_size,
|
||||
Self::Image { .. } | Self::Sampler | Self::SampledImage { .. } => Size::from_bytes(4),
|
||||
Self::Image { .. }
|
||||
| Self::AccelerationStructureKhr
|
||||
| Self::Sampler
|
||||
| Self::SampledImage { .. } => Size::from_bytes(4),
|
||||
|
||||
Self::InterfaceBlock { inner_type } => cx.lookup_type(inner_type).sizeof(cx)?,
|
||||
};
|
||||
@ -375,9 +381,10 @@ impl SpirvType {
|
||||
cx.lookup_type(element).alignof(cx)
|
||||
}
|
||||
Self::Pointer { .. } => cx.tcx.data_layout.pointer_align.abi,
|
||||
Self::Image { .. } | Self::Sampler | Self::SampledImage { .. } => {
|
||||
Align::from_bytes(4).unwrap()
|
||||
}
|
||||
Self::Image { .. }
|
||||
| Self::AccelerationStructureKhr
|
||||
| Self::Sampler
|
||||
| Self::SampledImage { .. } => Align::from_bytes(4).unwrap(),
|
||||
|
||||
Self::InterfaceBlock { inner_type } => cx.lookup_type(inner_type).alignof(cx),
|
||||
}
|
||||
@ -516,12 +523,12 @@ impl fmt::Debug for SpirvTypePrinter<'_, '_> {
|
||||
.field("id", &self.id)
|
||||
.field("image_type", &self.cx.debug_type(image_type))
|
||||
.finish(),
|
||||
|
||||
SpirvType::InterfaceBlock { inner_type } => f
|
||||
.debug_struct("InterfaceBlock")
|
||||
.field("id", &self.id)
|
||||
.field("inner_type", &self.cx.debug_type(inner_type))
|
||||
.finish(),
|
||||
SpirvType::AccelerationStructureKhr => f.debug_struct("AccelerationStructure").finish(),
|
||||
};
|
||||
{
|
||||
let mut debug_stack = DEBUG_STACK.lock().unwrap();
|
||||
@ -671,12 +678,12 @@ impl SpirvTypePrinter<'_, '_> {
|
||||
.debug_struct("SampledImage")
|
||||
.field("image_type", &self.cx.debug_type(image_type))
|
||||
.finish(),
|
||||
|
||||
SpirvType::InterfaceBlock { inner_type } => {
|
||||
f.write_str("interface block { ")?;
|
||||
ty(self.cx, stack, f, inner_type)?;
|
||||
f.write_str(" }")
|
||||
}
|
||||
SpirvType::AccelerationStructureKhr => f.write_str("AccelerationStructureKhr"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -727,7 +727,10 @@ 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 => {
|
||||
// NOTE(eddyb) we actually use these despite not being in the standard yet.
|
||||
// reserved!(SPV_KHR_ray_tracing)
|
||||
}
|
||||
// SPV_KHR_ray_query
|
||||
Op::TypeRayQueryKHR
|
||||
| Op::RayQueryInitializeKHR
|
||||
@ -735,7 +738,10 @@ 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 => {
|
||||
// NOTE(eddyb) we actually use these despite not being in the standard yet.
|
||||
// reserved!(SPV_KHR_ray_query)
|
||||
}
|
||||
// SPV_AMD_shader_fragment_mask
|
||||
Op::FragmentMaskFetchAMD | Op::FragmentFetchAMD => reserved!(SPV_AMD_shader_fragment_mask),
|
||||
// SPV_KHR_shader_clock
|
||||
@ -748,7 +754,10 @@ 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 => {
|
||||
// NOTE(eddyb) Some KHR variants are aliased to the the NV instructions.
|
||||
// reserved!(SPV_NV_ray_tracing)
|
||||
}
|
||||
// SPV_NV_cooperative_matrix
|
||||
Op::TypeCooperativeMatrixNV
|
||||
| Op::CooperativeMatrixLoadNV
|
||||
|
@ -119,21 +119,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", BuiltIn::LaunchIdKHR),
|
||||
("launch_size", BuiltIn::LaunchSizeKHR),
|
||||
("instance_custom_index", BuiltIn::InstanceCustomIndexKHR),
|
||||
("ray_geometry_index", BuiltIn::RayGeometryIndexKHR),
|
||||
("world_ray_origin", BuiltIn::WorldRayOriginKHR),
|
||||
("world_ray_direction", BuiltIn::WorldRayDirectionKHR),
|
||||
("object_ray_origin", BuiltIn::ObjectRayOriginKHR),
|
||||
("object_ray_direction", BuiltIn::ObjectRayDirectionKHR),
|
||||
("ray_tmin", BuiltIn::RayTminKHR),
|
||||
("ray_tmax", BuiltIn::RayTmaxKHR),
|
||||
("object_to_world", BuiltIn::ObjectToWorldKHR),
|
||||
("world_to_object", BuiltIn::WorldToObjectKHR),
|
||||
("hit_kind", BuiltIn::HitKindKHR),
|
||||
("incoming_ray_flags", BuiltIn::IncomingRayFlagsKHR),
|
||||
("warps_per_sm_nv", WarpsPerSMNV),
|
||||
("sm_count_nv", SMCountNV),
|
||||
("warp_id_nv", WarpIDNV),
|
||||
@ -157,21 +156,15 @@ const STORAGE_CLASSES: &[(&str, StorageClass)] = {
|
||||
("atomic_counter", AtomicCounter),
|
||||
("image", Image),
|
||||
("storage_buffer", StorageBuffer),
|
||||
("callable_data_khr", StorageClass::CallableDataKHR),
|
||||
("callable_data", StorageClass::CallableDataKHR),
|
||||
(
|
||||
"incoming_callable_data_khr",
|
||||
"incoming_callable_data",
|
||||
StorageClass::IncomingCallableDataKHR,
|
||||
),
|
||||
("ray_payload_khr", StorageClass::RayPayloadKHR),
|
||||
("hit_attribute_khr", StorageClass::HitAttributeKHR),
|
||||
(
|
||||
"incoming_ray_payload_khr",
|
||||
StorageClass::IncomingRayPayloadKHR,
|
||||
),
|
||||
(
|
||||
"shader_record_buffer_khr",
|
||||
StorageClass::ShaderRecordBufferKHR,
|
||||
),
|
||||
("ray_payload", StorageClass::RayPayloadKHR),
|
||||
("hit_attribute", StorageClass::HitAttributeKHR),
|
||||
("incoming_ray_payload", StorageClass::IncomingRayPayloadKHR),
|
||||
("shader_record_buffer", StorageClass::ShaderRecordBufferKHR),
|
||||
("physical_storage_buffer", PhysicalStorageBuffer),
|
||||
]
|
||||
};
|
||||
@ -188,12 +181,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", ExecutionModel::RayGenerationKHR),
|
||||
("intersection", ExecutionModel::IntersectionKHR),
|
||||
("any_hit", ExecutionModel::AnyHitKHR),
|
||||
("closest_hit", ExecutionModel::ClosestHitKHR),
|
||||
("miss", ExecutionModel::MissKHR),
|
||||
("callable", ExecutionModel::CallableKHR),
|
||||
]
|
||||
};
|
||||
|
||||
@ -324,6 +317,10 @@ impl Symbols {
|
||||
"sampler",
|
||||
SpirvAttribute::IntrinsicType(IntrinsicType::Sampler),
|
||||
),
|
||||
(
|
||||
"acceleration_structure",
|
||||
SpirvAttribute::IntrinsicType(IntrinsicType::AccelerationStructureKhr),
|
||||
),
|
||||
("block", SpirvAttribute::Block),
|
||||
("flat", SpirvAttribute::Flat),
|
||||
("invariant", SpirvAttribute::Invariant),
|
||||
|
@ -8,6 +8,7 @@ repository = "https://github.com/EmbarkStudios/rust-gpu"
|
||||
description = "Standard functions and types for SPIR-V"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.2.1"
|
||||
num-traits = { version = "0.2.14", default-features = false, features = ["libm"] }
|
||||
spirv-std-macros = { path = "../spirv-std-macros", version = "0.4.0-alpha.0" }
|
||||
|
||||
|
@ -10,12 +10,14 @@ mod arithmetic;
|
||||
mod barrier;
|
||||
mod derivative;
|
||||
mod primitive;
|
||||
mod ray_tracing;
|
||||
|
||||
pub use arithmetic::*;
|
||||
#[cfg(feature = "const-generics")]
|
||||
pub use barrier::*;
|
||||
pub use derivative::*;
|
||||
pub use primitive::*;
|
||||
pub use ray_tracing::*;
|
||||
|
||||
/// Result is true if any component of `vector` is true, otherwise result is
|
||||
/// false.
|
||||
|
85
crates/spirv-std/src/arch/ray_tracing.rs
Normal file
85
crates/spirv-std/src/arch/ray_tracing.rs
Normal file
@ -0,0 +1,85 @@
|
||||
/// 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` execution model.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpReportIntersectionKHR")]
|
||||
#[inline]
|
||||
pub unsafe fn report_intersection(hit: f32, hit_kind: u32) -> bool {
|
||||
let result: u32;
|
||||
|
||||
asm! {
|
||||
"%bool = OpTypeBool",
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%zero = OpConstant %u32 0",
|
||||
"%one = OpConstant %u32 1",
|
||||
"%result = OpReportIntersectionKHR %bool {hit} {hit_kind}",
|
||||
"{result} = OpSelect %u32 %result %one %zero",
|
||||
result = out(reg) 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` 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() {
|
||||
asm!("OpIgnoreIntersectionKHR", "%unused = OpLabel")
|
||||
}
|
||||
|
||||
/// Terminates the invocation that executes it, stops the ray traversal, accepts
|
||||
/// the current hit, and invokes the `closest_hit` execution model
|
||||
/// (if active). This instruction is allowed only in the `any_hit`
|
||||
/// 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() {
|
||||
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`
|
||||
/// or `incoming_callable_data`.
|
||||
///
|
||||
/// This instruction is allowed only in `ray_generation`, `closest_hit`,
|
||||
/// `miss` and `callable` execution models.
|
||||
///
|
||||
/// This instruction is a shader call instruction which will invoke a shader
|
||||
/// with the `callable` execution model.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpExecuteCallableKHR")]
|
||||
#[inline]
|
||||
pub unsafe fn execute_callable<T, const ID: usize>(data: &T) {
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%id = OpConstant %u32 {id}",
|
||||
"OpExecuteCallableKHR %id {data}",
|
||||
id = const ID,
|
||||
data = in(reg) data,
|
||||
};
|
||||
}
|
@ -78,6 +78,7 @@ pub mod arch;
|
||||
pub mod float;
|
||||
pub mod integer;
|
||||
pub mod memory;
|
||||
pub mod ray_tracing;
|
||||
pub mod scalar;
|
||||
pub(crate) mod sealed;
|
||||
mod textures;
|
||||
|
161
crates/spirv-std/src/ray_tracing.rs
Normal file
161
crates/spirv-std/src/ray_tracing.rs
Normal file
@ -0,0 +1,161 @@
|
||||
//! Ray-tracing data types
|
||||
use crate::vector::Vector;
|
||||
|
||||
/// An acceleration structure type which is an opaque reference to an
|
||||
/// acceleration structure handle as defined in the client API specification.
|
||||
#[spirv(acceleration_structure)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AccelerationStructure {
|
||||
pub(crate) _private: u32,
|
||||
}
|
||||
|
||||
impl AccelerationStructure {
|
||||
/// 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")]
|
||||
#[allow(clippy::empty_loop)]
|
||||
#[inline]
|
||||
pub unsafe fn from_u64(id: u64) -> AccelerationStructure {
|
||||
// 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 {}
|
||||
}
|
||||
|
||||
/// Converts a vector of two 32 bit integers into an [`AccelerationStructureKHR`].
|
||||
/// # Safety
|
||||
/// The combination must point to a valid acceleration structure.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpConvertUToAccelerationStructureKHR")]
|
||||
#[allow(clippy::empty_loop)]
|
||||
#[inline]
|
||||
pub unsafe fn from_vec(id: impl Vector<u32, 2>) -> AccelerationStructure {
|
||||
// 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",
|
||||
"%id = OpLoad _ {id}",
|
||||
"%result = OpConvertUToAccelerationStructureKHR %ret %id",
|
||||
"OpReturnValue %result",
|
||||
"%blah = OpLabel",
|
||||
id = in(reg) &id,
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[spirv_std_macros::gpu_only]
|
||||
/// 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`
|
||||
/// or `incoming_ray_payload`.
|
||||
///
|
||||
/// This instruction is allowed only in `ray_generation`, `closest_hit` and
|
||||
/// `miss` execution models.
|
||||
///
|
||||
/// This instruction is a shader call instruction which may invoke shaders with
|
||||
/// the `intersection`, `any_hit`, `closest_hit`, and `miss`
|
||||
/// execution models.
|
||||
#[doc(alias = "OpTraceRayKHR")]
|
||||
#[inline]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub unsafe fn trace_ray<T>(
|
||||
&self,
|
||||
ray_flags: RayFlags,
|
||||
cull_mask: i32,
|
||||
sbt_offset: i32,
|
||||
sbt_stride: i32,
|
||||
miss_index: i32,
|
||||
ray_origin: impl Vector<f32, 3>,
|
||||
ray_tmin: f32,
|
||||
ray_direction: impl Vector<f32, 3>,
|
||||
ray_tmax: f32,
|
||||
payload: &mut T,
|
||||
) {
|
||||
asm! {
|
||||
"%ray_origin = OpLoad _ {ray_origin}",
|
||||
"%ray_direction = OpLoad _ {ray_direction}",
|
||||
"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) self,
|
||||
ray_flags = in(reg) ray_flags.bits(),
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Flags controlling the properties of an OpTraceRayKHR instruction.
|
||||
/// Despite being a mask and allowing multiple bits to be combined, it is
|
||||
/// invalid for more than one of these four bits to be set: `OPAQUE`,
|
||||
/// `NO_OPAQUE`, `CULL_OPAQUE`, `CULL_NO_OPAQUE`, only one of
|
||||
/// `CULL_BACK_FACING_TRIANGLES` and `CULL_FRONT_FACING_TRIANGLES` may
|
||||
/// be set.
|
||||
pub struct RayFlags: u32 {
|
||||
/// No flags specified.
|
||||
const NONE = 0;
|
||||
/// Force all intersections with the trace to be opaque.
|
||||
const OPAQUE = 1;
|
||||
/// Force all intersections with the trace to be non-opaque.
|
||||
const NO_OPAQUE = 2;
|
||||
/// Accept the first hit discovered.
|
||||
const TERMINATE_ON_FIRST_HIT = 4;
|
||||
/// Do not execute a closest hit shader.
|
||||
const SKIP_CLOSEST_HIT_SHADER = 8;
|
||||
/// Do not intersect with the back face of triangles.
|
||||
const CULL_BACK_FACING_TRIANGLES = 16;
|
||||
/// Do not intersect with the front face of triangles.
|
||||
const CULL_FRONT_FACING_TRIANGLES = 32;
|
||||
/// Do not intersect with opaque geometry.
|
||||
const CULL_OPAQUE = 64;
|
||||
/// Do not intersect with non-opaque geometry.
|
||||
const CULL_NO_OPAQUE = 128;
|
||||
/// Do not intersect with any triangle geometries.
|
||||
const SKIP_TRIANGLES = 256;
|
||||
/// Do not intersect with any AABB (Axis Aligned Bounding Box) geometries.
|
||||
const SKIP_AABBS = 512;
|
||||
}
|
||||
}
|
39
tests/ui/arch/convert_u_to_acceleration_structure_khr.rs
Normal file
39
tests/ui/arch/convert_u_to_acceleration_structure_khr.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// build-pass
|
||||
|
||||
#[spirv(ray_generation)]
|
||||
pub fn main(#[spirv(ray_payload)] payload: &mut glam::Vec3) {
|
||||
unsafe {
|
||||
asm!(r#"OpExtension "SPV_KHR_ray_tracing""#);
|
||||
asm!("OpCapability RayTracingKHR");
|
||||
|
||||
let handle = spirv_std::ray_tracing::AccelerationStructure::from_u64(0xffff_ffff);
|
||||
let handle2 =
|
||||
spirv_std::ray_tracing::AccelerationStructure::from_vec(glam::UVec2::new(0, 0));
|
||||
|
||||
handle.trace_ray(
|
||||
spirv_std::ray_tracing::RayFlags::NONE,
|
||||
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,
|
||||
);
|
||||
|
||||
handle2.trace_ray(
|
||||
spirv_std::ray_tracing::RayFlags::NONE,
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
16
tests/ui/arch/execute_callable.rs
Normal file
16
tests/ui/arch/execute_callable.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// build-pass
|
||||
|
||||
#[spirv(ray_generation)]
|
||||
// Rustfmt will eat long attributes (https://github.com/rust-lang/rustfmt/issues/4579)
|
||||
#[rustfmt::skip]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)]
|
||||
acceleration_structure: &spirv_std::ray_tracing::AccelerationStructure,
|
||||
#[spirv(incoming_callable_data)] payload: &glam::Vec3,
|
||||
) {
|
||||
unsafe {
|
||||
asm!(r#"OpExtension "SPV_KHR_ray_tracing""#);
|
||||
asm!("OpCapability RayTracingKHR");
|
||||
spirv_std::arch::execute_callable::<_, 5>(payload);
|
||||
}
|
||||
}
|
10
tests/ui/arch/ignore_intersection_khr.rs
Normal file
10
tests/ui/arch/ignore_intersection_khr.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// build-pass
|
||||
|
||||
#[spirv(any_hit)]
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
asm!(r#"OpExtension "SPV_KHR_ray_tracing""#);
|
||||
asm!("OpCapability RayTracingKHR");
|
||||
spirv_std::arch::ignore_intersection();
|
||||
}
|
||||
}
|
10
tests/ui/arch/report_intersection_khr.rs
Normal file
10
tests/ui/arch/report_intersection_khr.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// build-pass
|
||||
|
||||
#[spirv(intersection)]
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
asm!(r#"OpExtension "SPV_KHR_ray_tracing""#);
|
||||
asm!("OpCapability RayTracingKHR");
|
||||
spirv_std::arch::report_intersection(2.0, 4);
|
||||
}
|
||||
}
|
10
tests/ui/arch/terminate_ray_khr.rs
Normal file
10
tests/ui/arch/terminate_ray_khr.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// build-pass
|
||||
|
||||
#[spirv(any_hit)]
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
asm!(r#"OpExtension "SPV_KHR_ray_tracing""#);
|
||||
asm!("OpCapability RayTracingKHR");
|
||||
spirv_std::arch::terminate_ray();
|
||||
}
|
||||
}
|
27
tests/ui/arch/trace_ray_khr.rs
Normal file
27
tests/ui/arch/trace_ray_khr.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// build-pass
|
||||
|
||||
#[spirv(ray_generation)]
|
||||
// Rustfmt will eat long attributes (https://github.com/rust-lang/rustfmt/issues/4579)
|
||||
#[rustfmt::skip]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)]
|
||||
acceleration_structure: &spirv_std::ray_tracing::AccelerationStructure,
|
||||
#[spirv(ray_payload)] payload: &mut glam::Vec3,
|
||||
) {
|
||||
unsafe {
|
||||
asm!(r#"OpExtension "SPV_KHR_ray_tracing""#);
|
||||
asm!("OpCapability RayTracingKHR");
|
||||
acceleration_structure.trace_ray(
|
||||
spirv_std::ray_tracing::RayFlags::NONE,
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user