From 536e24b68f73eb2d76f559bfae69de9d3251cefb Mon Sep 17 00:00:00 2001 From: Arno Date: Tue, 27 Oct 2026 08:41:55 -0600 Subject: [PATCH 1/2] tests: Enable safe mode for RT tests --- tests/unit/ray_tracing_positive.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/unit/ray_tracing_positive.cpp b/tests/unit/ray_tracing_positive.cpp index 923068d14ca..f4698b0a272 100644 --- a/tests/unit/ray_tracing_positive.cpp +++ b/tests/unit/ray_tracing_positive.cpp @@ -30,12 +30,14 @@ void RayTracingTest::InitFrameworkForRayTracingTest(VkValidationFeaturesEXT* ena AddRequiredExtensions(VK_KHR_SPIRV_1_4_EXTENSION_NAME); AddRequiredExtensions(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); AddRequiredExtensions(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); - VkLayerSettingEXT setting = {OBJECT_LAYER_NAME, "gpuav_ray_tracing_buffers_consistency", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, - &kVkTrue}; + + std::vector settings = { + {OBJECT_LAYER_NAME, "gpuav_ray_tracing_buffers_consistency", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}, + {OBJECT_LAYER_NAME, "gpuav_safe_mode", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}}; VkLayerSettingsCreateInfoEXT layer_setting_ci = vku::InitStructHelper(enabled_features); - layer_setting_ci.settingCount = 1; - layer_setting_ci.pSettings = &setting; + layer_setting_ci.settingCount = size32(settings); + layer_setting_ci.pSettings = settings.data(); RETURN_IF_SKIP(InitFramework(&layer_setting_ci)); } From b2e0b0c1095de5f323a51316d5de40456156e9de Mon Sep 17 00:00:00 2001 From: spencer-lunarg Date: Wed, 28 Oct 2026 09:46:51 -0600 Subject: [PATCH 2/2] gpuav: Fix RT in AccessPath --- layers/gpuav/spirv/access_path.cpp | 25 ++++++--- layers/gpuav/spirv/module.cpp | 2 +- layers/gpuav/spirv/pass.cpp | 14 +++-- layers/gpuav/spirv/trace_ray_pass.cpp | 21 +++---- layers/gpuav/spirv/trace_ray_pass.h | 5 +- .../vulkan/generated/spirv_grammar_helper.h | 31 ++++++++++ scripts/generators/spirv_grammar_generator.py | 23 ++++++++ tests/framework/layer_validation_tests.h | 2 +- tests/unit/gpu_av_ray_tracing.cpp | 12 ++-- tests/unit/gpu_av_ray_tracing_positive.cpp | 56 +++++++++---------- tests/unit/ray_tracing_positive.cpp | 11 +++- 11 files changed, 134 insertions(+), 68 deletions(-) diff --git a/layers/gpuav/spirv/access_path.cpp b/layers/gpuav/spirv/access_path.cpp index c6314811690..9d18d805357 100644 --- a/layers/gpuav/spirv/access_path.cpp +++ b/layers/gpuav/spirv/access_path.cpp @@ -46,6 +46,8 @@ static const Type* FindAccessType(const TypeManager& type_manager, const Functio access_type = type_manager.FindTypeGlobal(function, inst.Operand(2)); } else if (opcode == spv::OpAtomicStore) { access_type = type_manager.FindTypeGlobal(function, inst.Operand(3)); + } else if (const uint32_t as_position = OpcodeAccelerationStructureAccessPosition(opcode); as_position != 0) { + access_type = type_manager.FindTypeGlobal(function, inst.Word(as_position)); } } assert(access_type); @@ -97,20 +99,20 @@ static const Instruction* Unwarp(const Instruction* in_inst, const Function& fun // This is the "hide all the ugliness here" function // The goal is a new pass can just call this and have everything it needs to know about the memory access AccessPath::AccessPath(const Module& module, TypeManager& type_manager, const Function& function, const Instruction& inst) { - assert(inst.IsMemoryAccess()); + assert(inst.IsMemoryAccess() || OpcodeAccelerationStructureAccessPosition(inst.Opcode()) != 0); const spv::Op opcode = (spv::Op)inst.Opcode(); // Find Access Type { access_type = FindAccessType(type_manager, function, inst); - const bool image_sampler_access = access_type->spv_type_ == SpvType::kImage || - access_type->spv_type_ == SpvType::kSampledImage || - access_type->spv_type_ == SpvType::kSampler; + const bool handle_access = access_type->spv_type_ == SpvType::kImage || access_type->spv_type_ == SpvType::kSampledImage || + access_type->spv_type_ == SpvType::kSampler || + access_type->spv_type_ == SpvType::kAccelerationStructureKHR; - // This is just loading the image handle, this alone is the not the access. - // There will be an access (OpImageWrite, OpImageSampleImplicitLod, etc) later which has the real access information - if (opcode == spv::OpLoad && image_sampler_access) { + // This is just loading the image (or acceleration structure) handle, this alone is the not the access. + // There will be an access (OpImageWrite, OpImageSample*, OpTraceRayKHR, etc) later which has the real access information + if (opcode == spv::OpLoad && handle_access) { return; } } @@ -121,7 +123,14 @@ AccessPath::AccessPath(const Module& module, TypeManager& type_manager, const Fu uint32_t ptr_id = OpcodeImageAccessPosition(opcode); const bool is_image_access = ptr_id != 0; - if (!is_image_access) { + const uint32_t as_position = OpcodeAccelerationStructureAccessPosition(opcode); + if (as_position != 0) { + const Instruction* as_load_inst = Unwarp(function.FindInstruction(inst.Word(as_position)), function); + if (!as_load_inst || as_load_inst->Opcode() != spv::OpLoad) { + return; // ex. OpConvertUToAccelerationStructureKHR + } + ptr_id = as_load_inst->Operand(0); + } else if (!is_image_access) { ptr_id = inst.Operand(0); // Standard Store/Load } else { // Image access path diff --git a/layers/gpuav/spirv/module.cpp b/layers/gpuav/spirv/module.cpp index 0467b477a39..61d4f1f2781 100644 --- a/layers/gpuav/spirv/module.cpp +++ b/layers/gpuav/spirv/module.cpp @@ -499,7 +499,7 @@ const Variable& Module::GetBuiltInVariable(uint32_t built_in) { const AccessPath* Module::GetAccessPath(const Function& function, const Instruction& inst) { // Access path is only for memory accesses - if (!inst.IsMemoryAccess()) { + if (!inst.IsMemoryAccess() && OpcodeAccelerationStructureAccessPosition(inst.Opcode()) == 0) { return nullptr; } diff --git a/layers/gpuav/spirv/pass.cpp b/layers/gpuav/spirv/pass.cpp index 48e290efbba..6f462266a1c 100644 --- a/layers/gpuav/spirv/pass.cpp +++ b/layers/gpuav/spirv/pass.cpp @@ -849,13 +849,19 @@ InjectConditionalData Pass::InjectFunctionPre(Function& function, const BasicBlo // When skipping some instructions, we need something valid to replace it if (target_inst.Opcode() == spv::OpRayQueryInitializeKHR) { - // Currently assume the RayQuery and AS object were valid already + // Currently assume the RayQuery object was valid already + // The AS object is not, as it might have been loaded from an invalid descriptor, so use a null one + const Type& uvec2_type = type_manager_.GetTypeVector(type_manager_.GetTypeInt(32, false), 2); + const Constant& null_constant = type_manager_.GetConstantNull(uvec2_type); + const uint32_t null_as_id = module_.TakeNextId(); + invalid_block.CreateInstruction(spv::OpConvertUToAccelerationStructureKHR, + {type_manager_.GetTypeAccelerationStructure().Id(), null_as_id, null_constant.Id()}); + const uint32_t uint32_0_id = type_manager_.GetConstantZeroUint32().Id(); const uint32_t float32_0_id = type_manager_.GetConstantZeroFloat32().Id(); const uint32_t vec3_0_id = type_manager_.GetConstantZeroVec3().Id(); - invalid_block.CreateInstruction(spv::OpRayQueryInitializeKHR, - {target_inst.Operand(0), target_inst.Operand(1), uint32_0_id, uint32_0_id, vec3_0_id, - float32_0_id, vec3_0_id, float32_0_id}); + invalid_block.CreateInstruction(spv::OpRayQueryInitializeKHR, {target_inst.Operand(0), null_as_id, uint32_0_id, uint32_0_id, + vec3_0_id, float32_0_id, vec3_0_id, float32_0_id}); } invalid_block.CreateInstruction(spv::OpBranch, {merge_block_label}); diff --git a/layers/gpuav/spirv/trace_ray_pass.cpp b/layers/gpuav/spirv/trace_ray_pass.cpp index a204b5ffe5a..4efeaed96a5 100644 --- a/layers/gpuav/spirv/trace_ray_pass.cpp +++ b/layers/gpuav/spirv/trace_ray_pass.cpp @@ -48,20 +48,13 @@ const static OfflineFunction kReportIntersectionValidationFunction = {"inst_repo TraceRayPass::TraceRayPass(Module& module) : Pass(module, kOfflineModule) { module.use_bda_ = true; } -std::vector TraceRayPass::GetTlasValidationFunctionCallInstructions(const Function& function, uint32_t tlas_operand_pos, - uint32_t error_sub_code, BasicBlock& block, - InstructionIt* trace_ray_inst_it) { +std::vector TraceRayPass::GetTlasValidationFunctionCallInstructions(const Function& function, uint32_t error_sub_code, + BasicBlock& block, InstructionIt* trace_ray_inst_it) { if (module_.interface_.descriptor_mode != vvl::DescriptorMode::DescriptorModeClassic) { return {}; } - const uint32_t as_op_load_id = (*trace_ray_inst_it)->get()->Operand(tlas_operand_pos); - const Instruction* as_op_load_inst = function.FindInstruction(as_op_load_id); - if (!as_op_load_inst) { - return {}; - } - - const AccessPath* access_path = module_.GetAccessPath(function, *as_op_load_inst); + const AccessPath* access_path = module_.GetAccessPath(function, *(*trace_ray_inst_it)->get()); if (!access_path || !access_path->IsValidDescriptor() || access_path->access_type->spv_type_ != SpvType::kAccelerationStructureKHR) { return {}; @@ -268,15 +261,15 @@ bool TraceRayPass::Instrument() { }; switch (opcode) { case spv::OpRayQueryInitializeKHR: { - add_func_call(GetTlasValidationFunctionCallInstructions( - function, 1, glsl::kErrorSubCode_RayQuery_TlasNotBuilt, current_block, &inst_it)); + add_func_call(GetTlasValidationFunctionCallInstructions(function, glsl::kErrorSubCode_RayQuery_TlasNotBuilt, + current_block, &inst_it)); add_func_call(GetRayQueryInitializeValidationFunctionCallInstructions(&inst_it)); break; } case spv::OpTraceRayKHR: { add_func_call(GetTraceRayValidationFunctionCallInstructions(&inst_it)); - add_func_call(GetTlasValidationFunctionCallInstructions( - function, 0, glsl::kErrorSubCode_TraceRay_TlasNotBuilt, current_block, &inst_it)); + add_func_call(GetTlasValidationFunctionCallInstructions(function, glsl::kErrorSubCode_TraceRay_TlasNotBuilt, + current_block, &inst_it)); break; } case spv::OpHitObjectSetShaderBindingTableRecordIndexEXT: { diff --git a/layers/gpuav/spirv/trace_ray_pass.h b/layers/gpuav/spirv/trace_ray_pass.h index a5358571f5d..209c522a75d 100644 --- a/layers/gpuav/spirv/trace_ray_pass.h +++ b/layers/gpuav/spirv/trace_ray_pass.h @@ -30,9 +30,8 @@ class TraceRayPass : public Pass { void PrintDebugInfo() const final; private: - std::vector GetTlasValidationFunctionCallInstructions(const Function& function, uint32_t tlas_operand_pos, - uint32_t error_sub_code, BasicBlock& block, - InstructionIt* trace_ray_inst_it); + std::vector GetTlasValidationFunctionCallInstructions(const Function& function, uint32_t error_sub_code, + BasicBlock& block, InstructionIt* trace_ray_inst_it); std::vector GetTraceRayValidationFunctionCallInstructions(InstructionIt* trace_ray_inst_it); std::vector GetRayHitObjectValidationFunctionCallInstructions(InstructionIt* ray_hit_object_inst_it); std::vector GetRayHitObjectSbtIndexValidationFunctionCallInstructions( diff --git a/layers/vulkan/generated/spirv_grammar_helper.h b/layers/vulkan/generated/spirv_grammar_helper.h index d2d723546e1..a1a478d87f9 100644 --- a/layers/vulkan/generated/spirv_grammar_helper.h +++ b/layers/vulkan/generated/spirv_grammar_helper.h @@ -1347,6 +1347,37 @@ static constexpr uint32_t OpcodeImageAccessPosition(uint32_t opcode) { return position; } +// Return operand position of the 'Acceleration Structure' IdRef or zero if there is none. +static constexpr uint32_t OpcodeAccelerationStructureAccessPosition(uint32_t opcode) { + uint32_t position = 0; + switch (opcode) { + case spv::OpTraceRayKHR: + case spv::OpTraceNV: + case spv::OpTraceMotionNV: + case spv::OpTraceRayMotionNV: + return 1; + case spv::OpRayQueryInitializeKHR: + case spv::OpHitObjectRecordHitMotionNV: + case spv::OpHitObjectRecordHitWithIndexMotionNV: + case spv::OpHitObjectTraceRayMotionNV: + case spv::OpHitObjectTraceRayNV: + case spv::OpHitObjectRecordHitNV: + case spv::OpHitObjectRecordHitWithIndexNV: + case spv::OpHitObjectTraceReorderExecuteEXT: + case spv::OpHitObjectTraceMotionReorderExecuteEXT: + case spv::OpHitObjectTraceRayEXT: + case spv::OpHitObjectTraceRayMotionEXT: + return 2; + case spv::OpFetchMicroTriangleVertexPositionNV: + case spv::OpFetchMicroTriangleVertexBarycentricNV: + return 3; + + default: + break; + } + return position; +} + // All valid OpType* enum class SpvType { Empty = 0, diff --git a/scripts/generators/spirv_grammar_generator.py b/scripts/generators/spirv_grammar_generator.py index 6a7bc0d68c1..acb78515751 100644 --- a/scripts/generators/spirv_grammar_generator.py +++ b/scripts/generators/spirv_grammar_generator.py @@ -56,6 +56,7 @@ def __init__(self, self.executionScopePosition = [[] for i in range(4)] self.imageOperandsPosition = [[] for i in range(8)] self.imageAccessOperand = [[] for i in range(4)] + self.accelerationStructureAccessOperand = [[] for i in range(4)] self.kindId = [] # "category" : "Id" self.kindLiteral = [] # "category" : "Literal" @@ -209,6 +210,9 @@ def parseGrammar(self, grammar): self.opcodes[opcode]['imageRefPosition'] = index + 1 elif operand['name'] == 'Sampled Image': self.opcodes[opcode]['sampledImageRefPosition'] = index + 1 + # The grammar uses both names, OpConvertUToAccelerationStructureKHR also calls its uint64 input 'Accel' + elif operand['name'] in ['Accel', 'Acceleration Structure'] and opname != 'OpConvertUToAccelerationStructureKHR': + self.accelerationStructureAccessOperand[index + 1].append(opname) if re.search(r'OpImage*', opname) is not None: info = self.opcodes[opcode] @@ -483,6 +487,25 @@ def generateHeader(self): } ''') + out.append(''' + // Return operand position of the 'Acceleration Structure' IdRef or zero if there is none. + static constexpr uint32_t OpcodeAccelerationStructureAccessPosition(uint32_t opcode) { + uint32_t position = 0; + switch (opcode) { + ''') + for index, opcodes in enumerate(self.accelerationStructureAccessOperand): + for opcode in opcodes: + out.append(f' case spv::{opcode}:\n') + if len(opcodes) != 0: + out.append(f' return {index};\n') + out.append(''' + default: + break; + } + return position; + } + ''') + out.append(''' // All valid OpType* enum class SpvType { diff --git a/tests/framework/layer_validation_tests.h b/tests/framework/layer_validation_tests.h index 89dce5f4555..96d684f3bf5 100644 --- a/tests/framework/layer_validation_tests.h +++ b/tests/framework/layer_validation_tests.h @@ -430,7 +430,7 @@ class QueryTest : public VkLayerTest { class RayTracingTest : public virtual VkLayerTest { public: - void InitFrameworkForRayTracingTest(VkValidationFeaturesEXT* enabled_features = nullptr); + void InitFrameworkForRayTracingTest(VkValidationFeaturesEXT* enabled_features = nullptr, bool safe_mode = true); }; class GpuAVRayTracingTest : public GpuAVTest, public RayTracingTest {}; diff --git a/tests/unit/gpu_av_ray_tracing.cpp b/tests/unit/gpu_av_ray_tracing.cpp index 7deef3bba0e..b8cc23158bf 100644 --- a/tests/unit/gpu_av_ray_tracing.cpp +++ b/tests/unit/gpu_av_ray_tracing.cpp @@ -406,7 +406,7 @@ TEST_F(NegativeGpuAVRayTracing, ArrayOOBBufferRayGenShader) { { uniform_buffer_ptr[0] = 5; SCOPED_TRACE("uninitialized"); - m_errorMonitor->SetDesiredError("08114", 3); + m_errorMonitor->SetDesiredError("08114", 2); m_default_queue->SubmitAndWait(m_command_buffer); m_errorMonitor->VerifyFound(); } @@ -545,7 +545,7 @@ TEST_F(NegativeGpuAVRayTracing, ArrayOOBBufferMissShader) { { uniform_buffer_ptr[0] = 5; SCOPED_TRACE("uninitialized"); - m_errorMonitor->SetDesiredError("VUID-vkCmdTraceRaysKHR-None-08114", 2); + m_errorMonitor->SetDesiredError("VUID-vkCmdTraceRaysKHR-None-08114", 1); m_default_queue->SubmitAndWait(m_command_buffer); m_errorMonitor->VerifyFound(); } @@ -685,7 +685,7 @@ TEST_F(NegativeGpuAVRayTracing, ArrayOOBBufferClosetHitShader) { { uniform_buffer_ptr[0] = 5; SCOPED_TRACE("uninitialized"); - m_errorMonitor->SetDesiredError("VUID-vkCmdTraceRaysKHR-None-08114", 2); + m_errorMonitor->SetDesiredError("VUID-vkCmdTraceRaysKHR-None-08114", 1); m_default_queue->SubmitAndWait(m_command_buffer); m_errorMonitor->VerifyFound(); } @@ -844,7 +844,7 @@ TEST_F(NegativeGpuAVRayTracing, ArrayOOBBufferTwoClosetHitShader) { { uniform_buffer_ptr[0] = 5; SCOPED_TRACE("uninitialized"); - m_errorMonitor->SetDesiredError("VUID-vkCmdTraceRaysKHR-None-08114", 3); + m_errorMonitor->SetDesiredError("VUID-vkCmdTraceRaysKHR-None-08114", 2); m_default_queue->SubmitAndWait(m_command_buffer); m_errorMonitor->VerifyFound(); } @@ -1010,7 +1010,7 @@ TEST_F(NegativeGpuAVRayTracing, ArrayOOBBufferRayGenShaderGPL) { { uniform_buffer_ptr[0] = 5; SCOPED_TRACE("uninitialized"); - m_errorMonitor->SetDesiredError("08114", 3); + m_errorMonitor->SetDesiredError("08114", 2); m_default_queue->SubmitAndWait(m_command_buffer); m_errorMonitor->VerifyFound(); } @@ -1178,7 +1178,7 @@ TEST_F(NegativeGpuAVRayTracing, ArrayOOBBufferMissShaderGPL) { { uniform_buffer_ptr[0] = 5; SCOPED_TRACE("uninitialized"); - m_errorMonitor->SetDesiredError("08114", 3); + m_errorMonitor->SetDesiredError("08114", 2); m_default_queue->SubmitAndWait(m_command_buffer); m_errorMonitor->VerifyFound(); } diff --git a/tests/unit/gpu_av_ray_tracing_positive.cpp b/tests/unit/gpu_av_ray_tracing_positive.cpp index 1076c62f32b..9fe245f1717 100644 --- a/tests/unit/gpu_av_ray_tracing_positive.cpp +++ b/tests/unit/gpu_av_ray_tracing_positive.cpp @@ -32,7 +32,7 @@ TEST_F(PositiveGpuAVRayTracing, BasicTraceRays) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -121,7 +121,7 @@ TEST_F(PositiveGpuAVRayTracing, BasicTraceRaysDescriptorBuffer) { AddRequiredFeature(vkt::Feature::descriptorBindingPartiallyBound); AddRequiredFeature(vkt::Feature::descriptorBuffer); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -235,7 +235,7 @@ TEST_F(PositiveGpuAVRayTracing, BasicTraceRaysMultipleStages) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -322,7 +322,7 @@ TEST_F(PositiveGpuAVRayTracing, DynamicTminTmax) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -433,7 +433,7 @@ TEST_F(PositiveGpuAVRayTracing, BasicTraceRaysDynamicRayFlags) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -541,7 +541,7 @@ TEST_F(PositiveGpuAVRayTracing, DynamicRayFlagsSkipTriangle) { AddRequiredFeature(vkt::Feature::bufferDeviceAddress); AddRequiredFeature(vkt::Feature::rayTraversalPrimitiveCulling); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -654,7 +654,7 @@ TEST_F(PositiveGpuAVRayTracing, BasicTraceRaysMultiEntryPoint) { AddRequiredFeature(vkt::Feature::runtimeDescriptorArray); AddRequiredFeature(vkt::Feature::shaderSampledImageArrayNonUniformIndexing); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -863,7 +863,7 @@ TEST_F(PositiveGpuAVRayTracing, BasicTraceRaysDeferredBuild) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -951,7 +951,7 @@ TEST_F(PositiveGpuAVRayTracing, TraceRaysInCubes) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1107,7 +1107,7 @@ TEST_F(PositiveGpuAVRayTracing, TraceRaysInCubesTLASArray) { AddRequiredFeature(vkt::Feature::runtimeDescriptorArray); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1278,7 +1278,7 @@ TEST_F(PositiveGpuAVRayTracing, TraceRaysInCubesTLASArrayCallableShader) { AddRequiredFeature(vkt::Feature::runtimeDescriptorArray); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1459,7 +1459,7 @@ TEST_F(PositiveGpuAVRayTracing, TraceRaysInCubes2) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1682,7 +1682,7 @@ TEST_F(PositiveGpuAVRayTracing, OutOfBoundsIndex) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1742,7 +1742,7 @@ TEST_F(PositiveGpuAVRayTracing, OutOfBoundsIndex2) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1797,7 +1797,7 @@ TEST_F(PositiveGpuAVRayTracing, IndexBufferUpdate) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1886,7 +1886,7 @@ TEST_F(PositiveGpuAVRayTracing, VertexBufferUpdateStridedVertices) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -1984,7 +1984,7 @@ TEST_F(PositiveGpuAVRayTracing, AabbStatus) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::rayQuery); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2058,7 +2058,7 @@ TEST_F(PositiveGpuAVRayTracing, EmptyTlas) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::rayQuery); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2097,7 +2097,7 @@ TEST_F(PositiveGpuAVRayTracing, TlasBuildUsingZeroAsBlasAddress) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2188,7 +2188,7 @@ TEST_F(PositiveGpuAVRayTracing, BlasAddressRecycledFromDestroyedTlas) { AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2275,7 +2275,7 @@ TEST_F(PositiveGpuAVRayTracing, BlasReference1DescriptorHeap) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2454,7 +2454,7 @@ TEST_F(PositiveGpuAVRayTracing, BuildStateSnapshotFollowsExecutionOrder) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2523,7 +2523,7 @@ TEST_F(PositiveGpuAVRayTracing, VertexBufferUpdateOnlySubmittedBuildsMatter) { AddRequiredFeature(vkt::Feature::shaderInt64); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2630,7 +2630,7 @@ TEST_F(PositiveGpuAVRayTracing, TlasBuildReferencingClonedBlas) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2674,7 +2674,7 @@ TEST_F(PositiveGpuAVRayTracing, TlasBuildReferencingCompactedBlas) { AddRequiredFeature(vkt::Feature::accelerationStructure); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2717,7 +2717,7 @@ TEST_F(PositiveGpuAVRayTracing, TlasBuildReferencingIndirectBuiltBlas) { AddRequiredFeature(vkt::Feature::accelerationStructureIndirectBuild); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2745,7 +2745,7 @@ TEST_F(PositiveGpuAVRayTracing, SerializeAccelerationStructure) { AddRequiredFeature(vkt::Feature::accelerationStructureIndirectBuild); AddRequiredFeature(vkt::Feature::bufferDeviceAddress); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } @@ -2833,7 +2833,7 @@ TEST_F(PositiveGpuAVRayTracing, BuildAccelerationStructureDescriptorBuffer) { AddRequiredFeature(vkt::Feature::bufferDeviceAddress); AddRequiredFeature(vkt::Feature::descriptorBuffer); VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures(); - RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features)); + RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features, false)); if (!CanEnableGpuAV(*this)) { GTEST_SKIP() << "Requirements for GPU-AV are not met"; } diff --git a/tests/unit/ray_tracing_positive.cpp b/tests/unit/ray_tracing_positive.cpp index f4698b0a272..1d62f128b49 100644 --- a/tests/unit/ray_tracing_positive.cpp +++ b/tests/unit/ray_tracing_positive.cpp @@ -19,7 +19,8 @@ #include "utils/math_utils.h" #include -void RayTracingTest::InitFrameworkForRayTracingTest(VkValidationFeaturesEXT* enabled_features /*= nullptr*/) { +void RayTracingTest::InitFrameworkForRayTracingTest(VkValidationFeaturesEXT* enabled_features /*= nullptr*/, + bool safe_mode /*= true*/) { AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); AddRequiredExtensions(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); @@ -32,8 +33,12 @@ void RayTracingTest::InitFrameworkForRayTracingTest(VkValidationFeaturesEXT* ena AddRequiredExtensions(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); std::vector settings = { - {OBJECT_LAYER_NAME, "gpuav_ray_tracing_buffers_consistency", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}, - {OBJECT_LAYER_NAME, "gpuav_safe_mode", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}}; + {OBJECT_LAYER_NAME, "gpuav_ray_tracing_buffers_consistency", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}}; + // We have defaulted GPU-AV to use unsafe mode, but all negative tests need to be "safe" or they will crash + if (safe_mode) { + settings.emplace_back( + VkLayerSettingEXT{OBJECT_LAYER_NAME, "gpuav_safe_mode", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue}); + } VkLayerSettingsCreateInfoEXT layer_setting_ci = vku::InitStructHelper(enabled_features); layer_setting_ci.settingCount = size32(settings);