[spv-out] ray tracing pipelines (#9085)

This commit is contained in:
Vecvec
2026-04-21 03:02:49 +12:00
committed by GitHub
parent 5eeb484758
commit 56e4a389dd
19 changed files with 1192 additions and 598 deletions

View File

@@ -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

View File

@@ -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,
}
}
}

View File

@@ -4177,7 +4177,9 @@ impl BlockContext<'_> {
}
};
}
Statement::RayPipelineFunction(_) => unreachable!(),
Statement::RayPipelineFunction(ref fun) => {
self.write_ray_tracing_pipeline_function(fun, &mut block);
}
}
}

View File

@@ -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,
}
}

View File

@@ -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
//

View File

@@ -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

View File

@@ -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)
}
}

View 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],
));
}
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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);

View File

@@ -1,2 +1,2 @@
capabilities = "RAY_TRACING_PIPELINE"
targets = "WGSL"
targets = "WGSL | SPIRV"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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,
}
};