Graph-ify camera pass sequences

This commit is contained in:
2026-04-14 18:56:04 +08:00
parent 4c79554050
commit e77dbe40b1
2 changed files with 360 additions and 151 deletions

View File

@@ -6,6 +6,7 @@
#include "Rendering/Graph/RenderGraph.h"
#include "Rendering/Graph/RenderGraphCompiler.h"
#include "Rendering/Graph/RenderGraphExecutor.h"
#include "Rendering/Internal/RenderPassGraphUtils.h"
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
#include "Rendering/Passes/BuiltinObjectIdPass.h"
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
@@ -492,6 +493,34 @@ RenderPass* ResolveStandaloneStagePass(
}
}
std::unique_ptr<ScopedInitializedPassSequence>* ResolveStageSequenceState(
CameraFrameStage stage,
CameraFrameExecutionState& executionState) {
switch (stage) {
case CameraFrameStage::PreScenePasses:
return &executionState.preScenePasses;
case CameraFrameStage::PostProcess:
return &executionState.postProcessPasses;
case CameraFrameStage::FinalOutput:
return &executionState.finalOutputPasses;
case CameraFrameStage::PostScenePasses:
return &executionState.postScenePasses;
case CameraFrameStage::OverlayPasses:
return &executionState.overlayPasses;
default:
return nullptr;
}
}
bool RecordSequencePass(
RenderPass& pass,
const RenderPassRenderGraphContext& context,
const Internal::RenderPassGraphIO& io) {
return pass.SupportsRenderGraph()
? pass.RecordRenderGraph(context)
: Internal::RecordRasterRenderPass(pass, context, io);
}
bool ExecutePassSequenceStage(
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence,
RenderPassSequence* sequence,
@@ -817,6 +846,187 @@ bool ExecuteFrameStage(
}
}
bool RecordRegularPassSequenceStage(
CameraFrameStage stage,
const Containers::String& stageName,
const RenderPassContext& stagePassContext,
const RenderGraphImportedSurface& outputSurface,
const RenderSceneData& sceneData,
RenderPassSequence* stageSequence,
CameraFrameExecutionState& executionState,
RenderGraphBuilder& graphBuilder,
RenderGraphBlackboard& blackboard,
bool& stageExecutionSucceeded) {
if (stageSequence == nullptr || stageSequence->GetPassCount() == 0u) {
return true;
}
std::unique_ptr<ScopedInitializedPassSequence>* const activeSequence =
ResolveStageSequenceState(stage, executionState);
RenderPassSequence* const sequence = stageSequence;
const RenderContext* const renderContext = &stagePassContext.renderContext;
const RenderPassGraphBeginCallback beginSequencePass =
[&, activeSequence, sequence, renderContext](const RenderPassContext&) -> bool {
if (activeSequence == nullptr ||
!EnsureInitializedPassSequence(
*activeSequence,
sequence,
*renderContext)) {
stageExecutionSucceeded = false;
return false;
}
return true;
};
const bool writesColor = GetPrimaryColorTexture(outputSurface).IsValid();
const bool writesDepth = outputSurface.depthTexture.IsValid();
for (size_t passIndex = 0u; passIndex < stageSequence->GetPassCount(); ++passIndex) {
RenderPass* const pass = stageSequence->GetPass(passIndex);
if (pass == nullptr) {
continue;
}
const Containers::String passName =
stageSequence->GetPassCount() == 1u
? stageName
: BuildRenderGraphSequencePassName(stageName, passIndex);
const RenderPassRenderGraphContext passContext = {
graphBuilder,
passName,
stagePassContext.renderContext,
sceneData,
stagePassContext.surface,
stagePassContext.sourceSurface,
stagePassContext.sourceColorView,
stagePassContext.sourceColorState,
{},
outputSurface.colorTextures,
outputSurface.depthTexture,
&stageExecutionSucceeded,
beginSequencePass,
{},
&blackboard
};
if (!RecordSequencePass(
*pass,
passContext,
{
false,
writesColor,
writesDepth
})) {
return false;
}
}
return true;
}
bool RecordFullscreenPassSequenceStage(
CameraFrameStage stage,
const Containers::String& stageName,
const RenderPassContext& stagePassContext,
const RenderGraphImportedSurface& sourceSurface,
const RenderGraphImportedSurface& outputSurface,
const RenderSceneData& sceneData,
RenderPassSequence* stageSequence,
CameraFrameExecutionState& executionState,
RenderGraphBuilder& graphBuilder,
RenderGraphBlackboard& blackboard,
bool& stageExecutionSucceeded) {
if (stageSequence == nullptr || stageSequence->GetPassCount() == 0u) {
return true;
}
std::unique_ptr<ScopedInitializedPassSequence>* const activeSequence =
ResolveStageSequenceState(stage, executionState);
RenderPassSequence* const sequence = stageSequence;
const RenderContext* const renderContext = &stagePassContext.renderContext;
const RenderPassGraphBeginCallback beginSequencePass =
[&, activeSequence, sequence, renderContext](const RenderPassContext&) -> bool {
if (activeSequence == nullptr ||
!EnsureInitializedPassSequence(
*activeSequence,
sequence,
*renderContext)) {
stageExecutionSucceeded = false;
return false;
}
return true;
};
RenderGraphTextureHandle currentSourceColor =
GetPrimaryColorTexture(sourceSurface);
const RenderGraphTextureHandle finalOutputColor =
GetPrimaryColorTexture(outputSurface);
const RenderGraphTextureDesc transientDesc =
BuildFullscreenTransientTextureDesc(stagePassContext.surface);
for (size_t passIndex = 0u; passIndex < stageSequence->GetPassCount(); ++passIndex) {
RenderPass* const pass = stageSequence->GetPass(passIndex);
if (pass == nullptr) {
continue;
}
const bool isLastPass = (passIndex + 1u) == stageSequence->GetPassCount();
const Containers::String passName =
stageSequence->GetPassCount() == 1u
? stageName
: BuildRenderGraphSequencePassName(stageName, passIndex);
const RenderGraphTextureHandle passOutputColor =
isLastPass
? finalOutputColor
: graphBuilder.CreateTransientTexture(
passName + ".Color",
transientDesc);
const RenderSurface* const sourceSurfaceTemplate =
passIndex == 0u
? stagePassContext.sourceSurface
: &stagePassContext.surface;
RHI::RHIResourceView* const sourceColorView =
passIndex == 0u
? stagePassContext.sourceColorView
: nullptr;
const RHI::ResourceStates sourceColorState =
passIndex == 0u
? stagePassContext.sourceColorState
: RHI::ResourceStates::PixelShaderResource;
const RenderPassRenderGraphContext passContext = {
graphBuilder,
passName,
stagePassContext.renderContext,
sceneData,
stagePassContext.surface,
sourceSurfaceTemplate,
sourceColorView,
sourceColorState,
currentSourceColor,
std::vector<RenderGraphTextureHandle>{ passOutputColor },
{},
&stageExecutionSucceeded,
beginSequencePass,
{},
&blackboard
};
if (!RecordSequencePass(
*pass,
passContext,
{
true,
true,
false
})) {
return false;
}
currentSourceColor = passOutputColor;
}
return true;
}
bool ExecuteRenderGraphPlan(
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
@@ -841,157 +1051,6 @@ bool ExecuteRenderGraphPlan(
const Containers::String stageName(GetCameraFrameStageName(stageInfo.stage));
RenderPassSequence* const stageSequence = plan.GetPassSequence(stage);
if (IsFullscreenSequenceStage(stage) &&
stageSequence != nullptr &&
stageSequence->GetPassCount() > 1u) {
const RenderPassContext stagePassContext =
BuildFrameStagePassContext(stage, plan, shadowState, sceneData);
const RenderGraphImportedSurface sourceSurface =
ImportRenderGraphSurface(
graphBuilder,
importedTextures,
stageName + ".Source",
stagePassContext.sourceSurface,
RenderGraphSurfaceImportUsage::Source,
true);
const RenderGraphImportedSurface outputSurface =
ImportRenderGraphSurface(
graphBuilder,
importedTextures,
stageName + ".Output",
&stagePassContext.surface,
RenderGraphSurfaceImportUsage::Output,
true);
RenderGraphTextureHandle currentSourceColor = GetPrimaryColorTexture(sourceSurface);
const RenderGraphTextureHandle finalOutputColor =
GetPrimaryColorTexture(outputSurface);
const RenderGraphTextureDesc transientDesc =
BuildFullscreenTransientTextureDesc(stagePassContext.surface);
for (size_t passIndex = 0; passIndex < stageSequence->GetPassCount(); ++passIndex) {
const bool isLastPass = (passIndex + 1u) == stageSequence->GetPassCount();
const size_t sequencePassIndex = passIndex;
const RenderGraphTextureHandle passSourceColor = currentSourceColor;
const RenderGraphTextureHandle passOutputColor =
isLastPass
? finalOutputColor
: graphBuilder.CreateTransientTexture(
BuildRenderGraphSequencePassName(stageName, sequencePassIndex) + ".Color",
transientDesc);
RenderPass* const sequencePass =
stageSequence->GetPass(sequencePassIndex);
const Containers::String sequencePassName =
BuildRenderGraphSequencePassName(stageName, sequencePassIndex);
const RenderSurface* const passSourceSurfaceTemplate =
sequencePassIndex == 0u
? stagePassContext.sourceSurface
: &stagePassContext.surface;
RHI::RHIResourceView* const passSourceColorView =
sequencePassIndex == 0u
? stagePassContext.sourceColorView
: nullptr;
const RHI::ResourceStates passSourceColorState =
sequencePassIndex == 0u
? stagePassContext.sourceColorState
: RHI::ResourceStates::PixelShaderResource;
if (sequencePass != nullptr &&
sequencePass->SupportsRenderGraph()) {
const RenderPassGraphBeginCallback beginSequencePass =
[&, stage](const RenderPassContext&) -> bool {
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence =
stage == CameraFrameStage::PostProcess
? executionState.postProcessPasses
: executionState.finalOutputPasses;
if (!EnsureInitializedPassSequence(
activeSequence,
plan.GetPassSequence(stage),
plan.request.context)) {
stageExecutionSucceeded = false;
return false;
}
return true;
};
const RenderPassRenderGraphContext sequencePassContext = {
graphBuilder,
sequencePassName,
plan.request.context,
sceneData,
stagePassContext.surface,
passSourceSurfaceTemplate,
passSourceColorView,
passSourceColorState,
passSourceColor,
std::vector<RenderGraphTextureHandle>{ passOutputColor },
{},
&stageExecutionSucceeded,
beginSequencePass,
{},
&blackboard
};
if (!sequencePass->RecordRenderGraph(sequencePassContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") +
sequencePassName);
return false;
}
currentSourceColor = passOutputColor;
continue;
}
graphBuilder.AddRasterPass(
sequencePassName,
[&, stage, sequencePassIndex, passSourceColor, passOutputColor](
RenderGraphPassBuilder& passBuilder) {
if (passSourceColor.IsValid()) {
passBuilder.ReadTexture(passSourceColor);
}
if (passOutputColor.IsValid()) {
passBuilder.WriteTexture(passOutputColor);
}
passBuilder.SetExecuteCallback(
[&, stage, sequencePassIndex, passSourceColor, passOutputColor](
const RenderGraphExecutionContext& executionContext) {
if (!stageExecutionSucceeded) {
return;
}
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence =
stage == CameraFrameStage::PostProcess
? executionState.postProcessPasses
: executionState.finalOutputPasses;
if (!EnsureInitializedPassSequence(
activeSequence,
plan.GetPassSequence(stage),
plan.request.context)) {
stageExecutionSucceeded = false;
return;
}
stageExecutionSucceeded =
ExecuteFullscreenPassSequencePass(
plan.GetPassSequence(stage),
sequencePassIndex,
BuildFrameStagePassContext(
stage,
plan,
shadowState,
sceneData),
executionContext,
passSourceColor,
passOutputColor);
});
});
currentSourceColor = passOutputColor;
}
continue;
}
const RenderPassContext stagePassContext =
BuildFrameStagePassContext(stage, plan, shadowState, sceneData);
const RenderGraphImportedSurface sourceSurface =
@@ -1033,6 +1092,43 @@ bool ExecuteRenderGraphPlan(
const RHI::RHIResourceView* const stageSourceColorView = stagePassContext.sourceColorView;
const RHI::ResourceStates stageSourceColorState = stagePassContext.sourceColorState;
if (stageSequence != nullptr) {
const bool recordResult =
IsFullscreenSequenceStage(stage)
? RecordFullscreenPassSequenceStage(
stage,
stageName,
stagePassContext,
sourceSurface,
outputSurface,
sceneData,
stageSequence,
executionState,
graphBuilder,
blackboard,
stageExecutionSucceeded)
: RecordRegularPassSequenceStage(
stage,
stageName,
stagePassContext,
outputSurface,
sceneData,
stageSequence,
executionState,
graphBuilder,
blackboard,
stageExecutionSucceeded);
if (!recordResult) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
Containers::String("CameraRenderer::Render failed: pass-sequence graph recording returned false for ") +
stageName);
return false;
}
continue;
}
RenderPass* const standaloneStagePass =
ResolveStandaloneStagePass(stage, executionState);
if (standaloneStagePass != nullptr &&