spirv-val: Separate Location check for tess patch (#5654)

This commit is contained in:
Spencer Fricke 2024-05-01 01:29:22 +09:00 committed by GitHub
parent dd4b663e13
commit 57a42e6c1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 88 additions and 0 deletions

View File

@ -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;

View File

@ -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"(