diff --git a/.gitignore b/.gitignore index 82d65a8..9c8cb76 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ *.gch *.pch *.exe -*vgcore +*vgcore.* *.gdb_history .vs/ .xmake/ diff --git a/runtime/Includes/Core/Memory.h b/runtime/Includes/Core/Memory.h index 91b36c1..891baba 100644 --- a/runtime/Includes/Core/Memory.h +++ b/runtime/Includes/Core/Memory.h @@ -11,7 +11,9 @@ namespace mlx static void* Malloc(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* AlignedCalloc(std::size_t alignment, std::size_t n, 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); inline static bool IsInit() noexcept { return s_instance != nullptr; } @@ -19,9 +21,19 @@ namespace mlx ~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: static MemManager* s_instance; - inline static std::vector s_blocks; + inline static std::vector s_blocks; }; } diff --git a/runtime/Includes/PreCompiled.h b/runtime/Includes/PreCompiled.h index 2f17519..8d99dfc 100644 --- a/runtime/Includes/PreCompiled.h +++ b/runtime/Includes/PreCompiled.h @@ -68,12 +68,15 @@ #endif #include +#include #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #define VMA_VULKAN_VERSION 1000000 #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (mlx::MemManager::AlignedMalloc(alignment, size)) #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 #ifdef MLX_COMPILER_CLANG @@ -104,7 +107,6 @@ #endif #include -#include #include #include #include diff --git a/runtime/Sources/Core/Application.cpp b/runtime/Sources/Core/Application.cpp index ce32c96..3195ba2 100644 --- a/runtime/Sources/Core/Application.cpp +++ b/runtime/Sources/Core/Application.cpp @@ -91,7 +91,6 @@ namespace mlx if(gs) gs->TryEraseSpritesInScene(texture); } - m_image_registry.UnregisterTexture(texture); delete texture; } diff --git a/runtime/Sources/Core/Memory.cpp b/runtime/Sources/Core/Memory.cpp index c3eedbe..1dcb660 100644 --- a/runtime/Sources/Core/Memory.cpp +++ b/runtime/Sources/Core/Memory.cpp @@ -15,15 +15,24 @@ namespace mlx { void* ptr = std::malloc(size); if(ptr != nullptr) - s_blocks.push_back(ptr); + s_blocks.emplace_back(ptr, size, false); return ptr; } 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) - s_blocks.push_back(ptr); + s_blocks.emplace_back(ptr, size, true); return ptr; } @@ -31,7 +40,14 @@ namespace mlx { void* ptr = std::calloc(n, size); 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; } @@ -39,33 +55,65 @@ namespace mlx { void* ptr2 = std::realloc(ptr, size); if(ptr2 != nullptr) - s_blocks.push_back(ptr2); - auto it = std::find(s_blocks.begin(), s_blocks.end(), ptr); + s_blocks.emplace_back(ptr, size, false); + auto it = std::find_if(s_blocks.begin(), s_blocks.end(), [=](const Descriptor& rhs){ return ptr == rhs.ptr; }); if(it != s_blocks.end()) s_blocks.erase(it); 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) { if(ptr == nullptr) 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()) - { - Error("Memory Manager: trying to free a pointer not allocated by the memory manager"); return; - } - std::free(*it); + #ifdef MLX_COMPILER_MSVC + if(it->aligned) + _aligned_free(it->ptr); + else + std::free(it->ptr); + #else + std::free(it->ptr); + #endif s_blocks.erase(it); } 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; } } diff --git a/runtime/Sources/Graphics/Font.cpp b/runtime/Sources/Graphics/Font.cpp index 339aa62..b871dec 100644 --- a/runtime/Sources/Graphics/Font.cpp +++ b/runtime/Sources/Graphics/Font.cpp @@ -8,8 +8,8 @@ #include #define STB_TRUETYPE_IMPLEMENTATION -#define STB_malloc(x, u) ((void)(u), mlx::MemManager::Get().Malloc(x)) -#define STB_free(x, u) ((void)(u), mlx::MemManager::Get().Free(x)) +#define STB_malloc(x, u) ((void)(u), mlx::MemManager::Malloc(x)) +#define STB_free(x, u) ((void)(u), mlx::MemManager::Free(x)) #include namespace mlx @@ -64,6 +64,8 @@ namespace mlx void Font::Destroy() { + if(!m_atlas.IsInit()) + return; m_atlas.Destroy(); DebugLog("Font: unloaded % with a scale of %", m_name, m_scale); } diff --git a/runtime/Sources/Renderer/Image.cpp b/runtime/Sources/Renderer/Image.cpp index f4f1276..77b6539 100644 --- a/runtime/Sources/Renderer/Image.cpp +++ b/runtime/Sources/Renderer/Image.cpp @@ -9,9 +9,9 @@ #define STB_IMAGE_IMPLEMENTATION #define STBI_ASSERT(x) (mlx::Assert(x, "internal stb assertion " #x)) -#define STBI_MALLOC(x) (mlx::MemManager::Get().Malloc(x)) -#define STBI_REALLOC(p, x) (mlx::MemManager::Get().Realloc(p, x)) -#define STBI_FREE(x) (mlx::MemManager::Get().Free(x)) +#define STBI_MALLOC(x) (mlx::MemManager::Malloc(x)) +#define STBI_REALLOC(p, x) (mlx::MemManager::Realloc(p, x)) +#define STBI_FREE(x) (mlx::MemManager::Free(x)) #ifdef MLX_COMPILER_GCC #pragma GCC diagnostic push @@ -295,7 +295,7 @@ namespace mlx int channels; 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); std::memcpy(buffer.GetData(), data, buffer.GetSize()); diff --git a/runtime/Sources/Renderer/RenderCore.cpp b/runtime/Sources/Renderer/RenderCore.cpp index 5d49820..510801b 100644 --- a/runtime/Sources/Renderer/RenderCore.cpp +++ b/runtime/Sources/Renderer/RenderCore.cpp @@ -59,9 +59,9 @@ namespace mlx 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) diff --git a/runtime/Sources/Renderer/Swapchain.cpp b/runtime/Sources/Renderer/Swapchain.cpp index d598120..bc414bb 100644 --- a/runtime/Sources/Renderer/Swapchain.cpp +++ b/runtime/Sources/Renderer/Swapchain.cpp @@ -102,6 +102,7 @@ namespace mlx VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice()); kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence); kvfDestroyFence(RenderCore::Get().GetDevice(), fence); + m_resize = false; DebugLog("Vulkan: swapchain created"); } }