Graphics/ForwardFramePipeline: Use RenderGraph to merge viewers views

This commit is contained in:
Jérôme Leclercq 2021-12-03 22:17:24 +01:00
parent 5aefef2517
commit 11d4ba22da
2 changed files with 102 additions and 36 deletions

View File

@ -57,6 +57,8 @@ namespace Nz
template<typename F> void ProcessRenderQueue(const RenderQueue<RenderElement*>& 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<const ViewerData*> viewers;
ShaderBindingPtr blitShaderBinding;
};
struct VisibleRenderable
{
const InstancedRenderable* instancedRenderable;
@ -102,7 +111,7 @@ namespace Nz
std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
std::unordered_map<MaterialPass*, MaterialData> m_materials;
std::unordered_map<WorldInstancePtr, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables;
std::unordered_map<const RenderTarget*, std::vector<const ViewerData*>> m_viewerPerTarget;
std::unordered_map<const RenderTarget*, RenderTargetData> m_renderTargets;
std::unordered_set<AbstractViewer*> m_invalidatedViewerInstances;
std::unordered_set<MaterialPass*> m_invalidatedMaterials;
std::unordered_set<WorldInstance*> m_invalidatedWorldInstances;

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ForwardFramePipeline.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/FrameGraph.hpp>
#include <Nazara/Graphics/Graphics.hpp>
@ -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<Texture>& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(viewerData->colorAttachment);
const std::shared_ptr<Texture>& 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<CommandBufferBuilder::ClearValues, 2> 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<const RenderTarget*, const ViewerData*>;
StackArray<ViewerPair> 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();
}