NazaraEngine/src/Nazara/OpenGLRenderer/OpenGLCommandPool.cpp

90 lines
2.8 KiB
C++

// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - OpenGL renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
#include <Nazara/Utils/MemoryHelper.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
CommandBufferPtr OpenGLCommandPool::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
{
CommandBufferPtr commandBuffer;
for (std::size_t i = 0; i < m_commandPools.size(); ++i)
{
commandBuffer = AllocateFromPool(i);
if (commandBuffer)
break;
}
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;
}
void OpenGLCommandPool::UpdateDebugName(std::string_view name)
{
// No OpenGL object to name
}
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();
}
}