@@ -372,14 +372,36 @@ static std::optional<KnownType> ReadKnownScalarType(
372
372
return std::nullopt;
373
373
}
374
374
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 (
376
397
const spirv_cross::TypeID& type_id) const {
377
398
const auto & struct_type = compiler_->get_type (type_id);
378
399
FML_CHECK (struct_type.basetype == spirv_cross::SPIRType::BaseType::Struct);
379
400
380
401
std::vector<StructMember> result;
381
402
382
403
size_t current_byte_offset = 0 ;
404
+ size_t max_member_alignment = 0 ;
383
405
384
406
for (size_t i = 0 ; i < struct_type.member_types .size (); i++) {
385
407
const auto & member = compiler_->get_type (struct_type.member_types [i]);
@@ -390,14 +412,18 @@ std::vector<Reflector::StructMember> Reflector::ReadStructMembers(
390
412
const auto alignment_pad = struct_member_offset - current_byte_offset;
391
413
result.emplace_back (StructMember{
392
414
.type = TypeNameWithPaddingOfSize (alignment_pad),
393
- .name = SPrintF (" _align_%s " ,
415
+ .name = SPrintF (" _PADDING_%s_ " ,
394
416
GetMemberNameAtIndex (struct_type, i).c_str ()),
395
417
.offset = current_byte_offset,
396
418
.byte_length = alignment_pad,
397
419
});
398
420
current_byte_offset += alignment_pad;
399
421
}
400
422
423
+ max_member_alignment =
424
+ std::max<size_t >(max_member_alignment,
425
+ (member.width / 8 ) * member.columns * member.vecsize );
426
+
401
427
FML_CHECK (current_byte_offset == struct_member_offset);
402
428
403
429
// Tightly packed 4x4 Matrix is special cased as we know how to work with
@@ -499,6 +525,20 @@ std::vector<Reflector::StructMember> Reflector::ReadStructMembers(
499
525
continue ;
500
526
}
501
527
}
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
+
502
542
return result;
503
543
}
504
544
@@ -514,10 +554,13 @@ std::optional<Reflector::StructDefinition> Reflector::ReflectStructDefinition(
514
554
return std::nullopt;
515
555
}
516
556
557
+ auto struct_members = ReadStructMembers (type_id);
558
+ auto reflected_struct_size = GetReflectedStructSize (struct_members);
559
+
517
560
StructDefinition struc;
518
561
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 );
521
564
return struc;
522
565
}
523
566
0 commit comments