Graphics: Add support for multi-viewer rendering (a bit hacky)
This commit is contained in:
@@ -136,8 +136,6 @@ namespace Nz
|
||||
// Update UBOs and materials
|
||||
UploadPool& uploadPool = renderFrame.GetUploadPool();
|
||||
|
||||
bool prepare = false;
|
||||
|
||||
renderFrame.Execute([&](CommandBufferBuilder& builder)
|
||||
{
|
||||
builder.BeginDebugRegion("UBO Update", Color::Yellow);
|
||||
@@ -336,6 +334,7 @@ namespace Nz
|
||||
m_bakedFrameGraph.Execute(renderFrame);
|
||||
m_rebuildFrameGraph = false;
|
||||
|
||||
m_viewerPerTarget.clear();
|
||||
const Vector2ui& frameSize = renderFrame.GetSize();
|
||||
for (auto&& [viewer, viewerData] : m_viewers)
|
||||
{
|
||||
@@ -344,13 +343,25 @@ namespace Nz
|
||||
viewerData.prepare = false;
|
||||
|
||||
const RenderTarget& renderTarget = viewer->GetRenderTarget();
|
||||
|
||||
m_viewerPerTarget[&renderTarget].push_back(&viewerData);
|
||||
}
|
||||
|
||||
for (auto&& [renderTargetPtr, viewerDataVec] : m_viewerPerTarget)
|
||||
{
|
||||
Recti renderRegion(0, 0, frameSize.x, frameSize.y);
|
||||
const ShaderBindingPtr& blitShaderBinding = viewerData.blitShaderBinding;
|
||||
const std::shared_ptr<Texture>& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(viewerData.colorAttachment);
|
||||
|
||||
const RenderTarget& renderTarget = *renderTargetPtr;
|
||||
const auto& viewers = viewerDataVec;
|
||||
|
||||
renderFrame.Execute([&](CommandBufferBuilder& builder)
|
||||
{
|
||||
builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::FragmentShader, MemoryAccess::ColorWrite, MemoryAccess::ShaderRead, TextureLayout::ColorOutput, TextureLayout::ColorInput, *sourceTexture);
|
||||
for (const ViewerData* viewerData : viewers)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
std::array<CommandBufferBuilder::ClearValues, 2> clearValues;
|
||||
clearValues[0].color = Color::Black;
|
||||
@@ -363,12 +374,16 @@ namespace Nz
|
||||
{
|
||||
builder.SetScissor(renderRegion);
|
||||
builder.SetViewport(renderRegion);
|
||||
|
||||
builder.BindPipeline(*graphics->GetBlitPipeline());
|
||||
builder.BindVertexBuffer(0, *graphics->GetFullscreenVertexBuffer());
|
||||
builder.BindShaderBinding(0, *blitShaderBinding);
|
||||
|
||||
builder.Draw(3);
|
||||
for (const ViewerData* viewerData : viewers)
|
||||
{
|
||||
const ShaderBindingPtr& blitShaderBinding = viewerData->blitShaderBinding;
|
||||
|
||||
builder.BindShaderBinding(0, *blitShaderBinding);
|
||||
builder.Draw(3);
|
||||
}
|
||||
}
|
||||
builder.EndDebugRegion();
|
||||
}
|
||||
@@ -503,9 +518,8 @@ namespace Nz
|
||||
});
|
||||
}
|
||||
|
||||
//FIXME: This doesn't handle multiple window viewers
|
||||
for (auto&& [viewer, viewerData] : m_viewers)
|
||||
frameGraph.SetBackbufferOutput(viewerData.colorAttachment);
|
||||
frameGraph.AddBackbufferOutput(viewerData.colorAttachment);
|
||||
|
||||
return frameGraph.Bake();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Nz
|
||||
|
||||
BakedFrameGraph FrameGraph::Bake()
|
||||
{
|
||||
if (!m_backbufferOutput.has_value())
|
||||
if (m_backbufferOutputs.empty())
|
||||
throw std::runtime_error("no backbuffer output has been set");
|
||||
|
||||
m_pending.attachmentReadList.clear();
|
||||
@@ -46,17 +46,18 @@ namespace Nz
|
||||
m_pending.renderPasses.clear();
|
||||
m_pending.textures.clear();
|
||||
|
||||
m_pending.backbufferResourceIndex = m_backbufferOutput.value();
|
||||
|
||||
BuildReadWriteList();
|
||||
|
||||
auto it = m_pending.attachmentWriteList.find(m_pending.backbufferResourceIndex);
|
||||
if (it == m_pending.attachmentWriteList.end())
|
||||
throw std::runtime_error("no pass writes to backbuffer");
|
||||
for (std::size_t output : m_backbufferOutputs)
|
||||
{
|
||||
auto it = m_pending.attachmentWriteList.find(output);
|
||||
if (it == m_pending.attachmentWriteList.end())
|
||||
throw std::runtime_error("no pass writes to backbuffer");
|
||||
|
||||
const std::vector<std::size_t>& backbufferPasses = it->second;
|
||||
for (std::size_t passIndex : backbufferPasses)
|
||||
TraverseGraph(passIndex);
|
||||
const std::vector<std::size_t>& backbufferPasses = it->second;
|
||||
for (std::size_t passIndex : backbufferPasses)
|
||||
TraverseGraph(passIndex);
|
||||
}
|
||||
|
||||
std::reverse(m_pending.passList.begin(), m_pending.passList.end());
|
||||
|
||||
@@ -88,8 +89,22 @@ namespace Nz
|
||||
bakedSubpass.commandCallback = framePass.GetCommandCallback();
|
||||
|
||||
for (const auto& output : framePass.GetOutputs())
|
||||
{
|
||||
bakedPass.outputTextureIndices.push_back(Retrieve(m_pending.attachmentToTextures, output.attachmentId));
|
||||
|
||||
auto& clearValues = bakedPass.outputClearValues.emplace_back();
|
||||
if (output.clearColor)
|
||||
clearValues.color = *output.clearColor;
|
||||
}
|
||||
|
||||
// Add depth-stencil clear values
|
||||
auto& dsClearValues = bakedPass.outputClearValues.emplace_back();
|
||||
if (const auto& depthStencilClear = framePass.GetDepthStencilClear())
|
||||
{
|
||||
dsClearValues.depth = depthStencilClear->depth;
|
||||
dsClearValues.stencil = depthStencilClear->stencil;
|
||||
}
|
||||
|
||||
std::size_t attachmentId;
|
||||
if (attachmentId = framePass.GetDepthStencilOutput(); attachmentId != FramePass::InvalidAttachmentId)
|
||||
bakedPass.outputTextureIndices.push_back(Retrieve(m_pending.attachmentToTextures, attachmentId));
|
||||
@@ -228,12 +243,14 @@ namespace Nz
|
||||
}
|
||||
|
||||
// Add TextureUsage::Sampled to backbuffer output
|
||||
for (std::size_t output : m_backbufferOutputs)
|
||||
{
|
||||
auto it = m_pending.attachmentToTextures.find(output);
|
||||
assert(it != m_pending.attachmentToTextures.end());
|
||||
|
||||
auto it = m_pending.attachmentToTextures.find(m_pending.backbufferResourceIndex);
|
||||
assert(it != m_pending.attachmentToTextures.end());
|
||||
|
||||
auto& backbufferTexture = m_pending.textures[it->second];
|
||||
backbufferTexture.usage |= TextureUsage::ShaderSampling;
|
||||
auto& backbufferTexture = m_pending.textures[it->second];
|
||||
backbufferTexture.usage |= TextureUsage::ShaderSampling;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameGraph::BuildBarriers()
|
||||
|
||||
@@ -163,6 +163,16 @@ namespace Nz
|
||||
throw std::runtime_error("failed to instantiate blit shader");
|
||||
|
||||
RenderPipelineInfo pipelineInfo;
|
||||
|
||||
// Alpha blending
|
||||
pipelineInfo.blending = true;
|
||||
pipelineInfo.blend.modeColor = BlendEquation::Add;
|
||||
pipelineInfo.blend.modeAlpha = BlendEquation::Add;
|
||||
pipelineInfo.blend.srcColor = BlendFunc::One;
|
||||
pipelineInfo.blend.dstColor = BlendFunc::One;
|
||||
pipelineInfo.blend.srcAlpha = BlendFunc::One;
|
||||
pipelineInfo.blend.dstAlpha = BlendFunc::One;
|
||||
|
||||
pipelineInfo.pipelineLayout = m_blitPipelineLayout;
|
||||
pipelineInfo.shaderModules.push_back(std::move(blitShader));
|
||||
pipelineInfo.vertexBuffers.assign({
|
||||
|
||||
Reference in New Issue
Block a user