Integrate render target handling in frame graphs (#411)

* Graphics: Integrate RenderTarget in FrameGraph

- This handles the blit to texture/swapchain in the FrameGraph and fixes RenderTextureBlit
- Dummy attachments were added to the FrameGraph class to handle link without texture (used to setup a dependency between two passes with no texture)
- FramePass now supports custom access/layout/usage for inputs

* Graphics/RenderTarget: Allow to set any RenderTarget as output
This commit is contained in:
Jérôme Leclercq
2023-11-28 21:00:57 +01:00
committed by GitHub
parent f57fc3c1d5
commit 32d227628c
19 changed files with 490 additions and 340 deletions

View File

@@ -28,6 +28,7 @@
#include <NazaraUtils/MemoryPool.hpp>
#include <memory>
#include <optional>
#include <span>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -80,12 +81,14 @@ namespace Nz
ForwardFramePipeline& operator=(ForwardFramePipeline&&) = delete;
private:
struct ViewerData;
BakedFrameGraph BuildFrameGraph();
void RegisterMaterialInstance(MaterialInstance* materialPass);
void UnregisterMaterialInstance(MaterialInstance* material);
struct ViewerData;
static std::size_t BuildMergePass(FrameGraph& frameGraph, std::span<ViewerData*> targetViewers);
struct LightData
{
@@ -119,7 +122,6 @@ namespace Nz
struct RenderTargetData
{
std::size_t finalAttachment;
std::vector<const ViewerData*> viewers;
};

View File

@@ -15,6 +15,7 @@
#include <Nazara/Graphics/FramePassAttachment.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/RenderPass.hpp>
#include <limits>
#include <optional>
#include <string>
#include <unordered_map>
@@ -26,6 +27,8 @@ namespace Nz
{
class NAZARA_GRAPHICS_API FrameGraph
{
friend class BakedFrameGraph;
public:
FrameGraph() = default;
FrameGraph(const FrameGraph&) = delete;
@@ -38,6 +41,7 @@ namespace Nz
inline std::size_t AddAttachmentCube(FramePassAttachment attachment);
inline std::size_t AddAttachmentCubeFace(std::size_t attachmentId, CubemapFace face);
inline std::size_t AddAttachmentProxy(std::string name, std::size_t attachmentId);
inline std::size_t AddDummyAttachment();
inline FramePass& AddPass(std::string name);
inline void AddOutput(std::size_t attachmentIndex);
@@ -88,6 +92,10 @@ namespace Nz
TextureLayout layout;
};
struct DummyAttachment
{
};
struct PassBarriers
{
std::vector<Barrier> invalidationBarriers;
@@ -138,7 +146,10 @@ namespace Nz
void ReorderPasses();
void TraverseGraph(std::size_t passIndex);
using AttachmentType = std::variant<FramePassAttachment, AttachmentProxy, AttachmentArray, AttachmentCube, AttachmentLayer>;
using AttachmentType = std::variant<FramePassAttachment, AttachmentProxy, AttachmentArray, AttachmentCube, AttachmentLayer, DummyAttachment>;
static constexpr std::size_t InvalidAttachmentIndex = std::numeric_limits<std::size_t>::max();
static constexpr std::size_t InvalidTextureIndex = std::numeric_limits<std::size_t>::max();
std::vector<std::size_t> m_graphOutputs;
std::vector<FramePass> m_framePasses;

View File

@@ -78,6 +78,14 @@ namespace Nz
return id;
}
inline std::size_t FrameGraph::AddDummyAttachment()
{
std::size_t id = m_attachments.size();
m_attachments.emplace_back(DummyAttachment{});
return id;
}
inline FramePass& FrameGraph::AddPass(std::string name)
{
std::size_t id = m_framePasses.size();

View File

@@ -73,7 +73,9 @@ namespace Nz
inline void SetDepthStencilInput(std::size_t attachmentId);
inline void SetDepthStencilOutput(std::size_t attachmentId);
inline void SetExecutionCallback(ExecutionCallback callback);
inline void SetInputLayout(std::size_t inputIndex, TextureLayout layout);
inline void SetInputAccess(std::size_t inputIndex, TextureLayout layout, PipelineStageFlags stageFlags, MemoryAccessFlags accessFlags);
inline void SetInputAssumedLayout(std::size_t inputIndex, TextureLayout layout);
inline void SetInputUsage(std::size_t inputIndex, TextureUsageFlags usageFlags);
inline void SetReadInput(std::size_t inputIndex, bool doesRead);
FramePass& operator=(const FramePass&) = delete;
@@ -90,7 +92,11 @@ namespace Nz
struct Input
{
std::optional<TextureLayout> assumedLayout;
std::optional<TextureUsageFlags> textureUsageFlags;
std::size_t attachmentId;
MemoryAccessFlags accessFlags = MemoryAccess::ShaderRead;
PipelineStageFlags stageFlags = PipelineStage::FragmentShader;
TextureLayout layout = TextureLayout::ColorInput;
bool doesRead = true;
};

View File

@@ -127,12 +127,26 @@ namespace Nz
m_executionCallback = std::move(callback);
}
inline void FramePass::SetInputLayout(std::size_t inputIndex, TextureLayout layout)
inline void FramePass::SetInputAccess(std::size_t inputIndex, TextureLayout layout, PipelineStageFlags stageFlags, MemoryAccessFlags accessFlags)
{
assert(inputIndex < m_inputs.size());
m_inputs[inputIndex].accessFlags = accessFlags;
m_inputs[inputIndex].layout = layout;
m_inputs[inputIndex].stageFlags = stageFlags;
}
inline void FramePass::SetInputAssumedLayout(std::size_t inputIndex, TextureLayout layout)
{
assert(inputIndex < m_inputs.size());
m_inputs[inputIndex].assumedLayout = layout;
}
inline void FramePass::SetInputUsage(std::size_t inputIndex, TextureUsageFlags usageFlags)
{
assert(inputIndex < m_inputs.size());
m_inputs[inputIndex].textureUsageFlags = usageFlags;
}
inline void FramePass::SetReadInput(std::size_t inputIndex, bool doesRead)
{
assert(inputIndex < m_inputs.size());

View File

@@ -19,22 +19,33 @@ namespace Nz
class Framebuffer;
class FrameGraph;
class RenderPass;
class Texture;
class RenderResources;
class Texture;
class NAZARA_GRAPHICS_API RenderTarget
{
public:
RenderTarget() = default;
inline RenderTarget(Int32 renderOrder = 0);
virtual ~RenderTarget();
virtual void OnBuildGraph(FrameGraph& frameGraph, std::size_t attachmentIndex) const = 0;
virtual void OnRenderEnd(RenderResources& resources, const BakedFrameGraph& frameGraph, std::size_t finalAttachment) const = 0;
inline Int32 GetRenderOrder() const;
virtual const Vector2ui& GetSize() const = 0;
inline bool IsFrameGraphOutput() const;
virtual std::size_t OnBuildGraph(FrameGraph& frameGraph, std::size_t attachmentIndex) const = 0;
inline void SetFrameGraphOutput(bool output = true);
inline void UpdateRenderOrder(Int32 renderOrder);
NazaraSignal(OnRenderTargetRelease, const RenderTarget* /*renderTarget*/);
NazaraSignal(OnRenderTargetRenderOrderChange, const RenderTarget* /*renderTarget*/, Int32 /*newOrder*/);
NazaraSignal(OnRenderTargetSizeChange, const RenderTarget* /*renderTarget*/, const Vector2ui& /*newSize*/);
private:
Int32 m_renderOrder;
bool m_frameGraphOutput;
};
}

View File

@@ -6,6 +6,32 @@
namespace Nz
{
inline RenderTarget::RenderTarget(Int32 renderOrder) :
m_renderOrder(renderOrder),
m_frameGraphOutput(false)
{
}
inline Int32 RenderTarget::GetRenderOrder() const
{
return m_renderOrder;
}
inline bool RenderTarget::IsFrameGraphOutput() const
{
return m_frameGraphOutput;
}
inline void RenderTarget::SetFrameGraphOutput(bool output)
{
m_frameGraphOutput = output;
}
inline void RenderTarget::UpdateRenderOrder(Int32 renderOrder)
{
OnRenderTargetRenderOrderChange(this, renderOrder);
m_renderOrder = renderOrder;
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -24,8 +24,7 @@ namespace Nz
RenderTexture(RenderTexture&&) = delete;
~RenderTexture() = default;
void OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const override;
void OnRenderEnd(RenderResources& resources, const BakedFrameGraph& frameGraph, std::size_t finalAttachment) const override;
std::size_t OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const override;
const Vector2ui& GetSize() const override;

View File

@@ -26,8 +26,7 @@ namespace Nz
RenderTextureBlit(RenderTextureBlit&&) = delete;
~RenderTextureBlit() = default;
void OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const override;
void OnRenderEnd(RenderResources& resources, const BakedFrameGraph& frameGraph, std::size_t finalAttachment) const override;
std::size_t OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const override;
const Vector2ui& GetSize() const override;

View File

@@ -25,14 +25,15 @@ namespace Nz
RenderWindow(RenderWindow&&) = delete;
~RenderWindow() = default;
void OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const override;
void OnRenderEnd(RenderResources& renderResources, const BakedFrameGraph& frameGraph, std::size_t attachmentId) const override;
std::size_t OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const override;
const Vector2ui& GetSize() const override;
RenderWindow& operator=(const RenderWindow&) = delete;
RenderWindow& operator=(RenderWindow&&) = delete;
static constexpr Int32 DefaultRenderOrder = 1000;
private:
void SetSwapchain(Swapchain* swapchain);

View File

@@ -7,6 +7,7 @@
namespace Nz
{
inline RenderWindow::RenderWindow(Swapchain& swapchain) :
RenderTarget(DefaultRenderOrder),
m_swapchain(&swapchain),
m_windowSwapchain(nullptr)
{