Formalize camera frame composition stages

This commit is contained in:
2026-04-05 22:43:48 +08:00
parent 5342e447af
commit 58f97c416b
3 changed files with 306 additions and 41 deletions

View File

@@ -151,6 +151,77 @@ private:
bool m_failed = false;
};
struct CameraFrameExecutionState {
RenderPipeline* pipeline = nullptr;
RenderPass* objectIdPass = nullptr;
RenderPass* depthOnlyPass = nullptr;
RenderPass* shadowCasterPass = nullptr;
std::unique_ptr<ScopedInitializedPassSequence> preScenePasses;
std::unique_ptr<ScopedInitializedPassSequence> postScenePasses;
std::unique_ptr<ScopedInitializedPassSequence> overlayPasses;
};
bool ExecutePassSequenceStage(
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence,
RenderPassSequence* sequence,
const RenderContext& context,
const RenderPassContext& passContext) {
activeSequence = std::make_unique<ScopedInitializedPassSequence>(sequence, context);
return activeSequence->IsReady() && activeSequence->Execute(passContext);
}
bool ExecuteFrameStage(
CameraFrameStage stage,
const CameraRenderRequest& request,
const ShadowCasterRenderRequest& resolvedShadowCaster,
const RenderPassContext& passContext,
CameraFrameExecutionState& executionState) {
switch (stage) {
case CameraFrameStage::PreScenePasses:
return ExecutePassSequenceStage(
executionState.preScenePasses,
request.GetPassSequence(stage),
request.context,
passContext);
case CameraFrameStage::ShadowCaster:
return ExecuteScenePassRequest(
executionState.shadowCasterPass,
resolvedShadowCaster,
request.context,
passContext.sceneData);
case CameraFrameStage::DepthOnly:
return ExecuteScenePassRequest(
executionState.depthOnlyPass,
request.depthOnly,
request.context,
passContext.sceneData);
case CameraFrameStage::MainScene:
return executionState.pipeline != nullptr &&
executionState.pipeline->Render(request.context, request.surface, passContext.sceneData);
case CameraFrameStage::ObjectId:
return !request.objectId.IsRequested() ||
ExecuteStandalonePass(
executionState.objectIdPass,
request.context,
request.objectId.surface,
passContext.sceneData);
case CameraFrameStage::PostScenePasses:
return ExecutePassSequenceStage(
executionState.postScenePasses,
request.GetPassSequence(stage),
request.context,
passContext);
case CameraFrameStage::OverlayPasses:
return ExecutePassSequenceStage(
executionState.overlayPasses,
request.GetPassSequence(stage),
request.context,
passContext);
default:
return false;
}
}
RenderDirectionalShadowData BuildDirectionalShadowData(
const DirectionalShadowRenderPlan& plan,
RHI::RHIResourceView* shadowMapView) {
@@ -352,49 +423,26 @@ bool CameraRenderer::ExecuteRenderPlan(
request.surface,
sceneData
};
CameraFrameExecutionState executionState = {};
executionState.pipeline = m_pipeline.get();
executionState.objectIdPass = m_objectIdPass.get();
executionState.depthOnlyPass = m_depthOnlyPass.get();
executionState.shadowCasterPass = m_shadowCasterPass.get();
ScopedInitializedPassSequence preScenePasses(request.preScenePasses, request.context);
if (!preScenePasses.IsReady() || !preScenePasses.Execute(passContext)) {
return false;
}
for (const CameraFrameStageInfo& stageInfo : kOrderedCameraFrameStages) {
if (!request.HasFrameStage(stageInfo.stage) &&
stageInfo.stage != CameraFrameStage::MainScene) {
continue;
}
if (!ExecuteScenePassRequest(
m_shadowCasterPass.get(),
resolvedShadowCaster,
request.context,
sceneData)) {
return false;
}
if (!ExecuteScenePassRequest(
m_depthOnlyPass.get(),
request.depthOnly,
request.context,
sceneData)) {
return false;
}
if (!m_pipeline->Render(request.context, request.surface, sceneData)) {
return false;
}
if (request.objectId.IsRequested() &&
!ExecuteStandalonePass(
m_objectIdPass.get(),
request.context,
request.objectId.surface,
sceneData)) {
return false;
}
ScopedInitializedPassSequence postScenePasses(request.postScenePasses, request.context);
if (!postScenePasses.IsReady() || !postScenePasses.Execute(passContext)) {
return false;
}
ScopedInitializedPassSequence overlayPasses(request.overlayPasses, request.context);
if (!overlayPasses.IsReady() || !overlayPasses.Execute(passContext)) {
return false;
if (!ExecuteFrameStage(
stageInfo.stage,
request,
resolvedShadowCaster,
passContext,
executionState)) {
return false;
}
}
return true;