Extract camera frame render-graph stage pass runtime

This commit is contained in:
2026-04-15 00:13:35 +08:00
parent d92afa27da
commit 5edc4ed242
4 changed files with 241 additions and 192 deletions

View File

@@ -2,8 +2,8 @@
#include "Debug/Logger.h"
#include "Rendering/Execution/CameraFrameRenderGraphStagePolicy.h"
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphRecordingSession.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStagePassRuntime.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRecordContext.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageState.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphSurfaceUtils.h"
@@ -12,192 +12,15 @@
namespace XCEngine {
namespace Rendering {
namespace {
bool InitializeStandalonePass(
RenderPass* pass,
const RenderContext& context) {
if (pass == nullptr) {
return false;
}
if (pass->Initialize(context)) {
return true;
}
pass->Shutdown();
return false;
}
RenderSceneData BuildScenePassRequestSceneData(
const ScenePassRenderRequest& request,
const RenderSurface& requestSurface,
const RenderSceneData& baseSceneData) {
RenderSceneData sceneData = baseSceneData;
if (request.hasCameraDataOverride) {
sceneData.cameraData = request.cameraDataOverride;
}
sceneData.cameraData.viewportWidth = requestSurface.GetRenderAreaWidth();
sceneData.cameraData.viewportHeight = requestSurface.GetRenderAreaHeight();
sceneData.cameraData.clearFlags = request.clearFlags;
if (request.hasClearColorOverride) {
sceneData.cameraData.clearColor = request.clearColorOverride;
}
return sceneData;
}
bool ExecuteScenePassRequest(
RenderPass* pass,
const ScenePassRenderRequest& request,
const RenderContext& context,
const RenderSceneData& baseSceneData,
const RenderSurface* surfaceOverride = nullptr) {
if (!request.IsRequested()) {
return true;
}
if (!InitializeStandalonePass(pass, context)) {
return false;
}
const RenderSurface& requestSurface =
surfaceOverride != nullptr ? *surfaceOverride : request.surface;
const RenderSceneData sceneData =
BuildScenePassRequestSceneData(
request,
requestSurface,
baseSceneData);
const RenderPassContext passContext = {
context,
requestSurface,
sceneData,
nullptr,
nullptr,
RHI::ResourceStates::Common
};
return pass->Execute(passContext);
}
bool ExecuteStandalonePass(
RenderPass* pass,
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) {
if (pass == nullptr) {
return false;
}
if (!InitializeStandalonePass(pass, context)) {
return false;
}
const RenderPassContext passContext = {
context,
surface,
sceneData,
nullptr,
nullptr,
RHI::ResourceStates::Common
};
return pass->Execute(passContext);
}
RenderSceneData BuildStandaloneStageSceneData(
CameraFrameStage stage,
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
const RenderSceneData& baseSceneData,
const RenderSurface& stageSurface) {
if (stage == CameraFrameStage::ShadowCaster &&
shadowState.shadowCasterRequest.IsRequested()) {
return BuildScenePassRequestSceneData(
shadowState.shadowCasterRequest,
stageSurface,
baseSceneData);
}
if (const ScenePassRenderRequest* request = plan.GetScenePassRequest(stage);
request != nullptr) {
return BuildScenePassRequestSceneData(
*request,
stageSurface,
baseSceneData);
}
return baseSceneData;
}
RenderPass* ResolveStandaloneStagePass(
CameraFrameStage stage,
CameraFrameExecutionState& executionState) {
switch (stage) {
case CameraFrameStage::ShadowCaster:
return executionState.shadowCasterPass;
case CameraFrameStage::DepthOnly:
return executionState.depthOnlyPass;
case CameraFrameStage::ObjectId:
return executionState.objectIdPass;
default:
return nullptr;
}
}
bool ExecuteRecordedFrameStage(
CameraFrameStage stage,
const CameraFramePlan& plan,
const DirectionalShadowExecutionState& shadowState,
const RenderSceneData& sceneData,
CameraFrameExecutionState& executionState,
const RenderPassContext& passContext) {
switch (stage) {
case CameraFrameStage::ShadowCaster:
return ExecuteScenePassRequest(
executionState.shadowCasterPass,
shadowState.shadowCasterRequest,
plan.request.context,
sceneData,
&passContext.surface);
case CameraFrameStage::DepthOnly:
return ExecuteScenePassRequest(
executionState.depthOnlyPass,
plan.request.depthOnly,
plan.request.context,
sceneData,
&passContext.surface);
case CameraFrameStage::MainScene:
return executionState.pipeline != nullptr &&
executionState.pipeline->Render(
FrameExecutionContext(
plan.request.context,
passContext.surface,
sceneData,
passContext.sourceSurface,
passContext.sourceColorView,
passContext.sourceColorState));
case CameraFrameStage::ObjectId:
return !plan.request.objectId.IsRequested() ||
ExecuteStandalonePass(
executionState.objectIdPass,
plan.request.context,
passContext.surface,
sceneData);
default:
return false;
}
}
} // namespace
bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
const CameraFrameStageGraphBuildState& stageState,
const CameraFrameRenderGraphStageRecordContext& context,
bool& handled) {
CameraFrameRenderGraphRecordingSession& session = context.session;
RenderPass* const standaloneStagePass =
ResolveStandaloneStagePass(stageState.stage, session.executionState);
ResolveCameraFrameStandaloneStagePass(
stageState.stage,
session.executionState);
if (standaloneStagePass == nullptr ||
!standaloneStagePass->SupportsRenderGraph()) {
handled = false;
@@ -206,17 +29,15 @@ bool TryRecordCameraFrameStageStandaloneRenderGraphPass(
handled = true;
const RenderSceneData stageSceneData =
BuildStandaloneStageSceneData(
BuildCameraFrameStandaloneStageSceneData(
stageState.stage,
context.plan,
context.shadowState,
context.sceneData,
context,
stageState.surfaceTemplate);
bool* const stageExecutionSucceeded = &session.stageExecutionSucceeded;
const RenderPassGraphBeginCallback beginStandalonePass =
[stageExecutionSucceeded, standaloneStagePass, renderContext = &context.plan.request.context](
const RenderPassContext&) -> bool {
if (!InitializeStandalonePass(
if (!InitializeCameraFrameStandalonePass(
standaloneStagePass,
*renderContext)) {
*stageExecutionSucceeded = false;
@@ -301,12 +122,13 @@ void AddCameraFrameStageFallbackRasterPass(
const CameraFrameStageGraphBuildState capturedStageState = stageState;
CameraFrameExecutionState* const executionState = &session.executionState;
bool* const stageExecutionSucceeded = &session.stageExecutionSucceeded;
CameraFrameRenderGraphRecordingSession* const sessionPtr = &session;
const CameraFramePlan* const planPtr = &context.plan;
const DirectionalShadowExecutionState* const shadowStatePtr = &context.shadowState;
const RenderSceneData* const sceneDataPtr = &context.sceneData;
session.graphBuilder.AddRasterPass(
capturedStageState.stageName,
[capturedStageState, executionState, stageExecutionSucceeded, planPtr, shadowStatePtr, sceneDataPtr](
[capturedStageState, executionState, stageExecutionSucceeded, sessionPtr, planPtr, shadowStatePtr, sceneDataPtr](
RenderGraphPassBuilder& passBuilder) {
if (IsCameraFrameFullscreenSequenceStage(capturedStageState.stage)) {
ReadRenderGraphColorSurface(passBuilder, capturedStageState.sourceSurface);
@@ -316,7 +138,7 @@ void AddCameraFrameStageFallbackRasterPass(
WriteRenderGraphSurface(passBuilder, capturedStageState.outputSurface);
}
passBuilder.SetExecuteCallback(
[capturedStageState, executionState, stageExecutionSucceeded, planPtr, shadowStatePtr, sceneDataPtr](
[capturedStageState, executionState, stageExecutionSucceeded, sessionPtr, planPtr, shadowStatePtr, sceneDataPtr](
const RenderGraphExecutionContext& executionContext) {
if (!*stageExecutionSucceeded) {
return;
@@ -365,11 +187,14 @@ void AddCameraFrameStageFallbackRasterPass(
resolvedSourceColorView,
resolvedSourceColorState
};
*stageExecutionSucceeded = ExecuteRecordedFrameStage(
*stageExecutionSucceeded = ExecuteCameraFrameRecordedStage(
capturedStageState.stage,
*planPtr,
*shadowStatePtr,
*sceneDataPtr,
{
*planPtr,
*shadowStatePtr,
*sceneDataPtr,
*sessionPtr
},
*executionState,
passContextOverride);
});

View File

@@ -0,0 +1,186 @@
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStagePassRuntime.h"
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRecordContext.h"
#include "Rendering/Execution/Internal/CameraFrameRenderGraphStageRuntime.h"
namespace XCEngine {
namespace Rendering {
namespace {
RenderSceneData BuildScenePassRequestSceneData(
const ScenePassRenderRequest& request,
const RenderSurface& requestSurface,
const RenderSceneData& baseSceneData) {
RenderSceneData sceneData = baseSceneData;
if (request.hasCameraDataOverride) {
sceneData.cameraData = request.cameraDataOverride;
}
sceneData.cameraData.viewportWidth = requestSurface.GetRenderAreaWidth();
sceneData.cameraData.viewportHeight = requestSurface.GetRenderAreaHeight();
sceneData.cameraData.clearFlags = request.clearFlags;
if (request.hasClearColorOverride) {
sceneData.cameraData.clearColor = request.clearColorOverride;
}
return sceneData;
}
bool ExecuteScenePassRequest(
RenderPass* pass,
const ScenePassRenderRequest& request,
const RenderContext& context,
const RenderSceneData& baseSceneData,
const RenderSurface* surfaceOverride = nullptr) {
if (!request.IsRequested()) {
return true;
}
if (!InitializeCameraFrameStandalonePass(pass, context)) {
return false;
}
const RenderSurface& requestSurface =
surfaceOverride != nullptr ? *surfaceOverride : request.surface;
const RenderSceneData sceneData =
BuildScenePassRequestSceneData(
request,
requestSurface,
baseSceneData);
const RenderPassContext passContext = {
context,
requestSurface,
sceneData,
nullptr,
nullptr,
RHI::ResourceStates::Common
};
return pass->Execute(passContext);
}
bool ExecuteStandalonePass(
RenderPass* pass,
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) {
if (pass == nullptr) {
return false;
}
if (!InitializeCameraFrameStandalonePass(pass, context)) {
return false;
}
const RenderPassContext passContext = {
context,
surface,
sceneData,
nullptr,
nullptr,
RHI::ResourceStates::Common
};
return pass->Execute(passContext);
}
} // namespace
bool InitializeCameraFrameStandalonePass(
RenderPass* pass,
const RenderContext& context) {
if (pass == nullptr) {
return false;
}
if (pass->Initialize(context)) {
return true;
}
pass->Shutdown();
return false;
}
RenderSceneData BuildCameraFrameStandaloneStageSceneData(
CameraFrameStage stage,
const CameraFrameRenderGraphStageRecordContext& context,
const RenderSurface& stageSurface) {
if (stage == CameraFrameStage::ShadowCaster &&
context.shadowState.shadowCasterRequest.IsRequested()) {
return BuildScenePassRequestSceneData(
context.shadowState.shadowCasterRequest,
stageSurface,
context.sceneData);
}
if (const ScenePassRenderRequest* request = context.plan.GetScenePassRequest(stage);
request != nullptr) {
return BuildScenePassRequestSceneData(
*request,
stageSurface,
context.sceneData);
}
return context.sceneData;
}
RenderPass* ResolveCameraFrameStandaloneStagePass(
CameraFrameStage stage,
CameraFrameExecutionState& executionState) {
switch (stage) {
case CameraFrameStage::ShadowCaster:
return executionState.shadowCasterPass;
case CameraFrameStage::DepthOnly:
return executionState.depthOnlyPass;
case CameraFrameStage::ObjectId:
return executionState.objectIdPass;
default:
return nullptr;
}
}
bool ExecuteCameraFrameRecordedStage(
CameraFrameStage stage,
const CameraFrameRenderGraphStageRecordContext& context,
CameraFrameExecutionState& executionState,
const RenderPassContext& passContext) {
switch (stage) {
case CameraFrameStage::ShadowCaster:
return ExecuteScenePassRequest(
executionState.shadowCasterPass,
context.shadowState.shadowCasterRequest,
context.plan.request.context,
context.sceneData,
&passContext.surface);
case CameraFrameStage::DepthOnly:
return ExecuteScenePassRequest(
executionState.depthOnlyPass,
context.plan.request.depthOnly,
context.plan.request.context,
context.sceneData,
&passContext.surface);
case CameraFrameStage::MainScene:
return executionState.pipeline != nullptr &&
executionState.pipeline->Render(
FrameExecutionContext(
context.plan.request.context,
passContext.surface,
context.sceneData,
passContext.sourceSurface,
passContext.sourceColorView,
passContext.sourceColorState));
case CameraFrameStage::ObjectId:
return !context.plan.request.objectId.IsRequested() ||
ExecuteStandalonePass(
executionState.objectIdPass,
context.plan.request.context,
passContext.surface,
context.sceneData);
default:
return false;
}
}
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,36 @@
#pragma once
#include <XCEngine/Rendering/Execution/CameraFramePlan.h>
#include <XCEngine/Rendering/RenderContext.h>
namespace XCEngine {
namespace Rendering {
struct CameraFrameExecutionState;
struct CameraFrameRenderGraphStageRecordContext;
struct RenderPassContext;
struct RenderSceneData;
class RenderPass;
class RenderSurface;
bool InitializeCameraFrameStandalonePass(
RenderPass* pass,
const RenderContext& context);
RenderSceneData BuildCameraFrameStandaloneStageSceneData(
CameraFrameStage stage,
const CameraFrameRenderGraphStageRecordContext& context,
const RenderSurface& stageSurface);
RenderPass* ResolveCameraFrameStandaloneStagePass(
CameraFrameStage stage,
CameraFrameExecutionState& executionState);
bool ExecuteCameraFrameRecordedStage(
CameraFrameStage stage,
const CameraFrameRenderGraphStageRecordContext& context,
CameraFrameExecutionState& executionState,
const RenderPassContext& passContext);
} // namespace Rendering
} // namespace XCEngine