mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-06-01 09:09:48 +09:00
[spv-out] ray tracing pipelines (#9085)
This commit is contained in:
@@ -118,6 +118,10 @@ By @andyleiserson in [#9321](https://github.com/gfx-rs/wgpu/pull/9321).
|
||||
- Conditional compilation by @jimblandy in [#9390](https://github.com/gfx-rs/wgpu/pull/9390)
|
||||
- Fixed alignment and MatrixStride for mat2x2 in SPIR-V uniform blocks. By @39ali [#9369](https://github.com/gfx-rs/wgpu/pull/9369).
|
||||
|
||||
#### naga
|
||||
|
||||
- spirv-out ray tracing pipelines. By @Vecvec in [#9085](https://github.com/gfx-rs/wgpu/pull/9085).
|
||||
|
||||
### Changes
|
||||
|
||||
#### General
|
||||
|
||||
@@ -178,6 +178,7 @@ impl SpirvOutParameters {
|
||||
use_storage_input_output_16: self.use_storage_input_output_16,
|
||||
task_dispatch_limits: shared_info.task_limits,
|
||||
mesh_shader_primitive_indices_clamp: shared_info.mesh_output_validation,
|
||||
trace_ray_argument_validation: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4177,7 +4177,9 @@ impl BlockContext<'_> {
|
||||
}
|
||||
};
|
||||
}
|
||||
Statement::RayPipelineFunction(_) => unreachable!(),
|
||||
Statement::RayPipelineFunction(ref fun) => {
|
||||
self.write_ray_tracing_pipeline_function(fun, &mut block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,12 @@ pub(super) const fn map_storage_class(space: crate::AddressSpace) -> spirv::Stor
|
||||
crate::AddressSpace::WorkGroup => spirv::StorageClass::Workgroup,
|
||||
crate::AddressSpace::Immediate => spirv::StorageClass::PushConstant,
|
||||
crate::AddressSpace::TaskPayload => spirv::StorageClass::TaskPayloadWorkgroupEXT,
|
||||
crate::AddressSpace::IncomingRayPayload | crate::AddressSpace::RayPayload => unreachable!(),
|
||||
// We can't require capabilities here but we request capabilities on the ray pipeline stages
|
||||
// and when writing global variables - global variables because we may be writing an
|
||||
// uncompacted module and pipeline stages for all other cases because these can only be
|
||||
//accessed in a ray tracing pipeline stage.
|
||||
crate::AddressSpace::RayPayload => spirv::StorageClass::RayPayloadKHR,
|
||||
crate::AddressSpace::IncomingRayPayload => spirv::StorageClass::IncomingRayPayloadKHR,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -865,6 +865,39 @@ impl super::Instruction {
|
||||
instruction
|
||||
}
|
||||
|
||||
//
|
||||
// Ray Tracing Pipeline Instructions
|
||||
//
|
||||
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub(super) fn trace_ray(
|
||||
acceleration_structure: Word,
|
||||
ray_flags: Word,
|
||||
cull_mask: Word,
|
||||
sbt_offset: Word,
|
||||
sbt_stride: Word,
|
||||
miss_idx: Word,
|
||||
ray_origin: Word,
|
||||
ray_tmin: Word,
|
||||
ray_dir: Word,
|
||||
ray_tmax: Word,
|
||||
payload: Word,
|
||||
) -> Self {
|
||||
let mut instruction = Self::new(Op::TraceRayKHR);
|
||||
instruction.add_operand(acceleration_structure);
|
||||
instruction.add_operand(ray_flags);
|
||||
instruction.add_operand(cull_mask);
|
||||
instruction.add_operand(sbt_offset);
|
||||
instruction.add_operand(sbt_stride);
|
||||
instruction.add_operand(miss_idx);
|
||||
instruction.add_operand(ray_origin);
|
||||
instruction.add_operand(ray_tmin);
|
||||
instruction.add_operand(ray_dir);
|
||||
instruction.add_operand(ray_tmax);
|
||||
instruction.add_operand(payload);
|
||||
instruction
|
||||
}
|
||||
|
||||
//
|
||||
// Conversion Instructions
|
||||
//
|
||||
|
||||
@@ -593,6 +593,14 @@ enum LookupRayQueryFunction {
|
||||
Terminate,
|
||||
}
|
||||
|
||||
// Just one supported function right now, more in the future.
|
||||
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
|
||||
enum LookupRaytracingFunction {
|
||||
TraceRay {
|
||||
payload: Handle<crate::GlobalVariable>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Dimension {
|
||||
Scalar,
|
||||
@@ -962,6 +970,10 @@ pub struct Writer {
|
||||
|
||||
ray_query_functions: crate::FastHashMap<LookupRayQueryFunction, Word>,
|
||||
|
||||
ray_tracing_functions: crate::FastHashMap<LookupRaytracingFunction, Word>,
|
||||
|
||||
has_ray_tracing_pipeline: bool,
|
||||
|
||||
/// F16 I/O polyfill manager for handling `f16` input/output variables
|
||||
/// when `StorageInputOutput16` capability is not available.
|
||||
io_f16_polyfills: f16_polyfill::F16IoPolyfill,
|
||||
@@ -970,6 +982,9 @@ pub struct Writer {
|
||||
debug_printf: Option<Word>,
|
||||
pub(crate) ray_query_initialization_tracking: bool,
|
||||
|
||||
/// Whether the arguments to trace ray should be validated
|
||||
pub(crate) trace_ray_argument_validation: bool,
|
||||
|
||||
/// See docs in [`Options`]
|
||||
task_dispatch_limits: Option<TaskDispatchLimits>,
|
||||
/// See docs in [`Options`]
|
||||
@@ -1012,6 +1027,13 @@ bitflags::bitflags! {
|
||||
/// Note: VK_KHR_shader_non_semantic_info must be enabled. This will have no
|
||||
/// effect if `options.ray_query_initialization_tracking` is set to false.
|
||||
const PRINT_ON_RAY_QUERY_INITIALIZATION_FAIL = 0x20;
|
||||
|
||||
/// Instead of silently failing if the arguments to `traceRays` are
|
||||
/// invalid, uses debug printf extension to print to the command line
|
||||
///
|
||||
/// Note: VK_KHR_shader_non_semantic_info must be enabled. This will have no
|
||||
/// effect if `options.trace_ray_argument_validation` is set to false.
|
||||
const PRINT_ON_TRACE_RAYS_FAIL = 0x40;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,6 +1095,9 @@ pub struct Options<'a> {
|
||||
/// misuse.
|
||||
pub ray_query_initialization_tracking: bool,
|
||||
|
||||
/// If set, arguments to `traceRays` calls will be validated.
|
||||
pub trace_ray_argument_validation: bool,
|
||||
|
||||
/// Whether to use the `StorageInputOutput16` capability for `f16` shader I/O.
|
||||
/// When false, `f16` I/O is polyfilled using `f32` types with conversions.
|
||||
pub use_storage_input_output_16: bool,
|
||||
@@ -1109,6 +1134,7 @@ impl Default for Options<'_> {
|
||||
zero_initialize_workgroup_memory: ZeroInitializeWorkgroupMemoryMode::Polyfill,
|
||||
force_loop_bounding: true,
|
||||
ray_query_initialization_tracking: true,
|
||||
trace_ray_argument_validation: true,
|
||||
use_storage_input_output_16: true,
|
||||
debug_info: None,
|
||||
task_dispatch_limits: None,
|
||||
@@ -1191,7 +1217,7 @@ pub fn supported_capabilities() -> crate::valid::Capabilities {
|
||||
| Caps::STORAGE_BUFFER_BINDING_ARRAY_NON_UNIFORM_INDEXING
|
||||
| Caps::COOPERATIVE_MATRIX
|
||||
| Caps::PER_VERTEX
|
||||
// No RAY_TRACING_PIPELINE
|
||||
| Caps::RAY_TRACING_PIPELINE
|
||||
| Caps::DRAW_INDEX
|
||||
| Caps::MEMORY_DECORATION_COHERENT
|
||||
| Caps::MEMORY_DECORATION_VOLATILE
|
||||
|
||||
@@ -1,6 +1,454 @@
|
||||
/*!
|
||||
Module for code shared between ray queries and ray tracing pipeline code.
|
||||
Ray tracing pipelines are not yet implemented, so this is empty.
|
||||
*/
|
||||
|
||||
pub mod pipeline;
|
||||
pub mod query;
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
|
||||
use super::{Block, Function, FunctionArgument, Instruction, LookupFunctionType, Writer};
|
||||
|
||||
struct ExtractedRayDesc {
|
||||
ray_flags_id: spirv::Word,
|
||||
cull_mask_id: spirv::Word,
|
||||
tmin_id: spirv::Word,
|
||||
tmax_id: spirv::Word,
|
||||
ray_origin_id: spirv::Word,
|
||||
ray_dir_id: spirv::Word,
|
||||
valid_id: Option<spirv::Word>,
|
||||
}
|
||||
|
||||
/// helper function to check if a particular flag is set in a u32.
|
||||
fn write_ray_flags_contains_flags(
|
||||
writer: &mut Writer,
|
||||
block: &mut Block,
|
||||
id: spirv::Word,
|
||||
flag: u32,
|
||||
) -> spirv::Word {
|
||||
let bit_id = writer.get_constant_scalar(crate::Literal::U32(flag));
|
||||
let zero_id = writer.get_constant_scalar(crate::Literal::U32(0));
|
||||
let u32_type_id = writer.get_u32_type_id();
|
||||
let bool_ty = writer.get_bool_type_id();
|
||||
|
||||
let and_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::BitwiseAnd,
|
||||
u32_type_id,
|
||||
and_id,
|
||||
id,
|
||||
bit_id,
|
||||
));
|
||||
|
||||
let eq_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::INotEqual,
|
||||
bool_ty,
|
||||
eq_id,
|
||||
and_id,
|
||||
zero_id,
|
||||
));
|
||||
|
||||
eq_id
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
fn write_extract_ray_desc(
|
||||
&mut self,
|
||||
block: &mut Block,
|
||||
desc_id: spirv::Word,
|
||||
validate: bool,
|
||||
) -> ExtractedRayDesc {
|
||||
let bool_type_id = self.get_bool_type_id();
|
||||
let bool_vec3_type_id = self.get_vec3_bool_type_id();
|
||||
let f32_type_id = self.get_f32_type_id();
|
||||
let flag_type_id = self.get_numeric_type_id(super::NumericType::Scalar(crate::Scalar::U32));
|
||||
|
||||
//Note: composite extract indices and types must match `generate_ray_desc_type`
|
||||
let ray_flags_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
flag_type_id,
|
||||
ray_flags_id,
|
||||
desc_id,
|
||||
&[0],
|
||||
));
|
||||
let cull_mask_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
flag_type_id,
|
||||
cull_mask_id,
|
||||
desc_id,
|
||||
&[1],
|
||||
));
|
||||
|
||||
let tmin_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
f32_type_id,
|
||||
tmin_id,
|
||||
desc_id,
|
||||
&[2],
|
||||
));
|
||||
let tmax_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
f32_type_id,
|
||||
tmax_id,
|
||||
desc_id,
|
||||
&[3],
|
||||
));
|
||||
|
||||
let vector_type_id = self.get_numeric_type_id(super::NumericType::Vector {
|
||||
size: crate::VectorSize::Tri,
|
||||
scalar: crate::Scalar::F32,
|
||||
});
|
||||
let ray_origin_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
vector_type_id,
|
||||
ray_origin_id,
|
||||
desc_id,
|
||||
&[4],
|
||||
));
|
||||
let ray_dir_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
vector_type_id,
|
||||
ray_dir_id,
|
||||
desc_id,
|
||||
&[5],
|
||||
));
|
||||
|
||||
let valid_id = validate.then(||{
|
||||
let tmin_le_tmax_id = self.id_gen.next();
|
||||
// Check both that tmin is less than or equal to tmax (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06350)
|
||||
// and implicitly that neither tmin or tmax are NaN (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06351)
|
||||
// because this checks if tmin and tmax are ordered too (i.e: not NaN).
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::FOrdLessThanEqual,
|
||||
bool_type_id,
|
||||
tmin_le_tmax_id,
|
||||
tmin_id,
|
||||
tmax_id,
|
||||
));
|
||||
|
||||
// Check that tmin is greater than or equal to 0 (and
|
||||
// therefore also tmax is too because it is greater than
|
||||
// or equal to tmin) (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06349).
|
||||
let tmin_ge_zero_id = self.id_gen.next();
|
||||
let zero_id = self.get_constant_scalar(crate::Literal::F32(0.0));
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::FOrdGreaterThanEqual,
|
||||
bool_type_id,
|
||||
tmin_ge_zero_id,
|
||||
tmin_id,
|
||||
zero_id,
|
||||
));
|
||||
|
||||
// Check that ray origin is finite (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06348)
|
||||
let ray_origin_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsInf,
|
||||
bool_vec3_type_id,
|
||||
ray_origin_infinite_id,
|
||||
ray_origin_id,
|
||||
));
|
||||
let any_ray_origin_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_origin_infinite_id,
|
||||
ray_origin_infinite_id,
|
||||
));
|
||||
|
||||
let ray_origin_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsNan,
|
||||
bool_vec3_type_id,
|
||||
ray_origin_nan_id,
|
||||
ray_origin_id,
|
||||
));
|
||||
let any_ray_origin_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_origin_nan_id,
|
||||
ray_origin_nan_id,
|
||||
));
|
||||
|
||||
let ray_origin_not_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalOr,
|
||||
bool_type_id,
|
||||
ray_origin_not_finite_id,
|
||||
any_ray_origin_nan_id,
|
||||
any_ray_origin_infinite_id,
|
||||
));
|
||||
|
||||
let all_ray_origin_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::LogicalNot,
|
||||
bool_type_id,
|
||||
all_ray_origin_finite_id,
|
||||
ray_origin_not_finite_id,
|
||||
));
|
||||
|
||||
// Check that ray direction is finite (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06348)
|
||||
let ray_dir_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsInf,
|
||||
bool_vec3_type_id,
|
||||
ray_dir_infinite_id,
|
||||
ray_dir_id,
|
||||
));
|
||||
let any_ray_dir_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_dir_infinite_id,
|
||||
ray_dir_infinite_id,
|
||||
));
|
||||
|
||||
let ray_dir_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsNan,
|
||||
bool_vec3_type_id,
|
||||
ray_dir_nan_id,
|
||||
ray_dir_id,
|
||||
));
|
||||
let any_ray_dir_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_dir_nan_id,
|
||||
ray_dir_nan_id,
|
||||
));
|
||||
|
||||
let ray_dir_not_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalOr,
|
||||
bool_type_id,
|
||||
ray_dir_not_finite_id,
|
||||
any_ray_dir_nan_id,
|
||||
any_ray_dir_infinite_id,
|
||||
));
|
||||
|
||||
let all_ray_dir_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::LogicalNot,
|
||||
bool_type_id,
|
||||
all_ray_dir_finite_id,
|
||||
ray_dir_not_finite_id,
|
||||
));
|
||||
|
||||
/// Writes spirv to check that less than two booleans are true
|
||||
///
|
||||
/// For each boolean: removes it, `and`s it with all others (i.e for all possible combinations of two booleans in the list checks to see if both are true).
|
||||
/// Then `or`s all of these checks together. This produces whether two or more booleans are true.
|
||||
fn write_less_than_2_true(
|
||||
writer: &mut Writer,
|
||||
block: &mut Block,
|
||||
mut bools: Vec<spirv::Word>,
|
||||
) -> spirv::Word {
|
||||
assert!(bools.len() > 1, "Must have multiple booleans!");
|
||||
let bool_ty = writer.get_bool_type_id();
|
||||
let mut each_two_true = Vec::new();
|
||||
while let Some(last_bool) = bools.pop() {
|
||||
for &bool in &bools {
|
||||
let both_true_id = writer.write_logical_and(
|
||||
block,
|
||||
last_bool,
|
||||
bool,
|
||||
);
|
||||
each_two_true.push(both_true_id);
|
||||
}
|
||||
}
|
||||
let mut all_or_id = each_two_true.pop().expect("since this must have multiple booleans, there must be at least one thing in `each_two_true`");
|
||||
for two_true in each_two_true {
|
||||
let new_all_or_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalOr,
|
||||
bool_ty,
|
||||
new_all_or_id,
|
||||
all_or_id,
|
||||
two_true,
|
||||
));
|
||||
all_or_id = new_all_or_id;
|
||||
}
|
||||
|
||||
let less_than_two_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::LogicalNot,
|
||||
bool_ty,
|
||||
less_than_two_id,
|
||||
all_or_id,
|
||||
));
|
||||
less_than_two_id
|
||||
}
|
||||
|
||||
// Check that at most one of skip triangles and skip AABBs is
|
||||
// present (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06889)
|
||||
let contains_skip_triangles = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::SKIP_TRIANGLES.bits(),
|
||||
);
|
||||
let contains_skip_aabbs = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::SKIP_AABBS.bits(),
|
||||
);
|
||||
|
||||
let not_contain_skip_triangles_aabbs = write_less_than_2_true(
|
||||
self,
|
||||
block,
|
||||
vec![contains_skip_triangles, contains_skip_aabbs],
|
||||
);
|
||||
|
||||
// Check that at most one of skip triangles (taken from above check),
|
||||
// cull back facing, and cull front face is present (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06890)
|
||||
let contains_cull_back = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_BACK_FACING.bits(),
|
||||
);
|
||||
let contains_cull_front = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_FRONT_FACING.bits(),
|
||||
);
|
||||
|
||||
let not_contain_skip_triangles_cull = write_less_than_2_true(
|
||||
self,
|
||||
block,
|
||||
vec![
|
||||
contains_skip_triangles,
|
||||
contains_cull_back,
|
||||
contains_cull_front,
|
||||
],
|
||||
);
|
||||
|
||||
// Check that at most one of force opaque, force not opaque, cull opaque,
|
||||
// and cull not opaque are present (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06891)
|
||||
let contains_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::FORCE_OPAQUE.bits(),
|
||||
);
|
||||
let contains_no_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::FORCE_NO_OPAQUE.bits(),
|
||||
);
|
||||
let contains_cull_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_OPAQUE.bits(),
|
||||
);
|
||||
let contains_cull_no_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_NO_OPAQUE.bits(),
|
||||
);
|
||||
|
||||
let not_contain_multiple_opaque = write_less_than_2_true(
|
||||
self,
|
||||
block,
|
||||
vec![
|
||||
contains_opaque,
|
||||
contains_no_opaque,
|
||||
contains_cull_opaque,
|
||||
contains_cull_no_opaque,
|
||||
],
|
||||
);
|
||||
|
||||
// Combine all checks into a single flag saying whether the call is valid or not.
|
||||
self.write_reduce_and(
|
||||
block,
|
||||
vec![
|
||||
tmin_le_tmax_id,
|
||||
tmin_ge_zero_id,
|
||||
all_ray_origin_finite_id,
|
||||
all_ray_dir_finite_id,
|
||||
not_contain_skip_triangles_aabbs,
|
||||
not_contain_skip_triangles_cull,
|
||||
not_contain_multiple_opaque,
|
||||
],
|
||||
)
|
||||
});
|
||||
|
||||
ExtractedRayDesc {
|
||||
ray_flags_id,
|
||||
cull_mask_id,
|
||||
tmin_id,
|
||||
tmax_id,
|
||||
ray_origin_id,
|
||||
ray_dir_id,
|
||||
valid_id,
|
||||
}
|
||||
}
|
||||
/// writes a logical and of two scalar booleans
|
||||
fn write_logical_and(
|
||||
&mut self,
|
||||
block: &mut Block,
|
||||
one: spirv::Word,
|
||||
two: spirv::Word,
|
||||
) -> spirv::Word {
|
||||
let id = self.id_gen.next();
|
||||
let bool_id = self.get_bool_type_id();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalAnd,
|
||||
bool_id,
|
||||
id,
|
||||
one,
|
||||
two,
|
||||
));
|
||||
id
|
||||
}
|
||||
|
||||
fn write_reduce_and(&mut self, block: &mut Block, mut bools: Vec<spirv::Word>) -> spirv::Word {
|
||||
// The combined `and`ed together of all of the bools up to this point.
|
||||
let mut current_combined = bools.pop().unwrap();
|
||||
for boolean in bools {
|
||||
current_combined = self.write_logical_and(block, current_combined, boolean)
|
||||
}
|
||||
current_combined
|
||||
}
|
||||
|
||||
// returns the id of the function, the function, and ids for its arguments.
|
||||
fn write_function_signature(
|
||||
&mut self,
|
||||
arg_types: &[spirv::Word],
|
||||
return_ty: spirv::Word,
|
||||
) -> (spirv::Word, Function, Vec<spirv::Word>) {
|
||||
let func_ty = self.get_function_type(LookupFunctionType {
|
||||
parameter_type_ids: Vec::from(arg_types),
|
||||
return_type_id: return_ty,
|
||||
});
|
||||
|
||||
let mut function = Function::default();
|
||||
let func_id = self.id_gen.next();
|
||||
function.signature = Some(Instruction::function(
|
||||
return_ty,
|
||||
func_id,
|
||||
spirv::FunctionControl::empty(),
|
||||
func_ty,
|
||||
));
|
||||
|
||||
let mut arg_ids = Vec::with_capacity(arg_types.len());
|
||||
|
||||
for (idx, &arg_ty) in arg_types.iter().enumerate() {
|
||||
let id = self.id_gen.next();
|
||||
let instruction = Instruction::function_parameter(arg_ty, id);
|
||||
function.parameters.push(FunctionArgument {
|
||||
instruction,
|
||||
handle_id: idx as u32,
|
||||
});
|
||||
arg_ids.push(id);
|
||||
}
|
||||
(func_id, function, arg_ids)
|
||||
}
|
||||
}
|
||||
|
||||
157
naga/src/back/spv/ray/pipeline.rs
Normal file
157
naga/src/back/spv/ray/pipeline.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
//! Code for ray tracing pipelines
|
||||
|
||||
use crate::back::spv::{
|
||||
Block, BlockContext, Instruction, LocalType, LookupRaytracingFunction, Writer, WriterFlags,
|
||||
};
|
||||
|
||||
impl Writer {
|
||||
fn write_trace_ray(
|
||||
&mut self,
|
||||
ir_module: &crate::Module,
|
||||
payload: crate::Handle<crate::GlobalVariable>,
|
||||
) -> spirv::Word {
|
||||
if let Some(&word) = self
|
||||
.ray_tracing_functions
|
||||
.get(&LookupRaytracingFunction::TraceRay { payload })
|
||||
{
|
||||
return word;
|
||||
}
|
||||
|
||||
let acceleration_structure_type_id =
|
||||
self.get_localtype_id(LocalType::AccelerationStructure);
|
||||
|
||||
let ray_desc_type_id = self.get_handle_type_id(
|
||||
ir_module
|
||||
.special_types
|
||||
.ray_desc
|
||||
.expect("ray desc should be set if `traceRays` is called"),
|
||||
);
|
||||
|
||||
let (func_id, mut function, arg_ids) = self.write_function_signature(
|
||||
&[acceleration_structure_type_id, ray_desc_type_id],
|
||||
self.void_type,
|
||||
);
|
||||
|
||||
let acceleration_structure_id = arg_ids[0];
|
||||
let desc_id = arg_ids[1];
|
||||
let payload_id = self.global_variables[payload].access_id;
|
||||
|
||||
let label_id = self.id_gen.next();
|
||||
let mut block = Block::new(label_id);
|
||||
|
||||
let super::ExtractedRayDesc {
|
||||
ray_flags_id,
|
||||
cull_mask_id,
|
||||
tmin_id,
|
||||
tmax_id,
|
||||
ray_origin_id,
|
||||
ray_dir_id,
|
||||
valid_id,
|
||||
} = self.write_extract_ray_desc(&mut block, desc_id, self.trace_ray_argument_validation);
|
||||
|
||||
let merge_label_id = self.id_gen.next();
|
||||
let merge_block = Block::new(merge_label_id);
|
||||
|
||||
// NOTE: this block will be unreachable if trace ray validation is disabled.
|
||||
let invalid_label_id = self.id_gen.next();
|
||||
let mut invalid_block = Block::new(invalid_label_id);
|
||||
|
||||
let valid_label_id = self.id_gen.next();
|
||||
let mut valid_block = Block::new(valid_label_id);
|
||||
|
||||
match valid_id {
|
||||
Some(all_valid_id) => {
|
||||
block.body.push(Instruction::selection_merge(
|
||||
merge_label_id,
|
||||
spirv::SelectionControl::NONE,
|
||||
));
|
||||
function.consume(
|
||||
block,
|
||||
Instruction::branch_conditional(all_valid_id, valid_label_id, invalid_label_id),
|
||||
);
|
||||
}
|
||||
None => {
|
||||
function.consume(block, Instruction::branch(valid_label_id));
|
||||
}
|
||||
}
|
||||
|
||||
let zero = self.get_constant_scalar(crate::Literal::U32(0));
|
||||
|
||||
valid_block.body.push(Instruction::trace_ray(
|
||||
acceleration_structure_id,
|
||||
ray_flags_id,
|
||||
cull_mask_id,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
ray_origin_id,
|
||||
tmin_id,
|
||||
ray_dir_id,
|
||||
tmax_id,
|
||||
payload_id,
|
||||
));
|
||||
|
||||
function.consume(valid_block, Instruction::branch(merge_label_id));
|
||||
|
||||
if self.flags.contains(WriterFlags::PRINT_ON_TRACE_RAYS_FAIL) {
|
||||
self.write_debug_printf(
|
||||
&mut invalid_block,
|
||||
"Naga ignored invalid arguments to traceRay with flags: %u t_min: %f t_max: %f origin: %v4f dir: %v4f",
|
||||
&[
|
||||
ray_flags_id,
|
||||
tmin_id,
|
||||
tmax_id,
|
||||
ray_origin_id,
|
||||
ray_dir_id,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
function.consume(invalid_block, Instruction::branch(merge_label_id));
|
||||
|
||||
function.consume(merge_block, Instruction::return_void());
|
||||
|
||||
function.to_words(&mut self.logical_layout.function_definitions);
|
||||
|
||||
self.ray_tracing_functions
|
||||
.insert(LookupRaytracingFunction::TraceRay { payload }, func_id);
|
||||
|
||||
func_id
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockContext<'_> {
|
||||
pub(in super::super) fn write_ray_tracing_pipeline_function(
|
||||
&mut self,
|
||||
function: &crate::RayPipelineFunction,
|
||||
block: &mut Block,
|
||||
) {
|
||||
match *function {
|
||||
crate::RayPipelineFunction::TraceRay {
|
||||
acceleration_structure,
|
||||
descriptor,
|
||||
payload,
|
||||
} => {
|
||||
// Checked for when validating the module in `validate_block_impl`.
|
||||
let crate::Expression::GlobalVariable(payload) =
|
||||
self.ir_function.expressions[payload]
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let desc_id = self.cached[descriptor];
|
||||
let acc_struct_id = self.get_handle_id(acceleration_structure);
|
||||
|
||||
let func = self.writer.write_trace_ray(self.ir_module, payload);
|
||||
|
||||
let func_id = self.gen_id();
|
||||
block.body.push(Instruction::function_call(
|
||||
self.writer.void_type,
|
||||
func_id,
|
||||
func,
|
||||
&[acc_struct_id, desc_id],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,110 +2,16 @@
|
||||
Generating SPIR-V for ray query operations.
|
||||
*/
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
|
||||
use super::super::{
|
||||
Block, BlockContext, Function, FunctionArgument, Instruction, LocalType, LookupFunctionType,
|
||||
LookupRayQueryFunction, NumericType, Writer, WriterFlags,
|
||||
use super::{
|
||||
super::{
|
||||
Block, BlockContext, Instruction, LocalType, LookupRayQueryFunction, NumericType, Writer,
|
||||
WriterFlags,
|
||||
},
|
||||
write_ray_flags_contains_flags,
|
||||
};
|
||||
use crate::{arena::Handle, back::RayQueryPoint};
|
||||
|
||||
/// helper function to check if a particular flag is set in a u32.
|
||||
fn write_ray_flags_contains_flags(
|
||||
writer: &mut Writer,
|
||||
block: &mut Block,
|
||||
id: spirv::Word,
|
||||
flag: u32,
|
||||
) -> spirv::Word {
|
||||
let bit_id = writer.get_constant_scalar(crate::Literal::U32(flag));
|
||||
let zero_id = writer.get_constant_scalar(crate::Literal::U32(0));
|
||||
let u32_type_id = writer.get_u32_type_id();
|
||||
let bool_ty = writer.get_bool_type_id();
|
||||
|
||||
let and_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::BitwiseAnd,
|
||||
u32_type_id,
|
||||
and_id,
|
||||
id,
|
||||
bit_id,
|
||||
));
|
||||
|
||||
let eq_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::INotEqual,
|
||||
bool_ty,
|
||||
eq_id,
|
||||
and_id,
|
||||
zero_id,
|
||||
));
|
||||
|
||||
eq_id
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
/// writes a logical and of two scalar booleans
|
||||
fn write_logical_and(
|
||||
&mut self,
|
||||
block: &mut Block,
|
||||
one: spirv::Word,
|
||||
two: spirv::Word,
|
||||
) -> spirv::Word {
|
||||
let id = self.id_gen.next();
|
||||
let bool_id = self.get_bool_type_id();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalAnd,
|
||||
bool_id,
|
||||
id,
|
||||
one,
|
||||
two,
|
||||
));
|
||||
id
|
||||
}
|
||||
|
||||
fn write_reduce_and(&mut self, block: &mut Block, mut bools: Vec<spirv::Word>) -> spirv::Word {
|
||||
// The combined `and`ed together of all of the bools up to this point.
|
||||
let mut current_combined = bools.pop().unwrap();
|
||||
for boolean in bools {
|
||||
current_combined = self.write_logical_and(block, current_combined, boolean)
|
||||
}
|
||||
current_combined
|
||||
}
|
||||
|
||||
// returns the id of the function, the function, and ids for its arguments.
|
||||
fn write_function_signature(
|
||||
&mut self,
|
||||
arg_types: &[spirv::Word],
|
||||
return_ty: spirv::Word,
|
||||
) -> (spirv::Word, Function, Vec<spirv::Word>) {
|
||||
let func_ty = self.get_function_type(LookupFunctionType {
|
||||
parameter_type_ids: Vec::from(arg_types),
|
||||
return_type_id: return_ty,
|
||||
});
|
||||
|
||||
let mut function = Function::default();
|
||||
let func_id = self.id_gen.next();
|
||||
function.signature = Some(Instruction::function(
|
||||
return_ty,
|
||||
func_id,
|
||||
spirv::FunctionControl::empty(),
|
||||
func_ty,
|
||||
));
|
||||
|
||||
let mut arg_ids = Vec::with_capacity(arg_types.len());
|
||||
|
||||
for (idx, &arg_ty) in arg_types.iter().enumerate() {
|
||||
let id = self.id_gen.next();
|
||||
let instruction = Instruction::function_parameter(arg_ty, id);
|
||||
function.parameters.push(FunctionArgument {
|
||||
instruction,
|
||||
handle_id: idx as u32,
|
||||
});
|
||||
arg_ids.push(id);
|
||||
}
|
||||
(func_id, function, arg_ids)
|
||||
}
|
||||
|
||||
pub(in super::super) fn write_ray_query_get_intersection_function(
|
||||
&mut self,
|
||||
is_committed: bool,
|
||||
@@ -617,9 +523,6 @@ impl Writer {
|
||||
let f32_type_id = self.get_f32_type_id();
|
||||
let f32_ptr_ty = self.get_pointer_type_id(f32_type_id, spirv::StorageClass::Function);
|
||||
|
||||
let bool_type_id = self.get_bool_type_id();
|
||||
let bool_vec3_type_id = self.get_vec3_bool_type_id();
|
||||
|
||||
let (func_id, mut function, arg_ids) = self.write_function_signature(
|
||||
&[
|
||||
ray_query_type_id,
|
||||
@@ -640,327 +543,24 @@ impl Writer {
|
||||
let label_id = self.id_gen.next();
|
||||
let mut block = Block::new(label_id);
|
||||
|
||||
let flag_type_id = self.get_numeric_type_id(NumericType::Scalar(crate::Scalar::U32));
|
||||
|
||||
//Note: composite extract indices and types must match `generate_ray_desc_type`
|
||||
let ray_flags_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
flag_type_id,
|
||||
let super::ExtractedRayDesc {
|
||||
ray_flags_id,
|
||||
desc_id,
|
||||
&[0],
|
||||
));
|
||||
let cull_mask_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
flag_type_id,
|
||||
cull_mask_id,
|
||||
desc_id,
|
||||
&[1],
|
||||
));
|
||||
|
||||
let tmin_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
f32_type_id,
|
||||
tmin_id,
|
||||
desc_id,
|
||||
&[2],
|
||||
));
|
||||
let tmax_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
f32_type_id,
|
||||
tmax_id,
|
||||
ray_origin_id,
|
||||
ray_dir_id,
|
||||
valid_id,
|
||||
} = self.write_extract_ray_desc(
|
||||
&mut block,
|
||||
desc_id,
|
||||
&[3],
|
||||
));
|
||||
self.ray_query_initialization_tracking,
|
||||
);
|
||||
|
||||
block
|
||||
.body
|
||||
.push(Instruction::store(t_max_tracker_id, tmax_id, None));
|
||||
|
||||
let vector_type_id = self.get_numeric_type_id(NumericType::Vector {
|
||||
size: crate::VectorSize::Tri,
|
||||
scalar: crate::Scalar::F32,
|
||||
});
|
||||
let ray_origin_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
vector_type_id,
|
||||
ray_origin_id,
|
||||
desc_id,
|
||||
&[4],
|
||||
));
|
||||
let ray_dir_id = self.id_gen.next();
|
||||
block.body.push(Instruction::composite_extract(
|
||||
vector_type_id,
|
||||
ray_dir_id,
|
||||
desc_id,
|
||||
&[5],
|
||||
));
|
||||
|
||||
let valid_id = self.ray_query_initialization_tracking.then(||{
|
||||
let tmin_le_tmax_id = self.id_gen.next();
|
||||
// Check both that tmin is less than or equal to tmax (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06350)
|
||||
// and implicitly that neither tmin or tmax are NaN (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06351)
|
||||
// because this checks if tmin and tmax are ordered too (i.e: not NaN).
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::FOrdLessThanEqual,
|
||||
bool_type_id,
|
||||
tmin_le_tmax_id,
|
||||
tmin_id,
|
||||
tmax_id,
|
||||
));
|
||||
|
||||
// Check that tmin is greater than or equal to 0 (and
|
||||
// therefore also tmax is too because it is greater than
|
||||
// or equal to tmin) (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06349).
|
||||
let tmin_ge_zero_id = self.id_gen.next();
|
||||
let zero_id = self.get_constant_scalar(crate::Literal::F32(0.0));
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::FOrdGreaterThanEqual,
|
||||
bool_type_id,
|
||||
tmin_ge_zero_id,
|
||||
tmin_id,
|
||||
zero_id,
|
||||
));
|
||||
|
||||
// Check that ray origin is finite (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06348)
|
||||
let ray_origin_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsInf,
|
||||
bool_vec3_type_id,
|
||||
ray_origin_infinite_id,
|
||||
ray_origin_id,
|
||||
));
|
||||
let any_ray_origin_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_origin_infinite_id,
|
||||
ray_origin_infinite_id,
|
||||
));
|
||||
|
||||
let ray_origin_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsNan,
|
||||
bool_vec3_type_id,
|
||||
ray_origin_nan_id,
|
||||
ray_origin_id,
|
||||
));
|
||||
let any_ray_origin_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_origin_nan_id,
|
||||
ray_origin_nan_id,
|
||||
));
|
||||
|
||||
let ray_origin_not_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalOr,
|
||||
bool_type_id,
|
||||
ray_origin_not_finite_id,
|
||||
any_ray_origin_nan_id,
|
||||
any_ray_origin_infinite_id,
|
||||
));
|
||||
|
||||
let all_ray_origin_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::LogicalNot,
|
||||
bool_type_id,
|
||||
all_ray_origin_finite_id,
|
||||
ray_origin_not_finite_id,
|
||||
));
|
||||
|
||||
// Check that ray direction is finite (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06348)
|
||||
let ray_dir_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsInf,
|
||||
bool_vec3_type_id,
|
||||
ray_dir_infinite_id,
|
||||
ray_dir_id,
|
||||
));
|
||||
let any_ray_dir_infinite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_dir_infinite_id,
|
||||
ray_dir_infinite_id,
|
||||
));
|
||||
|
||||
let ray_dir_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::IsNan,
|
||||
bool_vec3_type_id,
|
||||
ray_dir_nan_id,
|
||||
ray_dir_id,
|
||||
));
|
||||
let any_ray_dir_nan_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::Any,
|
||||
bool_type_id,
|
||||
any_ray_dir_nan_id,
|
||||
ray_dir_nan_id,
|
||||
));
|
||||
|
||||
let ray_dir_not_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalOr,
|
||||
bool_type_id,
|
||||
ray_dir_not_finite_id,
|
||||
any_ray_dir_nan_id,
|
||||
any_ray_dir_infinite_id,
|
||||
));
|
||||
|
||||
let all_ray_dir_finite_id = self.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::LogicalNot,
|
||||
bool_type_id,
|
||||
all_ray_dir_finite_id,
|
||||
ray_dir_not_finite_id,
|
||||
));
|
||||
|
||||
/// Writes spirv to check that less than two booleans are true
|
||||
///
|
||||
/// For each boolean: removes it, `and`s it with all others (i.e for all possible combinations of two booleans in the list checks to see if both are true).
|
||||
/// Then `or`s all of these checks together. This produces whether two or more booleans are true.
|
||||
fn write_less_than_2_true(
|
||||
writer: &mut Writer,
|
||||
block: &mut Block,
|
||||
mut bools: Vec<spirv::Word>,
|
||||
) -> spirv::Word {
|
||||
assert!(bools.len() > 1, "Must have multiple booleans!");
|
||||
let bool_ty = writer.get_bool_type_id();
|
||||
let mut each_two_true = Vec::new();
|
||||
while let Some(last_bool) = bools.pop() {
|
||||
for &bool in &bools {
|
||||
let both_true_id = writer.write_logical_and(
|
||||
block,
|
||||
last_bool,
|
||||
bool,
|
||||
);
|
||||
each_two_true.push(both_true_id);
|
||||
}
|
||||
}
|
||||
let mut all_or_id = each_two_true.pop().expect("since this must have multiple booleans, there must be at least one thing in `each_two_true`");
|
||||
for two_true in each_two_true {
|
||||
let new_all_or_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::binary(
|
||||
spirv::Op::LogicalOr,
|
||||
bool_ty,
|
||||
new_all_or_id,
|
||||
all_or_id,
|
||||
two_true,
|
||||
));
|
||||
all_or_id = new_all_or_id;
|
||||
}
|
||||
|
||||
let less_than_two_id = writer.id_gen.next();
|
||||
block.body.push(Instruction::unary(
|
||||
spirv::Op::LogicalNot,
|
||||
bool_ty,
|
||||
less_than_two_id,
|
||||
all_or_id,
|
||||
));
|
||||
less_than_two_id
|
||||
}
|
||||
|
||||
// Check that at most one of skip triangles and skip AABBs is
|
||||
// present (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06889)
|
||||
let contains_skip_triangles = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::SKIP_TRIANGLES.bits(),
|
||||
);
|
||||
let contains_skip_aabbs = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::SKIP_AABBS.bits(),
|
||||
);
|
||||
|
||||
let not_contain_skip_triangles_aabbs = write_less_than_2_true(
|
||||
self,
|
||||
&mut block,
|
||||
vec![contains_skip_triangles, contains_skip_aabbs],
|
||||
);
|
||||
|
||||
// Check that at most one of skip triangles (taken from above check),
|
||||
// cull back facing, and cull front face is present (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06890)
|
||||
let contains_cull_back = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_BACK_FACING.bits(),
|
||||
);
|
||||
let contains_cull_front = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_FRONT_FACING.bits(),
|
||||
);
|
||||
|
||||
let not_contain_skip_triangles_cull = write_less_than_2_true(
|
||||
self,
|
||||
&mut block,
|
||||
vec![
|
||||
contains_skip_triangles,
|
||||
contains_cull_back,
|
||||
contains_cull_front,
|
||||
],
|
||||
);
|
||||
|
||||
// Check that at most one of force opaque, force not opaque, cull opaque,
|
||||
// and cull not opaque are present (https://docs.vulkan.org/spec/latest/appendices/spirvenv.html#VUID-RuntimeSpirv-OpRayQueryInitializeKHR-06891)
|
||||
let contains_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::FORCE_OPAQUE.bits(),
|
||||
);
|
||||
let contains_no_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::FORCE_NO_OPAQUE.bits(),
|
||||
);
|
||||
let contains_cull_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_OPAQUE.bits(),
|
||||
);
|
||||
let contains_cull_no_opaque = write_ray_flags_contains_flags(
|
||||
self,
|
||||
&mut block,
|
||||
ray_flags_id,
|
||||
crate::RayFlag::CULL_NO_OPAQUE.bits(),
|
||||
);
|
||||
|
||||
let not_contain_multiple_opaque = write_less_than_2_true(
|
||||
self,
|
||||
&mut block,
|
||||
vec![
|
||||
contains_opaque,
|
||||
contains_no_opaque,
|
||||
contains_cull_opaque,
|
||||
contains_cull_no_opaque,
|
||||
],
|
||||
);
|
||||
|
||||
// Combine all checks into a single flag saying whether the call is valid or not.
|
||||
self.write_reduce_and(
|
||||
&mut block,
|
||||
vec![
|
||||
tmin_le_tmax_id,
|
||||
tmin_ge_zero_id,
|
||||
all_ray_origin_finite_id,
|
||||
all_ray_dir_finite_id,
|
||||
not_contain_skip_triangles_aabbs,
|
||||
not_contain_skip_triangles_cull,
|
||||
not_contain_multiple_opaque,
|
||||
],
|
||||
)
|
||||
});
|
||||
|
||||
let merge_label_id = self.id_gen.next();
|
||||
let merge_block = Block::new(merge_label_id);
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ impl Writer {
|
||||
zero_initialize_workgroup_memory: options.zero_initialize_workgroup_memory,
|
||||
force_loop_bounding: options.force_loop_bounding,
|
||||
ray_query_initialization_tracking: options.ray_query_initialization_tracking,
|
||||
trace_ray_argument_validation: options.trace_ray_argument_validation,
|
||||
use_storage_input_output_16: options.use_storage_input_output_16,
|
||||
void_type,
|
||||
tuple_of_u32s_ty_id: None,
|
||||
@@ -111,6 +112,8 @@ impl Writer {
|
||||
gl450_ext_inst_id,
|
||||
temp_list: Vec::new(),
|
||||
ray_query_functions: crate::FastHashMap::default(),
|
||||
ray_tracing_functions: crate::FastHashMap::default(),
|
||||
has_ray_tracing_pipeline: false,
|
||||
io_f16_polyfills: super::f16_polyfill::F16IoPolyfill::new(
|
||||
options.use_storage_input_output_16,
|
||||
),
|
||||
@@ -171,6 +174,7 @@ impl Writer {
|
||||
zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
|
||||
force_loop_bounding: self.force_loop_bounding,
|
||||
ray_query_initialization_tracking: self.ray_query_initialization_tracking,
|
||||
trace_ray_argument_validation: self.trace_ray_argument_validation,
|
||||
use_storage_input_output_16: self.use_storage_input_output_16,
|
||||
capabilities_available: take(&mut self.capabilities_available),
|
||||
fake_missing_bindings: self.fake_missing_bindings,
|
||||
@@ -203,6 +207,8 @@ impl Writer {
|
||||
saved_cached: take(&mut self.saved_cached).reclaim(),
|
||||
temp_list: take(&mut self.temp_list).reclaim(),
|
||||
ray_query_functions: take(&mut self.ray_query_functions).reclaim(),
|
||||
ray_tracing_functions: take(&mut self.ray_tracing_functions).reclaim(),
|
||||
has_ray_tracing_pipeline: false,
|
||||
io_f16_polyfills: take(&mut self.io_f16_polyfills).reclaim(),
|
||||
debug_printf: None,
|
||||
};
|
||||
@@ -1857,10 +1863,22 @@ impl Writer {
|
||||
.to_words(&mut self.logical_layout.execution_modes);
|
||||
spirv::ExecutionModel::MeshEXT
|
||||
}
|
||||
crate::ShaderStage::RayGeneration
|
||||
| crate::ShaderStage::AnyHit
|
||||
| crate::ShaderStage::ClosestHit
|
||||
| crate::ShaderStage::Miss => unreachable!(),
|
||||
crate::ShaderStage::RayGeneration => {
|
||||
self.require_any("ray tracing pipelines", &[spirv::Capability::RayTracingKHR])?;
|
||||
spirv::ExecutionModel::RayGenerationKHR
|
||||
}
|
||||
crate::ShaderStage::AnyHit => {
|
||||
self.require_any("ray tracing pipelines", &[spirv::Capability::RayTracingKHR])?;
|
||||
spirv::ExecutionModel::AnyHitKHR
|
||||
}
|
||||
crate::ShaderStage::ClosestHit => {
|
||||
self.require_any("ray tracing pipelines", &[spirv::Capability::RayTracingKHR])?;
|
||||
spirv::ExecutionModel::ClosestHitKHR
|
||||
}
|
||||
crate::ShaderStage::Miss => {
|
||||
self.require_any("ray tracing pipelines", &[spirv::Capability::RayTracingKHR])?;
|
||||
spirv::ExecutionModel::MissKHR
|
||||
}
|
||||
};
|
||||
//self.check(exec_model.required_capabilities())?;
|
||||
|
||||
@@ -1960,7 +1978,16 @@ impl Writer {
|
||||
}
|
||||
}
|
||||
crate::TypeInner::AccelerationStructure { .. } => {
|
||||
self.require_any("Acceleration Structure", &[spirv::Capability::RayQueryKHR])?;
|
||||
self.require_any(
|
||||
"Acceleration Structure",
|
||||
// unless we use this conditional, the ray query snapshot
|
||||
// tests pick the wrong capability
|
||||
&[if self.has_ray_tracing_pipeline {
|
||||
spirv::Capability::RayTracingKHR
|
||||
} else {
|
||||
spirv::Capability::RayQueryKHR
|
||||
}],
|
||||
)?;
|
||||
}
|
||||
crate::TypeInner::RayQuery { .. } => {
|
||||
self.require_any("Ray Query", &[spirv::Capability::RayQueryKHR])?;
|
||||
@@ -3198,19 +3225,20 @@ impl Writer {
|
||||
Bi::VertexCount | Bi::Vertices | Bi::PrimitiveCount | Bi::Primitives => {
|
||||
unreachable!()
|
||||
}
|
||||
Bi::RayInvocationId
|
||||
| Bi::NumRayInvocations
|
||||
| Bi::InstanceCustomData
|
||||
| Bi::GeometryIndex
|
||||
| Bi::WorldRayOrigin
|
||||
| Bi::WorldRayDirection
|
||||
| Bi::ObjectRayOrigin
|
||||
| Bi::ObjectRayDirection
|
||||
| Bi::RayTmin
|
||||
| Bi::RayTCurrentMax
|
||||
| Bi::ObjectToWorld
|
||||
| Bi::WorldToObject
|
||||
| Bi::HitKind => unreachable!(),
|
||||
// ray tracing pipeline
|
||||
Bi::RayInvocationId => BuiltIn::LaunchIdKHR,
|
||||
Bi::NumRayInvocations => BuiltIn::LaunchSizeKHR,
|
||||
Bi::InstanceCustomData => BuiltIn::InstanceCustomIndexKHR,
|
||||
Bi::GeometryIndex => BuiltIn::RayGeometryIndexKHR,
|
||||
Bi::WorldRayOrigin => BuiltIn::WorldRayOriginKHR,
|
||||
Bi::WorldRayDirection => BuiltIn::WorldRayDirectionKHR,
|
||||
Bi::ObjectRayOrigin => BuiltIn::ObjectRayOriginKHR,
|
||||
Bi::ObjectRayDirection => BuiltIn::ObjectRayDirectionKHR,
|
||||
Bi::RayTmin => BuiltIn::RayTminKHR,
|
||||
Bi::RayTCurrentMax => BuiltIn::RayTmaxKHR,
|
||||
Bi::ObjectToWorld => BuiltIn::ObjectToWorldKHR,
|
||||
Bi::WorldToObject => BuiltIn::WorldToObjectKHR,
|
||||
Bi::HitKind => BuiltIn::HitKindKHR,
|
||||
};
|
||||
|
||||
use crate::ScalarKind as Sk;
|
||||
@@ -3297,6 +3325,12 @@ impl Writer {
|
||||
let id = self.id_gen.next();
|
||||
let class = map_storage_class(global_variable.space);
|
||||
|
||||
if let crate::AddressSpace::RayPayload | crate::AddressSpace::IncomingRayPayload =
|
||||
global_variable.space
|
||||
{
|
||||
self.require_any("ray tracing pipelines", &[spirv::Capability::RayTracingKHR])?;
|
||||
}
|
||||
|
||||
//self.check(class.required_capabilities())?;
|
||||
|
||||
if global_variable
|
||||
@@ -3575,18 +3609,13 @@ impl Writer {
|
||||
.iter()
|
||||
.flat_map(|entry| entry.function.arguments.iter())
|
||||
.any(|arg| has_view_index_check(ir_module, arg.binding.as_ref(), arg.ty));
|
||||
let mut has_ray_query = ir_module.special_types.ray_desc.is_some()
|
||||
| ir_module.special_types.ray_intersection.is_some();
|
||||
let has_vertex_return = ir_module.special_types.ray_vertex_return.is_some();
|
||||
|
||||
for (_, &crate::Type { ref inner, .. }) in ir_module.types.iter() {
|
||||
// spirv does not know whether these have vertex return - that is done by us
|
||||
if let &crate::TypeInner::AccelerationStructure { .. }
|
||||
| &crate::TypeInner::RayQuery { .. } = inner
|
||||
{
|
||||
has_ray_query = true
|
||||
}
|
||||
}
|
||||
let rt_uses = ir_module.uses_ray_tracing(ep_index);
|
||||
let has_ray_query = rt_uses.queries;
|
||||
let has_ray_tracing_pipeline = rt_uses.pipelines;
|
||||
|
||||
self.has_ray_tracing_pipeline = has_ray_tracing_pipeline;
|
||||
|
||||
if self.physical_layout.version < 0x10300 && has_storage_buffers {
|
||||
// enable the storage buffer class on < SPV-1.3
|
||||
@@ -3613,6 +3642,10 @@ impl Writer {
|
||||
return Err(Error::SpirvVersionTooLow(1, 4));
|
||||
}
|
||||
}
|
||||
if has_ray_tracing_pipeline {
|
||||
Instruction::extension("SPV_KHR_ray_tracing")
|
||||
.to_words(&mut self.logical_layout.extensions)
|
||||
}
|
||||
Instruction::type_void(self.void_type).to_words(&mut self.logical_layout.declarations);
|
||||
Instruction::ext_inst_import(self.gl450_ext_inst_id, "GLSL.std.450")
|
||||
.to_words(&mut self.logical_layout.ext_inst_imports);
|
||||
|
||||
@@ -948,6 +948,55 @@ impl crate::Module {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn uses_ray_tracing(&self, ep_index: Option<usize>) -> RayTracingUses {
|
||||
let mut uses = RayTracingUses::default();
|
||||
// Whether this uses ray tracing (unknown whether the usage is pipelines or ray queries).
|
||||
let mut uses_ray_tracing = self.special_types.ray_desc.is_some();
|
||||
|
||||
uses.queries |= self.special_types.ray_intersection.is_some();
|
||||
|
||||
for (_, &crate::Type { ref inner, .. }) in self.types.iter() {
|
||||
// Backends do not know whether these have vertex return - that is done by us
|
||||
match *inner {
|
||||
crate::TypeInner::AccelerationStructure { .. } => {
|
||||
uses_ray_tracing = true;
|
||||
}
|
||||
crate::TypeInner::RayQuery { .. } => uses.queries = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
for (index, ep) in self.entry_points.iter().enumerate() {
|
||||
if ep_index.is_some() && ep_index != Some(index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we have a ray tracing pipeline shader we are definitely using
|
||||
// pipelines, otherwise, if we have a ray tracing type, we might
|
||||
// be using it in the shader (which would require ray queries),
|
||||
// so we should use queries.
|
||||
if matches!(
|
||||
ep.stage,
|
||||
crate::ShaderStage::RayGeneration
|
||||
| crate::ShaderStage::AnyHit
|
||||
| crate::ShaderStage::ClosestHit
|
||||
| crate::ShaderStage::Miss
|
||||
) {
|
||||
uses.pipelines = true;
|
||||
} else {
|
||||
uses.queries |= uses_ray_tracing;
|
||||
}
|
||||
}
|
||||
|
||||
uses
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct RayTracingUses {
|
||||
pub pipelines: bool,
|
||||
pub queries: bool,
|
||||
}
|
||||
|
||||
impl crate::MeshOutputTopology {
|
||||
|
||||
@@ -234,6 +234,8 @@ pub enum FunctionError {
|
||||
InvalidPayloadAddressSpace(crate::AddressSpace),
|
||||
#[error("The payload type ({0:?}) passed to `traceRay` does not match the previous one {1:?}")]
|
||||
MismatchedPayloadType(Handle<crate::Type>, Handle<crate::Type>),
|
||||
#[error("The payload passed to `traceRay` must be a pointer directly to a global variable")]
|
||||
PayloadPointerNotGlobal,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
@@ -1735,6 +1737,13 @@ impl super::Validator {
|
||||
}
|
||||
};
|
||||
|
||||
// spir-v requires a direct reference to a global variable.
|
||||
let crate::Expression::GlobalVariable(_) = context.expressions[payload]
|
||||
else {
|
||||
return Err(FunctionError::PayloadPointerNotGlobal
|
||||
.with_span_handle(payload, context.expressions));
|
||||
};
|
||||
|
||||
let ty = *self
|
||||
.trace_rays_payload_type
|
||||
.get_or_insert(current_payload_ty);
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
capabilities = "RAY_TRACING_PIPELINE"
|
||||
targets = "WGSL"
|
||||
targets = "WGSL | SPIRV"
|
||||
|
||||
@@ -62,8 +62,8 @@ OpDecorate %13 Binding 0
|
||||
%33 = OpTypePointer Function %7
|
||||
%35 = OpConstant %7 0
|
||||
%36 = OpTypePointer Function %5
|
||||
%39 = OpTypeVector %10 3
|
||||
%40 = OpTypeFunction %2 %32 %4 %8 %33 %36
|
||||
%39 = OpTypeFunction %2 %32 %4 %8 %33 %36
|
||||
%47 = OpTypeVector %10 3
|
||||
%68 = OpConstant %7 256
|
||||
%71 = OpConstant %7 512
|
||||
%76 = OpConstant %7 16
|
||||
@@ -85,31 +85,30 @@ OpDecorate %13 Binding 0
|
||||
%175 = OpConstant %7 8
|
||||
%184 = OpTypeFunction %2 %32 %33 %5 %36
|
||||
%225 = OpTypeFunction %2 %32 %33
|
||||
%41 = OpFunction %2 None %40
|
||||
%42 = OpFunctionParameter %32
|
||||
%43 = OpFunctionParameter %4
|
||||
%44 = OpFunctionParameter %8
|
||||
%45 = OpFunctionParameter %33
|
||||
%46 = OpFunctionParameter %36
|
||||
%47 = OpLabel
|
||||
%48 = OpCompositeExtract %7 %44 0
|
||||
%49 = OpCompositeExtract %7 %44 1
|
||||
%50 = OpCompositeExtract %5 %44 2
|
||||
%51 = OpCompositeExtract %5 %44 3
|
||||
OpStore %46 %51
|
||||
%52 = OpCompositeExtract %6 %44 4
|
||||
%53 = OpCompositeExtract %6 %44 5
|
||||
%40 = OpFunction %2 None %39
|
||||
%41 = OpFunctionParameter %32
|
||||
%42 = OpFunctionParameter %4
|
||||
%43 = OpFunctionParameter %8
|
||||
%44 = OpFunctionParameter %33
|
||||
%45 = OpFunctionParameter %36
|
||||
%46 = OpLabel
|
||||
%48 = OpCompositeExtract %7 %43 0
|
||||
%49 = OpCompositeExtract %7 %43 1
|
||||
%50 = OpCompositeExtract %5 %43 2
|
||||
%51 = OpCompositeExtract %5 %43 3
|
||||
%52 = OpCompositeExtract %6 %43 4
|
||||
%53 = OpCompositeExtract %6 %43 5
|
||||
%54 = OpFOrdLessThanEqual %10 %50 %51
|
||||
%55 = OpFOrdGreaterThanEqual %10 %50 %19
|
||||
%56 = OpIsInf %39 %52
|
||||
%56 = OpIsInf %47 %52
|
||||
%57 = OpAny %10 %56
|
||||
%58 = OpIsNan %39 %52
|
||||
%58 = OpIsNan %47 %52
|
||||
%59 = OpAny %10 %58
|
||||
%60 = OpLogicalOr %10 %59 %57
|
||||
%61 = OpLogicalNot %10 %60
|
||||
%62 = OpIsInf %39 %53
|
||||
%62 = OpIsInf %47 %53
|
||||
%63 = OpAny %10 %62
|
||||
%64 = OpIsNan %39 %53
|
||||
%64 = OpIsNan %47 %53
|
||||
%65 = OpAny %10 %64
|
||||
%66 = OpLogicalOr %10 %65 %63
|
||||
%67 = OpLogicalNot %10 %66
|
||||
@@ -155,11 +154,12 @@ OpStore %46 %51
|
||||
%114 = OpLogicalAnd %10 %113 %67
|
||||
%115 = OpLogicalAnd %10 %114 %75
|
||||
%116 = OpLogicalAnd %10 %115 %87
|
||||
OpStore %45 %51
|
||||
OpSelectionMerge %117 None
|
||||
OpBranchConditional %116 %119 %118
|
||||
%119 = OpLabel
|
||||
OpRayQueryInitializeKHR %42 %43 %48 %49 %52 %50 %53 %51
|
||||
OpStore %45 %30
|
||||
OpRayQueryInitializeKHR %41 %42 %48 %49 %52 %50 %53 %51
|
||||
OpStore %44 %30
|
||||
OpBranch %117
|
||||
%118 = OpLabel
|
||||
OpBranch %117
|
||||
@@ -335,7 +335,7 @@ OpFunctionEnd
|
||||
%18 = OpLoad %4 %13
|
||||
OpBranch %38
|
||||
%38 = OpLabel
|
||||
%120 = OpFunctionCall %2 %41 %31 %18 %27 %34 %37
|
||||
%120 = OpFunctionCall %2 %40 %31 %18 %27 %34 %37
|
||||
%178 = OpFunctionCall %12 %126 %31 %34
|
||||
%179 = OpCompositeExtract %7 %178 0
|
||||
%180 = OpIEqual %10 %179 %28
|
||||
|
||||
@@ -44,9 +44,9 @@ OpDecorate %10 Binding 0
|
||||
%31 = OpConstant %6 0
|
||||
%32 = OpTypePointer Function %3
|
||||
%34 = OpConstant %3 0
|
||||
%36 = OpTypeBool
|
||||
%37 = OpTypeVector %36 3
|
||||
%38 = OpTypeFunction %2 %28 %4 %8 %29 %32
|
||||
%36 = OpTypeFunction %2 %28 %4 %8 %29 %32
|
||||
%44 = OpTypeBool
|
||||
%45 = OpTypeVector %44 3
|
||||
%66 = OpConstant %6 256
|
||||
%69 = OpConstant %6 512
|
||||
%74 = OpConstant %6 16
|
||||
@@ -57,114 +57,114 @@ OpDecorate %10 Binding 0
|
||||
%95 = OpConstant %6 128
|
||||
%124 = OpTypeVector %6 2
|
||||
%125 = OpTypePointer Function %124
|
||||
%126 = OpTypeVector %36 2
|
||||
%126 = OpTypeVector %44 2
|
||||
%127 = OpConstantComposite %124 %31 %31
|
||||
%128 = OpConstant %6 4294967295
|
||||
%129 = OpConstantComposite %124 %128 %128
|
||||
%142 = OpTypePointer Function %36
|
||||
%143 = OpTypeFunction %36 %28 %29
|
||||
%149 = OpConstantFalse %36
|
||||
%142 = OpTypePointer Function %44
|
||||
%143 = OpTypeFunction %44 %28 %29
|
||||
%149 = OpConstantFalse %44
|
||||
%156 = OpConstant %6 6
|
||||
%39 = OpFunction %2 None %38
|
||||
%40 = OpFunctionParameter %28
|
||||
%41 = OpFunctionParameter %4
|
||||
%42 = OpFunctionParameter %8
|
||||
%43 = OpFunctionParameter %29
|
||||
%44 = OpFunctionParameter %32
|
||||
%45 = OpLabel
|
||||
%46 = OpCompositeExtract %6 %42 0
|
||||
%47 = OpCompositeExtract %6 %42 1
|
||||
%48 = OpCompositeExtract %3 %42 2
|
||||
%49 = OpCompositeExtract %3 %42 3
|
||||
OpStore %44 %49
|
||||
%50 = OpCompositeExtract %7 %42 4
|
||||
%51 = OpCompositeExtract %7 %42 5
|
||||
%52 = OpFOrdLessThanEqual %36 %48 %49
|
||||
%53 = OpFOrdGreaterThanEqual %36 %48 %34
|
||||
%54 = OpIsInf %37 %50
|
||||
%55 = OpAny %36 %54
|
||||
%56 = OpIsNan %37 %50
|
||||
%57 = OpAny %36 %56
|
||||
%58 = OpLogicalOr %36 %57 %55
|
||||
%59 = OpLogicalNot %36 %58
|
||||
%60 = OpIsInf %37 %51
|
||||
%61 = OpAny %36 %60
|
||||
%62 = OpIsNan %37 %51
|
||||
%63 = OpAny %36 %62
|
||||
%64 = OpLogicalOr %36 %63 %61
|
||||
%65 = OpLogicalNot %36 %64
|
||||
%37 = OpFunction %2 None %36
|
||||
%38 = OpFunctionParameter %28
|
||||
%39 = OpFunctionParameter %4
|
||||
%40 = OpFunctionParameter %8
|
||||
%41 = OpFunctionParameter %29
|
||||
%42 = OpFunctionParameter %32
|
||||
%43 = OpLabel
|
||||
%46 = OpCompositeExtract %6 %40 0
|
||||
%47 = OpCompositeExtract %6 %40 1
|
||||
%48 = OpCompositeExtract %3 %40 2
|
||||
%49 = OpCompositeExtract %3 %40 3
|
||||
%50 = OpCompositeExtract %7 %40 4
|
||||
%51 = OpCompositeExtract %7 %40 5
|
||||
%52 = OpFOrdLessThanEqual %44 %48 %49
|
||||
%53 = OpFOrdGreaterThanEqual %44 %48 %34
|
||||
%54 = OpIsInf %45 %50
|
||||
%55 = OpAny %44 %54
|
||||
%56 = OpIsNan %45 %50
|
||||
%57 = OpAny %44 %56
|
||||
%58 = OpLogicalOr %44 %57 %55
|
||||
%59 = OpLogicalNot %44 %58
|
||||
%60 = OpIsInf %45 %51
|
||||
%61 = OpAny %44 %60
|
||||
%62 = OpIsNan %45 %51
|
||||
%63 = OpAny %44 %62
|
||||
%64 = OpLogicalOr %44 %63 %61
|
||||
%65 = OpLogicalNot %44 %64
|
||||
%67 = OpBitwiseAnd %6 %46 %66
|
||||
%68 = OpINotEqual %36 %67 %31
|
||||
%68 = OpINotEqual %44 %67 %31
|
||||
%70 = OpBitwiseAnd %6 %46 %69
|
||||
%71 = OpINotEqual %36 %70 %31
|
||||
%72 = OpLogicalAnd %36 %71 %68
|
||||
%73 = OpLogicalNot %36 %72
|
||||
%71 = OpINotEqual %44 %70 %31
|
||||
%72 = OpLogicalAnd %44 %71 %68
|
||||
%73 = OpLogicalNot %44 %72
|
||||
%75 = OpBitwiseAnd %6 %46 %74
|
||||
%76 = OpINotEqual %36 %75 %31
|
||||
%76 = OpINotEqual %44 %75 %31
|
||||
%78 = OpBitwiseAnd %6 %46 %77
|
||||
%79 = OpINotEqual %36 %78 %31
|
||||
%80 = OpLogicalAnd %36 %79 %68
|
||||
%81 = OpLogicalAnd %36 %79 %76
|
||||
%82 = OpLogicalAnd %36 %76 %68
|
||||
%83 = OpLogicalOr %36 %82 %80
|
||||
%84 = OpLogicalOr %36 %83 %81
|
||||
%85 = OpLogicalNot %36 %84
|
||||
%79 = OpINotEqual %44 %78 %31
|
||||
%80 = OpLogicalAnd %44 %79 %68
|
||||
%81 = OpLogicalAnd %44 %79 %76
|
||||
%82 = OpLogicalAnd %44 %76 %68
|
||||
%83 = OpLogicalOr %44 %82 %80
|
||||
%84 = OpLogicalOr %44 %83 %81
|
||||
%85 = OpLogicalNot %44 %84
|
||||
%87 = OpBitwiseAnd %6 %46 %86
|
||||
%88 = OpINotEqual %36 %87 %31
|
||||
%88 = OpINotEqual %44 %87 %31
|
||||
%90 = OpBitwiseAnd %6 %46 %89
|
||||
%91 = OpINotEqual %36 %90 %31
|
||||
%91 = OpINotEqual %44 %90 %31
|
||||
%93 = OpBitwiseAnd %6 %46 %92
|
||||
%94 = OpINotEqual %36 %93 %31
|
||||
%94 = OpINotEqual %44 %93 %31
|
||||
%96 = OpBitwiseAnd %6 %46 %95
|
||||
%97 = OpINotEqual %36 %96 %31
|
||||
%98 = OpLogicalAnd %36 %97 %88
|
||||
%99 = OpLogicalAnd %36 %97 %91
|
||||
%100 = OpLogicalAnd %36 %97 %94
|
||||
%101 = OpLogicalAnd %36 %94 %88
|
||||
%102 = OpLogicalAnd %36 %94 %91
|
||||
%103 = OpLogicalAnd %36 %91 %88
|
||||
%104 = OpLogicalOr %36 %103 %98
|
||||
%105 = OpLogicalOr %36 %104 %99
|
||||
%106 = OpLogicalOr %36 %105 %100
|
||||
%107 = OpLogicalOr %36 %106 %101
|
||||
%108 = OpLogicalOr %36 %107 %102
|
||||
%109 = OpLogicalNot %36 %108
|
||||
%110 = OpLogicalAnd %36 %109 %52
|
||||
%111 = OpLogicalAnd %36 %110 %53
|
||||
%112 = OpLogicalAnd %36 %111 %59
|
||||
%113 = OpLogicalAnd %36 %112 %65
|
||||
%114 = OpLogicalAnd %36 %113 %73
|
||||
%115 = OpLogicalAnd %36 %114 %85
|
||||
%97 = OpINotEqual %44 %96 %31
|
||||
%98 = OpLogicalAnd %44 %97 %88
|
||||
%99 = OpLogicalAnd %44 %97 %91
|
||||
%100 = OpLogicalAnd %44 %97 %94
|
||||
%101 = OpLogicalAnd %44 %94 %88
|
||||
%102 = OpLogicalAnd %44 %94 %91
|
||||
%103 = OpLogicalAnd %44 %91 %88
|
||||
%104 = OpLogicalOr %44 %103 %98
|
||||
%105 = OpLogicalOr %44 %104 %99
|
||||
%106 = OpLogicalOr %44 %105 %100
|
||||
%107 = OpLogicalOr %44 %106 %101
|
||||
%108 = OpLogicalOr %44 %107 %102
|
||||
%109 = OpLogicalNot %44 %108
|
||||
%110 = OpLogicalAnd %44 %109 %52
|
||||
%111 = OpLogicalAnd %44 %110 %53
|
||||
%112 = OpLogicalAnd %44 %111 %59
|
||||
%113 = OpLogicalAnd %44 %112 %65
|
||||
%114 = OpLogicalAnd %44 %113 %73
|
||||
%115 = OpLogicalAnd %44 %114 %85
|
||||
OpStore %42 %49
|
||||
OpSelectionMerge %116 None
|
||||
OpBranchConditional %115 %118 %117
|
||||
%118 = OpLabel
|
||||
OpRayQueryInitializeKHR %40 %41 %46 %47 %50 %48 %51 %49
|
||||
OpStore %43 %86
|
||||
OpRayQueryInitializeKHR %38 %39 %46 %47 %50 %48 %51 %49
|
||||
OpStore %41 %86
|
||||
OpBranch %116
|
||||
%117 = OpLabel
|
||||
OpBranch %116
|
||||
%116 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%144 = OpFunction %36 None %143
|
||||
%144 = OpFunction %44 None %143
|
||||
%145 = OpFunctionParameter %28
|
||||
%146 = OpFunctionParameter %29
|
||||
%147 = OpLabel
|
||||
%148 = OpVariable %142 Function %149
|
||||
%150 = OpLoad %6 %146
|
||||
%153 = OpBitwiseAnd %6 %150 %86
|
||||
%154 = OpINotEqual %36 %153 %31
|
||||
%154 = OpINotEqual %44 %153 %31
|
||||
OpSelectionMerge %151 None
|
||||
OpBranchConditional %154 %152 %151
|
||||
%152 = OpLabel
|
||||
%155 = OpRayQueryProceedKHR %36 %145
|
||||
%155 = OpRayQueryProceedKHR %44 %145
|
||||
OpStore %148 %155
|
||||
%157 = OpSelect %6 %155 %89 %156
|
||||
%158 = OpBitwiseOr %6 %150 %157
|
||||
OpStore %146 %158
|
||||
OpBranch %151
|
||||
%151 = OpLabel
|
||||
%159 = OpLoad %36 %148
|
||||
%159 = OpLoad %44 %148
|
||||
OpReturnValue %159
|
||||
OpFunctionEnd
|
||||
%13 = OpFunction %2 None %14
|
||||
@@ -176,7 +176,7 @@ OpFunctionEnd
|
||||
%15 = OpLoad %4 %10
|
||||
OpBranch %35
|
||||
%35 = OpLabel
|
||||
%119 = OpFunctionCall %2 %39 %27 %15 %26 %30 %33
|
||||
%119 = OpFunctionCall %2 %37 %27 %15 %26 %30 %33
|
||||
OpBranch %120
|
||||
%120 = OpLabel
|
||||
OpLoopMerge %121 %123 None
|
||||
@@ -184,19 +184,19 @@ OpBranch %131
|
||||
%131 = OpLabel
|
||||
%132 = OpLoad %124 %130
|
||||
%133 = OpIEqual %126 %127 %132
|
||||
%134 = OpAll %36 %133
|
||||
%134 = OpAll %44 %133
|
||||
OpSelectionMerge %135 None
|
||||
OpBranchConditional %134 %121 %135
|
||||
%135 = OpLabel
|
||||
%136 = OpCompositeExtract %6 %132 1
|
||||
%137 = OpIEqual %36 %136 %31
|
||||
%137 = OpIEqual %44 %136 %31
|
||||
%138 = OpSelect %6 %137 %86 %31
|
||||
%139 = OpCompositeConstruct %124 %138 %86
|
||||
%140 = OpISub %124 %132 %139
|
||||
OpStore %130 %140
|
||||
OpBranch %122
|
||||
%122 = OpLabel
|
||||
%141 = OpFunctionCall %36 %144 %27 %30
|
||||
%141 = OpFunctionCall %44 %144 %27 %30
|
||||
OpSelectionMerge %160 None
|
||||
OpBranchConditional %141 %160 %161
|
||||
%161 = OpLabel
|
||||
|
||||
@@ -68,8 +68,8 @@ OpMemberDecorate %18 0 Offset 0
|
||||
%35 = OpConstant %6 0
|
||||
%36 = OpTypePointer Function %3
|
||||
%38 = OpConstant %3 0
|
||||
%41 = OpTypeVector %8 3
|
||||
%42 = OpTypeFunction %2 %32 %5 %12 %33 %36
|
||||
%41 = OpTypeFunction %2 %32 %5 %12 %33 %36
|
||||
%49 = OpTypeVector %8 3
|
||||
%70 = OpConstant %6 256
|
||||
%73 = OpConstant %6 512
|
||||
%78 = OpConstant %6 16
|
||||
@@ -112,31 +112,30 @@ OpMemberDecorate %18 0 Offset 0
|
||||
%265 = OpConstant %3 10
|
||||
%322 = OpTypeFunction %2 %32 %33 %3 %36
|
||||
%363 = OpTypeFunction %2 %32 %33
|
||||
%43 = OpFunction %2 None %42
|
||||
%44 = OpFunctionParameter %32
|
||||
%45 = OpFunctionParameter %5
|
||||
%46 = OpFunctionParameter %12
|
||||
%47 = OpFunctionParameter %33
|
||||
%48 = OpFunctionParameter %36
|
||||
%49 = OpLabel
|
||||
%50 = OpCompositeExtract %6 %46 0
|
||||
%51 = OpCompositeExtract %6 %46 1
|
||||
%52 = OpCompositeExtract %3 %46 2
|
||||
%53 = OpCompositeExtract %3 %46 3
|
||||
OpStore %48 %53
|
||||
%54 = OpCompositeExtract %4 %46 4
|
||||
%55 = OpCompositeExtract %4 %46 5
|
||||
%42 = OpFunction %2 None %41
|
||||
%43 = OpFunctionParameter %32
|
||||
%44 = OpFunctionParameter %5
|
||||
%45 = OpFunctionParameter %12
|
||||
%46 = OpFunctionParameter %33
|
||||
%47 = OpFunctionParameter %36
|
||||
%48 = OpLabel
|
||||
%50 = OpCompositeExtract %6 %45 0
|
||||
%51 = OpCompositeExtract %6 %45 1
|
||||
%52 = OpCompositeExtract %3 %45 2
|
||||
%53 = OpCompositeExtract %3 %45 3
|
||||
%54 = OpCompositeExtract %4 %45 4
|
||||
%55 = OpCompositeExtract %4 %45 5
|
||||
%56 = OpFOrdLessThanEqual %8 %52 %53
|
||||
%57 = OpFOrdGreaterThanEqual %8 %52 %38
|
||||
%58 = OpIsInf %41 %54
|
||||
%58 = OpIsInf %49 %54
|
||||
%59 = OpAny %8 %58
|
||||
%60 = OpIsNan %41 %54
|
||||
%60 = OpIsNan %49 %54
|
||||
%61 = OpAny %8 %60
|
||||
%62 = OpLogicalOr %8 %61 %59
|
||||
%63 = OpLogicalNot %8 %62
|
||||
%64 = OpIsInf %41 %55
|
||||
%64 = OpIsInf %49 %55
|
||||
%65 = OpAny %8 %64
|
||||
%66 = OpIsNan %41 %55
|
||||
%66 = OpIsNan %49 %55
|
||||
%67 = OpAny %8 %66
|
||||
%68 = OpLogicalOr %8 %67 %65
|
||||
%69 = OpLogicalNot %8 %68
|
||||
@@ -182,11 +181,12 @@ OpStore %48 %53
|
||||
%117 = OpLogicalAnd %8 %116 %69
|
||||
%118 = OpLogicalAnd %8 %117 %77
|
||||
%119 = OpLogicalAnd %8 %118 %89
|
||||
OpStore %47 %53
|
||||
OpSelectionMerge %120 None
|
||||
OpBranchConditional %119 %122 %121
|
||||
%122 = OpLabel
|
||||
OpRayQueryInitializeKHR %44 %45 %50 %51 %54 %52 %55 %53
|
||||
OpStore %47 %90
|
||||
OpRayQueryInitializeKHR %43 %44 %50 %51 %54 %52 %55 %53
|
||||
OpStore %46 %90
|
||||
OpBranch %120
|
||||
%121 = OpLabel
|
||||
OpBranch %120
|
||||
@@ -291,7 +291,7 @@ OpFunctionEnd
|
||||
OpBranch %39
|
||||
%39 = OpLabel
|
||||
%40 = OpCompositeConstruct %12 %27 %28 %29 %30 %21 %22
|
||||
%123 = OpFunctionCall %2 %43 %31 %24 %40 %34 %37
|
||||
%123 = OpFunctionCall %2 %42 %31 %24 %40 %34 %37
|
||||
OpBranch %124
|
||||
%124 = OpLabel
|
||||
OpLoopMerge %125 %127 None
|
||||
@@ -535,7 +535,7 @@ OpFunctionEnd
|
||||
%263 = OpLoad %5 %15
|
||||
OpBranch %269
|
||||
%269 = OpLabel
|
||||
%270 = OpFunctionCall %2 %43 %266 %263 %264 %267 %268
|
||||
%270 = OpFunctionCall %2 %42 %266 %263 %264 %267 %268
|
||||
%316 = OpFunctionCall %10 %271 %266 %267
|
||||
%317 = OpCompositeExtract %6 %316 0
|
||||
%318 = OpIEqual %8 %317 %199
|
||||
|
||||
@@ -68,8 +68,8 @@ OpMemberDecorate %18 0 Offset 0
|
||||
%35 = OpConstant %6 0
|
||||
%36 = OpTypePointer Function %3
|
||||
%38 = OpConstant %3 0
|
||||
%41 = OpTypeVector %8 3
|
||||
%42 = OpTypeFunction %2 %32 %5 %12 %33 %36
|
||||
%41 = OpTypeFunction %2 %32 %5 %12 %33 %36
|
||||
%49 = OpTypeVector %8 3
|
||||
%70 = OpConstant %6 256
|
||||
%73 = OpConstant %6 512
|
||||
%78 = OpConstant %6 16
|
||||
@@ -112,31 +112,30 @@ OpMemberDecorate %18 0 Offset 0
|
||||
%265 = OpConstant %3 10
|
||||
%322 = OpTypeFunction %2 %32 %33 %3 %36
|
||||
%363 = OpTypeFunction %2 %32 %33
|
||||
%43 = OpFunction %2 None %42
|
||||
%44 = OpFunctionParameter %32
|
||||
%45 = OpFunctionParameter %5
|
||||
%46 = OpFunctionParameter %12
|
||||
%47 = OpFunctionParameter %33
|
||||
%48 = OpFunctionParameter %36
|
||||
%49 = OpLabel
|
||||
%50 = OpCompositeExtract %6 %46 0
|
||||
%51 = OpCompositeExtract %6 %46 1
|
||||
%52 = OpCompositeExtract %3 %46 2
|
||||
%53 = OpCompositeExtract %3 %46 3
|
||||
OpStore %48 %53
|
||||
%54 = OpCompositeExtract %4 %46 4
|
||||
%55 = OpCompositeExtract %4 %46 5
|
||||
%42 = OpFunction %2 None %41
|
||||
%43 = OpFunctionParameter %32
|
||||
%44 = OpFunctionParameter %5
|
||||
%45 = OpFunctionParameter %12
|
||||
%46 = OpFunctionParameter %33
|
||||
%47 = OpFunctionParameter %36
|
||||
%48 = OpLabel
|
||||
%50 = OpCompositeExtract %6 %45 0
|
||||
%51 = OpCompositeExtract %6 %45 1
|
||||
%52 = OpCompositeExtract %3 %45 2
|
||||
%53 = OpCompositeExtract %3 %45 3
|
||||
%54 = OpCompositeExtract %4 %45 4
|
||||
%55 = OpCompositeExtract %4 %45 5
|
||||
%56 = OpFOrdLessThanEqual %8 %52 %53
|
||||
%57 = OpFOrdGreaterThanEqual %8 %52 %38
|
||||
%58 = OpIsInf %41 %54
|
||||
%58 = OpIsInf %49 %54
|
||||
%59 = OpAny %8 %58
|
||||
%60 = OpIsNan %41 %54
|
||||
%60 = OpIsNan %49 %54
|
||||
%61 = OpAny %8 %60
|
||||
%62 = OpLogicalOr %8 %61 %59
|
||||
%63 = OpLogicalNot %8 %62
|
||||
%64 = OpIsInf %41 %55
|
||||
%64 = OpIsInf %49 %55
|
||||
%65 = OpAny %8 %64
|
||||
%66 = OpIsNan %41 %55
|
||||
%66 = OpIsNan %49 %55
|
||||
%67 = OpAny %8 %66
|
||||
%68 = OpLogicalOr %8 %67 %65
|
||||
%69 = OpLogicalNot %8 %68
|
||||
@@ -182,11 +181,12 @@ OpStore %48 %53
|
||||
%117 = OpLogicalAnd %8 %116 %69
|
||||
%118 = OpLogicalAnd %8 %117 %77
|
||||
%119 = OpLogicalAnd %8 %118 %89
|
||||
OpStore %47 %53
|
||||
OpSelectionMerge %120 None
|
||||
OpBranchConditional %119 %122 %121
|
||||
%122 = OpLabel
|
||||
OpRayQueryInitializeKHR %44 %45 %50 %51 %54 %52 %55 %53
|
||||
OpStore %47 %90
|
||||
OpRayQueryInitializeKHR %43 %44 %50 %51 %54 %52 %55 %53
|
||||
OpStore %46 %90
|
||||
OpBranch %120
|
||||
%121 = OpLabel
|
||||
OpBranch %120
|
||||
@@ -291,7 +291,7 @@ OpFunctionEnd
|
||||
OpBranch %39
|
||||
%39 = OpLabel
|
||||
%40 = OpCompositeConstruct %12 %27 %28 %29 %30 %21 %22
|
||||
%123 = OpFunctionCall %2 %43 %31 %24 %40 %34 %37
|
||||
%123 = OpFunctionCall %2 %42 %31 %24 %40 %34 %37
|
||||
OpBranch %124
|
||||
%124 = OpLabel
|
||||
OpLoopMerge %125 %127 None
|
||||
@@ -535,7 +535,7 @@ OpFunctionEnd
|
||||
%263 = OpLoad %5 %15
|
||||
OpBranch %269
|
||||
%269 = OpLabel
|
||||
%270 = OpFunctionCall %2 %43 %266 %263 %264 %267 %268
|
||||
%270 = OpFunctionCall %2 %42 %266 %263 %264 %267 %268
|
||||
%316 = OpFunctionCall %10 %271 %266 %267
|
||||
%317 = OpCompositeExtract %6 %316 0
|
||||
%318 = OpIEqual %8 %317 %199
|
||||
|
||||
226
naga/tests/out/spv/wgsl-ray-tracing-pipeline.spvasm
Normal file
226
naga/tests/out/spv/wgsl-ray-tracing-pipeline.spvasm
Normal file
@@ -0,0 +1,226 @@
|
||||
; SPIR-V
|
||||
; Version: 1.1
|
||||
; Generator: rspirv
|
||||
; Bound: 170
|
||||
OpCapability Shader
|
||||
OpCapability RayTracingKHR
|
||||
OpExtension "SPV_KHR_ray_tracing"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint RayGenerationKHR %23 "ray_gen_main" %18 %21
|
||||
OpEntryPoint MissKHR %138 "miss" %130 %133 %135
|
||||
OpEntryPoint AnyHitKHR %150 "any_hit_main" %141 %144 %146 %148
|
||||
OpEntryPoint ClosestHitKHR %168 "closest_hit_main" %159 %161 %163 %166
|
||||
OpMemberDecorate %4 0 Offset 0
|
||||
OpMemberDecorate %4 1 Offset 4
|
||||
OpMemberDecorate %9 0 Offset 0
|
||||
OpMemberDecorate %9 1 Offset 4
|
||||
OpMemberDecorate %9 2 Offset 8
|
||||
OpMemberDecorate %9 3 Offset 12
|
||||
OpMemberDecorate %9 4 Offset 16
|
||||
OpMemberDecorate %9 5 Offset 32
|
||||
OpDecorate %13 DescriptorSet 0
|
||||
OpDecorate %13 Binding 0
|
||||
OpDecorate %18 BuiltIn LaunchIdKHR
|
||||
OpDecorate %21 BuiltIn LaunchSizeKHR
|
||||
OpDecorate %130 BuiltIn WorldRayOriginKHR
|
||||
OpDecorate %133 BuiltIn WorldRayDirectionKHR
|
||||
OpDecorate %135 BuiltIn RayTminKHR
|
||||
OpDecorate %141 BuiltIn InstanceCustomIndexKHR
|
||||
OpDecorate %144 BuiltIn RayGeometryIndexKHR
|
||||
OpDecorate %146 BuiltIn RayTmaxKHR
|
||||
OpDecorate %148 BuiltIn HitKindKHR
|
||||
OpDecorate %159 BuiltIn ObjectRayOriginKHR
|
||||
OpDecorate %161 BuiltIn ObjectRayDirectionKHR
|
||||
OpDecorate %163 BuiltIn ObjectToWorldKHR
|
||||
OpDecorate %166 BuiltIn WorldToObjectKHR
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 32 0
|
||||
%4 = OpTypeStruct %3 %3
|
||||
%5 = OpTypeAccelerationStructureKHR
|
||||
%6 = OpTypeVector %3 3
|
||||
%7 = OpTypeFloat 32
|
||||
%8 = OpTypeVector %7 3
|
||||
%9 = OpTypeStruct %3 %3 %7 %7 %8 %8
|
||||
%10 = OpTypeMatrix %8 4
|
||||
%12 = OpTypePointer RayPayloadKHR %4
|
||||
%11 = OpVariable %12 RayPayloadKHR
|
||||
%14 = OpTypePointer UniformConstant %5
|
||||
%13 = OpVariable %14 UniformConstant
|
||||
%16 = OpTypePointer IncomingRayPayloadKHR %4
|
||||
%15 = OpVariable %16 IncomingRayPayloadKHR
|
||||
%19 = OpTypePointer Input %6
|
||||
%18 = OpVariable %19 Input
|
||||
%21 = OpVariable %19 Input
|
||||
%24 = OpTypeFunction %2
|
||||
%26 = OpConstantNull %4
|
||||
%27 = OpConstant %7 0
|
||||
%28 = OpConstant %7 2
|
||||
%29 = OpConstant %7 1
|
||||
%30 = OpConstantComposite %8 %29 %29 %29
|
||||
%31 = OpConstant %3 0
|
||||
%32 = OpConstantComposite %8 %27 %29 %27
|
||||
%33 = OpConstant %3 255
|
||||
%34 = OpConstant %7 0.01
|
||||
%35 = OpConstant %7 100
|
||||
%36 = OpConstantComposite %8 %27 %27 %27
|
||||
%48 = OpTypeFunction %2 %5 %9
|
||||
%53 = OpTypeBool
|
||||
%54 = OpTypeVector %53 3
|
||||
%75 = OpConstant %3 256
|
||||
%78 = OpConstant %3 512
|
||||
%83 = OpConstant %3 16
|
||||
%86 = OpConstant %3 32
|
||||
%95 = OpConstant %3 1
|
||||
%98 = OpConstant %3 2
|
||||
%101 = OpConstant %3 64
|
||||
%104 = OpConstant %3 128
|
||||
%131 = OpTypePointer Input %8
|
||||
%130 = OpVariable %131 Input
|
||||
%133 = OpVariable %131 Input
|
||||
%136 = OpTypePointer Input %7
|
||||
%135 = OpVariable %136 Input
|
||||
%142 = OpTypePointer Input %3
|
||||
%141 = OpVariable %142 Input
|
||||
%144 = OpVariable %142 Input
|
||||
%146 = OpVariable %136 Input
|
||||
%148 = OpVariable %142 Input
|
||||
%152 = OpTypePointer IncomingRayPayloadKHR %3
|
||||
%159 = OpVariable %131 Input
|
||||
%161 = OpVariable %131 Input
|
||||
%164 = OpTypePointer Input %10
|
||||
%163 = OpVariable %164 Input
|
||||
%166 = OpVariable %164 Input
|
||||
%49 = OpFunction %2 None %48
|
||||
%50 = OpFunctionParameter %5
|
||||
%51 = OpFunctionParameter %9
|
||||
%52 = OpLabel
|
||||
%55 = OpCompositeExtract %3 %51 0
|
||||
%56 = OpCompositeExtract %3 %51 1
|
||||
%57 = OpCompositeExtract %7 %51 2
|
||||
%58 = OpCompositeExtract %7 %51 3
|
||||
%59 = OpCompositeExtract %8 %51 4
|
||||
%60 = OpCompositeExtract %8 %51 5
|
||||
%61 = OpFOrdLessThanEqual %53 %57 %58
|
||||
%62 = OpFOrdGreaterThanEqual %53 %57 %27
|
||||
%63 = OpIsInf %54 %59
|
||||
%64 = OpAny %53 %63
|
||||
%65 = OpIsNan %54 %59
|
||||
%66 = OpAny %53 %65
|
||||
%67 = OpLogicalOr %53 %66 %64
|
||||
%68 = OpLogicalNot %53 %67
|
||||
%69 = OpIsInf %54 %60
|
||||
%70 = OpAny %53 %69
|
||||
%71 = OpIsNan %54 %60
|
||||
%72 = OpAny %53 %71
|
||||
%73 = OpLogicalOr %53 %72 %70
|
||||
%74 = OpLogicalNot %53 %73
|
||||
%76 = OpBitwiseAnd %3 %55 %75
|
||||
%77 = OpINotEqual %53 %76 %31
|
||||
%79 = OpBitwiseAnd %3 %55 %78
|
||||
%80 = OpINotEqual %53 %79 %31
|
||||
%81 = OpLogicalAnd %53 %80 %77
|
||||
%82 = OpLogicalNot %53 %81
|
||||
%84 = OpBitwiseAnd %3 %55 %83
|
||||
%85 = OpINotEqual %53 %84 %31
|
||||
%87 = OpBitwiseAnd %3 %55 %86
|
||||
%88 = OpINotEqual %53 %87 %31
|
||||
%89 = OpLogicalAnd %53 %88 %77
|
||||
%90 = OpLogicalAnd %53 %88 %85
|
||||
%91 = OpLogicalAnd %53 %85 %77
|
||||
%92 = OpLogicalOr %53 %91 %89
|
||||
%93 = OpLogicalOr %53 %92 %90
|
||||
%94 = OpLogicalNot %53 %93
|
||||
%96 = OpBitwiseAnd %3 %55 %95
|
||||
%97 = OpINotEqual %53 %96 %31
|
||||
%99 = OpBitwiseAnd %3 %55 %98
|
||||
%100 = OpINotEqual %53 %99 %31
|
||||
%102 = OpBitwiseAnd %3 %55 %101
|
||||
%103 = OpINotEqual %53 %102 %31
|
||||
%105 = OpBitwiseAnd %3 %55 %104
|
||||
%106 = OpINotEqual %53 %105 %31
|
||||
%107 = OpLogicalAnd %53 %106 %97
|
||||
%108 = OpLogicalAnd %53 %106 %100
|
||||
%109 = OpLogicalAnd %53 %106 %103
|
||||
%110 = OpLogicalAnd %53 %103 %97
|
||||
%111 = OpLogicalAnd %53 %103 %100
|
||||
%112 = OpLogicalAnd %53 %100 %97
|
||||
%113 = OpLogicalOr %53 %112 %107
|
||||
%114 = OpLogicalOr %53 %113 %108
|
||||
%115 = OpLogicalOr %53 %114 %109
|
||||
%116 = OpLogicalOr %53 %115 %110
|
||||
%117 = OpLogicalOr %53 %116 %111
|
||||
%118 = OpLogicalNot %53 %117
|
||||
%119 = OpLogicalAnd %53 %118 %61
|
||||
%120 = OpLogicalAnd %53 %119 %62
|
||||
%121 = OpLogicalAnd %53 %120 %68
|
||||
%122 = OpLogicalAnd %53 %121 %74
|
||||
%123 = OpLogicalAnd %53 %122 %82
|
||||
%124 = OpLogicalAnd %53 %123 %94
|
||||
OpSelectionMerge %125 None
|
||||
OpBranchConditional %124 %127 %126
|
||||
%127 = OpLabel
|
||||
OpTraceRayKHR %50 %55 %56 %31 %31 %31 %59 %57 %60 %58 %11
|
||||
OpBranch %125
|
||||
%126 = OpLabel
|
||||
OpBranch %125
|
||||
%125 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%23 = OpFunction %2 None %24
|
||||
%17 = OpLabel
|
||||
%20 = OpLoad %6 %18
|
||||
%22 = OpLoad %6 %21
|
||||
%25 = OpLoad %5 %13
|
||||
OpBranch %37
|
||||
%37 = OpLabel
|
||||
OpStore %11 %26
|
||||
%38 = OpConvertUToF %8 %20
|
||||
%39 = OpConvertUToF %8 %22
|
||||
%40 = OpFDiv %8 %38 %39
|
||||
%41 = OpCompositeExtract %7 %40 0
|
||||
%42 = OpCompositeExtract %7 %40 1
|
||||
%43 = OpCompositeConstruct %8 %41 %27 %42
|
||||
%44 = OpVectorTimesScalar %8 %43 %28
|
||||
%45 = OpFSub %8 %44 %30
|
||||
%46 = OpFAdd %8 %32 %45
|
||||
%47 = OpCompositeConstruct %9 %31 %33 %34 %35 %36 %46
|
||||
%128 = OpFunctionCall %2 %49 %25 %47
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%138 = OpFunction %2 None %24
|
||||
%129 = OpLabel
|
||||
%132 = OpLoad %8 %130
|
||||
%134 = OpLoad %8 %133
|
||||
%137 = OpLoad %7 %135
|
||||
OpBranch %139
|
||||
%139 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%150 = OpFunction %2 None %24
|
||||
%140 = OpLabel
|
||||
%143 = OpLoad %3 %141
|
||||
%145 = OpLoad %3 %144
|
||||
%147 = OpLoad %7 %146
|
||||
%149 = OpLoad %3 %148
|
||||
OpBranch %151
|
||||
%151 = OpLabel
|
||||
%153 = OpAccessChain %152 %15 %31
|
||||
%154 = OpLoad %3 %153
|
||||
%155 = OpIAdd %3 %154 %95
|
||||
%156 = OpAccessChain %152 %15 %31
|
||||
OpStore %156 %155
|
||||
%157 = OpAccessChain %152 %15 %95
|
||||
OpStore %157 %143
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%168 = OpFunction %2 None %24
|
||||
%158 = OpLabel
|
||||
%160 = OpLoad %8 %159
|
||||
%162 = OpLoad %8 %161
|
||||
%165 = OpLoad %10 %163
|
||||
%167 = OpLoad %10 %166
|
||||
OpBranch %169
|
||||
%169 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
@@ -2731,6 +2731,7 @@ impl super::Adapter {
|
||||
max_mesh_workgroups_total: limits.max_mesh_workgroup_total_count,
|
||||
}),
|
||||
mesh_shader_primitive_indices_clamp: true,
|
||||
trace_ray_argument_validation: true,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user