Correctly reflect declared buffer size for out of order members.

Need to deduce size based on member with highest offset, not highest
index.
This commit is contained in:
Hans-Kristian Arntzen 2021-11-07 10:08:17 +01:00
parent 04293e03fd
commit 05e8e5a953
3 changed files with 72 additions and 4 deletions

View File

@ -0,0 +1,44 @@
{
"entryPoints" : [
{
"name" : "main",
"mode" : "comp",
"workgroup_size" : [
1,
1,
1
],
"workgroup_size_is_spec_constant_id" : [
false,
false,
false
]
}
],
"types" : {
"_7" : {
"name" : "SSBO",
"members" : [
{
"name" : "foo",
"type" : "uint",
"offset" : 8
},
{
"name" : "bar",
"type" : "uint",
"offset" : 4
}
]
}
},
"ssbos" : [
{
"type" : "_7",
"name" : "SSBO",
"block_size" : 12,
"set" : 0,
"binding" : 0
}
]
}

View File

@ -0,0 +1,12 @@
#version 450
layout(set = 0, binding = 0) buffer SSBO
{
layout(offset = 8) uint foo;
layout(offset = 4) uint bar;
};
void main()
{
bar = foo;
}

View File

@ -1729,10 +1729,22 @@ size_t Compiler::get_declared_struct_size(const SPIRType &type) const
if (type.member_types.empty())
SPIRV_CROSS_THROW("Declared struct in block cannot be empty.");
uint32_t last = uint32_t(type.member_types.size() - 1);
size_t offset = type_struct_member_offset(type, last);
size_t size = get_declared_struct_member_size(type, last);
return offset + size;
// Offsets can be declared out of order, so we need to deduce the actual size
// based on last member instead.
uint32_t member_index = 0;
size_t highest_offset = 0;
for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
{
size_t offset = type_struct_member_offset(type, i);
if (offset > highest_offset)
{
highest_offset = offset;
member_index = i;
}
}
size_t size = get_declared_struct_member_size(type, member_index);
return highest_offset + size;
}
size_t Compiler::get_declared_struct_size_runtime_array(const SPIRType &type, size_t array_size) const