Allocate command buffers from pools

This commit is contained in:
Jérôme Leclercq
2020-08-27 18:31:26 +02:00
parent cbdac32f5f
commit 7c9dcdfbe4
18 changed files with 333 additions and 23 deletions

View File

@@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLVaoCache.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/VertexArray.hpp>
@@ -139,4 +140,10 @@ namespace Nz
const GL::VertexArray& vao = context.GetVaoCache().Get(vaoSetup);
context.BindVertexArray(vao.GetObjectId(), true);
}
void OpenGLCommandBuffer::Release()
{
assert(m_owner);
m_owner->Release(*this);
}
}

View File

@@ -3,19 +3,82 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
std::unique_ptr<CommandBuffer> OpenGLCommandPool::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
CommandBufferPtr OpenGLCommandPool::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
{
std::unique_ptr<OpenGLCommandBuffer> commandBuffer = std::make_unique<OpenGLCommandBuffer>();
CommandBufferPtr commandBuffer;
for (std::size_t i = 0; i < m_commandPools.size(); ++i)
{
commandBuffer = AllocateFromPool(i);
if (commandBuffer)
break;
}
OpenGLCommandBufferBuilder builder(*commandBuffer);
if (!commandBuffer)
{
// No allocation could be made, time to allocate a new pool
std::size_t newPoolIndex = m_commandPools.size();
AllocatePool();
commandBuffer = AllocateFromPool(newPoolIndex);
assert(commandBuffer);
}
OpenGLCommandBufferBuilder builder(static_cast<OpenGLCommandBuffer&>(*commandBuffer.get()));
callback(builder);
return commandBuffer;
}
auto OpenGLCommandPool::AllocatePool() -> CommandPool&
{
constexpr UInt32 MaxSet = 128;
CommandPool pool;
pool.freeCommands.Resize(MaxSet, true);
pool.storage = std::make_unique<CommandPool::BindingStorage[]>(MaxSet);
return m_commandPools.emplace_back(std::move(pool));
}
CommandBufferPtr OpenGLCommandPool::AllocateFromPool(std::size_t poolIndex)
{
auto& pool = m_commandPools[poolIndex];
std::size_t freeBindingId = pool.freeCommands.FindFirst();
if (freeBindingId == pool.freeCommands.npos)
return {}; //< No free binding in this pool
pool.freeCommands.Reset(freeBindingId);
OpenGLCommandBuffer* freeBindingMemory = reinterpret_cast<OpenGLCommandBuffer*>(&pool.storage[freeBindingId]);
return CommandBufferPtr(PlacementNew(freeBindingMemory, *this, poolIndex, freeBindingId));
}
void OpenGLCommandPool::Release(CommandBuffer& binding)
{
OpenGLCommandBuffer& openglBinding = static_cast<OpenGLCommandBuffer&>(binding);
std::size_t poolIndex = openglBinding.GetPoolIndex();
std::size_t bindingIndex = openglBinding.GetBindingIndex();
assert(poolIndex < m_commandPools.size());
auto& pool = m_commandPools[poolIndex];
assert(!pool.freeCommands.Test(bindingIndex));
OpenGLCommandBuffer* bindingMemory = reinterpret_cast<OpenGLCommandBuffer*>(&pool.storage[bindingIndex]);
PlacementDestroy(bindingMemory);
pool.freeCommands.Set(bindingIndex);
// Try to free pool if it's one of the last one
if (poolIndex >= m_commandPools.size() - 1 && poolIndex <= m_commandPools.size())
TryToShrink();
}
}

View File

@@ -19,7 +19,7 @@ namespace Nz
void OpenGLRenderImage::Execute(const std::function<void(CommandBufferBuilder& builder)>& callback, QueueTypeFlags /*queueTypeFlags*/)
{
OpenGLCommandBuffer commandBuffer;
OpenGLCommandBuffer commandBuffer; //< TODO: Use a pool and remove default constructor
OpenGLCommandBufferBuilder builder(commandBuffer);
callback(builder);