diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index f7419679a..2e680b9d0 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -88,6 +88,11 @@ namespace Nz UploadPool::Allocation* allocation = nullptr; }; + struct LightUboPool + { + std::vector> lightUboBuffers; + }; + struct MaterialData { std::size_t usedCount = 0; @@ -139,6 +144,7 @@ namespace Nz std::size_t m_depthPassIndex; std::size_t m_forwardPassIndex; + std::shared_ptr m_lightUboPool; std::unordered_map m_viewers; std::unordered_map m_lights; std::unordered_map m_materials; diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index 6f4fecfbd..e440d5fdf 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -38,6 +38,8 @@ namespace Nz m_elementRenderers.resize(BasicRenderElementCount); m_elementRenderers[UnderlyingCast(BasicRenderElement::SpriteChain)] = std::make_unique(*Graphics::Instance()->GetRenderDevice()); m_elementRenderers[UnderlyingCast(BasicRenderElement::Submesh)] = std::make_unique(); + + m_lightUboPool = std::make_shared(); } void ForwardFramePipeline::InvalidateViewer(AbstractViewer* viewerInstance) @@ -302,9 +304,12 @@ namespace Nz for (auto& lightDataUbo : m_lightDataBuffers) { - lightDataUbo.allocation = nullptr; - lightDataUbo.offset = 0; + renderFrame.PushReleaseCallback([pool = m_lightUboPool, lightUbo = std::move(lightDataUbo.renderBuffer)]() + { + pool->lightUboBuffers.push_back(std::move(lightUbo)); + }); } + m_lightDataBuffers.clear(); for (const auto& renderableData : m_visibleRenderables) { @@ -353,9 +358,17 @@ namespace Nz if (!targetLightData) { - // Allocate a new light UBO + // Make a new light UBO auto& lightUboData = m_lightDataBuffers.emplace_back(); - lightUboData.renderBuffer = graphics->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform, 256 * lightUboAlignedSize, BufferUsage::DeviceLocal | BufferUsage::Dynamic | BufferUsage::Write); + + // Reuse from pool if possible + if (!m_lightUboPool->lightUboBuffers.empty()) + { + lightUboData.renderBuffer = m_lightUboPool->lightUboBuffers.back(); + m_lightUboPool->lightUboBuffers.pop_back(); + } + else + lightUboData.renderBuffer = graphics->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform, 256 * lightUboAlignedSize, BufferUsage::DeviceLocal | BufferUsage::Dynamic | BufferUsage::Write); targetLightData = &lightUboData; } @@ -405,8 +418,6 @@ namespace Nz { builder.BeginDebugRegion("Light UBO Update", Color::Yellow); { - builder.PreTransferBarrier(); - for (auto& lightUboData : m_lightDataBuffers) { if (!lightUboData.allocation)