diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp index 5b9eed6407..1d85f88777 100644 --- a/source/val/validate_builtins.cpp +++ b/source/val/validate_builtins.cpp @@ -16,8 +16,6 @@ // Validates correctness of built-in variables. -#include "source/val/validate.h" - #include #include #include @@ -33,6 +31,7 @@ #include "source/spirv_target_env.h" #include "source/util/bitutils.h" #include "source/val/instruction.h" +#include "source/val/validate.h" #include "source/val/validation_state.h" namespace spvtools { @@ -2641,12 +2640,26 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( case SpvExecutionModelVertex: case SpvExecutionModelTessellationEvaluation: { if (!_.HasCapability(SpvCapabilityShaderViewportIndexLayerEXT)) { + if (operand == SpvBuiltInViewportIndex && + _.HasCapability(SpvCapabilityShaderViewportIndex)) + break; // Ok + if (operand == SpvBuiltInLayer && + _.HasCapability(SpvCapabilityShaderLayer)) + break; // Ok + + const char* capability = "ShaderViewportIndexLayerEXT"; + + if (operand == SpvBuiltInViewportIndex) + capability = "ShaderViewportIndexLayerEXT or ShaderViewportIndex"; + if (operand == SpvBuiltInLayer) + capability = "ShaderViewportIndexLayerEXT or ShaderLayer"; + return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) << "Using BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, operand) - << " in Vertex or Tessellation execution model requires " - "the ShaderViewportIndexLayerEXT capability."; + << " in Vertex or Tessellation execution model requires the " + << capability << " capability."; } break; } diff --git a/test/val/val_builtins_test.cpp b/test/val/val_builtins_test.cpp index 4248caa9b1..6bfcca34f8 100644 --- a/test/val/val_builtins_test.cpp +++ b/test/val/val_builtins_test.cpp @@ -71,6 +71,11 @@ using ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResul std::tuple>; +using ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult = + spvtest::ValidateBase>; + bool InitializerRequired(spv_target_env env, const char* const storage_class) { return spvIsWebGPUEnv(env) && (strncmp(storage_class, "Output", 6) == 0 || strncmp(storage_class, "Private", 7) == 0 || @@ -258,6 +263,36 @@ TEST_P( } } +TEST_P( + ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, + InMain) { + const spv_target_env env = std::get<0>(GetParam()); + const char* const built_in = std::get<1>(GetParam()); + const char* const execution_model = std::get<2>(GetParam()); + const char* const storage_class = std::get<3>(GetParam()); + const char* const data_type = std::get<4>(GetParam()); + const char* const capabilities = std::get<5>(GetParam()); + const char* const extensions = std::get<6>(GetParam()); + const char* const vuid = std::get<7>(GetParam()); + const TestResult& test_result = std::get<8>(GetParam()); + + CodeGenerator generator = + GetInMainCodeGenerator(env, built_in, execution_model, storage_class, + capabilities, extensions, data_type); + + CompileSuccessfully(generator.Build(), env); + ASSERT_EQ(test_result.validation_result, ValidateInstructions(env)); + if (test_result.error_str) { + EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str)); + } + if (test_result.error_str2) { + EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2)); + } + if (vuid) { + EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid)); + } +} + CodeGenerator GetInFunctionCodeGenerator(spv_target_env env, const char* const built_in, const char* const execution_model, @@ -1207,14 +1242,21 @@ INSTANTIATE_TEST_SUITE_P( "Geometry, or Fragment execution models")))); INSTANTIATE_TEST_SUITE_P( - LayerAndViewportIndexExecutionModelEnabledByCapability, + ViewportIndexExecutionModelEnabledByCapability, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, - Combine(Values("Layer", "ViewportIndex"), - Values("Vertex", "TessellationEvaluation"), Values("Output"), - Values("%u32"), Values(nullptr), + Combine(Values("ViewportIndex"), Values("Vertex", "TessellationEvaluation"), + Values("Output"), Values("%u32"), Values(nullptr), Values(TestResult( SPV_ERROR_INVALID_DATA, - "requires the ShaderViewportIndexLayerEXT capability")))); + "ShaderViewportIndexLayerEXT or ShaderViewportIndex")))); + +INSTANTIATE_TEST_SUITE_P( + LayerExecutionModelEnabledByCapability, + ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, + Combine(Values("Layer"), Values("Vertex", "TessellationEvaluation"), + Values("Output"), Values("%u32"), Values(nullptr), + Values(TestResult(SPV_ERROR_INVALID_DATA, + "ShaderViewportIndexLayerEXT or ShaderLayer")))); INSTANTIATE_TEST_SUITE_P( LayerAndViewportIndexFragmentNotInput, @@ -1260,6 +1302,22 @@ INSTANTIATE_TEST_SUITE_P( "needs to be a 32-bit int scalar", "has bit width 64")))); +INSTANTIATE_TEST_SUITE_P( + LayerCapability, + ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, + Combine(Values(SPV_ENV_VULKAN_1_2), Values("Layer"), Values("Vertex"), + Values("Output"), Values("%u32"), + Values("OpCapability ShaderLayer\n"), Values(nullptr), + Values(nullptr), Values(TestResult()))); + +INSTANTIATE_TEST_SUITE_P( + ViewportIndexCapability, + ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult, + Combine(Values(SPV_ENV_VULKAN_1_2), Values("ViewportIndex"), + Values("Vertex"), Values("Output"), Values("%u32"), + Values("OpCapability ShaderViewportIndex\n"), Values(nullptr), + Values(nullptr), Values(TestResult()))); + INSTANTIATE_TEST_SUITE_P( PatchVerticesSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,