spirv-val: Add support for SPV_AMD_shader_early_and_late_fragment_tests (#4812)
- Update SPIR-V headers.
- Add validator support.
- Add validator tests.
diff --git a/DEPS b/DEPS
index 808ef6c..78c9dd3 100644
--- a/DEPS
+++ b/DEPS
@@ -6,7 +6,7 @@
'effcee_revision': 'ddf5e2bb92957dc8a12c5392f8495333d6844133',
'googletest_revision': '548b13dc3c02b93f60eeff9a0cc6e11c1ea722ca',
're2_revision': '5723bb8950318135ed9cf4fc76bed988a087f536',
- 'spirv_headers_revision': '5a121866927a16ab9d49bed4788b532c7fcea766',
+ 'spirv_headers_revision': 'b2a156e1c0434bc8c99aaebba1c7be98be7ac580',
}
deps = {
diff --git a/source/val/validate_mode_setting.cpp b/source/val/validate_mode_setting.cpp
index 9635268..67b10c5 100644
--- a/source/val/validate_mode_setting.cpp
+++ b/source/val/validate_mode_setting.cpp
@@ -112,6 +112,44 @@
<< "Fragment execution model entry points can specify at most "
"one fragment shader interlock execution mode.";
}
+ if (execution_modes &&
+ 1 < std::count_if(
+ execution_modes->begin(), execution_modes->end(),
+ [](const SpvExecutionMode& mode) {
+ switch (mode) {
+ case SpvExecutionModeStencilRefUnchangedFrontAMD:
+ case SpvExecutionModeStencilRefLessFrontAMD:
+ case SpvExecutionModeStencilRefGreaterFrontAMD:
+ return true;
+ default:
+ return false;
+ }
+ })) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "Fragment execution model entry points can specify at most "
+ "one of StencilRefUnchangedFrontAMD, "
+ "StencilRefLessFrontAMD or StencilRefGreaterFrontAMD "
+ "execution modes.";
+ }
+ if (execution_modes &&
+ 1 < std::count_if(
+ execution_modes->begin(), execution_modes->end(),
+ [](const SpvExecutionMode& mode) {
+ switch (mode) {
+ case SpvExecutionModeStencilRefUnchangedBackAMD:
+ case SpvExecutionModeStencilRefLessBackAMD:
+ case SpvExecutionModeStencilRefGreaterBackAMD:
+ return true;
+ default:
+ return false;
+ }
+ })) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "Fragment execution model entry points can specify at most "
+ "one of StencilRefUnchangedBackAMD, "
+ "StencilRefLessBackAMD or StencilRefGreaterBackAMD "
+ "execution modes.";
+ }
break;
case SpvExecutionModelTessellationControl:
case SpvExecutionModelTessellationEvaluation:
@@ -412,6 +450,13 @@
case SpvExecutionModeSampleInterlockUnorderedEXT:
case SpvExecutionModeShadingRateInterlockOrderedEXT:
case SpvExecutionModeShadingRateInterlockUnorderedEXT:
+ case SpvExecutionModeEarlyAndLateFragmentTestsAMD:
+ case SpvExecutionModeStencilRefUnchangedFrontAMD:
+ case SpvExecutionModeStencilRefGreaterFrontAMD:
+ case SpvExecutionModeStencilRefLessFrontAMD:
+ case SpvExecutionModeStencilRefUnchangedBackAMD:
+ case SpvExecutionModeStencilRefGreaterBackAMD:
+ case SpvExecutionModeStencilRefLessBackAMD:
if (!std::all_of(models->begin(), models->end(),
[](const SpvExecutionModel& model) {
return model == SpvExecutionModelFragment;
diff --git a/test/val/val_modes_test.cpp b/test/val/val_modes_test.cpp
index a37989b..689f0ba 100644
--- a/test/val/val_modes_test.cpp
+++ b/test/val/val_modes_test.cpp
@@ -1101,6 +1101,89 @@
EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
}
+
+TEST_F(ValidateMode, FragmentShaderStencilRefFrontTooManyModesBad) {
+ const std::string spirv = R"(
+OpCapability Shader
+OpCapability StencilExportEXT
+OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
+OpExtension "SPV_EXT_shader_stencil_export"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+OpExecutionMode %main EarlyAndLateFragmentTestsAMD
+OpExecutionMode %main StencilRefLessFrontAMD
+OpExecutionMode %main StencilRefGreaterFrontAMD
+)" + kVoidFunction;
+
+ CompileSuccessfully(spirv);
+ EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Fragment execution model entry points can specify at most "
+ "one of StencilRefUnchangedFrontAMD, "
+ "StencilRefLessFrontAMD or StencilRefGreaterFrontAMD "
+ "execution modes."));
+}
+
+TEST_F(ValidateMode, FragmentShaderStencilRefBackTooManyModesBad) {
+ const std::string spirv = R"(
+OpCapability Shader
+OpCapability StencilExportEXT
+OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
+OpExtension "SPV_EXT_shader_stencil_export"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+OpExecutionMode %main EarlyAndLateFragmentTestsAMD
+OpExecutionMode %main StencilRefLessBackAMD
+OpExecutionMode %main StencilRefGreaterBackAMD
+)" + kVoidFunction;
+
+ CompileSuccessfully(spirv);
+ EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Fragment execution model entry points can specify at most "
+ "one of StencilRefUnchangedBackAMD, "
+ "StencilRefLessBackAMD or StencilRefGreaterBackAMD "
+ "execution modes."));
+}
+
+TEST_F(ValidateMode, FragmentShaderStencilRefFrontGood) {
+ const std::string spirv = R"(
+OpCapability Shader
+OpCapability StencilExportEXT
+OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
+OpExtension "SPV_EXT_shader_stencil_export"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+OpExecutionMode %main EarlyAndLateFragmentTestsAMD
+OpExecutionMode %main StencilRefLessFrontAMD
+)" + kVoidFunction;
+
+ CompileSuccessfully(spirv);
+ EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateMode, FragmentShaderStencilRefBackGood) {
+ const std::string spirv = R"(
+OpCapability Shader
+OpCapability StencilExportEXT
+OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
+OpExtension "SPV_EXT_shader_stencil_export"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+OpExecutionMode %main EarlyAndLateFragmentTestsAMD
+OpExecutionMode %main StencilRefLessBackAMD
+)" + kVoidFunction;
+
+ CompileSuccessfully(spirv);
+ EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
+}
+
TEST_F(ValidateMode, FragmentShaderDemoteVertexBad) {
const std::string spirv = R"(
OpCapability Shader