From 11d4ba22da72d224138d3a8deb25df1df2dff4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 3 Dec 2021 22:17:24 +0100 Subject: [PATCH] Graphics/ForwardFramePipeline: Use RenderGraph to merge viewers views --- .../Nazara/Graphics/ForwardFramePipeline.hpp | 11 +- src/Nazara/Graphics/ForwardFramePipeline.cpp | 127 +++++++++++++----- 2 files changed, 102 insertions(+), 36 deletions(-) diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index dcb612c14..b28d537f2 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -57,6 +57,8 @@ namespace Nz template void ProcessRenderQueue(const RenderQueue& renderQueue, F&& callback); void UnregisterMaterialPass(MaterialPass* material); + struct ViewerData; + struct MaterialData { std::size_t usedCount = 0; @@ -72,6 +74,13 @@ namespace Nz NazaraSlot(InstancedRenderable, OnMaterialInvalidated, onMaterialInvalidated); }; + struct RenderTargetData + { + std::size_t finalAttachment; + std::vector viewers; + ShaderBindingPtr blitShaderBinding; + }; + struct VisibleRenderable { const InstancedRenderable* instancedRenderable; @@ -102,7 +111,7 @@ namespace Nz std::unordered_map m_viewers; std::unordered_map m_materials; std::unordered_map> m_renderables; - std::unordered_map> m_viewerPerTarget; + std::unordered_map m_renderTargets; std::unordered_set m_invalidatedViewerInstances; std::unordered_set m_invalidatedMaterials; std::unordered_set m_invalidatedWorldInstances; diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index 57894c153..5a7025b30 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -351,44 +352,47 @@ namespace Nz } }); } + + for (auto&& [_, renderTargetData] : m_renderTargets) + { + if (renderTargetData.blitShaderBinding) + renderFrame.PushForRelease(std::move(renderTargetData.blitShaderBinding)); + + renderTargetData.blitShaderBinding = graphics->GetBlitPipelineLayout()->AllocateShaderBinding(0); + renderTargetData.blitShaderBinding->Update({ + { + 0, + ShaderBinding::TextureBinding { + m_bakedFrameGraph.GetAttachmentTexture(renderTargetData.finalAttachment).get(), + sampler.get() + } + } + }); + } } m_bakedFrameGraph.Execute(renderFrame); m_rebuildFrameGraph = false; - m_viewerPerTarget.clear(); - const Vector2ui& frameSize = renderFrame.GetSize(); for (auto&& [viewer, viewerData] : m_viewers) { viewerData.rebuildForwardPass = false; viewerData.rebuildDepthPrepass = false; viewerData.prepare = false; - - const RenderTarget& renderTarget = viewer->GetRenderTarget(); - - m_viewerPerTarget[&renderTarget].push_back(&viewerData); } - for (auto&& [renderTargetPtr, viewerDataVec] : m_viewerPerTarget) + const Vector2ui& frameSize = renderFrame.GetSize(); + for (auto&& [renderTargetPtr, renderTargetData] : m_renderTargets) { Recti renderRegion(0, 0, frameSize.x, frameSize.y); const RenderTarget& renderTarget = *renderTargetPtr; - auto& viewers = viewerDataVec; - - std::sort(viewers.begin(), viewers.end(), [](const ViewerData* lhs, const ViewerData* rhs) - { - return lhs->renderOrder < rhs->renderOrder; - }); - + const auto& data = renderTargetData; renderFrame.Execute([&](CommandBufferBuilder& builder) { - for (const ViewerData* viewerData : viewers) - { - const std::shared_ptr& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(viewerData->colorAttachment); + const std::shared_ptr& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(data.finalAttachment); - builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::FragmentShader, MemoryAccess::ColorWrite, MemoryAccess::ShaderRead, TextureLayout::ColorOutput, TextureLayout::ColorInput, *sourceTexture); - } + builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::FragmentShader, MemoryAccess::ColorWrite, MemoryAccess::ShaderRead, TextureLayout::ColorOutput, TextureLayout::ColorInput, *sourceTexture); std::array clearValues; clearValues[0].color = Color::Black; @@ -404,21 +408,8 @@ namespace Nz builder.BindPipeline(*graphics->GetBlitPipeline(false)); builder.BindVertexBuffer(0, *graphics->GetFullscreenVertexBuffer()); - bool first = true; - - for (const ViewerData* viewerData : viewers) - { - const ShaderBindingPtr& blitShaderBinding = viewerData->blitShaderBinding; - - builder.BindShaderBinding(0, *blitShaderBinding); - builder.Draw(3); - - if (first) - { - builder.BindPipeline(*graphics->GetBlitPipeline(true)); - first = false; - } - } + builder.BindShaderBinding(0, *data.blitShaderBinding); + builder.Draw(3); } builder.EndDebugRegion(); } @@ -554,8 +545,74 @@ namespace Nz }); } + using ViewerPair = std::pair; + + StackArray viewers = NazaraStackArray(ViewerPair, m_viewers.size()); + auto viewerIt = viewers.begin(); + for (auto&& [viewer, viewerData] : m_viewers) - frameGraph.AddBackbufferOutput(viewerData.colorAttachment); + { + const RenderTarget& renderTarget = viewer->GetRenderTarget(); + *viewerIt++ = std::make_pair(&renderTarget, &viewerData); + } + + std::sort(viewers.begin(), viewers.end(), [](const ViewerPair& lhs, const ViewerPair& rhs) + { + return lhs.second->renderOrder < rhs.second->renderOrder; + }); + + m_renderTargets.clear(); + for (auto&& [renderTarget, viewerData] : viewers) + { + auto& renderTargetData = m_renderTargets[renderTarget]; + renderTargetData.viewers.push_back(viewerData); + } + + for (auto&& [renderTarget, renderTargetData] : m_renderTargets) + { + const auto& targetViewers = renderTargetData.viewers; + + FramePass& forwardPass = frameGraph.AddPass("Merge pass"); + + renderTargetData.finalAttachment = frameGraph.AddAttachment({ + "Viewer output", + PixelFormat::RGBA8 + }); + + for (const ViewerData* viewerData : targetViewers) + forwardPass.AddInput(viewerData->colorAttachment); + + forwardPass.AddOutput(renderTargetData.finalAttachment); + forwardPass.SetClearColor(0, Color::Black); + + forwardPass.SetCommandCallback([this, &targetViewers](CommandBufferBuilder& builder, const Recti& renderRect) + { + builder.SetScissor(renderRect); + builder.SetViewport(renderRect); + + Graphics* graphics = Graphics::Instance(); + builder.BindPipeline(*graphics->GetBlitPipeline(false)); + builder.BindVertexBuffer(0, *graphics->GetFullscreenVertexBuffer()); + + bool first = true; + + for (const ViewerData* viewerData : targetViewers) + { + const ShaderBindingPtr& blitShaderBinding = viewerData->blitShaderBinding; + + builder.BindShaderBinding(0, *blitShaderBinding); + builder.Draw(3); + + if (first) + { + builder.BindPipeline(*graphics->GetBlitPipeline(true)); + first = false; + } + } + }); + + frameGraph.AddBackbufferOutput(renderTargetData.finalAttachment); + } return frameGraph.Bake(); }