mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-10-26 13:15:41 +00:00
fix: properly calculate matching memory layout with multiple variants
This commit is contained in:
8 files changed
+49
-40
No files matched your search
@@ -5,7 +5,7 @@ StructureInformation::StructureInformation(DefinitionWithMembers* definition, Ty
|
||||
m_type_info(typeInfo),
|
||||
m_is_leaf(false),
|
||||
m_requires_marking(false),
|
||||
m_has_matching_cross_platform_structure(false),
|
||||
m_has_matching_cross_platform_memory_layout(false),
|
||||
m_embedded_reference_exists(false),
|
||||
m_non_embedded_reference_exists(false),
|
||||
m_single_pointer_reference_exists(false),
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
|
||||
bool m_is_leaf;
|
||||
bool m_requires_marking;
|
||||
bool m_has_matching_cross_platform_structure;
|
||||
bool m_has_matching_cross_platform_memory_layout;
|
||||
|
||||
bool m_embedded_reference_exists;
|
||||
bool m_non_embedded_reference_exists;
|
||||
|
||||
@@ -36,13 +36,13 @@ namespace
|
||||
LINE("{")
|
||||
m_intendation++;
|
||||
|
||||
if (m_env.m_asset->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*m_env.m_asset))
|
||||
TestMethod(m_env.m_asset);
|
||||
|
||||
for (const auto* structure : m_env.m_used_structures)
|
||||
{
|
||||
StructureComputations computations(structure->m_info);
|
||||
if (!structure->m_info->m_definition->IsAnonymous() && !computations.IsAsset() && structure->m_info->m_has_matching_cross_platform_structure)
|
||||
if (!structure->m_info->m_definition->IsAnonymous() && !computations.IsAsset() && MemoryLayoutMatches(*structure->m_info))
|
||||
TestMethod(structure->m_info);
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ std::string BaseTemplate::MakeEvaluation(const IEvaluation* evaluation)
|
||||
bool BaseTemplate::ShouldGenerateFillMethod(const RenderingUsedType& type)
|
||||
{
|
||||
const auto isNotForeignAsset = type.m_is_context_asset || !type.m_info || !StructureComputations(type.m_info).IsAsset();
|
||||
const auto hasMismatchingStructure = type.m_info && type.m_type == type.m_info->m_definition && !type.m_info->m_has_matching_cross_platform_structure;
|
||||
const auto hasMismatchingStructure = type.m_info && type.m_type == type.m_info->m_definition && !type.m_info->m_has_matching_cross_platform_memory_layout;
|
||||
const auto isEmbeddedDynamic = type.m_info && type.m_info->m_embedded_reference_exists && StructureComputations(type.m_info).GetDynamicMember();
|
||||
|
||||
return isNotForeignAsset && (hasMismatchingStructure || isEmbeddedDynamic);
|
||||
@@ -319,3 +319,8 @@ size_t BaseTemplate::OffsetForMemberModifier(const MemberInformation& memberInfo
|
||||
|
||||
return curOffset + nestedBaseOffset;
|
||||
}
|
||||
|
||||
bool BaseTemplate::MemoryLayoutMatches(const StructureInformation& structureInfo) const
|
||||
{
|
||||
return !m_env.m_word_size_mismatch || structureInfo.m_has_matching_cross_platform_memory_layout;
|
||||
}
|
||||
@@ -45,6 +45,11 @@ protected:
|
||||
[[nodiscard]] size_t
|
||||
OffsetForMemberModifier(const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, size_t nestedBaseOffset) const;
|
||||
|
||||
/**
|
||||
* Evaluates whether the struct/union has matching memory layouts between the generated code and game.
|
||||
*/
|
||||
[[nodiscard]] bool MemoryLayoutMatches(const StructureInformation& structureInfo) const;
|
||||
|
||||
std::ostream& m_out;
|
||||
unsigned m_intendation;
|
||||
|
||||
|
||||
@@ -142,8 +142,8 @@ namespace
|
||||
// Variable Declarations: type varType;
|
||||
for (const auto* type : m_env.m_used_types)
|
||||
{
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous()
|
||||
&& (!type->m_info->m_is_leaf || !type->m_info->m_has_matching_cross_platform_structure) && !StructureComputations(type->m_info).IsAsset())
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous() && (!type->m_info->m_is_leaf || !MemoryLayoutMatches(*type->m_info))
|
||||
&& !StructureComputations(type->m_info).IsAsset())
|
||||
{
|
||||
LINE(VariableDecl(type->m_type))
|
||||
}
|
||||
@@ -349,8 +349,8 @@ namespace
|
||||
|
||||
for (const auto* type : m_env.m_used_types)
|
||||
{
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous()
|
||||
&& (!type->m_info->m_is_leaf || !type->m_info->m_has_matching_cross_platform_structure) && !StructureComputations(type->m_info).IsAsset())
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous() && (!type->m_info->m_is_leaf || !MemoryLayoutMatches(*type->m_info))
|
||||
&& !StructureComputations(type->m_info).IsAsset())
|
||||
{
|
||||
PrintVariableInitialization(type->m_type);
|
||||
}
|
||||
@@ -378,7 +378,7 @@ namespace
|
||||
LINE("{")
|
||||
m_intendation++;
|
||||
|
||||
const auto callFillForMember = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure;
|
||||
const auto callFillForMember = memberInfo.m_type && !MemoryLayoutMatches(*memberInfo.m_type);
|
||||
|
||||
if (callFillForMember)
|
||||
{
|
||||
@@ -458,7 +458,7 @@ namespace
|
||||
const DeclarationModifierComputations& modifier,
|
||||
const size_t nestedBaseOffset)
|
||||
{
|
||||
if (memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure)
|
||||
if (memberInfo.m_type && !MemoryLayoutMatches(*memberInfo.m_type))
|
||||
{
|
||||
LINEF("for (auto i = 0u; i < std::extent_v<decltype({0}::{1})>; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name)
|
||||
LINE("{")
|
||||
@@ -488,7 +488,7 @@ namespace
|
||||
|
||||
if (!hasAnonymousType)
|
||||
{
|
||||
const auto hasMismatchingStructure = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure;
|
||||
const auto hasMismatchingStructure = memberInfo.m_type && !MemoryLayoutMatches(*memberInfo.m_type);
|
||||
const auto hasDynamicMember = memberInfo.m_type && StructureComputations(memberInfo.m_type).GetDynamicMember();
|
||||
if (hasMismatchingStructure || hasDynamicMember)
|
||||
{
|
||||
@@ -893,7 +893,7 @@ namespace
|
||||
void PrintLoadPtrArrayMethod_Loading(const DataDefinition* def, const StructureInformation* info) const
|
||||
{
|
||||
const auto alignment = info && def == info->m_definition ? MakeAllocAlignment(*info) : std::to_string(def->GetAlignment(m_env.m_word_size));
|
||||
if (info && !info->m_has_matching_cross_platform_structure && StructureComputations(info).GetDynamicMember())
|
||||
if (info && !MemoryLayoutMatches(*info) && StructureComputations(info).GetDynamicMember())
|
||||
{
|
||||
assert(def == info->m_definition);
|
||||
LINE("// Alloc first for alignment, then proceed to read as game does")
|
||||
@@ -949,7 +949,7 @@ namespace
|
||||
LINE("{")
|
||||
m_intendation++;
|
||||
|
||||
if (info && !info->m_has_matching_cross_platform_structure)
|
||||
if (info && !MemoryLayoutMatches(*info))
|
||||
{
|
||||
LINEF("*{0} = m_stream.ConvertOffsetToPointerLookup(*{0}).Expect();", MakeTypePtrVarName(def))
|
||||
}
|
||||
@@ -1036,7 +1036,7 @@ namespace
|
||||
LINE("")
|
||||
LINE("if (atStreamStart)")
|
||||
|
||||
if (info->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
m_intendation++;
|
||||
LINEF("m_stream.Load<{0}>({1}, count);", info->m_definition->GetFullName(), MakeTypeVarName(def))
|
||||
@@ -1163,7 +1163,7 @@ namespace
|
||||
LINE(MakeCustomActionCall(member->m_post_load_action.get()))
|
||||
}
|
||||
}
|
||||
else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
|
||||
else if (member->m_type && !MemoryLayoutMatches(*member->m_type))
|
||||
{
|
||||
LINEF("const auto fillArraySize = static_cast<size_t>({0});", MakeEvaluation(modifier.GetArrayPointerCountEvaluation()))
|
||||
LINEF("const auto fill = m_stream.LoadWithFill({0} * fillArraySize);", member->m_member->m_type_declaration->m_type->GetSize(m_env.m_word_size))
|
||||
@@ -1257,7 +1257,7 @@ namespace
|
||||
m_env.m_word_size_mismatch ? "false" : "true",
|
||||
MakeEvaluation(modifier.GetDynamicArraySizeEvaluation()))
|
||||
}
|
||||
else if (info->m_has_matching_cross_platform_structure)
|
||||
else if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
if (m_env.m_word_size_mismatch)
|
||||
{
|
||||
@@ -1336,7 +1336,7 @@ namespace
|
||||
LINE(MakeCustomActionCall(member->m_post_load_action.get()))
|
||||
}
|
||||
}
|
||||
else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
|
||||
else if (member->m_type && !MemoryLayoutMatches(*member->m_type))
|
||||
{
|
||||
LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier))
|
||||
LINEF("FillStruct_{0}(m_stream.LoadWithFill({1}));",
|
||||
@@ -1427,8 +1427,7 @@ namespace
|
||||
|
||||
[[nodiscard]] bool ShouldAllocOutOfBlock(const MemberInformation& member, const MemberLoadType loadType) const
|
||||
{
|
||||
return m_env.m_word_size_mismatch
|
||||
&& ((member.m_type && !member.m_type->m_has_matching_cross_platform_structure) || loadType == MemberLoadType::POINTER_ARRAY);
|
||||
return m_env.m_word_size_mismatch && ((member.m_type && !MemoryLayoutMatches(*member.m_type)) || loadType == MemberLoadType::POINTER_ARRAY);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
@@ -1589,7 +1588,7 @@ namespace
|
||||
LINE("{")
|
||||
m_intendation++;
|
||||
|
||||
if (info->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
LINEF("{0} = m_stream.ConvertOffsetToAliasNative({0});", MakeMemberAccess(info, member, modifier))
|
||||
}
|
||||
@@ -1871,7 +1870,7 @@ namespace
|
||||
LINEF("assert({0} != nullptr);", MakeTypeVarName(info->m_definition))
|
||||
|
||||
const auto* dynamicMember = computations.GetDynamicMember();
|
||||
if (!info->m_has_matching_cross_platform_structure && dynamicMember && !info->m_non_embedded_reference_exists)
|
||||
if (!MemoryLayoutMatches(*info) && dynamicMember && !info->m_non_embedded_reference_exists)
|
||||
{
|
||||
LINE("assert(!atStreamStart);")
|
||||
}
|
||||
@@ -1881,7 +1880,7 @@ namespace
|
||||
LINE("if (atStreamStart)")
|
||||
|
||||
m_intendation++;
|
||||
if (info->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
if (dynamicMember == nullptr)
|
||||
{
|
||||
@@ -2073,7 +2072,7 @@ namespace
|
||||
|
||||
if (inTemp)
|
||||
{
|
||||
if (info->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
LINEF("*{0} = m_stream.ConvertOffsetToAliasNative(*{0});", MakeTypePtrVarName(info->m_definition))
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ namespace
|
||||
// Variable Declarations: type varType;
|
||||
for (const auto* type : m_env.m_used_types)
|
||||
{
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous()
|
||||
&& (!type->m_info->m_is_leaf || !type->m_info->m_has_matching_cross_platform_structure) && !StructureComputations(type->m_info).IsAsset())
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous() && (!type->m_info->m_is_leaf || !MemoryLayoutMatches(*type->m_info))
|
||||
&& !StructureComputations(type->m_info).IsAsset())
|
||||
LINE(VariableDecl(type->m_type))
|
||||
}
|
||||
for (const auto* type : m_env.m_used_types)
|
||||
@@ -374,8 +374,8 @@ namespace
|
||||
|
||||
for (const auto* type : m_env.m_used_types)
|
||||
{
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous()
|
||||
&& (!type->m_info->m_is_leaf || !type->m_info->m_has_matching_cross_platform_structure) && !StructureComputations(type->m_info).IsAsset())
|
||||
if (type->m_info && !type->m_info->m_definition->IsAnonymous() && (!type->m_info->m_is_leaf || !MemoryLayoutMatches(*type->m_info))
|
||||
&& !StructureComputations(type->m_info).IsAsset())
|
||||
PrintVariableInitialization(type->m_type);
|
||||
}
|
||||
for (const auto* type : m_env.m_used_types)
|
||||
@@ -488,7 +488,7 @@ namespace
|
||||
MakeSafeTypeName(member->m_member->m_type_declaration->m_type),
|
||||
MakeEvaluation(modifier.GetArrayPointerCountEvaluation()))
|
||||
}
|
||||
else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
|
||||
else if (member->m_type && !MemoryLayoutMatches(*member->m_type))
|
||||
{
|
||||
LINEF("const auto fillArraySize = static_cast<size_t>({0});", MakeEvaluation(modifier.GetArrayPointerCountEvaluation()))
|
||||
if (!computations.IsInRuntimeBlock())
|
||||
@@ -626,7 +626,7 @@ namespace
|
||||
LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier))
|
||||
LINEF("Write_{0}(true);", MakeSafeTypeName(member->m_type->m_definition))
|
||||
}
|
||||
else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
|
||||
else if (member->m_type && !MemoryLayoutMatches(*member->m_type))
|
||||
{
|
||||
LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier))
|
||||
LINEF("FillStruct_{0}(m_stream->WriteWithFill({1}));",
|
||||
@@ -741,7 +741,7 @@ namespace
|
||||
|
||||
if (writeType == MemberWriteType::ARRAY_POINTER)
|
||||
{
|
||||
if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
|
||||
if (member->m_type && !MemoryLayoutMatches(*member->m_type))
|
||||
{
|
||||
LINE_MIDDLEF(", {0}", member->m_type->m_definition->GetSize(m_env.m_word_size))
|
||||
}
|
||||
@@ -750,7 +750,7 @@ namespace
|
||||
}
|
||||
else if (writeType == MemberWriteType::POINTER_ARRAY)
|
||||
{
|
||||
if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
|
||||
if (member->m_type && !MemoryLayoutMatches(*member->m_type))
|
||||
{
|
||||
LINE_MIDDLEF(", {0}", m_env.m_pointer_size)
|
||||
}
|
||||
@@ -1111,7 +1111,7 @@ namespace
|
||||
{
|
||||
LINE("if (atStreamStart)")
|
||||
|
||||
if (info->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
m_intendation++;
|
||||
if (dynamicMember == nullptr)
|
||||
@@ -1261,7 +1261,7 @@ namespace
|
||||
const DeclarationModifierComputations& modifier,
|
||||
const size_t nestedBaseOffset)
|
||||
{
|
||||
if (memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure)
|
||||
if (memberInfo.m_type && !MemoryLayoutMatches(*memberInfo.m_type))
|
||||
{
|
||||
LINEF("for (auto i = 0u; i < std::extent_v<decltype({0}::{1})>; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name)
|
||||
LINE("{")
|
||||
@@ -1291,7 +1291,7 @@ namespace
|
||||
|
||||
if (!hasAnonymousType)
|
||||
{
|
||||
const auto hasMismatchingStructure = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure;
|
||||
const auto hasMismatchingStructure = memberInfo.m_type && !MemoryLayoutMatches(*memberInfo.m_type);
|
||||
const auto hasDynamicMember = memberInfo.m_type && StructureComputations(memberInfo.m_type).GetDynamicMember();
|
||||
if (hasMismatchingStructure || hasDynamicMember)
|
||||
{
|
||||
@@ -1584,7 +1584,7 @@ namespace
|
||||
LINE("")
|
||||
LINE("if (atStreamStart)")
|
||||
|
||||
if (info->m_has_matching_cross_platform_structure)
|
||||
if (MemoryLayoutMatches(*info))
|
||||
{
|
||||
m_intendation++;
|
||||
LINEF("{0} = m_stream->Write<{1}>({2}, count);", MakeTypeWrittenVarName(def), def->GetFullName(), MakeTypeVarName(def))
|
||||
|
||||
+4
-4
@@ -9,7 +9,7 @@ namespace
|
||||
bool CalculateHasMatchingCrossPlatformStructure(std::unordered_set<const void*>& visitedStructures, StructureInformation* info)
|
||||
{
|
||||
if (visitedStructures.find(info) != visitedStructures.end())
|
||||
return info->m_has_matching_cross_platform_structure;
|
||||
return info->m_has_matching_cross_platform_memory_layout;
|
||||
|
||||
visitedStructures.emplace(info);
|
||||
|
||||
@@ -19,19 +19,19 @@ namespace
|
||||
{
|
||||
if (modifier->GetType() == DeclarationModifierType::POINTER)
|
||||
{
|
||||
info->m_has_matching_cross_platform_structure = false;
|
||||
info->m_has_matching_cross_platform_memory_layout = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (member->m_type != nullptr && member->m_type != info && !CalculateHasMatchingCrossPlatformStructure(visitedStructures, member->m_type))
|
||||
{
|
||||
info->m_has_matching_cross_platform_structure = false;
|
||||
info->m_has_matching_cross_platform_memory_layout = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
info->m_has_matching_cross_platform_structure = true;
|
||||
info->m_has_matching_cross_platform_memory_layout = true;
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Reference in new issue
Block a user