Reduced Imgui memory usage by implementing a free node list.
This commit is contained in:
@@ -75,32 +75,53 @@ namespace Juliet
|
||||
JULIET_API void ArenaClear(NonNullPtr<Arena> arena);
|
||||
[[nodiscard]] JULIET_API size_t ArenaPos(NonNullPtr<Arena> arena);
|
||||
|
||||
#if JULIET_DEBUG
|
||||
template <typename FirstDebugArg, typename... DebugArgs>
|
||||
#endif
|
||||
[[nodiscard]] inline void* ArenaPushSize(NonNullPtr<Arena> arena, size_t size, size_t align,
|
||||
bool shouldBeZeroed JULIET_DEBUG_PARAM(FirstDebugArg&& firstDebugArg,
|
||||
DebugArgs&&... debugArgs))
|
||||
{
|
||||
return ArenaPush(arena, size, align,
|
||||
shouldBeZeroed JULIET_DEBUG_PARAM(
|
||||
[&]() -> const char*
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg),
|
||||
std::forward<DebugArgs>(debugArgs)...)
|
||||
.Data;
|
||||
}()));
|
||||
}
|
||||
|
||||
template <typename Type JULIET_DEBUG_ONLY(, typename... DebugArgs)>
|
||||
[[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
|
||||
{
|
||||
return static_cast<Type*>(ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type), true JULIET_DEBUG_PARAM(
|
||||
[&]() -> const char* {
|
||||
if constexpr (sizeof...(DebugArgs) > 0)
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data;
|
||||
}
|
||||
return GetTypeName<Type>();
|
||||
}()
|
||||
)));
|
||||
return static_cast<Type*>(
|
||||
ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type),
|
||||
true JULIET_DEBUG_PARAM(
|
||||
[&]() -> const char*
|
||||
{
|
||||
if constexpr (sizeof...(DebugArgs) > 0)
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data;
|
||||
}
|
||||
return GetTypeName<Type>();
|
||||
}())));
|
||||
}
|
||||
|
||||
template <typename Type JULIET_DEBUG_ONLY(, typename... DebugArgs)>
|
||||
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
|
||||
{
|
||||
return static_cast<Type*>(ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)), true JULIET_DEBUG_PARAM(
|
||||
[&]() -> const char* {
|
||||
if constexpr (sizeof...(DebugArgs) > 0)
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data;
|
||||
}
|
||||
return GetTypeName<Type>();
|
||||
}()
|
||||
)));
|
||||
return static_cast<Type*>(
|
||||
ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)),
|
||||
true JULIET_DEBUG_PARAM(
|
||||
[&]() -> const char*
|
||||
{
|
||||
if constexpr (sizeof...(DebugArgs) > 0)
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data;
|
||||
}
|
||||
return GetTypeName<Type>();
|
||||
}())));
|
||||
}
|
||||
|
||||
TempArena ArenaTempBegin(NonNullPtr<Arena> arena);
|
||||
|
||||
@@ -22,18 +22,54 @@ namespace Juliet::ImGuiService
|
||||
ImGuiContext* g_ImGuiContext = nullptr;
|
||||
bool g_Initialized = false;
|
||||
|
||||
struct FreeNode
|
||||
{
|
||||
size_t Size;
|
||||
FreeNode* Next;
|
||||
}* FirstFreeNode = nullptr;
|
||||
|
||||
// Dedicated Paged Arena for ImGui
|
||||
// Sharing the same underlying Engine Pool for blocks, but separate Arena chain.
|
||||
Arena* g_ImGuiArena = {};
|
||||
|
||||
void* ImGuiAllocWrapper(size_t size, void* /*user_data*/)
|
||||
{
|
||||
return ArenaPush(g_ImGuiArena, size, 8, false JULIET_DEBUG_PARAM("ImGuiAlloc"));
|
||||
Assert(size); // I trust Dear Imgui but just in case
|
||||
|
||||
// Let's make FreeNode a part of each alloc.
|
||||
size_t sizeOfHeader = sizeof(FreeNode);
|
||||
size_t totalSize = AlignPow2<size_t>(size + sizeOfHeader, 16);
|
||||
FreeNode** previous = &FirstFreeNode;
|
||||
FreeNode* current = FirstFreeNode;
|
||||
|
||||
// Find a free node if there is one big enough
|
||||
while (current != nullptr)
|
||||
{
|
||||
if (current->Size >= totalSize)
|
||||
{
|
||||
*previous = current->Next;
|
||||
return current + 1;
|
||||
}
|
||||
previous = ¤t->Next;
|
||||
current = current->Next;
|
||||
}
|
||||
|
||||
auto* ptr = ArenaPushSize(g_ImGuiArena, totalSize, 8, false JULIET_DEBUG_PARAM("ImGuiAlloc {}", totalSize));
|
||||
|
||||
FreeNode* node = static_cast<FreeNode*>(ptr);
|
||||
node->Size = totalSize;
|
||||
node->Next = nullptr;
|
||||
|
||||
return node + 1;
|
||||
}
|
||||
|
||||
void ImGuiFreeWrapper(void* /*ptr*/, void* /*user_data*/)
|
||||
void ImGuiFreeWrapper(void* ptr, void* /*user_data*/)
|
||||
{
|
||||
// TODO : Free list of imgui elements.
|
||||
Assert(ptr); // I trust Dear Imgui but just in case
|
||||
|
||||
FreeNode* node = reinterpret_cast<FreeNode*>(static_cast<char*>(ptr) - sizeof(FreeNode));
|
||||
node->Next = FirstFreeNode;
|
||||
FirstFreeNode = node;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in New Issue
Block a user