Skip to content

Commit

Permalink
Disallow duplicate decorations generally
Browse files Browse the repository at this point in the history
* Only FuncParamAttr and UserSemantic can be applied to the same target
  multiple times
* Unchecked: completely duplicate UserSemantic and FuncParamAttr
  • Loading branch information
alan-baker committed Apr 10, 2024
1 parent 3983d15 commit 09edc76
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 32 deletions.
13 changes: 3 additions & 10 deletions source/val/validate_decorations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1325,21 +1325,14 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {

// Returns true if |decoration| cannot be applied to the same id more than once.
bool AtMostOncePerId(spv::Decoration decoration) {
return decoration == spv::Decoration::ArrayStride;
return decoration != spv::Decoration::UserSemantic &&
decoration != spv::Decoration::FuncParamAttr;
}

// Returns true if |decoration| cannot be applied to the same member more than
// once.
bool AtMostOncePerMember(spv::Decoration decoration) {
switch (decoration) {
case spv::Decoration::Offset:
case spv::Decoration::MatrixStride:
case spv::Decoration::RowMajor:
case spv::Decoration::ColMajor:
return true;
default:
return false;
}
return decoration != spv::Decoration::UserSemantic;
}

spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) {
Expand Down
15 changes: 1 addition & 14 deletions source/val/validate_interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,37 +254,24 @@ spv_result_t GetLocationsForVariable(
// equal. Also track Patch and PerTaskNV decorations.
bool has_location = false;
uint32_t location = 0;
bool has_component = false;
uint32_t component = 0;
bool has_index = false;
uint32_t index = 0;
bool has_patch = false;
bool has_per_task_nv = false;
bool has_per_vertex_khr = false;
// Duplicate Location, Component, Index are checked elsewhere.
for (auto& dec : _.id_decorations(variable->id())) {
if (dec.dec_type() == spv::Decoration::Location) {
if (has_location && dec.params()[0] != location) {
return _.diag(SPV_ERROR_INVALID_DATA, variable)
<< "Variable has conflicting location decorations";
}
has_location = true;
location = dec.params()[0];
} else if (dec.dec_type() == spv::Decoration::Component) {
if (has_component && dec.params()[0] != component) {
return _.diag(SPV_ERROR_INVALID_DATA, variable)
<< "Variable has conflicting component decorations";
}
has_component = true;
component = dec.params()[0];
} else if (dec.dec_type() == spv::Decoration::Index) {
if (!is_output || !is_fragment) {
return _.diag(SPV_ERROR_INVALID_DATA, variable)
<< "Index can only be applied to Fragment output variables";
}
if (has_index && dec.params()[0] != index) {
return _.diag(SPV_ERROR_INVALID_DATA, variable)
<< "Variable has conflicting index decorations";
}
has_index = true;
index = dec.params()[0];
} else if (dec.dec_type() == spv::Decoration::BuiltIn) {
Expand Down
16 changes: 8 additions & 8 deletions test/val/val_interfaces_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,9 @@ OpFunctionEnd
)";

CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Variable has conflicting location decorations"));
HasSubstr("decorated with Location multiple times is not allowed"));
}

TEST_F(ValidateInterfacesTest, VulkanLocationsVariableAndMemberAssigned) {
Expand Down Expand Up @@ -505,9 +505,9 @@ OpFunctionEnd
)";

CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Member index 1 has conflicting location assignments"));
HasSubstr("decorated with Location multiple times is not allowed"));
}

TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
Expand Down Expand Up @@ -1157,9 +1157,9 @@ OpFunctionEnd
)";

CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Variable has conflicting component decorations"));
HasSubstr("decorated with Component multiple times is not allowed"));
}

TEST_F(ValidateInterfacesTest,
Expand All @@ -1186,10 +1186,10 @@ OpFunctionEnd
)";

CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("Member index 0 has conflicting component assignments"));
HasSubstr("decorated with Component multiple times is not allowed"));
}

TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
Expand Down

0 comments on commit 09edc76

Please sign in to comment.