diff --git a/engine/src/flutter/impeller/compiler/code_gen_template.h b/engine/src/flutter/impeller/compiler/code_gen_template.h index 7eef0949878..20afb9e2714 100644 --- a/engine/src/flutter/impeller/compiler/code_gen_template.h +++ b/engine/src/flutter/impeller/compiler/code_gen_template.h @@ -39,12 +39,13 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader { struct {{def.name}} { {% for member in def.members %} - {{member.type}} {{member.name}}; + {{member.type}} {{member.name}}; // (offset {{member.offset}}, size {{member.byte_length}}) {% endfor %} - }; // struct {{def.name}} + }; // struct {{def.name}} (size {{def.byte_length}}) {% endfor %} {% endif %} {% if length(uniform_buffers) > 0 %} + // =========================================================================== // Stage Uniforms ============================================================ // =========================================================================== @@ -52,10 +53,11 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader { static constexpr auto kResource{{camel_case(uniform.name)}} = ShaderUniformSlot<{{uniform.name}}> { // {{uniform.name}} "{{uniform.name}}", // name - {{uniform.binding}}u, // binding + {{uniform.msl_res_0}}u, // binding }; {% endfor %} {% endif %} + // =========================================================================== // Stage Inputs ============================================================== // =========================================================================== diff --git a/engine/src/flutter/impeller/compiler/reflector.cc b/engine/src/flutter/impeller/compiler/reflector.cc index e97d7f7c390..b44dbd45fc4 100644 --- a/engine/src/flutter/impeller/compiler/reflector.cc +++ b/engine/src/flutter/impeller/compiler/reflector.cc @@ -372,7 +372,28 @@ static std::optional ReadKnownScalarType( return std::nullopt; } -std::vector Reflector::ReadStructMembers( +//------------------------------------------------------------------------------ +/// @brief Get the reflected struct size. In the vast majority of the +/// cases, this is the same as the declared struct size as given by +/// the compiler. But, additional padding may need to be introduced +/// after the end of the struct to keep in line with the alignment +/// requirement of the individual struct members. This method +/// figures out the actual size of the reflected struct that can be +/// referenced in native code. +/// +/// @param[in] members The members +/// +/// @return The reflected structure size. +/// +static size_t GetReflectedStructSize(const std::vector& members) { + auto struct_size = 0u; + for (const auto& member : members) { + struct_size += member.byte_length; + } + return struct_size; +} + +std::vector Reflector::ReadStructMembers( const spirv_cross::TypeID& type_id) const { const auto& struct_type = compiler_->get_type(type_id); FML_CHECK(struct_type.basetype == spirv_cross::SPIRType::BaseType::Struct); @@ -380,6 +401,7 @@ std::vector Reflector::ReadStructMembers( std::vector result; size_t current_byte_offset = 0; + size_t max_member_alignment = 0; for (size_t i = 0; i < struct_type.member_types.size(); i++) { const auto& member = compiler_->get_type(struct_type.member_types[i]); @@ -390,7 +412,7 @@ std::vector Reflector::ReadStructMembers( const auto alignment_pad = struct_member_offset - current_byte_offset; result.emplace_back(StructMember{ .type = TypeNameWithPaddingOfSize(alignment_pad), - .name = SPrintF("_align_%s", + .name = SPrintF("_PADDING_%s_", GetMemberNameAtIndex(struct_type, i).c_str()), .offset = current_byte_offset, .byte_length = alignment_pad, @@ -398,6 +420,10 @@ std::vector Reflector::ReadStructMembers( current_byte_offset += alignment_pad; } + max_member_alignment = + std::max(max_member_alignment, + (member.width / 8) * member.columns * member.vecsize); + FML_CHECK(current_byte_offset == struct_member_offset); // Tightly packed 4x4 Matrix is special cased as we know how to work with @@ -499,6 +525,20 @@ std::vector Reflector::ReadStructMembers( continue; } } + + const auto struct_length = current_byte_offset; + { + const auto padding = struct_length % max_member_alignment; + if (padding != 0) { + result.emplace_back(StructMember{ + .type = TypeNameWithPaddingOfSize(padding), + .name = "_PADDING_", + .offset = current_byte_offset, + .byte_length = padding, + }); + } + } + return result; } @@ -514,10 +554,13 @@ std::optional Reflector::ReflectStructDefinition( return std::nullopt; } + auto struct_members = ReadStructMembers(type_id); + auto reflected_struct_size = GetReflectedStructSize(struct_members); + StructDefinition struc; struc.name = struct_name; - struc.byte_length = compiler_->get_declared_struct_size(type); - struc.members = ReadStructMembers(type_id); + struc.byte_length = reflected_struct_size; + struc.members = std::move(struct_members); return struc; } diff --git a/engine/src/flutter/impeller/compiler/reflector.h b/engine/src/flutter/impeller/compiler/reflector.h index b71a84aad5f..302b26456c6 100644 --- a/engine/src/flutter/impeller/compiler/reflector.h +++ b/engine/src/flutter/impeller/compiler/reflector.h @@ -16,6 +16,13 @@ namespace impeller { namespace compiler { +struct StructMember { + std::string type; + std::string name; + size_t offset = 0u; + size_t byte_length = 0u; +}; + class Reflector { public: struct Options { @@ -38,13 +45,6 @@ class Reflector { std::shared_ptr GetReflectionCC() const; private: - struct StructMember { - std::string type; - std::string name; - size_t offset = 0u; - size_t byte_length = 0u; - }; - struct StructDefinition { std::string name; size_t byte_length = 0u;