spirv-val: Allow the ViewportIndex and Layer built-ins on SPIR-V 1.5 (#3986)
* spirv-val: Allow the ViewportIndex and Layer built-ins when their corresponding SPIR-V 1.5 capabilities are present
* Added tests for OpCapability ShaderViewportIndex and OpCapability ShaderLayer
diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp
index 5b9eed6..1d85f88 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 <functional>
#include <list>
#include <map>
@@ -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 @@
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 4248caa..6bfcca3 100644
--- a/test/val/val_builtins_test.cpp
+++ b/test/val/val_builtins_test.cpp
@@ -71,6 +71,11 @@
std::tuple<const char*, const char*, const char*, const char*,
const char*, const char*, const char*, TestResult>>;
+using ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult =
+ spvtest::ValidateBase<std::tuple<spv_target_env, const char*, const char*,
+ const char*, const char*, const char*,
+ const char*, const char*, TestResult>>;
+
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(
+ 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 @@
"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,
@@ -1261,6 +1303,22 @@
"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,
Combine(Values("PatchVertices"),