diff --git a/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp b/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp index badfd8901..cd7a71db3 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLUploadPool.hpp @@ -35,10 +35,12 @@ namespace Nz private: struct Block { - //< TODO - UInt64 freeOffset; + std::vector memory; + UInt64 freeOffset = 0; }; + std::vector m_blocks; + std::vector m_allocations; UInt64 m_blockSize; }; } diff --git a/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp b/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp index f16c2335a..454c75840 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLUploadPool.cpp @@ -11,23 +11,56 @@ namespace Nz { auto OpenGLUploadPool::Allocate(UInt64 size) -> Allocation& { - /*const auto& deviceProperties = m_device.GetPhysicalDeviceInfo().properties; - UInt64 preferredAlignement = deviceProperties.limits.optimalBufferCopyOffsetAlignment;*/ - - return Allocate(size, 0); //< FIXME + return Allocate(size, 1); //< Alignment doesn't matter } - auto OpenGLUploadPool::Allocate(UInt64 size, UInt64 alignment) -> Allocation& + auto OpenGLUploadPool::Allocate(UInt64 size, UInt64 /*alignment*/) -> Allocation& { assert(size <= m_blockSize); - static Allocation dummy; - return dummy; + // Try to minimize lost space + struct + { + Block* block = nullptr; + UInt64 offset = 0; + } bestBlock; + + for (Block& block : m_blocks) + { + UInt64 alignedOffset = block.freeOffset; + if (block.freeOffset + size > m_blockSize) + continue; //< Not enough space + + if (!bestBlock.block) + { + bestBlock.block = █ + bestBlock.offset = block.freeOffset; + break; //< Since we have no alignment constraint, the first block is good + } + } + + // No block found, allocate a new one + if (!bestBlock.block) + { + Block newBlock; + newBlock.memory.resize(m_blockSize); + + bestBlock.block = &m_blocks.emplace_back(std::move(newBlock)); + bestBlock.offset = 0; + } + + Allocation& allocationData = m_allocations.emplace_back(); + allocationData.mappedPtr = static_cast(bestBlock.block->memory.data()) + bestBlock.offset; + allocationData.size = size; + + return allocationData; } void OpenGLUploadPool::Reset() { - /*for (Block& block : m_blocks) - block.freeOffset = 0;*/ + for (Block& block : m_blocks) + block.freeOffset = 0; + + m_allocations.clear(); } }