refactor(srp): remove renderer fullscreen stage heuristics

This commit is contained in:
2026-04-21 13:07:24 +08:00
parent 5bec70dcc5
commit 2d4ff384fd
3 changed files with 75 additions and 65 deletions

View File

@@ -0,0 +1,52 @@
# SRP Universal Explicit Fullscreen Stage Planning Plan 2026-04-21
## Goal
Remove renderer-level fullscreen stage request heuristics and make managed URP fullscreen stage ownership explicit through renderer features.
## Why This Stage
Current managed URP already owns more of the camera-frame plan, but one important seam is still implicit:
1. `ScriptableRenderer.ConfigureCameraFramePlan(...)` scans queued render passes;
2. it infers whether `PostProcess` or `FinalOutput` should exist from `RenderPassEvent`;
3. fullscreen stage planning therefore still depends on hidden pass-event heuristics instead of explicit managed planning code.
That is weak architecture for a Unity-style SRP/URP direction. A renderer feature that needs a fullscreen stage should explicitly request it.
## Scope
Included:
1. remove fullscreen-stage inference from `ScriptableRenderer`;
2. make first-party post-process-style feature planning explicit;
3. keep builtin final-color feature on explicit planning path;
4. rebuild `XCEditor` and run old editor smoke.
Not included:
1. moving all native fullscreen request legacy paths out of the engine;
2. deleting native final-color or vector fullscreen pass implementations;
3. deferred renderer work;
4. editor UI work.
## Acceptance
This stage is complete when:
1. `ScriptableRenderer` no longer auto-requests fullscreen stages from queued pass events;
2. first-party managed fullscreen features explicitly request the stages they need;
3. `XCEditor` build passes;
4. old editor smoke passes and `editor.log` contains a fresh `SceneReady`.
## Validation
Validated on 2026-04-21:
1. built old editor target with `cmake --build . --config Debug --target XCEditor` from `build/`;
2. launched `editor/bin/Debug/XCEngine.exe` for about 12 seconds;
3. verified fresh `editor/bin/Debug/editor.log` contains `SceneReady`.
Observed log line:
`[2026-04-21 13:06:17] [INFO] [General] [SceneLoadTrace] SceneReady elapsed_ms=5372 first_frame_ms=536 peak_pending_async=9`

View File

@@ -23,19 +23,17 @@ namespace XCEngine.Rendering.Universal
if (context == null ||
renderingData == null ||
!renderingData.isPostProcessStage ||
m_feature == null ||
!context.sourceColorTexture.isValid ||
!context.primaryColorTarget.isValid)
m_feature == null)
{
return false;
}
return context
.AddRasterPass("Universal.ColorScalePostProcess")
.UseColorSource(context.sourceColorTexture)
.SetColorAttachment(context.primaryColorTarget)
.SetColorScaleFullscreenExecution(m_feature.colorScale)
.Commit();
return RecordColorScaleFullscreenPass(
context,
context.sourceColorTexture,
context.primaryColorTarget,
m_feature.colorScale,
"Universal.ColorScalePostProcess");
}
}
@@ -56,6 +54,22 @@ namespace XCEngine.Rendering.Universal
new ColorScalePostProcessPass(this);
}
public override void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null ||
context.IsStageRequested(
CameraFrameStage.PostProcess))
{
return;
}
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
CameraFrameColorSource.MainSceneColor,
context.HasFinalColorProcessing());
}
public override void AddRenderPasses(
ScriptableRenderer renderer,
RenderingData renderingData)

View File

@@ -179,62 +179,6 @@ namespace XCEngine.Rendering.Universal
protected virtual void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null)
{
return;
}
BuildPassQueue(new RenderingData(CameraFrameStage.MainScene));
bool hasPostProcessPass = false;
bool hasFinalOutputPass = false;
for (int i = 0; i < m_activePassQueue.Count; ++i)
{
ScriptableRenderPass renderPass = m_activePassQueue[i];
if (renderPass == null)
{
continue;
}
CameraFrameStage passStage;
if (!ScriptableRenderPass.TryResolveStage(
renderPass.renderPassEvent,
out passStage))
{
continue;
}
if (passStage == CameraFrameStage.PostProcess)
{
hasPostProcessPass = true;
}
else if (passStage ==
CameraFrameStage.FinalOutput)
{
hasFinalOutputPass = true;
}
}
if (hasPostProcessPass &&
!context.IsStageRequested(
CameraFrameStage.PostProcess))
{
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
CameraFrameColorSource.MainSceneColor,
hasFinalOutputPass);
}
if (hasFinalOutputPass &&
!context.IsStageRequested(
CameraFrameStage.FinalOutput))
{
context.RequestFullscreenStage(
CameraFrameStage.FinalOutput,
hasPostProcessPass
? CameraFrameColorSource.PostProcessColor
: CameraFrameColorSource.MainSceneColor);
}
}
private void BuildPassQueue(