Graphics/SpriteChainRenderer: Reuse vertex buffers and memory

This commit is contained in:
Jérôme Leclercq 2021-09-05 16:04:10 +02:00
parent 938d965e06
commit 26e5a41dce
2 changed files with 35 additions and 10 deletions

View File

@ -9,6 +9,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/ElementRenderer.hpp>
#include <Nazara/Renderer/UploadPool.hpp>
#include <memory>
#include <unordered_map>
#include <vector>
@ -33,9 +34,16 @@ namespace Nz
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
private:
struct VertexBufferPool
{
std::vector<std::shared_ptr<AbstractBuffer>> vertexBuffers;
};
std::shared_ptr<AbstractBuffer> m_indexBuffer;
std::shared_ptr<VertexBufferPool> m_vertexBufferPool;
std::size_t m_maxVertexBufferSize;
std::size_t m_maxVertexCount;
std::vector<std::pair<UploadPool::Allocation*, AbstractBuffer*>> m_pendingCopies;
RenderDevice& m_device;
};

View File

@ -18,6 +18,8 @@ namespace Nz
m_maxVertexBufferSize(maxVertexBufferSize),
m_maxVertexCount(m_maxVertexBufferSize / (2 * sizeof(float))) // Treat vec2 as the minimum declaration possible
{
m_vertexBufferPool = std::make_shared<VertexBufferPool>();
std::size_t maxQuadCount = m_maxVertexCount / 4;
std::size_t indexCount = 6 * maxQuadCount;
@ -52,8 +54,6 @@ namespace Nz
{
auto& data = static_cast<SpriteChainRendererData&>(rendererData);
std::vector<std::pair<UploadPool::Allocation*, AbstractBuffer*>> pendingCopies;
std::size_t firstQuadIndex = 0;
SpriteChainRendererData::DrawCall* currentDrawCall = nullptr;
UploadPool::Allocation* currentAllocation = nullptr;
@ -76,7 +76,7 @@ namespace Nz
if (currentAllocation)
{
pendingCopies.emplace_back(currentAllocation, currentVertexBuffer);
m_pendingCopies.emplace_back(currentAllocation, currentVertexBuffer);
firstQuadIndex = 0;
currentAllocation = nullptr;
@ -130,8 +130,19 @@ namespace Nz
currentAllocation = &currentFrame.GetUploadPool().Allocate(m_maxVertexBufferSize);
currentAllocationMemPtr = static_cast<UInt8*>(currentAllocation->mappedPtr);
std::shared_ptr<AbstractBuffer> vertexBuffer = m_device.InstantiateBuffer(BufferType::Vertex);
vertexBuffer->Initialize(m_maxVertexBufferSize, BufferUsage::DeviceLocal);
std::shared_ptr<AbstractBuffer> vertexBuffer;
// Try to reuse vertex buffers from pool if any
if (!m_vertexBufferPool->vertexBuffers.empty())
{
vertexBuffer = std::move(m_vertexBufferPool->vertexBuffers.back());
m_vertexBufferPool->vertexBuffers.pop_back();
}
else
{
vertexBuffer = m_device.InstantiateBuffer(BufferType::Vertex);
vertexBuffer->Initialize(m_maxVertexBufferSize, BufferUsage::DeviceLocal);
}
currentVertexBuffer = vertexBuffer.get();
@ -183,15 +194,17 @@ namespace Nz
std::size_t drawCallCount = data.drawCalls.size() - oldDrawCallCount;
data.drawCallPerElement[firstSpriteChain] = SpriteChainRendererData::DrawCallIndices{ oldDrawCallCount, drawCallCount };
if (!pendingCopies.empty())
if (!m_pendingCopies.empty())
{
currentFrame.Execute([&](CommandBufferBuilder& builder)
{
for (auto&& [allocation, buffer] : pendingCopies)
for (auto&& [allocation, buffer] : m_pendingCopies)
builder.CopyBuffer(*allocation, buffer);
builder.PostTransferBarrier();
}, Nz::QueueType::Transfer);
m_pendingCopies.clear();
}
}
@ -248,11 +261,15 @@ namespace Nz
{
auto& data = static_cast<SpriteChainRendererData&>(rendererData);
// TODO: Reuse vertex buffers
for (auto& vertexBufferPtr : data.vertexBuffers)
currentFrame.PushForRelease(std::move(vertexBufferPtr));
{
currentFrame.PushReleaseCallback([pool = m_vertexBufferPool, vertexBuffer = std::move(vertexBufferPtr)]()
{
pool->vertexBuffers.push_back(std::move(vertexBuffer));
});
}
data.vertexBuffers.clear();
data.drawCalls.clear();
data.vertexBuffers.clear();
}
}