From be4b0cb67b5bf2328bbdd4d353c6e3164f1f339a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 May 2025 14:26:24 +0200 Subject: [PATCH] Stop memory allocations by keeping the RectPacker around --- .../rendering/hwrenderer/data/hw_rectpacker.cpp | 17 +++++++++++++++++ .../rendering/hwrenderer/data/hw_rectpacker.h | 2 ++ src/common/rendering/vulkan/vk_lightmapper.cpp | 7 +++++-- src/common/rendering/vulkan/vk_lightmapper.h | 2 ++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_rectpacker.cpp b/src/common/rendering/hwrenderer/data/hw_rectpacker.cpp index ae7c1d003..757f270d9 100644 --- a/src/common/rendering/hwrenderer/data/hw_rectpacker.cpp +++ b/src/common/rendering/hwrenderer/data/hw_rectpacker.cpp @@ -16,6 +16,23 @@ RectPacker::RectPacker(int width, int height, int padding) : PageWidth(width), P { } +void RectPacker::Clear() +{ + Pages.clear(); + ItemFreeList.resize(Items.size()); + size_t i = Items.size(); + for (auto& item : Items) + { + item->Shelf = nullptr; + item->PrevItem = nullptr; + item->NextItem = nullptr; + item->IsAvailable = false; + item->PrevAvailable = nullptr; + item->NextAvailable = nullptr; + ItemFreeList[--i] = item.get(); + } +} + RectPackerItem* RectPacker::Alloc(int width, int height) { width += Padding * 2; diff --git a/src/common/rendering/hwrenderer/data/hw_rectpacker.h b/src/common/rendering/hwrenderer/data/hw_rectpacker.h index d8819108e..433bca9e2 100644 --- a/src/common/rendering/hwrenderer/data/hw_rectpacker.h +++ b/src/common/rendering/hwrenderer/data/hw_rectpacker.h @@ -56,6 +56,8 @@ class RectPacker public: RectPacker(int width, int height, int padding); + void Clear(); + RectPackerItem* Alloc(int width, int height); void Free(RectPackerItem* item); diff --git a/src/common/rendering/vulkan/vk_lightmapper.cpp b/src/common/rendering/vulkan/vk_lightmapper.cpp index e32709d2d..1029ac139 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.cpp +++ b/src/common/rendering/vulkan/vk_lightmapper.cpp @@ -133,7 +133,10 @@ void VkLightmapper::SelectTiles(const TArray& tiles) selectedTiles.Clear(); // We use a 3 texel spacing between rectangles so that the blur pass will not pick up anything from a neighbour tile. - RectPacker packer(bakeImageSize, bakeImageSize, 3); + if (!packer) + packer = std::make_unique(bakeImageSize, bakeImageSize, 3); + else + packer->Clear(); for (int i = 0, count = tiles.Size(); i < count; i++) { @@ -143,7 +146,7 @@ void VkLightmapper::SelectTiles(const TArray& tiles) continue; // Only grab surfaces until our bake texture is full - auto result = packer.Alloc(tile->AtlasLocation.Width, tile->AtlasLocation.Height); + auto result = packer->Alloc(tile->AtlasLocation.Width, tile->AtlasLocation.Height); if (result->PageIndex == 0) { SelectedTile selected; diff --git a/src/common/rendering/vulkan/vk_lightmapper.h b/src/common/rendering/vulkan/vk_lightmapper.h index 80ea7f1ab..7b79aa0a3 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.h +++ b/src/common/rendering/vulkan/vk_lightmapper.h @@ -6,6 +6,7 @@ class VulkanRenderDevice; class FString; class ShaderIncludeResult; +class RectPacker; struct Uniforms { @@ -232,4 +233,5 @@ private: LightmapBakeImage bakeImage; static const int bakeImageSize = 2048; + std::unique_ptr packer; };