aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer Fricke <115671160+spencer-lunarg@users.noreply.github.com>2024-05-01 01:29:22 +0900
committerGitHub <noreply@github.com>2024-04-30 12:29:22 -0400
commit57a42e6c1dfa44ca96a662044bd43637d1d4822e (patch)
tree6b69f30c5fa0c8135a1cfa9ddf727d949555bcae
parentdd4b663e13c07fea4fbb3f70c1c91c86731099f7 (diff)
downloadspirv-tools-57a42e6c1dfa44ca96a662044bd43637d1d4822e.tar.gz
spirv-val: Separate Location check for tess patch (#5654)
-rw-r--r--source/val/validate_interfaces.cpp22
-rw-r--r--test/val/val_interfaces_test.cpp66
2 files changed, 88 insertions, 0 deletions
diff --git a/source/val/validate_interfaces.cpp b/source/val/validate_interfaces.cpp
index ace548aa..8f10b9d0 100644
--- a/source/val/validate_interfaces.cpp
+++ b/source/val/validate_interfaces.cpp
@@ -519,6 +519,8 @@ spv_result_t ValidateLocations(ValidationState_t& _,
std::unordered_set<uint32_t> input_locations;
std::unordered_set<uint32_t> output_locations_index0;
std::unordered_set<uint32_t> output_locations_index1;
+ std::unordered_set<uint32_t> patch_locations_index0;
+ std::unordered_set<uint32_t> patch_locations_index1;
std::unordered_set<uint32_t> seen;
for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
@@ -534,6 +536,26 @@ spv_result_t ValidateLocations(ValidationState_t& _,
continue;
}
+ // The two Tessellation stages have a "Patch" variable that interface with
+ // the Location mechanism, but are not suppose to be tied to the "normal"
+ // input/output Location.
+ // TODO - SPIR-V allows the Patch decoration to be applied to struct
+ // members, but is not allowed in GLSL/HLSL
+ bool has_patch = false;
+ for (auto& dec : _.id_decorations(interface_var->id())) {
+ if (dec.dec_type() == spv::Decoration::Patch) {
+ has_patch = true;
+ if (auto error = GetLocationsForVariable(_, entry_point, interface_var,
+ &patch_locations_index0,
+ &patch_locations_index1))
+ return error;
+ break;
+ }
+ }
+ if (has_patch) {
+ continue;
+ }
+
auto locations = (storage_class == spv::StorageClass::Input)
? &input_locations
: &output_locations_index0;
diff --git a/test/val/val_interfaces_test.cpp b/test/val/val_interfaces_test.cpp
index 4f62be79..40e67184 100644
--- a/test/val/val_interfaces_test.cpp
+++ b/test/val/val_interfaces_test.cpp
@@ -623,6 +623,72 @@ OpFunctionEnd
"at location 1"));
}
+TEST_F(ValidateInterfacesTest, VulkanPatchAndNonPatchOverlap) {
+ const std::string text = R"(
+ OpCapability Tessellation
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationControl %main "main" %a %b
+ OpExecutionMode %main OutputVertices 4
+ OpDecorate %a Location 0
+ OpDecorate %b Patch
+ OpDecorate %b Location 0
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %uint = OpTypeInt 32 0
+ %uint_4 = OpConstant %uint 4
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+ %a = OpVariable %_ptr_Output__arr_float_uint_4 Output
+%_ptr_Output_float = OpTypePointer Output %float
+ %b = OpVariable %_ptr_Output_float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+}
+
+TEST_F(ValidateInterfacesTest, VulkanPatchOverlap) {
+ const std::string text = R"(
+ OpCapability Tessellation
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint TessellationControl %main "main" %a %b %c
+ OpExecutionMode %main OutputVertices 4
+ OpDecorate %a Location 0
+ OpDecorate %b Patch
+ OpDecorate %b Location 6
+ OpDecorate %c Patch
+ OpDecorate %c Location 6
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %uint = OpTypeInt 32 0
+ %uint_4 = OpConstant %uint 4
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+ %a = OpVariable %_ptr_Output__arr_float_uint_4 Output
+%_ptr_Output_float = OpTypePointer Output %float
+ %b = OpVariable %_ptr_Output_float Output
+ %c = OpVariable %_ptr_Output_float Output
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Entry-point has conflicting output location "
+ "assignment at location 6, component 0"));
+}
+
TEST_F(ValidateInterfacesTest,
VulkanLocationsSameLocationInputAndOutputNoConflict) {
const std::string text = R"(