mirror of
https://github.com/RPCSX/SPIRV-Tools.git
synced 2025-02-25 05:40:30 +00:00
Fix checks for offset in nested structs (#4531)
Fixes #4533 Fixes https://crbug.com/38771 * Fixes offset checks to look through arrays for nested structures
This commit is contained in:
parent
0f4508752f
commit
a6c5056db2
@ -129,18 +129,28 @@ std::vector<uint32_t> getStructMembers(uint32_t struct_id, SpvOp type,
|
||||
// Returns whether the given structure is missing Offset decoration for any
|
||||
// member. Handles also nested structures.
|
||||
bool isMissingOffsetInStruct(uint32_t struct_id, ValidationState_t& vstate) {
|
||||
std::vector<bool> hasOffset(getStructMembers(struct_id, vstate).size(),
|
||||
false);
|
||||
// Check offsets of member decorations
|
||||
for (auto& decoration : vstate.id_decorations(struct_id)) {
|
||||
if (SpvDecorationOffset == decoration.dec_type() &&
|
||||
Decoration::kInvalidMember != decoration.struct_member_index()) {
|
||||
hasOffset[decoration.struct_member_index()] = true;
|
||||
const auto* inst = vstate.FindDef(struct_id);
|
||||
std::vector<bool> hasOffset;
|
||||
std::vector<uint32_t> struct_members;
|
||||
if (inst->opcode() == SpvOpTypeStruct) {
|
||||
// Check offsets of member decorations.
|
||||
struct_members = getStructMembers(struct_id, vstate);
|
||||
hasOffset.resize(struct_members.size(), false);
|
||||
|
||||
for (auto& decoration : vstate.id_decorations(struct_id)) {
|
||||
if (SpvDecorationOffset == decoration.dec_type() &&
|
||||
Decoration::kInvalidMember != decoration.struct_member_index()) {
|
||||
hasOffset[decoration.struct_member_index()] = true;
|
||||
}
|
||||
}
|
||||
} else if (inst->opcode() == SpvOpTypeArray ||
|
||||
inst->opcode() == SpvOpTypeRuntimeArray) {
|
||||
hasOffset.resize(1, true);
|
||||
struct_members.push_back(inst->GetOperandAs<uint32_t>(1u));
|
||||
}
|
||||
// Check also nested structures
|
||||
// Look through nested structs (which may be in an array).
|
||||
bool nestedStructsMissingOffset = false;
|
||||
for (auto id : getStructMembers(struct_id, SpvOpTypeStruct, vstate)) {
|
||||
for (auto id : struct_members) {
|
||||
if (isMissingOffsetInStruct(id, vstate)) {
|
||||
nestedStructsMissingOffset = true;
|
||||
break;
|
||||
|
@ -7791,6 +7791,40 @@ OpFunctionEnd
|
||||
"member 0 is a matrix with stride 3 not satisfying alignment to 4"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, MissingOffsetStructNestedInArray) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpDecorate %array ArrayStride 4
|
||||
OpDecorate %outer Block
|
||||
OpMemberDecorate %outer 0 Offset 0
|
||||
OpDecorate %var DescriptorSet 0
|
||||
OpDecorate %var Binding 0
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 0
|
||||
%int_4 = OpConstant %int 4
|
||||
%inner = OpTypeStruct %int
|
||||
%array = OpTypeArray %inner %int_4
|
||||
%outer = OpTypeStruct %array
|
||||
%ptr_ssbo_outer = OpTypePointer StorageBuffer %outer
|
||||
%var = OpVariable %ptr_ssbo_outer StorageBuffer
|
||||
%void_fn = OpTypeFunction %void
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Structure id 3 decorated as Block must be explicitly "
|
||||
"laid out with Offset decorations"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
Loading…
x
Reference in New Issue
Block a user