Factor camera frame render-graph stage build state

This commit is contained in:
2026-04-14 22:28:13 +08:00
parent a67f8597ba
commit 3ea8ce81d6

View File

@@ -839,6 +839,353 @@ bool RecordFullscreenPassSequenceStage(
return true;
}
struct CameraFrameStageGraphBuildState {
CameraFrameStage stage = CameraFrameStage::MainScene;
Containers::String stageName = {};
RenderPassSequence* stageSequence = nullptr;
RenderSurface surfaceTemplate = {};
bool hasSourceSurface = false;
RenderSurface sourceSurfaceTemplate = {};
RHI::RHIResourceView* sourceColorView = nullptr;
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
RenderGraphImportedSurface sourceSurface = {};
RenderGraphImportedSurface outputSurface = {};
RenderGraphTextureHandle outputColor = {};
};
RenderPassContext BuildCameraFrameStageGraphPassContext(
const CameraFramePlan& plan,
const CameraFrameStageGraphBuildState& stageState,
const RenderSceneData& sceneData) {
return {
plan.request.context,
stageState.surfaceTemplate,
sceneData,
stageState.hasSourceSurface
? &stageState.sourceSurfaceTemplate
: nullptr,
stageState.sourceColorView,
stageState.sourceColorState
};
}
CameraFrameStageGraphBuildState BuildCameraFrameStageGraphBuildState(
CameraFrameStage stage,
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
const RenderSceneData& sceneData,
RenderGraphBuilder& graphBuilder,
RenderGraphImportedTextureRegistry& importedTextures) {
CameraFrameStageGraphBuildState stageState = {};
stageState.stage = stage;
stageState.stageName = Containers::String(GetCameraFrameStageName(stage));
stageState.stageSequence = plan.GetPassSequence(stage);
const RenderPassContext stagePassContext =
BuildFrameStagePassContext(stage, plan, shadowState, sceneData);
stageState.surfaceTemplate = stagePassContext.surface;
stageState.hasSourceSurface = stagePassContext.sourceSurface != nullptr;
if (stageState.hasSourceSurface) {
stageState.sourceSurfaceTemplate = *stagePassContext.sourceSurface;
}
stageState.sourceColorView = stagePassContext.sourceColorView;
stageState.sourceColorState = stagePassContext.sourceColorState;
stageState.sourceSurface =
ImportRenderGraphSurface(
graphBuilder,
importedTextures,
stageState.stageName + ".Source",
stagePassContext.sourceSurface,
RenderGraphSurfaceImportUsage::Source,
IsCameraFrameFullscreenSequenceStage(stage));
stageState.outputSurface =
ImportRenderGraphSurface(
graphBuilder,
importedTextures,
stageState.stageName + ".Output",
&stagePassContext.surface,
RenderGraphSurfaceImportUsage::Output,
DoesCameraFrameStageGraphOwnColorTransitions(stage),
DoesCameraFrameStageGraphOwnDepthTransitions(stage));
stageState.outputColor =
ResolveStageOutputColorHandle(
stage,
plan,
stageState.stageName,
stagePassContext,
stageState.outputSurface,
graphBuilder);
return stageState;
}
void PublishCameraFrameStageGraphBuildState(
const CameraFrameStageGraphBuildState& stageState,
const DirectionalShadowExecutionState& shadowState,
CameraFrameRenderGraphResources& frameResources) {
if (stageState.stage == CameraFrameStage::ShadowCaster &&
shadowState.HasShadowSampling() &&
stageState.outputSurface.depthTexture.IsValid()) {
frameResources.mainDirectionalShadow = stageState.outputSurface.depthTexture;
}
WriteCameraFrameRenderGraphStageSurfaceResources(
frameResources,
stageState.stage,
stageState.outputColor,
stageState.outputSurface.depthTexture);
}
bool TryRecordCameraFrameStageSequence(
const CameraFrameStageGraphBuildState& stageState,
const CameraFramePlan& plan,
const RenderSceneData& sceneData,
CameraFrameExecutionState& executionState,
RenderGraphBuilder& graphBuilder,
RenderGraphBlackboard& blackboard,
bool& stageExecutionSucceeded,
bool& handled) {
if (stageState.stageSequence == nullptr) {
handled = false;
return true;
}
handled = true;
const RenderPassContext stagePassContext =
BuildCameraFrameStageGraphPassContext(plan, stageState, sceneData);
const bool recordResult =
IsCameraFrameFullscreenSequenceStage(stageState.stage)
? RecordFullscreenPassSequenceStage(
stageState.stage,
stageState.stageName,
stagePassContext,
ResolveCameraFrameFullscreenStageGraphSourceBinding(
plan,
stageState.stage,
stageState.surfaceTemplate,
stagePassContext.sourceSurface,
stagePassContext.sourceColorView,
stagePassContext.sourceColorState,
GetPrimaryColorTexture(stageState.sourceSurface),
&blackboard),
stageState.outputColor,
sceneData,
stageState.stageSequence,
executionState,
graphBuilder,
blackboard,
stageExecutionSucceeded)
: RecordRegularPassSequenceStage(
stageState.stage,
stageState.stageName,
stagePassContext,
stageState.outputSurface,
sceneData,
stageState.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 ") +
stageState.stageName);
return false;
}
return true;
}
bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
const CameraFrameStageGraphBuildState& stageState,
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
const RenderSceneData& sceneData,
CameraFrameExecutionState& executionState,
RenderGraphBuilder& graphBuilder,
RenderGraphBlackboard& blackboard,
bool& stageExecutionSucceeded,
bool& handled) {
RenderPass* const standaloneStagePass =
ResolveStandaloneStagePass(stageState.stage, executionState);
if (standaloneStagePass == nullptr ||
!standaloneStagePass->SupportsRenderGraph()) {
handled = false;
return true;
}
handled = true;
const RenderSceneData stageSceneData =
BuildStandaloneStageSceneData(
stageState.stage,
plan,
shadowState,
sceneData,
stageState.surfaceTemplate);
const RenderPassGraphBeginCallback beginStandalonePass =
[&, standaloneStagePass](const RenderPassContext&) -> bool {
if (!InitializeStandalonePass(
standaloneStagePass,
plan.request.context)) {
stageExecutionSucceeded = false;
return false;
}
return true;
};
const RenderPassRenderGraphContext standalonePassContext = {
graphBuilder,
stageState.stageName,
plan.request.context,
stageSceneData,
stageState.surfaceTemplate,
stageState.hasSourceSurface
? &stageState.sourceSurfaceTemplate
: nullptr,
stageState.sourceColorView,
stageState.sourceColorState,
GetPrimaryColorTexture(stageState.sourceSurface),
std::vector<RenderGraphTextureHandle>{ stageState.outputColor },
stageState.outputSurface.depthTexture,
&stageExecutionSucceeded,
beginStandalonePass,
{},
&blackboard
};
if (!standaloneStagePass->RecordRenderGraph(standalonePassContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") +
stageState.stageName);
return false;
}
return true;
}
bool TryRecordCameraFrameMainSceneGraphPass(
const CameraFrameStageGraphBuildState& stageState,
const CameraFramePlan& plan,
const RenderSceneData& sceneData,
CameraFrameExecutionState& executionState,
RenderGraphBuilder& graphBuilder,
RenderGraphBlackboard& blackboard,
bool& stageExecutionSucceeded,
bool& handled) {
if (stageState.stage != CameraFrameStage::MainScene ||
executionState.pipeline == nullptr ||
!executionState.pipeline->SupportsMainSceneRenderGraph()) {
handled = false;
return true;
}
handled = true;
const RenderPipelineMainSceneRenderGraphContext mainSceneContext = {
graphBuilder,
stageState.stageName,
plan.request.context,
sceneData,
stageState.surfaceTemplate,
stageState.hasSourceSurface
? &stageState.sourceSurfaceTemplate
: nullptr,
stageState.sourceColorView,
stageState.sourceColorState,
std::vector<RenderGraphTextureHandle>{ stageState.outputColor },
stageState.outputSurface.depthTexture,
&stageExecutionSucceeded,
&blackboard
};
if (!executionState.pipeline->RecordMainSceneRenderGraph(mainSceneContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"CameraRenderer::Render failed: RenderPipeline::RecordMainSceneRenderGraph returned false");
return false;
}
return true;
}
void AddCameraFrameStageFallbackRasterPass(
const CameraFrameStageGraphBuildState& stageState,
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
const RenderSceneData& sceneData,
CameraFrameExecutionState& executionState,
RenderGraphBuilder& graphBuilder,
bool& stageExecutionSucceeded) {
const CameraFrameStageGraphBuildState capturedStageState = stageState;
graphBuilder.AddRasterPass(
capturedStageState.stageName,
[&, capturedStageState](RenderGraphPassBuilder& passBuilder) {
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage)) {
ReadRenderGraphColorSurface(passBuilder, capturedStageState.sourceSurface);
WriteRenderGraphColorSurface(passBuilder, capturedStageState.outputSurface);
} else {
ReadRenderGraphSurface(passBuilder, capturedStageState.sourceSurface);
WriteRenderGraphSurface(passBuilder, capturedStageState.outputSurface);
}
passBuilder.SetExecuteCallback(
[&, capturedStageState](
const RenderGraphExecutionContext& executionContext) {
if (!stageExecutionSucceeded) {
return;
}
const RenderSurface* resolvedSourceSurface =
capturedStageState.hasSourceSurface
? &capturedStageState.sourceSurfaceTemplate
: nullptr;
RHI::RHIResourceView* resolvedSourceColorView =
capturedStageState.sourceColorView;
RHI::ResourceStates resolvedSourceColorState =
capturedStageState.sourceColorState;
RenderSurface graphManagedSourceSurface = {};
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage) &&
capturedStageState.hasSourceSurface &&
CanUseGraphManagedImportedSurface(
capturedStageState.sourceSurface,
executionContext)) {
graphManagedSourceSurface =
BuildGraphManagedImportedSurface(
capturedStageState.sourceSurfaceTemplate,
RHI::ResourceStates::PixelShaderResource,
RHI::ResourceStates::PixelShaderResource);
resolvedSourceSurface = &graphManagedSourceSurface;
resolvedSourceColorState = RHI::ResourceStates::PixelShaderResource;
}
const RenderSurface* resolvedOutputSurface =
&capturedStageState.surfaceTemplate;
RenderSurface graphManagedOutputSurface = {};
if (CanUseGraphManagedImportedSurface(
capturedStageState.outputSurface,
executionContext)) {
graphManagedOutputSurface =
BuildGraphManagedPassSurface(
capturedStageState.surfaceTemplate);
resolvedOutputSurface = &graphManagedOutputSurface;
}
const RenderPassContext passContextOverride = {
plan.request.context,
*resolvedOutputSurface,
sceneData,
resolvedSourceSurface,
resolvedSourceColorView,
resolvedSourceColorState
};
stageExecutionSucceeded = ExecuteRecordedFrameStage(
capturedStageState.stage,
plan,
shadowState,
sceneData,
executionState,
passContextOverride);
});
});
}
bool ExecuteRenderGraphPlan(
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
@@ -858,239 +1205,74 @@ bool ExecuteRenderGraphPlan(
continue;
}
const CameraFrameStage stage = stageInfo.stage;
const Containers::String stageName(GetCameraFrameStageName(stageInfo.stage));
RenderPassSequence* const stageSequence = plan.GetPassSequence(stage);
const RenderPassContext stagePassContext =
BuildFrameStagePassContext(stage, plan, shadowState, sceneData);
const RenderGraphImportedSurface sourceSurface =
ImportRenderGraphSurface(
graphBuilder,
importedTextures,
stageName + ".Source",
stagePassContext.sourceSurface,
RenderGraphSurfaceImportUsage::Source,
IsCameraFrameFullscreenSequenceStage(stage));
const RenderGraphImportedSurface outputSurface =
ImportRenderGraphSurface(
graphBuilder,
importedTextures,
stageName + ".Output",
&stagePassContext.surface,
RenderGraphSurfaceImportUsage::Output,
DoesCameraFrameStageGraphOwnColorTransitions(stage),
DoesCameraFrameStageGraphOwnDepthTransitions(stage));
const RenderGraphTextureHandle stageOutputColor =
ResolveStageOutputColorHandle(
stage,
const CameraFrameStageGraphBuildState stageState =
BuildCameraFrameStageGraphBuildState(
stageInfo.stage,
plan,
stageName,
stagePassContext,
outputSurface,
graphBuilder);
if (stage == CameraFrameStage::ShadowCaster &&
shadowState.HasShadowSampling() &&
outputSurface.depthTexture.IsValid()) {
frameResources.mainDirectionalShadow = outputSurface.depthTexture;
}
WriteCameraFrameRenderGraphStageSurfaceResources(
frameResources,
stage,
stageOutputColor,
outputSurface.depthTexture);
const RenderSurface stageSurfaceTemplate = stagePassContext.surface;
const bool hasStageSourceSurface = stagePassContext.sourceSurface != nullptr;
const RenderSurface stageSourceSurfaceTemplate =
hasStageSourceSurface
? *stagePassContext.sourceSurface
: RenderSurface();
const RHI::RHIResourceView* const stageSourceColorView = stagePassContext.sourceColorView;
const RHI::ResourceStates stageSourceColorState = stagePassContext.sourceColorState;
if (stageSequence != nullptr) {
const bool recordResult =
IsCameraFrameFullscreenSequenceStage(stage)
? RecordFullscreenPassSequenceStage(
stage,
stageName,
stagePassContext,
ResolveCameraFrameFullscreenStageGraphSourceBinding(
plan,
stage,
stagePassContext.surface,
stagePassContext.sourceSurface,
stagePassContext.sourceColorView,
stagePassContext.sourceColorState,
GetPrimaryColorTexture(sourceSurface),
&blackboard),
stageOutputColor,
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 &&
standaloneStagePass->SupportsRenderGraph()) {
const RenderSceneData stageSceneData =
BuildStandaloneStageSceneData(
stage,
plan,
shadowState,
sceneData,
stageSurfaceTemplate);
const RenderPassGraphBeginCallback beginStandalonePass =
[&, standaloneStagePass](const RenderPassContext&) -> bool {
if (!InitializeStandalonePass(
standaloneStagePass,
plan.request.context)) {
stageExecutionSucceeded = false;
return false;
}
return true;
};
const RenderPassRenderGraphContext standalonePassContext = {
graphBuilder,
stageName,
plan.request.context,
stageSceneData,
stageSurfaceTemplate,
hasStageSourceSurface ? &stageSourceSurfaceTemplate : nullptr,
const_cast<RHI::RHIResourceView*>(stageSourceColorView),
stageSourceColorState,
GetPrimaryColorTexture(sourceSurface),
std::vector<RenderGraphTextureHandle>{ stageOutputColor },
outputSurface.depthTexture,
&stageExecutionSucceeded,
beginStandalonePass,
{},
&blackboard
};
if (!standaloneStagePass->RecordRenderGraph(standalonePassContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
Containers::String("CameraRenderer::Render failed: RenderPass::RecordRenderGraph returned false for ") +
stageName);
return false;
}
continue;
}
if (stage == CameraFrameStage::MainScene &&
executionState.pipeline != nullptr &&
executionState.pipeline->SupportsMainSceneRenderGraph()) {
const RenderPipelineMainSceneRenderGraphContext mainSceneContext = {
graphBuilder,
stageName,
plan.request.context,
shadowState,
sceneData,
stageSurfaceTemplate,
hasStageSourceSurface ? &stageSourceSurfaceTemplate : nullptr,
const_cast<RHI::RHIResourceView*>(stageSourceColorView),
stageSourceColorState,
std::vector<RenderGraphTextureHandle>{ stageOutputColor },
outputSurface.depthTexture,
&stageExecutionSucceeded,
&blackboard
};
if (!executionState.pipeline->RecordMainSceneRenderGraph(mainSceneContext)) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,
"CameraRenderer::Render failed: RenderPipeline::RecordMainSceneRenderGraph returned false");
return false;
}
graphBuilder,
importedTextures);
PublishCameraFrameStageGraphBuildState(
stageState,
shadowState,
frameResources);
bool stageHandled = false;
if (!TryRecordCameraFrameStageSequence(
stageState,
plan,
sceneData,
executionState,
graphBuilder,
blackboard,
stageExecutionSucceeded,
stageHandled)) {
return false;
}
if (stageHandled) {
continue;
}
graphBuilder.AddRasterPass(
stageName,
[&, sourceSurface, outputSurface, stage, stageSurfaceTemplate, hasStageSourceSurface, stageSourceSurfaceTemplate, stageSourceColorView, stageSourceColorState](
RenderGraphPassBuilder& passBuilder) {
if (IsCameraFrameFullscreenSequenceStage(stage)) {
ReadRenderGraphColorSurface(passBuilder, sourceSurface);
WriteRenderGraphColorSurface(passBuilder, outputSurface);
} else {
ReadRenderGraphSurface(passBuilder, sourceSurface);
WriteRenderGraphSurface(passBuilder, outputSurface);
}
passBuilder.SetExecuteCallback(
[&, stage, sourceSurface, outputSurface, stageSurfaceTemplate, hasStageSourceSurface, stageSourceSurfaceTemplate, stageSourceColorView, stageSourceColorState](
const RenderGraphExecutionContext& executionContext) {
if (!stageExecutionSucceeded) {
return;
}
if (!TryRecordCameraFrameStageStandaloneRenderGraphPass(
stageState,
plan,
shadowState,
sceneData,
executionState,
graphBuilder,
blackboard,
stageExecutionSucceeded,
stageHandled)) {
return false;
}
if (stageHandled) {
continue;
}
const RenderSurface* resolvedSourceSurface =
hasStageSourceSurface
? &stageSourceSurfaceTemplate
: nullptr;
RHI::RHIResourceView* resolvedSourceColorView =
const_cast<RHI::RHIResourceView*>(stageSourceColorView);
RHI::ResourceStates resolvedSourceColorState = stageSourceColorState;
RenderSurface graphManagedSourceSurface = {};
if (IsCameraFrameFullscreenSequenceStage(stage) &&
hasStageSourceSurface &&
CanUseGraphManagedImportedSurface(sourceSurface, executionContext)) {
graphManagedSourceSurface =
BuildGraphManagedImportedSurface(
stageSourceSurfaceTemplate,
RHI::ResourceStates::PixelShaderResource,
RHI::ResourceStates::PixelShaderResource);
resolvedSourceSurface = &graphManagedSourceSurface;
resolvedSourceColorState = RHI::ResourceStates::PixelShaderResource;
}
if (!TryRecordCameraFrameMainSceneGraphPass(
stageState,
plan,
sceneData,
executionState,
graphBuilder,
blackboard,
stageExecutionSucceeded,
stageHandled)) {
return false;
}
if (stageHandled) {
continue;
}
const RenderSurface* resolvedOutputSurface = &stageSurfaceTemplate;
RenderSurface graphManagedOutputSurface = {};
if (CanUseGraphManagedImportedSurface(outputSurface, executionContext)) {
graphManagedOutputSurface =
BuildGraphManagedPassSurface(stageSurfaceTemplate);
resolvedOutputSurface = &graphManagedOutputSurface;
}
const RenderPassContext passContextOverride = {
plan.request.context,
*resolvedOutputSurface,
sceneData,
resolvedSourceSurface,
resolvedSourceColorView,
resolvedSourceColorState
};
stageExecutionSucceeded = ExecuteRecordedFrameStage(
stage,
plan,
shadowState,
sceneData,
executionState,
passContextOverride);
});
});
AddCameraFrameStageFallbackRasterPass(
stageState,
plan,
shadowState,
sceneData,
executionState,
graphBuilder,
stageExecutionSucceeded);
}
CompiledRenderGraph compiledGraph = {};