Graphics/ForwardFramePipeline: Use RenderGraph to merge viewers views
This commit is contained in:
parent
5aefef2517
commit
11d4ba22da
|
|
@ -57,6 +57,8 @@ namespace Nz
|
||||||
template<typename F> void ProcessRenderQueue(const RenderQueue<RenderElement*>& renderQueue, F&& callback);
|
template<typename F> void ProcessRenderQueue(const RenderQueue<RenderElement*>& renderQueue, F&& callback);
|
||||||
void UnregisterMaterialPass(MaterialPass* material);
|
void UnregisterMaterialPass(MaterialPass* material);
|
||||||
|
|
||||||
|
struct ViewerData;
|
||||||
|
|
||||||
struct MaterialData
|
struct MaterialData
|
||||||
{
|
{
|
||||||
std::size_t usedCount = 0;
|
std::size_t usedCount = 0;
|
||||||
|
|
@ -72,6 +74,13 @@ namespace Nz
|
||||||
NazaraSlot(InstancedRenderable, OnMaterialInvalidated, onMaterialInvalidated);
|
NazaraSlot(InstancedRenderable, OnMaterialInvalidated, onMaterialInvalidated);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RenderTargetData
|
||||||
|
{
|
||||||
|
std::size_t finalAttachment;
|
||||||
|
std::vector<const ViewerData*> viewers;
|
||||||
|
ShaderBindingPtr blitShaderBinding;
|
||||||
|
};
|
||||||
|
|
||||||
struct VisibleRenderable
|
struct VisibleRenderable
|
||||||
{
|
{
|
||||||
const InstancedRenderable* instancedRenderable;
|
const InstancedRenderable* instancedRenderable;
|
||||||
|
|
@ -102,7 +111,7 @@ namespace Nz
|
||||||
std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
|
std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
|
||||||
std::unordered_map<MaterialPass*, MaterialData> m_materials;
|
std::unordered_map<MaterialPass*, MaterialData> m_materials;
|
||||||
std::unordered_map<WorldInstancePtr, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables;
|
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<AbstractViewer*> m_invalidatedViewerInstances;
|
||||||
std::unordered_set<MaterialPass*> m_invalidatedMaterials;
|
std::unordered_set<MaterialPass*> m_invalidatedMaterials;
|
||||||
std::unordered_set<WorldInstance*> m_invalidatedWorldInstances;
|
std::unordered_set<WorldInstance*> m_invalidatedWorldInstances;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Graphics/ForwardFramePipeline.hpp>
|
#include <Nazara/Graphics/ForwardFramePipeline.hpp>
|
||||||
|
#include <Nazara/Core/StackArray.hpp>
|
||||||
#include <Nazara/Graphics/AbstractViewer.hpp>
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
#include <Nazara/Graphics/FrameGraph.hpp>
|
#include <Nazara/Graphics/FrameGraph.hpp>
|
||||||
#include <Nazara/Graphics/Graphics.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_bakedFrameGraph.Execute(renderFrame);
|
||||||
m_rebuildFrameGraph = false;
|
m_rebuildFrameGraph = false;
|
||||||
|
|
||||||
m_viewerPerTarget.clear();
|
|
||||||
const Vector2ui& frameSize = renderFrame.GetSize();
|
|
||||||
for (auto&& [viewer, viewerData] : m_viewers)
|
for (auto&& [viewer, viewerData] : m_viewers)
|
||||||
{
|
{
|
||||||
viewerData.rebuildForwardPass = false;
|
viewerData.rebuildForwardPass = false;
|
||||||
viewerData.rebuildDepthPrepass = false;
|
viewerData.rebuildDepthPrepass = false;
|
||||||
viewerData.prepare = 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);
|
Recti renderRegion(0, 0, frameSize.x, frameSize.y);
|
||||||
|
|
||||||
const RenderTarget& renderTarget = *renderTargetPtr;
|
const RenderTarget& renderTarget = *renderTargetPtr;
|
||||||
auto& viewers = viewerDataVec;
|
const auto& data = renderTargetData;
|
||||||
|
|
||||||
std::sort(viewers.begin(), viewers.end(), [](const ViewerData* lhs, const ViewerData* rhs)
|
|
||||||
{
|
|
||||||
return lhs->renderOrder < rhs->renderOrder;
|
|
||||||
});
|
|
||||||
|
|
||||||
renderFrame.Execute([&](CommandBufferBuilder& builder)
|
renderFrame.Execute([&](CommandBufferBuilder& builder)
|
||||||
{
|
{
|
||||||
for (const ViewerData* viewerData : viewers)
|
const std::shared_ptr<Texture>& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(data.finalAttachment);
|
||||||
{
|
|
||||||
const std::shared_ptr<Texture>& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(viewerData->colorAttachment);
|
|
||||||
|
|
||||||
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;
|
std::array<CommandBufferBuilder::ClearValues, 2> clearValues;
|
||||||
clearValues[0].color = Color::Black;
|
clearValues[0].color = Color::Black;
|
||||||
|
|
@ -404,21 +408,8 @@ namespace Nz
|
||||||
builder.BindPipeline(*graphics->GetBlitPipeline(false));
|
builder.BindPipeline(*graphics->GetBlitPipeline(false));
|
||||||
builder.BindVertexBuffer(0, *graphics->GetFullscreenVertexBuffer());
|
builder.BindVertexBuffer(0, *graphics->GetFullscreenVertexBuffer());
|
||||||
|
|
||||||
bool first = true;
|
builder.BindShaderBinding(0, *data.blitShaderBinding);
|
||||||
|
builder.Draw(3);
|
||||||
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.EndDebugRegion();
|
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)
|
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();
|
return frameGraph.Bake();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue