working on garbage collection, fixing small issues with font destroy

This commit is contained in:
2024-12-14 01:39:50 +01:00
parent f78c3e9f0f
commit 7bd2b9c4c7
9 changed files with 90 additions and 26 deletions

2
.gitignore vendored
View File

@@ -14,7 +14,7 @@
*.gch *.gch
*.pch *.pch
*.exe *.exe
*vgcore *vgcore.*
*.gdb_history *.gdb_history
.vs/ .vs/
.xmake/ .xmake/

View File

@@ -11,7 +11,9 @@ namespace mlx
static void* Malloc(std::size_t size); static void* Malloc(std::size_t size);
static void* AlignedMalloc(std::size_t alignment, std::size_t size); static void* AlignedMalloc(std::size_t alignment, std::size_t size);
static void* Calloc(std::size_t n, std::size_t size); static void* Calloc(std::size_t n, std::size_t size);
static void* AlignedCalloc(std::size_t alignment, std::size_t n, std::size_t size);
static void* Realloc(void* ptr, std::size_t size); static void* Realloc(void* ptr, std::size_t size);
static void* AlignedRealloc(void* ptr, std::size_t alignment, std::size_t size);
static void Free(void* ptr); static void Free(void* ptr);
inline static bool IsInit() noexcept { return s_instance != nullptr; } inline static bool IsInit() noexcept { return s_instance != nullptr; }
@@ -19,9 +21,19 @@ namespace mlx
~MemManager(); ~MemManager();
private:
struct Descriptor
{
void* ptr;
std::size_t size;
bool aligned;
Descriptor(void* ptr, std::size_t size, bool aligned) : ptr(ptr), size(size), aligned(aligned) {}
};
private: private:
static MemManager* s_instance; static MemManager* s_instance;
inline static std::vector<void*> s_blocks; inline static std::vector<Descriptor> s_blocks;
}; };
} }

View File

@@ -68,12 +68,15 @@
#endif #endif
#include <Core/Memory.h> #include <Core/Memory.h>
#include <Core/Logs.h>
#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
#define VMA_VULKAN_VERSION 1000000 #define VMA_VULKAN_VERSION 1000000
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (mlx::MemManager::AlignedMalloc(alignment, size)) #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (mlx::MemManager::AlignedMalloc(alignment, size))
#define VMA_SYSTEM_ALIGNED_FREE(ptr) (mlx::MemManager::Free(ptr)) #define VMA_SYSTEM_ALIGNED_FREE(ptr) (mlx::MemManager::Free(ptr))
//#define VMA_ASSERT(expr) (mlx::Assert(expr, "VMA Assertion: " #expr))
#define VMA_ASSERT(expr) ((void)0)
#define VMA_ASSERT_LEAK(expr) ((void)0) // Because why not #define VMA_ASSERT_LEAK(expr) ((void)0) // Because why not
#ifdef MLX_COMPILER_CLANG #ifdef MLX_COMPILER_CLANG
@@ -104,7 +107,6 @@
#endif #endif
#include <kvf.h> #include <kvf.h>
#include <Core/Logs.h>
#include <Core/EventBus.h> #include <Core/EventBus.h>
#include <Core/Profiler.h> #include <Core/Profiler.h>
#include <Utils/NonOwningPtr.h> #include <Utils/NonOwningPtr.h>

View File

@@ -91,7 +91,6 @@ namespace mlx
if(gs) if(gs)
gs->TryEraseSpritesInScene(texture); gs->TryEraseSpritesInScene(texture);
} }
m_image_registry.UnregisterTexture(texture);
delete texture; delete texture;
} }

View File

@@ -15,15 +15,24 @@ namespace mlx
{ {
void* ptr = std::malloc(size); void* ptr = std::malloc(size);
if(ptr != nullptr) if(ptr != nullptr)
s_blocks.push_back(ptr); s_blocks.emplace_back(ptr, size, false);
return ptr; return ptr;
} }
void* MemManager::AlignedMalloc(std::size_t alignment, std::size_t size) void* MemManager::AlignedMalloc(std::size_t alignment, std::size_t size)
{ {
void* ptr = std::aligned_alloc(alignment, size); if(alignment < sizeof(void*))
alignment = sizeof(void*);
if(size % alignment != 0)
size += alignment - (size % alignment);
#ifdef MLX_COMPILER_MSVC
void* ptr = _aligned_malloc(alignment, size);
#else
void* ptr = std::aligned_alloc(alignment, size);
#endif
if(ptr != nullptr) if(ptr != nullptr)
s_blocks.push_back(ptr); s_blocks.emplace_back(ptr, size, true);
return ptr; return ptr;
} }
@@ -31,7 +40,14 @@ namespace mlx
{ {
void* ptr = std::calloc(n, size); void* ptr = std::calloc(n, size);
if(ptr != nullptr) if(ptr != nullptr)
s_blocks.push_back(ptr); s_blocks.emplace_back(ptr, n * size, false);
return ptr;
}
void* MemManager::AlignedCalloc(std::size_t alignment, std::size_t n, std::size_t size)
{
void* ptr = AlignedMalloc(alignment, n * size);
std::memset(ptr, 0, n * size);
return ptr; return ptr;
} }
@@ -39,33 +55,65 @@ namespace mlx
{ {
void* ptr2 = std::realloc(ptr, size); void* ptr2 = std::realloc(ptr, size);
if(ptr2 != nullptr) if(ptr2 != nullptr)
s_blocks.push_back(ptr2); s_blocks.emplace_back(ptr, size, false);
auto it = std::find(s_blocks.begin(), s_blocks.end(), ptr); auto it = std::find_if(s_blocks.begin(), s_blocks.end(), [=](const Descriptor& rhs){ return ptr == rhs.ptr; });
if(it != s_blocks.end()) if(it != s_blocks.end())
s_blocks.erase(it); s_blocks.erase(it);
return ptr2; return ptr2;
} }
void* MemManager::AlignedRealloc(void* ptr, std::size_t alignment, std::size_t size)
{
auto it = std::find_if(s_blocks.begin(), s_blocks.end(), [=](const Descriptor& rhs){ return ptr == rhs.ptr; });
#ifdef MLX_COMPILER_MSVC
void* ptr2 = _aligned_realloc(ptr, alignment, size);
#else
void* ptr2 = AlignedMalloc(alignment, size);
if(it != s_blocks.end())
std::memcpy(ptr2, ptr, it->size);
#endif
if(it != s_blocks.end())
s_blocks.erase(it);
if(ptr2 != nullptr)
s_blocks.emplace_back(ptr, size, true);
return ptr2;
}
void MemManager::Free(void* ptr) void MemManager::Free(void* ptr)
{ {
if(ptr == nullptr) if(ptr == nullptr)
return; return;
auto it = std::find(s_blocks.begin(), s_blocks.end(), ptr); auto it = std::find_if(s_blocks.begin(), s_blocks.end(), [=](const Descriptor& rhs){ return ptr == rhs.ptr; });
if(it == s_blocks.end()) if(it == s_blocks.end())
{
Error("Memory Manager: trying to free a pointer not allocated by the memory manager");
return; return;
} #ifdef MLX_COMPILER_MSVC
std::free(*it); if(it->aligned)
_aligned_free(it->ptr);
else
std::free(it->ptr);
#else
std::free(it->ptr);
#endif
s_blocks.erase(it); s_blocks.erase(it);
} }
MemManager::~MemManager() MemManager::~MemManager()
{ {
std::for_each(s_blocks.begin(), s_blocks.end(), [](void* ptr) for(const Descriptor& desc : s_blocks)
{ {
std::free(ptr); #ifdef MLX_COMPILER_MSVC
}); if(it->aligned)
_aligned_free(desc.ptr);
else
std::free(desc.ptr);
#else
std::free(desc.ptr);
#endif
}
DebugLog("Memory Manager: finished garbage collection");
s_instance = nullptr; s_instance = nullptr;
} }
} }

View File

@@ -8,8 +8,8 @@
#include <stb_rect_pack.h> #include <stb_rect_pack.h>
#define STB_TRUETYPE_IMPLEMENTATION #define STB_TRUETYPE_IMPLEMENTATION
#define STB_malloc(x, u) ((void)(u), mlx::MemManager::Get().Malloc(x)) #define STB_malloc(x, u) ((void)(u), mlx::MemManager::Malloc(x))
#define STB_free(x, u) ((void)(u), mlx::MemManager::Get().Free(x)) #define STB_free(x, u) ((void)(u), mlx::MemManager::Free(x))
#include <stb_truetype.h> #include <stb_truetype.h>
namespace mlx namespace mlx
@@ -64,6 +64,8 @@ namespace mlx
void Font::Destroy() void Font::Destroy()
{ {
if(!m_atlas.IsInit())
return;
m_atlas.Destroy(); m_atlas.Destroy();
DebugLog("Font: unloaded % with a scale of %", m_name, m_scale); DebugLog("Font: unloaded % with a scale of %", m_name, m_scale);
} }

View File

@@ -9,9 +9,9 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#define STBI_ASSERT(x) (mlx::Assert(x, "internal stb assertion " #x)) #define STBI_ASSERT(x) (mlx::Assert(x, "internal stb assertion " #x))
#define STBI_MALLOC(x) (mlx::MemManager::Get().Malloc(x)) #define STBI_MALLOC(x) (mlx::MemManager::Malloc(x))
#define STBI_REALLOC(p, x) (mlx::MemManager::Get().Realloc(p, x)) #define STBI_REALLOC(p, x) (mlx::MemManager::Realloc(p, x))
#define STBI_FREE(x) (mlx::MemManager::Get().Free(x)) #define STBI_FREE(x) (mlx::MemManager::Free(x))
#ifdef MLX_COMPILER_GCC #ifdef MLX_COMPILER_GCC
#pragma GCC diagnostic push #pragma GCC diagnostic push
@@ -295,7 +295,7 @@ namespace mlx
int channels; int channels;
std::uint8_t* data = stbi_load(filename.c_str(), &size.x, &size.y, &channels, 4); std::uint8_t* data = stbi_load(filename.c_str(), &size.x, &size.y, &channels, 4);
CallOnExit defer([=]() { stbi_image_free(data); }); CallOnExit defer([&]() { stbi_image_free(data); });
CPUBuffer buffer(size.x * size.y * 4); CPUBuffer buffer(size.x * size.y * 4);
std::memcpy(buffer.GetData(), data, buffer.GetSize()); std::memcpy(buffer.GetData(), data, buffer.GetSize());

View File

@@ -59,9 +59,9 @@ namespace mlx
return MemManager::AlignedMalloc(alignment, size); return MemManager::AlignedMalloc(alignment, size);
} }
void* VulkanReallocationFunction(void*, void* ptr, std::size_t size, std::size_t, VkSystemAllocationScope) void* VulkanReallocationFunction(void*, void* ptr, std::size_t size, std::size_t alignment, VkSystemAllocationScope)
{ {
return MemManager::Realloc(ptr, size); return MemManager::AlignedRealloc(ptr, alignment, size);
} }
void VulkanFreeFunction(void*, void* ptr) void VulkanFreeFunction(void*, void* ptr)

View File

@@ -102,6 +102,7 @@ namespace mlx
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice()); VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence); kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
kvfDestroyFence(RenderCore::Get().GetDevice(), fence); kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
m_resize = false;
DebugLog("Vulkan: swapchain created"); DebugLog("Vulkan: swapchain created");
} }
} }