Allocate command buffers from pools
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/VulkanRenderer/VulkanCommandBuffer.hpp>
|
||||
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
|
||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
void VulkanCommandBuffer::Release()
|
||||
{
|
||||
m_owner.Release(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
|
||||
#include <Nazara/Core/StackVector.hpp>
|
||||
#include <Nazara/VulkanRenderer/VulkanCommandBuffer.hpp>
|
||||
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
|
||||
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
|
||||
@@ -10,14 +11,14 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
std::unique_ptr<CommandBuffer> VulkanCommandPool::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
|
||||
CommandBufferPtr VulkanCommandPool::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
|
||||
{
|
||||
std::vector<Vk::AutoCommandBuffer> commandBuffers;
|
||||
auto BuildCommandBuffer = [&](std::size_t imageIndex)
|
||||
{
|
||||
Vk::AutoCommandBuffer& commandBuffer = commandBuffers.emplace_back(m_commandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
|
||||
|
||||
if (!commandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT))
|
||||
if (!commandBuffer->Begin())
|
||||
throw std::runtime_error("failed to begin command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
|
||||
|
||||
VulkanCommandBufferBuilder builder(commandBuffer.Get(), imageIndex);
|
||||
@@ -33,6 +34,50 @@ namespace Nz
|
||||
for (std::size_t i = 1; i < maxFramebufferCount; ++i)
|
||||
BuildCommandBuffer(i);
|
||||
|
||||
return std::make_unique<VulkanCommandBuffer>(std::move(commandBuffers));
|
||||
for (std::size_t i = 0; i < m_commandPools.size(); ++i)
|
||||
{
|
||||
if (m_commandPools[i].freeCommands.TestNone())
|
||||
continue;
|
||||
|
||||
return AllocateFromPool(i, std::move(commandBuffers));
|
||||
}
|
||||
|
||||
// No allocation could be made, time to allocate a new pool
|
||||
std::size_t newPoolIndex = m_commandPools.size();
|
||||
AllocatePool();
|
||||
|
||||
return AllocateFromPool(newPoolIndex, std::move(commandBuffers));
|
||||
}
|
||||
|
||||
auto VulkanCommandPool::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));
|
||||
}
|
||||
|
||||
void VulkanCommandPool::Release(CommandBuffer& binding)
|
||||
{
|
||||
VulkanCommandBuffer& vulkanBinding = static_cast<VulkanCommandBuffer&>(binding);
|
||||
|
||||
std::size_t poolIndex = vulkanBinding.GetPoolIndex();
|
||||
std::size_t bindingIndex = vulkanBinding.GetBindingIndex();
|
||||
|
||||
assert(poolIndex < m_commandPools.size());
|
||||
auto& pool = m_commandPools[poolIndex];
|
||||
assert(!pool.freeCommands.Test(bindingIndex));
|
||||
|
||||
VulkanCommandBuffer* bindingMemory = reinterpret_cast<VulkanCommandBuffer*>(&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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user