diff --git a/source/val/validate_interfaces.cpp b/source/val/validate_interfaces.cpp index ace548aa1af..5817e1144a1 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 input_locations; std::unordered_set output_locations_index0; std::unordered_set output_locations_index1; + std::unordered_set patch_locations_index0; + std::unordered_set patch_locations_index1; std::unordered_set seen; for (uint32_t i = 3; i < entry_point->operands().size(); ++i) { auto interface_id = entry_point->GetOperandAs(i); @@ -534,6 +536,16 @@ spv_result_t ValidateLocations(ValidationState_t& _, continue; } + for (auto& dec : _.id_decorations(interface_var->id())) { + if (dec.dec_type() == spv::Decoration::Patch) { + if (auto error = GetLocationsForVariable(_, entry_point, interface_var, + &patch_locations_index0, + &patch_locations_index1)) + return error; + break; + } + } + 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 4f62be799dc..40e67184d50 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"(