Fix get_declared_struct_member_size for struct members

When a member of a struct is a struct, get_declared_struct_member_size
instead returned the size of the entire outer struct because it added
the offset of the last field to the size of the last field.

Restructure the function so that it handles all arrays in the same way
(by using array stride) and for the rest reuses get_declared_struct_size
if possible - this simplifies the function and fixes the issue.
This commit is contained in:
Arseny Kapoulkine 2017-01-17 01:52:12 -08:00
parent a3bac9e4ce
commit f63e7c5c98

View File

@ -2058,63 +2058,49 @@ size_t Compiler::get_declared_struct_member_size(const SPIRType &struct_type, ui
auto flags = get_member_decoration_mask(struct_type.self, index); auto flags = get_member_decoration_mask(struct_type.self, index);
auto &type = get<SPIRType>(struct_type.member_types[index]); auto &type = get<SPIRType>(struct_type.member_types[index]);
if (type.basetype != SPIRType::Struct) switch (type.basetype)
{ {
switch (type.basetype) case SPIRType::Unknown:
{ case SPIRType::Void:
case SPIRType::Unknown: case SPIRType::Boolean: // Bools are purely logical, and cannot be used for externally visible types.
case SPIRType::Void: case SPIRType::AtomicCounter:
case SPIRType::Boolean: // Bools are purely logical, and cannot be used for externally visible types. case SPIRType::Image:
case SPIRType::AtomicCounter: case SPIRType::SampledImage:
case SPIRType::Image: case SPIRType::Sampler:
case SPIRType::SampledImage: SPIRV_CROSS_THROW("Querying size for object with opaque size.\n");
case SPIRType::Sampler:
SPIRV_CROSS_THROW("Querying size for object with opaque size.\n");
default: default:
break; break;
} }
if (!type.array.empty())
{
// For arrays, we can use ArrayStride to get an easy check.
return type_struct_member_array_stride(struct_type, index) * type.array.back();
}
else if (type.basetype == SPIRType::Struct)
{
return get_declared_struct_size(type);
}
else
{
size_t component_size = type.width / 8; size_t component_size = type.width / 8;
unsigned vecsize = type.vecsize; unsigned vecsize = type.vecsize;
unsigned columns = type.columns; unsigned columns = type.columns;
if (type.array.empty()) // Vectors.
{ if (columns == 1)
// Vectors. return vecsize * component_size;
if (columns == 1)
return vecsize * component_size;
else
{
// Per SPIR-V spec, matrices must be tightly packed and aligned up for vec3 accesses.
if ((flags & (1ull << DecorationRowMajor)) && columns == 3)
columns = 4;
else if ((flags & (1ull << DecorationColMajor)) && vecsize == 3)
vecsize = 4;
return vecsize * columns * component_size;
}
}
else else
{ {
// For arrays, we can use ArrayStride to get an easy check. // Per SPIR-V spec, matrices must be tightly packed and aligned up for vec3 accesses.
return type_struct_member_array_stride(struct_type, index) * type.array.back(); if ((flags & (1ull << DecorationRowMajor)) && columns == 3)
} columns = 4;
} else if ((flags & (1ull << DecorationColMajor)) && vecsize == 3)
else vecsize = 4;
{
// Recurse.
uint32_t last = uint32_t(struct_type.member_types.size() - 1);
uint32_t offset = type_struct_member_offset(struct_type, last);
size_t size;
// If we have an array of structs inside our struct, handle that with array strides instead. return vecsize * columns * component_size;
auto &last_type = get<SPIRType>(struct_type.member_types.back()); }
if (last_type.array.empty())
size = get_declared_struct_size(last_type);
else
size = type_struct_member_array_stride(struct_type, last) * last_type.array.back();
return offset + size;
} }
} }