90 lines
2.8 KiB
C++
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();
|
|
}
|
|
}
|