Skip to content

Commit 2bf7953

Browse files
committed
layers: Add VK_EXT_ray_tracing_invocation_reorder (KhronosGroup#11525)
Also add tests for VK_EXT_ray_tracing_invocation_reorder
1 parent 3a139d6 commit 2bf7953

27 files changed

+2135
-6
lines changed

layers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ target_sources(vvl PRIVATE
334334
gpuav/instrumentation/mesh_shading.cpp
335335
gpuav/instrumentation/post_process_descriptor_indexing.cpp
336336
gpuav/instrumentation/ray_query.cpp
337+
gpuav/instrumentation/ray_hit_object.cpp
337338
gpuav/instrumentation/register_validation.h
338339
gpuav/instrumentation/sanitizer.cpp
339340
gpuav/instrumentation/vertex_attribute_fetch_oob.cpp

layers/chassis/dispatch_object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct DeviceExtensionProperties {
116116
#endif
117117
VkPhysicalDeviceMemoryDecompressionPropertiesEXT memory_decompression_props;
118118
VkPhysicalDevicePerformanceCountersByRegionPropertiesARM renderpass_counter_by_region_props;
119+
VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT ray_tracing_invocation_reorder_props;
119120
VkPhysicalDeviceShaderLongVectorPropertiesEXT shader_long_vector_props;
120121
};
121122

layers/chassis/dispatch_object_manual.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ StatelessDeviceData::StatelessDeviceData(vvl::dispatch::Instance *instance, VkPh
396396
&phys_dev_ext_props.ray_tracing_props_nv);
397397
instance->GetPhysicalDeviceExtProperties(physical_device, extensions.vk_khr_ray_tracing_pipeline,
398398
&phys_dev_ext_props.ray_tracing_props_khr);
399+
instance->GetPhysicalDeviceExtProperties(physical_device, extensions.vk_ext_ray_tracing_invocation_reorder,
400+
&phys_dev_ext_props.ray_tracing_invocation_reorder_props);
399401
instance->GetPhysicalDeviceExtProperties(physical_device, extensions.vk_khr_acceleration_structure,
400402
&phys_dev_ext_props.acc_structure_props);
401403
instance->GetPhysicalDeviceExtProperties(physical_device, extensions.vk_ext_fragment_density_map,

layers/gpuav/core/gpuav_record.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ void Validator::PreCallRecordBeginCommandBuffer(VkCommandBuffer commandBuffer, c
159159
RegisterVertexAttributeFetchOobValidation(*this, gpuav_cb_state);
160160
RegisterMeshShadingValidation(*this, gpuav_cb_state);
161161
RegisterRayQueryValidation(*this, gpuav_cb_state);
162+
RegisterRayHitObjectValidation(*this, gpuav_cb_state);
162163
RegisterSanitizer(*this, gpuav_cb_state);
163164
debug_printf::RegisterDebugPrintf(*this, gpuav_cb_state);
164165
}

layers/gpuav/core/gpuav_settings.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
bool GpuAVSettings::IsShaderInstrumentationEnabled() const {
3333
return shader_instrumentation.descriptor_checks || shader_instrumentation.buffer_device_address ||
34-
shader_instrumentation.ray_query || shader_instrumentation.mesh_shading ||
34+
shader_instrumentation.ray_query || shader_instrumentation.ray_hit_object || shader_instrumentation.mesh_shading ||
3535
shader_instrumentation.post_process_descriptor_indexing || shader_instrumentation.vertex_attribute_fetch_oob ||
3636
shader_instrumentation.sanitizer;
3737
}
@@ -42,6 +42,7 @@ void GpuAVSettings::DisableShaderInstrumentationAndOptions() {
4242
shader_instrumentation.descriptor_checks = false;
4343
shader_instrumentation.buffer_device_address = false;
4444
shader_instrumentation.ray_query = false;
45+
shader_instrumentation.ray_hit_object = false;
4546
shader_instrumentation.mesh_shading = false;
4647
shader_instrumentation.post_process_descriptor_indexing = false;
4748
shader_instrumentation.vertex_attribute_fetch_oob = false;
@@ -120,6 +121,7 @@ void GpuAVSettings::TracyLogSettings() const {
120121
VVL_TracyMessageStream(" descriptor_checks: " << shader_instrumentation.descriptor_checks);
121122
VVL_TracyMessageStream(" buffer_device_address: " << shader_instrumentation.buffer_device_address);
122123
VVL_TracyMessageStream(" ray_query: " << shader_instrumentation.ray_query);
124+
VVL_TracyMessageStream(" ray_hit_object: " << shader_instrumentation.ray_hit_object);
123125
VVL_TracyMessageStream(" mesh_shading: " << shader_instrumentation.mesh_shading);
124126
VVL_TracyMessageStream(" post_process_descriptor_indexing: " << shader_instrumentation.post_process_descriptor_indexing);
125127
VVL_TracyMessageStream(" vertex_attribute_fetch_oob: " << shader_instrumentation.vertex_attribute_fetch_oob);

layers/gpuav/core/gpuav_settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct GpuAVSettings {
5555
bool descriptor_checks = true;
5656
bool buffer_device_address = true;
5757
bool ray_query = true;
58+
bool ray_hit_object = true;
5859
bool mesh_shading = true;
5960
bool post_process_descriptor_indexing = true;
6061
bool vertex_attribute_fetch_oob = true;

layers/gpuav/core/gpuav_setup.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ struct RayQuery : public Setting {
347347
"gpuav_validate_ray_query]\n";
348348
}
349349
};
350+
struct RayHitObject : public Setting {
351+
bool IsEnabled(const GpuAVSettings &settings) { return settings.shader_instrumentation.ray_hit_object; }
352+
bool HasRequiredFeatures(const DeviceFeatures &features) { return features.rayTracingInvocationReorder; }
353+
void Disable(GpuAVSettings &settings) { settings.shader_instrumentation.ray_hit_object = false; }
354+
std::string DisableMessage() {
355+
return "\tRay Hit Object validation option was enabled, but the rayTracingInvocationReorder feature is not supported. [Disabling "
356+
"gpuav_validate_ray_hit_object]\n";
357+
}
358+
};
350359
struct MeshShading : public Setting {
351360
bool IsEnabled(const GpuAVSettings &settings) { return settings.shader_instrumentation.mesh_shading; }
352361
bool HasRequiredFeatures(const DeviceFeatures &features) { return features.meshShader; }
@@ -394,12 +403,13 @@ struct AccelerationStructuresBuild : public Setting {
394403
void Validator::InitSettings(const Location &loc) {
395404
setting::BufferDeviceAddress buffer_device_address;
396405
setting::RayQuery ray_query;
406+
setting::RayHitObject ray_hit_object;
397407
setting::MeshShading mesh_shading;
398408
setting::BufferCopies buffer_copies;
399409
setting::BufferContent buffer_content;
400410
setting::AccelerationStructuresBuild as_builds;
401-
std::array<setting::Setting *, 6> all_settings = {&buffer_device_address, &ray_query, &mesh_shading,
402-
&buffer_copies, &buffer_content, &as_builds};
411+
std::array<setting::Setting *, 7> all_settings = {&buffer_device_address, &ray_query, &ray_hit_object,
412+
&mesh_shading, &buffer_copies, &buffer_content, &as_builds};
403413

404414
std::string adjustment_warnings;
405415
for (auto &setting_object : all_settings) {

layers/gpuav/instrumentation/gpuav_shader_instrumentor.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "gpuav/spirv/descriptor_class_general_buffer_pass.h"
4949
#include "gpuav/spirv/descriptor_class_texel_buffer_pass.h"
5050
#include "gpuav/spirv/ray_query_pass.h"
51+
#include "gpuav/spirv/ray_hit_object_pass.h"
5152
#include "gpuav/spirv/mesh_shading_pass.h"
5253
#include "gpuav/spirv/debug_printf_pass.h"
5354
#include "gpuav/spirv/post_process_descriptor_indexing_pass.h"
@@ -1001,6 +1002,15 @@ void GpuShaderInstrumentor::BuildDescriptorSetLayoutInfo(const vvl::Pipeline &pi
10011002
BuildDescriptorSetLayoutInfo(*set_layout_state, set_layout_index, out_instrumentation_dsl);
10021003
}
10031004
}
1005+
1006+
// Set ray tracing pipeline flags for VUIDs 11886/11887
1007+
out_instrumentation_dsl.pipeline_has_skip_aabbs_flag =
1008+
(pipeline_state.create_flags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR) != 0;
1009+
out_instrumentation_dsl.pipeline_has_skip_triangles_flag =
1010+
(pipeline_state.create_flags & VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR) != 0;
1011+
// For VUID 11888 - maxShaderBindingTableRecordIndex limit
1012+
out_instrumentation_dsl.max_shader_binding_table_record_index =
1013+
phys_dev_ext_props.ray_tracing_invocation_reorder_props.maxShaderBindingTableRecordIndex;
10041014
}
10051015

10061016
void GpuShaderInstrumentor::BuildDescriptorSetLayoutInfo(const vku::safe_VkShaderCreateInfoEXT &modified_create_info,
@@ -1504,6 +1514,11 @@ bool GpuShaderInstrumentor::InstrumentShader(const vvl::span<const uint32_t> &in
15041514
module_settings.support_non_semantic_info =
15051515
IsExtEnabled(extensions.vk_khr_shader_non_semantic_info) && !IsExtEnabled(extensions.vk_khr_portability_subset);
15061516
module_settings.has_bindless_descriptors = instrumentation_dsl.has_bindless_descriptors;
1517+
// Ray tracing pipeline flags for VUIDs 11886/11887
1518+
module_settings.pipeline_has_skip_aabbs_flag = instrumentation_dsl.pipeline_has_skip_aabbs_flag;
1519+
module_settings.pipeline_has_skip_triangles_flag = instrumentation_dsl.pipeline_has_skip_triangles_flag;
1520+
// For VUID 11888 - maxShaderBindingTableRecordIndex limit
1521+
module_settings.max_shader_binding_table_record_index = instrumentation_dsl.max_shader_binding_table_record_index;
15071522

15081523
spirv::Module module(input_spirv, debug_report, module_settings, modified_features,
15091524
instrumentation_dsl.set_index_to_bindings_layout_lut);
@@ -1543,6 +1558,11 @@ bool GpuShaderInstrumentor::InstrumentShader(const vvl::span<const uint32_t> &in
15431558
modified |= pass.Run();
15441559
}
15451560

1561+
if (gpuav_settings.shader_instrumentation.ray_hit_object) {
1562+
spirv::RayHitObjectPass pass(module);
1563+
modified |= pass.Run();
1564+
}
1565+
15461566
if (gpuav_settings.shader_instrumentation.mesh_shading) {
15471567
spirv::MeshShading pass(module);
15481568
modified |= pass.Run();

layers/gpuav/instrumentation/gpuav_shader_instrumentor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ class GpuShaderInstrumentor : public vvl::DeviceProxy {
184184
bool has_bindless_descriptors = false;
185185
// < set , [ bindings ] >
186186
std::vector<std::vector<spirv::BindingLayout>> set_index_to_bindings_layout_lut;
187+
// Pipeline flags for ray tracing validation (VUIDs 11886/11887)
188+
bool pipeline_has_skip_aabbs_flag = false;
189+
bool pipeline_has_skip_triangles_flag = false;
190+
// For VUID 11888 - maxShaderBindingTableRecordIndex limit check
191+
uint32_t max_shader_binding_table_record_index = 0;
187192
};
188193
void BuildDescriptorSetLayoutInfo(const vvl::Pipeline &pipeline_state,
189194
InstrumentationDescriptorSetLayouts &out_instrumentation_dsl);
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/* Copyright (c) 2024-2026 LunarG, Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#include "gpuav/core/gpuav.h"
17+
#include "gpuav/resources/gpuav_state_trackers.h"
18+
#include "gpuav/shaders/gpuav_error_codes.h"
19+
#include "gpuav/shaders/gpuav_error_header.h"
20+
21+
namespace gpuav {
22+
23+
void RegisterRayHitObjectValidation(Validator &gpuav, CommandBufferSubState &cb) {
24+
if (!gpuav.gpuav_settings.shader_instrumentation.ray_hit_object) {
25+
return;
26+
}
27+
28+
cb.on_instrumentation_error_logger_register_functions.emplace_back([](Validator &gpuav, CommandBufferSubState &cb,
29+
const LastBound &last_bound) {
30+
CommandBufferSubState::InstrumentationErrorLogger inst_error_logger = [](Validator &gpuav, const Location &loc,
31+
const uint32_t *error_record,
32+
std::string &out_error_msg,
33+
std::string &out_vuid_msg) {
34+
using namespace glsl;
35+
bool error_found = false;
36+
if (GetErrorGroup(error_record) != kErrorGroupInstRayHitObject) {
37+
return error_found;
38+
}
39+
error_found = true;
40+
41+
std::ostringstream strm;
42+
43+
const uint32_t error_sub_code = GetSubError(error_record);
44+
// opcode_type: 0 = OpHitObjectTraceRayEXT, 1 = OpHitObjectTraceReorderExecuteEXT,
45+
// 2 = OpHitObjectTraceRayMotionEXT, 3 = OpHitObjectTraceMotionReorderExecuteEXT
46+
const uint32_t opcode_type = error_record[kInstRayHitObjectOpcodeType];
47+
const char* opcode_name = "OpHitObjectTraceRayEXT";
48+
if (opcode_type == 1) {
49+
opcode_name = "OpHitObjectTraceReorderExecuteEXT";
50+
} else if (opcode_type == 2) {
51+
opcode_name = "OpHitObjectTraceRayMotionEXT";
52+
} else if (opcode_type == 3) {
53+
opcode_name = "OpHitObjectTraceMotionReorderExecuteEXT";
54+
}
55+
56+
switch (error_sub_code) {
57+
case kErrorSubCodeRayHitObjectNegativeMin: {
58+
// TODO - Figure a way to properly use GLSL floatBitsToUint and print the float values
59+
strm << opcode_name << " operand Ray Tmin value is negative. ";
60+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11879";
61+
} break;
62+
case kErrorSubCodeRayHitObjectNegativeMax: {
63+
strm << opcode_name << " operand Ray Tmax value is negative. ";
64+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11879";
65+
} break;
66+
case kErrorSubCodeRayHitObjectMinMax: {
67+
strm << opcode_name << " operand Ray Tmax is less than RayTmin. ";
68+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11880";
69+
} break;
70+
case kErrorSubCodeRayHitObjectMinNaN: {
71+
strm << opcode_name << " operand Ray Tmin is NaN. ";
72+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11881";
73+
} break;
74+
case kErrorSubCodeRayHitObjectMaxNaN: {
75+
strm << opcode_name << " operand Ray Tmax is NaN. ";
76+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11881";
77+
} break;
78+
case kErrorSubCodeRayHitObjectOriginNaN: {
79+
strm << opcode_name << " operand Ray Origin contains a NaN. ";
80+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11881";
81+
} break;
82+
case kErrorSubCodeRayHitObjectDirectionNaN: {
83+
strm << opcode_name << " operand Ray Direction contains a NaN. ";
84+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11881";
85+
} break;
86+
case kErrorSubCodeRayHitObjectOriginFinite: {
87+
strm << opcode_name << " operand Ray Origin contains a non-finite value. ";
88+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11878";
89+
} break;
90+
case kErrorSubCodeRayHitObjectDirectionFinite: {
91+
strm << opcode_name << " operand Ray Direction contains a non-finite value. ";
92+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11878";
93+
} break;
94+
case kErrorSubCodeRayHitObjectBothSkip: {
95+
const uint32_t value = error_record[kInstRayHitObjectParamOffset_0];
96+
strm << opcode_name << " operand Ray Flags is 0x" << std::hex << value << ". ";
97+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11883";
98+
} break;
99+
case kErrorSubCodeRayHitObjectSkipCull: {
100+
const uint32_t value = error_record[kInstRayHitObjectParamOffset_0];
101+
strm << opcode_name << " operand Ray Flags is 0x" << std::hex << value << ". ";
102+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11884";
103+
} break;
104+
case kErrorSubCodeRayHitObjectOpaque: {
105+
const uint32_t value = error_record[kInstRayHitObjectParamOffset_0];
106+
strm << opcode_name << " operand Ray Flags is 0x" << std::hex << value << ". ";
107+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11885";
108+
} break;
109+
case kErrorSubCodeRayHitObjectSkipTrianglesWithPipelineSkipAABBs: {
110+
const uint32_t value = error_record[kInstRayHitObjectParamOffset_0];
111+
strm << opcode_name << " operand Ray Flags (0x" << std::hex << value
112+
<< ") contains SkipTrianglesKHR, but pipeline was created with VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR. ";
113+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11886";
114+
} break;
115+
case kErrorSubCodeRayHitObjectSkipAABBsWithPipelineSkipTriangles: {
116+
const uint32_t value = error_record[kInstRayHitObjectParamOffset_0];
117+
strm << opcode_name << " operand Ray Flags (0x" << std::hex << value
118+
<< ") contains SkipAABBsKHR, but pipeline was created with VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR. ";
119+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11887";
120+
} break;
121+
case kErrorSubCodeRayHitObjectSBTIndexExceedsLimit: {
122+
// For this case, param_0 contains the SBT index and opcode_type slot contains the max SBT index
123+
const uint32_t sbt_index = error_record[kInstRayHitObjectParamOffset_0];
124+
const uint32_t max_sbt_index = error_record[kInstRayHitObjectOpcodeType];
125+
strm << "OpHitObjectSetShaderBindingTableRecordIndexEXT SBT index (" << std::dec << sbt_index
126+
<< ") exceeds VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT::maxShaderBindingTableRecordIndex (" << max_sbt_index << "). ";
127+
out_vuid_msg = "VUID-RuntimeSpirv-maxShaderBindingTableRecordIndex-11888";
128+
} break;
129+
case kErrorSubCodeRayHitObjectTimeOutOfRange: {
130+
strm << opcode_name << " operand time is not between 0.0 and 1.0. ";
131+
out_vuid_msg = "VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11882";
132+
} break;
133+
default:
134+
error_found = false;
135+
break;
136+
}
137+
out_error_msg += strm.str();
138+
return error_found;
139+
};
140+
141+
return inst_error_logger;
142+
});
143+
}
144+
145+
} // namespace gpuav

0 commit comments

Comments
 (0)