fix(rendering): derive URP stages from pass queue

This commit is contained in:
2026-04-27 13:45:50 +08:00
parent 1de1f768d3
commit 8ebbd5d633
9 changed files with 267 additions and 112 deletions

View File

@@ -7,6 +7,14 @@ namespace XCEngine.Rendering.Universal
{
public abstract class ScriptableRenderer
{
private struct PassQueueStageManifest
{
public bool shadowCaster;
public bool depthOnly;
public bool postProcess;
public bool finalOutput;
}
private readonly List<ScriptableRendererFeature> m_features =
new List<ScriptableRendererFeature>();
private readonly List<ScriptableRenderPass> m_activePassQueue =
@@ -118,6 +126,20 @@ namespace XCEngine.Rendering.Universal
ConfigureRendererFeaturesCameraFramePlan(context);
}
internal void ConfigurePassQueueCameraFramePlanInstance(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null)
{
return;
}
PassQueueStageManifest manifest =
BuildPassQueueStageManifest(context);
ApplyPassQueueStageManifest(context, manifest);
ClearPassQueue();
}
internal void FinalizeCameraFramePlanInstance(
ScriptableRenderPipelinePlanningContext context)
{
@@ -282,7 +304,13 @@ namespace XCEngine.Rendering.Universal
return false;
}
switch (context.stage)
return HasRendererStageBlocks(context.stage);
}
private bool HasRendererStageBlocks(
CameraFrameStage stage)
{
switch (stage)
{
case CameraFrameStage.ShadowCaster:
return HasRendererBlock(
@@ -308,6 +336,180 @@ namespace XCEngine.Rendering.Universal
}
}
private PassQueueStageManifest BuildPassQueueStageManifest(
ScriptableRenderPipelinePlanningContext context)
{
bool finalColorRequiresProcessing =
context.HasFinalColorProcessing();
int rendererIndex = context.rendererIndex;
return new PassQueueStageManifest
{
shadowCaster =
HasPassQueueStage(
CameraFrameStage.ShadowCaster,
rendererIndex,
finalColorRequiresProcessing),
depthOnly =
HasPassQueueStage(
CameraFrameStage.DepthOnly,
rendererIndex,
finalColorRequiresProcessing),
postProcess =
HasPassQueueStage(
CameraFrameStage.PostProcess,
rendererIndex,
finalColorRequiresProcessing),
finalOutput =
HasPassQueueStage(
CameraFrameStage.FinalOutput,
rendererIndex,
finalColorRequiresProcessing)
};
}
private bool HasPassQueueStage(
CameraFrameStage stage,
int rendererIndex,
bool finalColorRequiresProcessing)
{
BuildPassQueue(
RenderingData.CreatePlanning(
stage,
rendererIndex,
finalColorRequiresProcessing));
return HasRendererStageBlocks(stage);
}
private static void ApplyPassQueueStageManifest(
ScriptableRenderPipelinePlanningContext context,
PassQueueStageManifest manifest)
{
if (manifest.shadowCaster)
{
context.RequestShadowCasterStage();
}
else
{
context.ClearShadowCasterStage();
}
if (manifest.depthOnly)
{
context.RequestCameraDepthOnlyStage();
}
else
{
context.ClearDepthOnlyStage();
}
ApplyPostProcessStageManifest(context, manifest);
ApplyFinalOutputStageManifest(context, manifest);
}
private static void ApplyPostProcessStageManifest(
ScriptableRenderPipelinePlanningContext context,
PassQueueStageManifest manifest)
{
if (!manifest.postProcess)
{
context.ClearFullscreenStage(
CameraFrameStage.PostProcess);
return;
}
bool finalOutputReadsPostProcess =
ShouldFinalOutputReadPostProcess(
context,
manifest);
if (!context.IsStageRequested(
CameraFrameStage.PostProcess))
{
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
CameraFrameColorSource.MainSceneColor,
finalOutputReadsPostProcess);
return;
}
if (finalOutputReadsPostProcess &&
!context.UsesGraphManagedOutputColor(
CameraFrameStage.PostProcess))
{
CameraFrameColorSource source =
context.GetStageColorSource(
CameraFrameStage.PostProcess);
context.ClearFullscreenStage(
CameraFrameStage.PostProcess);
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
source,
true);
}
}
private static bool ShouldFinalOutputReadPostProcess(
ScriptableRenderPipelinePlanningContext context,
PassQueueStageManifest manifest)
{
if (!manifest.finalOutput ||
!manifest.postProcess)
{
return false;
}
return !context.IsStageRequested(
CameraFrameStage.PostProcess) ||
context.GetStageColorSource(
CameraFrameStage.PostProcess) !=
CameraFrameColorSource.ExplicitSurface;
}
private static void ApplyFinalOutputStageManifest(
ScriptableRenderPipelinePlanningContext context,
PassQueueStageManifest manifest)
{
if (!manifest.finalOutput)
{
context.ClearFullscreenStage(
CameraFrameStage.FinalOutput);
return;
}
if (context.IsStageRequested(
CameraFrameStage.FinalOutput) &&
context.GetStageColorSource(
CameraFrameStage.FinalOutput) ==
CameraFrameColorSource.ExplicitSurface)
{
return;
}
context.ClearFullscreenStage(
CameraFrameStage.FinalOutput);
context.RequestFullscreenStage(
CameraFrameStage.FinalOutput,
ResolveFinalOutputSource(context));
}
private static CameraFrameColorSource ResolveFinalOutputSource(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null ||
!context.IsStageRequested(
CameraFrameStage.PostProcess))
{
return CameraFrameColorSource.MainSceneColor;
}
return context.GetStageColorSource(
CameraFrameStage.PostProcess) ==
CameraFrameColorSource.ExplicitSurface
? CameraFrameColorSource.MainSceneColor
: CameraFrameColorSource.PostProcessColor;
}
protected virtual bool RecordRendererStage(
RendererRecordingContext context,
RenderGraph renderGraph,
@@ -432,8 +634,7 @@ namespace XCEngine.Rendering.Universal
private void BuildPassQueue(
RenderingData renderingData)
{
m_activePassQueue.Clear();
m_rendererBlocks.Clear();
ClearPassQueue();
m_isBuildingPassQueue = true;
m_passQueueStage =
renderingData != null
@@ -469,6 +670,12 @@ namespace XCEngine.Rendering.Universal
}
}
private void ClearPassQueue()
{
m_activePassQueue.Clear();
m_rendererBlocks.Clear();
}
private void FinishCameraStackRendering()
{
for (int i = 0; i < m_activePassQueue.Count; ++i)