@@ -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
0 commit comments