diff options
author | Spencer Fricke <115671160+spencer-lunarg@users.noreply.github.com> | 2024-05-01 01:29:22 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-30 12:29:22 -0400 |
commit | 57a42e6c1dfa44ca96a662044bd43637d1d4822e (patch) | |
tree | 6b69f30c5fa0c8135a1cfa9ddf727d949555bcae | |
parent | dd4b663e13c07fea4fbb3f70c1c91c86731099f7 (diff) | |
download | spirv-tools-57a42e6c1dfa44ca96a662044bd43637d1d4822e.tar.gz |
spirv-val: Separate Location check for tess patch (#5654)
-rw-r--r-- | source/val/validate_interfaces.cpp | 22 | ||||
-rw-r--r-- | test/val/val_interfaces_test.cpp | 66 |
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"( |