From f76431cbaf86e7d5a148dd45ecbe2d4531fcdd21 Mon Sep 17 00:00:00 2001 From: Spencer Fricke Date: Tue, 30 Aug 2022 00:09:06 +0900 Subject: [PATCH] spirv-val: Add SPV_KHR_ray_tracing storage class (#4868) * Added VUID labels --- source/val/validate_memory.cpp | 37 ++++- source/val/validation_state.cpp | 128 +++++++++++++- test/val/val_storage_test.cpp | 285 +++++++++++++++++++++++++++++++- 3 files changed, 432 insertions(+), 18 deletions(-) diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp index 425a8d3d2..5571aa64d 100644 --- a/source/val/validate_memory.cpp +++ b/source/val/validate_memory.cpp @@ -438,11 +438,11 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { storage_class != SpvStorageClassCrossWorkgroup && storage_class != SpvStorageClassPrivate && storage_class != SpvStorageClassFunction && - storage_class != SpvStorageClassRayPayloadNV && - storage_class != SpvStorageClassIncomingRayPayloadNV && - storage_class != SpvStorageClassHitAttributeNV && - storage_class != SpvStorageClassCallableDataNV && - storage_class != SpvStorageClassIncomingCallableDataNV) { + storage_class != SpvStorageClassRayPayloadKHR && + storage_class != SpvStorageClassIncomingRayPayloadKHR && + storage_class != SpvStorageClassHitAttributeKHR && + storage_class != SpvStorageClassCallableDataKHR && + storage_class != SpvStorageClassIncomingCallableDataKHR) { bool storage_input_or_output = storage_class == SpvStorageClassInput || storage_class == SpvStorageClassOutput; bool builtin = false; @@ -889,8 +889,11 @@ spv_result_t ValidateLoad(ValidationState_t& _, const Instruction* inst) { << "' is not a pointer type."; } - const auto pointee_type = _.FindDef(pointer_type->GetOperandAs(2)); - if (!pointee_type || result_type->id() != pointee_type->id()) { + uint32_t pointee_data_type; + uint32_t storage_class; + if (!_.GetPointerTypeInfo(pointer_type->id(), &pointee_data_type, + &storage_class) || + result_type->id() != pointee_data_type) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpLoad Result Type '" << _.getIdName(inst->type_id()) << "' does not match Pointer '" << _.getIdName(pointer->id()) @@ -964,6 +967,26 @@ spv_result_t ValidateStore(ValidationState_t& _, const Instruction* inst) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpStore Pointer '" << _.getIdName(pointer_id) << "' storage class is read-only"; + } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "ShaderRecordBufferKHR Storage Class variables are read only"; + } else if (storage_class == SpvStorageClassHitAttributeKHR) { + std::string errorVUID = _.VkErrorID(4703); + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model == SpvExecutionModelAnyHitKHR || + model == SpvExecutionModelClosestHitKHR) { + if (message) { + *message = + errorVUID + + "HitAttributeKHR Storage Class variables are read only " + "with AnyHitKHR and ClosestHitKHR"; + } + return false; + } + return true; + }); } if (spvIsVulkanEnv(_.context()->target_env) && diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index 2702b2b08..3501e8ceb 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -608,7 +608,8 @@ void ValidationState_t::RegisterStorageClassConsumer( std::string errorVUID = VkErrorID(4644); function(consumer->function()->id()) ->RegisterExecutionModelLimitation([errorVUID]( - SpvExecutionModel model, std::string* message) { + SpvExecutionModel model, + std::string* message) { if (model == SpvExecutionModelGLCompute || model == SpvExecutionModelRayGenerationKHR || model == SpvExecutionModelIntersectionKHR || @@ -634,7 +635,8 @@ void ValidationState_t::RegisterStorageClassConsumer( std::string errorVUID = VkErrorID(4645); function(consumer->function()->id()) ->RegisterExecutionModelLimitation([errorVUID]( - SpvExecutionModel model, std::string* message) { + SpvExecutionModel model, + std::string* message) { if (model != SpvExecutionModelGLCompute && model != SpvExecutionModelTaskNV && model != SpvExecutionModelMeshNV) { @@ -650,6 +652,116 @@ void ValidationState_t::RegisterStorageClassConsumer( }); } } + + if (storage_class == SpvStorageClassCallableDataKHR) { + std::string errorVUID = VkErrorID(4704); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelCallableKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = errorVUID + + "CallableDataKHR Storage Class is limited to " + "RayGenerationKHR, ClosestHitKHR, CallableKHR, and " + "MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassIncomingCallableDataKHR) { + std::string errorVUID = VkErrorID(4705); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelCallableKHR) { + if (message) { + *message = errorVUID + + "IncomingCallableDataKHR Storage Class is limited to " + "CallableKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassRayPayloadKHR) { + std::string errorVUID = VkErrorID(4698); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + errorVUID + + "RayPayloadKHR Storage Class is limited to RayGenerationKHR, " + "ClosestHitKHR, and MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassHitAttributeKHR) { + std::string errorVUID = VkErrorID(4701); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelIntersectionKHR && + model != SpvExecutionModelAnyHitKHR && + model != SpvExecutionModelClosestHitKHR) { + if (message) { + *message = errorVUID + + "HitAttributeKHR Storage Class is limited to " + "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR " + "execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassIncomingRayPayloadKHR) { + std::string errorVUID = VkErrorID(4699); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelAnyHitKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + errorVUID + + "IncomingRayPayloadKHR Storage Class is limited to " + "AnyHitKHR, ClosestHitKHR, and MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) { + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelIntersectionKHR && + model != SpvExecutionModelAnyHitKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelCallableKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + "ShaderRecordBufferKHR Storage Class is limited to " + "RayGenerationKHR, IntersectionKHR, AnyHitKHR, " + "ClosestHitKHR, CallableKHR, and MissKHR execution model"; + } + return false; + } + return true; + }); + } } uint32_t ValidationState_t::getIdBound() const { return id_bound_; } @@ -1911,6 +2023,18 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685); case 4686: return VUID_WRAP(VUID-StandaloneSpirv-None-04686); + case 4698: + return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698); + case 4699: + return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699); + case 4701: + return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701); + case 4703: + return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703); + case 4704: + return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704); + case 4705: + return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705); case 4708: return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708); case 4710: diff --git a/test/val/val_storage_test.cpp b/test/val/val_storage_test.cpp index ae4047b9a..600e5b918 100644 --- a/test/val/val_storage_test.cpp +++ b/test/val/val_storage_test.cpp @@ -251,30 +251,46 @@ TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParamBad) { HasSubstr("OpFunctionCall Argument '")); } -TEST_P(ValidateStorageExecutionModel, VulkanOutsideStoreFailure) { - std::stringstream ss; +std::string GenerateExecutionModelCode(const std::string& execution_model, + const std::string& storage_class, + bool store) { + const std::string mode = (execution_model.compare("GLCompute") == 0) + ? "OpExecutionMode %func LocalSize 1 1 1" + : ""; + const std::string operation = + (store) ? "OpStore %var %int0" : "%load = OpLoad %intt %var"; + std::ostringstream ss; ss << R"( OpCapability Shader OpCapability RayTracingKHR OpExtension "SPV_KHR_ray_tracing" OpMemoryModel Logical GLSL450 OpEntryPoint )" - << GetParam() << R"( %func "func" %output - OpDecorate %output Location 0 + << execution_model << R"( %func "func" %var + )" << mode << R"( + OpDecorate %var Location 0 %intt = OpTypeInt 32 0 %int0 = OpConstant %intt 0 %voidt = OpTypeVoid %vfunct = OpTypeFunction %voidt -%outputptrt = OpTypePointer Output %intt -%output = OpVariable %outputptrt Output +%ptr = OpTypePointer )" + << storage_class << R"( %intt +%var = OpVariable %ptr )" << storage_class << R"( %func = OpFunction %voidt None %vfunct %funcl = OpLabel - OpStore %output %int0 + )" << operation << R"( OpReturn OpFunctionEnd )"; - CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0); + return ss.str(); +} + +TEST_P(ValidateStorageExecutionModel, VulkanOutsideStoreFailure) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "Output", true).c_str(), + SPV_ENV_VULKAN_1_0); ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0)); EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-StandaloneSpirv-None-04644")); @@ -285,11 +301,262 @@ TEST_P(ValidateStorageExecutionModel, VulkanOutsideStoreFailure) { "ClosestHitKHR, MissKHR, or CallableKHR execution models")); } +TEST_P(ValidateStorageExecutionModel, CallableDataStore) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "CallableDataKHR", true) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("RayGenerationKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("CallableKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-CallableDataKHR-04704")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "CallableDataKHR Storage Class is limited to RayGenerationKHR, " + "ClosestHitKHR, CallableKHR, and MissKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, CallableDataLoad) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "CallableDataKHR", false) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("RayGenerationKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("CallableKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-CallableDataKHR-04704")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "CallableDataKHR Storage Class is limited to RayGenerationKHR, " + "ClosestHitKHR, CallableKHR, and MissKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, IncomingCallableDataStore) { + std::string execution_model = GetParam(); + CompileSuccessfully(GenerateExecutionModelCode( + execution_model, "IncomingCallableDataKHR", true) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("CallableKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04705")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("IncomingCallableDataKHR Storage Class is limited to " + "CallableKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, IncomingCallableDataLoad) { + std::string execution_model = GetParam(); + CompileSuccessfully(GenerateExecutionModelCode( + execution_model, "IncomingCallableDataKHR", false) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("CallableKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04705")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("IncomingCallableDataKHR Storage Class is limited to " + "CallableKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, RayPayloadStore) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "RayPayloadKHR", true) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("RayGenerationKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-RayPayloadKHR-04698")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("RayPayloadKHR Storage Class is limited to RayGenerationKHR, " + "ClosestHitKHR, and MissKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, RayPayloadLoad) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "RayPayloadKHR", false) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("RayGenerationKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-RayPayloadKHR-04698")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("RayPayloadKHR Storage Class is limited to RayGenerationKHR, " + "ClosestHitKHR, and MissKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, HitAttributeStore) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "HitAttributeKHR", true) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("IntersectionKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else if (execution_model.compare("AnyHitKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0) { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04703")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("HitAttributeKHR Storage Class variables are read " + "only with AnyHitKHR and ClosestHitKHR")); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04701")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "HitAttributeKHR Storage Class is limited to IntersectionKHR, " + "AnyHitKHR, sand ClosestHitKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, HitAttributeLoad) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "HitAttributeKHR", false) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("IntersectionKHR") == 0 || + execution_model.compare("AnyHitKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04701")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "HitAttributeKHR Storage Class is limited to IntersectionKHR, " + "AnyHitKHR, sand ClosestHitKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, IncomingRayPayloadStore) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "IncomingRayPayloadKHR", true) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("AnyHitKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("IncomingRayPayloadKHR Storage Class is limited to " + "AnyHitKHR, ClosestHitKHR, and MissKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, IncomingRayPayloadLoad) { + std::string execution_model = GetParam(); + CompileSuccessfully(GenerateExecutionModelCode(execution_model, + "IncomingRayPayloadKHR", false) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("AnyHitKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699")); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("IncomingRayPayloadKHR Storage Class is limited to " + "AnyHitKHR, ClosestHitKHR, and MissKHR execution model")); + } +} + +TEST_P(ValidateStorageExecutionModel, ShaderRecordBufferStore) { + std::string execution_model = GetParam(); + CompileSuccessfully( + GenerateExecutionModelCode(execution_model, "ShaderRecordBufferKHR", true) + .c_str(), + SPV_ENV_VULKAN_1_2); + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("ShaderRecordBufferKHR Storage Class variables are read only")); +} + +TEST_P(ValidateStorageExecutionModel, ShaderRecordBufferLoad) { + std::string execution_model = GetParam(); + CompileSuccessfully(GenerateExecutionModelCode(execution_model, + "ShaderRecordBufferKHR", false) + .c_str(), + SPV_ENV_VULKAN_1_2); + if (execution_model.compare("RayGenerationKHR") == 0 || + execution_model.compare("IntersectionKHR") == 0 || + execution_model.compare("AnyHitKHR") == 0 || + execution_model.compare("ClosestHitKHR") == 0 || + execution_model.compare("CallableKHR") == 0 || + execution_model.compare("MissKHR") == 0) { + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + } else { + ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2)); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("ShaderRecordBufferKHR Storage Class is limited to " + "RayGenerationKHR, IntersectionKHR, AnyHitKHR, " + "ClosestHitKHR, CallableKHR, and MissKHR execution model")); + } +} + INSTANTIATE_TEST_SUITE_P(MatrixExecutionModel, ValidateStorageExecutionModel, ::testing::Values("RayGenerationKHR", "IntersectionKHR", "AnyHitKHR", "ClosestHitKHR", "MissKHR", - "CallableKHR")); + "CallableKHR", "GLCompute")); } // namespace } // namespace val