diff --git a/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp b/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp index 5fed9397d..6147bd970 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp @@ -42,6 +42,7 @@ namespace Nz { std::vector memory; UInt64 freeOffset = 0; + UInt64 size; }; std::size_t m_nextAllocationIndex; diff --git a/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp b/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp index 490f81084..52ed8175c 100644 --- a/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp +++ b/include/Nazara/VulkanRenderer/VulkanUploadPool.hpp @@ -49,6 +49,7 @@ namespace Nz Vk::DeviceMemory blockMemory; Vk::Buffer buffer; UInt64 freeOffset = 0; + UInt64 size; }; UInt64 m_blockSize; diff --git a/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp b/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp index 92427f7d8..a4c610c84 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp @@ -27,7 +27,7 @@ namespace Nz for (Block& block : m_blocks) { - if (block.freeOffset + size > m_blockSize) + if (block.freeOffset + size > block.size) continue; //< Not enough space if (!bestBlock.block) @@ -41,7 +41,12 @@ namespace Nz // No block found, allocate a new one if (!bestBlock.block) { + // Handle really big allocations (TODO: Handle them separately as they shouldn't be common and can consume a lot of memory) + UInt64 blockSize = std::max(m_blockSize, size); + Block newBlock; + newBlock.size = blockSize; + newBlock.memory.resize(m_blockSize); bestBlock.block = &m_blocks.emplace_back(std::move(newBlock)); diff --git a/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp b/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp index 3da028846..5897d09b7 100644 --- a/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp +++ b/src/Nazara/VulkanRenderer/VulkanUploadPool.cpp @@ -19,8 +19,6 @@ namespace Nz auto VulkanUploadPool::Allocate(UInt64 size, UInt64 alignment) -> VulkanAllocation& { - assert(size <= m_blockSize); - // Try to minimize lost space struct { @@ -32,7 +30,7 @@ namespace Nz for (Block& block : m_blocks) { UInt64 alignedOffset = AlignPow2(block.freeOffset, alignment); - if (alignedOffset + size > m_blockSize) + if (alignedOffset + size > block.size) continue; //< Not enough space UInt64 lostSpace = alignedOffset - block.freeOffset; @@ -48,8 +46,13 @@ namespace Nz // No block found, allocate a new one if (!bestBlock.block) { + // Handle really big allocations (TODO: Handle them separately as they shouldn't be common and can consume a lot of memory) + UInt64 blockSize = std::max(m_blockSize, size); + Block newBlock; - if (!newBlock.buffer.Create(m_device, 0U, m_blockSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) + newBlock.size = blockSize; + + if (!newBlock.buffer.Create(m_device, 0U, blockSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) throw std::runtime_error("failed to create block buffer: " + TranslateVulkanError(newBlock.buffer.GetLastErrorCode())); VkMemoryRequirements requirement = newBlock.buffer.GetMemoryRequirements();