// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include namespace Nz { inline void RenderImage::FlushReleaseQueue() { for (Releasable* releasable : m_releaseQueue) { releasable->Release(); PlacementDestroy(releasable); } m_releaseQueue.clear(); for (auto& memoryblock : m_releaseMemoryPool) memoryblock.clear(); } template void RenderImage::PushReleaseCallback(F&& callback) { using Functor = ReleasableLambda>>; constexpr std::size_t functorSize = sizeof(Functor); constexpr std::size_t functorAlignment = alignof(Functor); // Try to minimize lost space struct { Block* block = nullptr; UInt64 alignedOffset = 0; UInt64 lostSpace = 0; } bestBlock; for (Block& block : m_releaseMemoryPool) { std::size_t freeOffset = block.size(); UInt64 alignedOffset = Align(freeOffset, functorAlignment); if (alignedOffset + functorSize > block.capacity()) continue; //< Not enough space UInt64 lostSpace = alignedOffset - freeOffset; if (!bestBlock.block || lostSpace < bestBlock.lostSpace) { bestBlock.block = █ bestBlock.alignedOffset = alignedOffset; bestBlock.lostSpace = lostSpace; } } // No block found, allocate a new one if (!bestBlock.block) { Block newBlock; newBlock.reserve(BlockSize); bestBlock.block = &m_releaseMemoryPool.emplace_back(std::move(newBlock)); bestBlock.alignedOffset = 0; bestBlock.lostSpace = 0; } Block& targetBlock = *bestBlock.block; targetBlock.resize(bestBlock.alignedOffset + functorSize); Functor* releasable = reinterpret_cast(&targetBlock[bestBlock.alignedOffset]); PlacementNew(releasable, std::forward(callback)); m_releaseQueue.push_back(releasable); } template template RenderImage::ReleasableLambda::ReleasableLambda(U&& lambda) : m_lambda(std::forward(lambda)) { } template void RenderImage::ReleasableLambda::Release() { m_lambda(); } } #include