Skip to content

Commit d35f10a

Browse files
chinmaygardednfield
authored andcommitted
Insert additional padding at the end of the struct if the size of the struct does not satisfy the alignment requirements of all its members.
1 parent 866045d commit d35f10a

File tree

3 files changed

+59
-14
lines changed

3 files changed

+59
-14
lines changed

impeller/compiler/code_gen_template.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,25 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader {
3939
4040
struct {{def.name}} {
4141
{% for member in def.members %}
42-
{{member.type}} {{member.name}};
42+
{{member.type}} {{member.name}}; // (offset {{member.offset}}, size {{member.byte_length}})
4343
{% endfor %}
44-
}; // struct {{def.name}}
44+
}; // struct {{def.name}} (size {{def.byte_length}})
4545
{% endfor %}
4646
{% endif %}
4747
{% if length(uniform_buffers) > 0 %}
48+
4849
// ===========================================================================
4950
// Stage Uniforms ============================================================
5051
// ===========================================================================
5152
{% for uniform in uniform_buffers %}
5253
5354
static constexpr auto kResource{{camel_case(uniform.name)}} = ShaderUniformSlot<{{uniform.name}}> { // {{uniform.name}}
5455
"{{uniform.name}}", // name
55-
{{uniform.binding}}u, // binding
56+
{{uniform.msl_res_0}}u, // binding
5657
};
5758
{% endfor %}
5859
{% endif %}
60+
5961
// ===========================================================================
6062
// Stage Inputs ==============================================================
6163
// ===========================================================================

impeller/compiler/reflector.cc

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,14 +372,36 @@ static std::optional<KnownType> ReadKnownScalarType(
372372
return std::nullopt;
373373
}
374374

375-
std::vector<Reflector::StructMember> Reflector::ReadStructMembers(
375+
//------------------------------------------------------------------------------
376+
/// @brief Get the reflected struct size. In the vast majority of the
377+
/// cases, this is the same as the declared struct size as given by
378+
/// the compiler. But, additional padding may need to be introduced
379+
/// after the end of the struct to keep in line with the alignment
380+
/// requirement of the individual struct members. This method
381+
/// figures out the actual size of the reflected struct that can be
382+
/// referenced in native code.
383+
///
384+
/// @param[in] members The members
385+
///
386+
/// @return The reflected structure size.
387+
///
388+
static size_t GetReflectedStructSize(const std::vector<StructMember>& members) {
389+
auto struct_size = 0u;
390+
for (const auto& member : members) {
391+
struct_size += member.byte_length;
392+
}
393+
return struct_size;
394+
}
395+
396+
std::vector<StructMember> Reflector::ReadStructMembers(
376397
const spirv_cross::TypeID& type_id) const {
377398
const auto& struct_type = compiler_->get_type(type_id);
378399
FML_CHECK(struct_type.basetype == spirv_cross::SPIRType::BaseType::Struct);
379400

380401
std::vector<StructMember> result;
381402

382403
size_t current_byte_offset = 0;
404+
size_t max_member_alignment = 0;
383405

384406
for (size_t i = 0; i < struct_type.member_types.size(); i++) {
385407
const auto& member = compiler_->get_type(struct_type.member_types[i]);
@@ -390,14 +412,18 @@ std::vector<Reflector::StructMember> Reflector::ReadStructMembers(
390412
const auto alignment_pad = struct_member_offset - current_byte_offset;
391413
result.emplace_back(StructMember{
392414
.type = TypeNameWithPaddingOfSize(alignment_pad),
393-
.name = SPrintF("_align_%s",
415+
.name = SPrintF("_PADDING_%s_",
394416
GetMemberNameAtIndex(struct_type, i).c_str()),
395417
.offset = current_byte_offset,
396418
.byte_length = alignment_pad,
397419
});
398420
current_byte_offset += alignment_pad;
399421
}
400422

423+
max_member_alignment =
424+
std::max<size_t>(max_member_alignment,
425+
(member.width / 8) * member.columns * member.vecsize);
426+
401427
FML_CHECK(current_byte_offset == struct_member_offset);
402428

403429
// Tightly packed 4x4 Matrix is special cased as we know how to work with
@@ -499,6 +525,20 @@ std::vector<Reflector::StructMember> Reflector::ReadStructMembers(
499525
continue;
500526
}
501527
}
528+
529+
const auto struct_length = current_byte_offset;
530+
{
531+
const auto padding = struct_length % max_member_alignment;
532+
if (padding != 0) {
533+
result.emplace_back(StructMember{
534+
.type = TypeNameWithPaddingOfSize(padding),
535+
.name = "_PADDING_",
536+
.offset = current_byte_offset,
537+
.byte_length = padding,
538+
});
539+
}
540+
}
541+
502542
return result;
503543
}
504544

@@ -514,10 +554,13 @@ std::optional<Reflector::StructDefinition> Reflector::ReflectStructDefinition(
514554
return std::nullopt;
515555
}
516556

557+
auto struct_members = ReadStructMembers(type_id);
558+
auto reflected_struct_size = GetReflectedStructSize(struct_members);
559+
517560
StructDefinition struc;
518561
struc.name = struct_name;
519-
struc.byte_length = compiler_->get_declared_struct_size(type);
520-
struc.members = ReadStructMembers(type_id);
562+
struc.byte_length = reflected_struct_size;
563+
struc.members = std::move(struct_members);
521564
return struc;
522565
}
523566

impeller/compiler/reflector.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
namespace impeller {
1717
namespace compiler {
1818

19+
struct StructMember {
20+
std::string type;
21+
std::string name;
22+
size_t offset = 0u;
23+
size_t byte_length = 0u;
24+
};
25+
1926
class Reflector {
2027
public:
2128
struct Options {
@@ -38,13 +45,6 @@ class Reflector {
3845
std::shared_ptr<fml::Mapping> GetReflectionCC() const;
3946

4047
private:
41-
struct StructMember {
42-
std::string type;
43-
std::string name;
44-
size_t offset = 0u;
45-
size_t byte_length = 0u;
46-
};
47-
4848
struct StructDefinition {
4949
std::string name;
5050
size_t byte_length = 0u;

0 commit comments

Comments
 (0)