Tighten URP pass queue snapshot ownership
This commit is contained in:
@@ -7,6 +7,8 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public abstract class ScriptableRenderer
|
||||
{
|
||||
private const int kMaxFramePlanSnapshotCount = 64;
|
||||
|
||||
private struct PassQueueStageManifest
|
||||
{
|
||||
public bool shadowCaster;
|
||||
@@ -15,12 +17,77 @@ namespace XCEngine.Rendering.Universal
|
||||
public bool finalOutput;
|
||||
}
|
||||
|
||||
private sealed class PassQueueStageSnapshot
|
||||
{
|
||||
public PassQueueStageSnapshot(
|
||||
CameraFrameStage stage,
|
||||
List<ScriptableRenderPass> activePassQueue,
|
||||
RendererBlocks rendererBlocks)
|
||||
{
|
||||
this.stage = stage;
|
||||
this.activePassQueue =
|
||||
activePassQueue ??
|
||||
new List<ScriptableRenderPass>();
|
||||
this.rendererBlocks =
|
||||
rendererBlocks ?? new RendererBlocks();
|
||||
}
|
||||
|
||||
public readonly CameraFrameStage stage;
|
||||
public readonly List<ScriptableRenderPass> activePassQueue;
|
||||
public readonly RendererBlocks rendererBlocks;
|
||||
}
|
||||
|
||||
private sealed class PassQueueFrameSnapshot
|
||||
{
|
||||
private readonly Dictionary<
|
||||
CameraFrameStage,
|
||||
PassQueueStageSnapshot> m_stageSnapshots =
|
||||
new Dictionary<
|
||||
CameraFrameStage,
|
||||
PassQueueStageSnapshot>();
|
||||
|
||||
public PassQueueFrameSnapshot(
|
||||
ulong framePlanId,
|
||||
int rendererIndex)
|
||||
{
|
||||
this.framePlanId = framePlanId;
|
||||
this.rendererIndex = rendererIndex;
|
||||
}
|
||||
|
||||
public readonly ulong framePlanId;
|
||||
public readonly int rendererIndex;
|
||||
public PassQueueStageManifest manifest;
|
||||
|
||||
public void SetStageSnapshot(
|
||||
PassQueueStageSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_stageSnapshots[snapshot.stage] = snapshot;
|
||||
}
|
||||
|
||||
public bool TryGetStageSnapshot(
|
||||
CameraFrameStage stage,
|
||||
out PassQueueStageSnapshot snapshot)
|
||||
{
|
||||
return m_stageSnapshots.TryGetValue(
|
||||
stage,
|
||||
out snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<ScriptableRendererFeature> m_features =
|
||||
new List<ScriptableRendererFeature>();
|
||||
private readonly List<ScriptableRenderPass> m_activePassQueue =
|
||||
new List<ScriptableRenderPass>();
|
||||
private readonly RendererBlocks m_rendererBlocks =
|
||||
new RendererBlocks();
|
||||
private readonly Dictionary<ulong, PassQueueFrameSnapshot>
|
||||
m_framePlanSnapshots =
|
||||
new Dictionary<ulong, PassQueueFrameSnapshot>();
|
||||
private readonly CommandBuffer m_finishCameraStackCommandBuffer =
|
||||
new CommandBuffer("ScriptableRenderer.FinishCameraStack");
|
||||
private bool m_isBuildingPassQueue;
|
||||
@@ -53,6 +120,7 @@ namespace XCEngine.Rendering.Universal
|
||||
m_features.Clear();
|
||||
m_activePassQueue.Clear();
|
||||
m_rendererBlocks.Clear();
|
||||
m_framePlanSnapshots.Clear();
|
||||
m_disposed = true;
|
||||
}
|
||||
|
||||
@@ -134,9 +202,10 @@ namespace XCEngine.Rendering.Universal
|
||||
return;
|
||||
}
|
||||
|
||||
PassQueueStageManifest manifest =
|
||||
BuildPassQueueStageManifest(context);
|
||||
ApplyPassQueueStageManifest(context, manifest);
|
||||
PassQueueFrameSnapshot snapshot =
|
||||
BuildPassQueueFrameSnapshot(context);
|
||||
ApplyPassQueueStageManifest(context, snapshot.manifest);
|
||||
StorePassQueueFrameSnapshot(snapshot);
|
||||
ClearPassQueue();
|
||||
}
|
||||
|
||||
@@ -177,8 +246,30 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
RenderingData renderingData =
|
||||
context.renderingData;
|
||||
PassQueueStageSnapshot snapshot;
|
||||
if (TryGetPassQueueStageSnapshot(
|
||||
context,
|
||||
out snapshot))
|
||||
{
|
||||
return SupportsRendererRecordingFromSnapshot(
|
||||
context,
|
||||
snapshot);
|
||||
}
|
||||
|
||||
if (context.framePlanId != 0UL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildPassQueue(renderingData);
|
||||
return SupportsRendererStage(context);
|
||||
try
|
||||
{
|
||||
return SupportsRendererStage(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ClearPassQueue();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool RecordRenderer(
|
||||
@@ -192,24 +283,46 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
RenderingData renderingData =
|
||||
context.renderingData;
|
||||
BuildPassQueue(renderingData);
|
||||
bool recorded;
|
||||
using (ContextContainer frameData =
|
||||
ScriptableRenderPass.BuildRenderGraphFrameData(
|
||||
renderingData))
|
||||
PassQueueStageSnapshot snapshot;
|
||||
if (TryGetPassQueueStageSnapshot(
|
||||
context,
|
||||
out snapshot))
|
||||
{
|
||||
recorded =
|
||||
RecordRendererStage(
|
||||
context,
|
||||
new RenderGraph(context.renderContext),
|
||||
frameData);
|
||||
}
|
||||
if (recorded)
|
||||
{
|
||||
FinishCameraStackRendering();
|
||||
return RecordRendererFromSnapshot(
|
||||
context,
|
||||
snapshot);
|
||||
}
|
||||
|
||||
return recorded;
|
||||
if (context.framePlanId != 0UL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildPassQueue(renderingData);
|
||||
try
|
||||
{
|
||||
bool recorded;
|
||||
using (ContextContainer frameData =
|
||||
ScriptableRenderPass.BuildRenderGraphFrameData(
|
||||
renderingData))
|
||||
{
|
||||
recorded =
|
||||
RecordRendererStage(
|
||||
context,
|
||||
new RenderGraph(context.renderContext),
|
||||
frameData);
|
||||
}
|
||||
if (recorded)
|
||||
{
|
||||
FinishCameraStackRendering();
|
||||
}
|
||||
|
||||
return recorded;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ClearPassQueue();
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual bool SupportsStageRenderGraph(
|
||||
@@ -296,6 +409,14 @@ namespace XCEngine.Rendering.Universal
|
||||
return m_rendererBlocks.HasPasses(block);
|
||||
}
|
||||
|
||||
private static bool HasRendererBlock(
|
||||
RendererBlocks rendererBlocks,
|
||||
RendererBlock block)
|
||||
{
|
||||
return rendererBlocks != null &&
|
||||
rendererBlocks.HasPasses(block);
|
||||
}
|
||||
|
||||
protected virtual bool SupportsRendererStage(
|
||||
RendererRecordingContext context)
|
||||
{
|
||||
@@ -309,76 +430,152 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
private bool HasRendererStageBlocks(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
return HasRendererStageBlocks(
|
||||
stage,
|
||||
m_rendererBlocks);
|
||||
}
|
||||
|
||||
private static bool HasRendererStageBlocks(
|
||||
CameraFrameStage stage,
|
||||
RendererBlocks rendererBlocks)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case CameraFrameStage.ShadowCaster:
|
||||
return HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.ShadowCaster);
|
||||
case CameraFrameStage.DepthOnly:
|
||||
return HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.DepthPrepass);
|
||||
case CameraFrameStage.MainScene:
|
||||
return HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.MainOpaque) ||
|
||||
HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.MainSkybox) ||
|
||||
HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.MainTransparent);
|
||||
case CameraFrameStage.PostProcess:
|
||||
return HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.PostProcess);
|
||||
case CameraFrameStage.FinalOutput:
|
||||
return HasRendererBlock(
|
||||
rendererBlocks,
|
||||
RendererBlock.FinalOutput);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private PassQueueStageManifest BuildPassQueueStageManifest(
|
||||
private PassQueueFrameSnapshot BuildPassQueueFrameSnapshot(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
bool finalColorRequiresProcessing =
|
||||
context.HasFinalColorProcessing();
|
||||
int rendererIndex = context.rendererIndex;
|
||||
ulong framePlanId = context.framePlanId;
|
||||
|
||||
return new PassQueueStageManifest
|
||||
PassQueueFrameSnapshot snapshot =
|
||||
new PassQueueFrameSnapshot(
|
||||
framePlanId,
|
||||
rendererIndex);
|
||||
|
||||
snapshot.SetStageSnapshot(
|
||||
BuildPassQueueStageSnapshot(
|
||||
CameraFrameStage.ShadowCaster,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing,
|
||||
framePlanId));
|
||||
snapshot.SetStageSnapshot(
|
||||
BuildPassQueueStageSnapshot(
|
||||
CameraFrameStage.DepthOnly,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing,
|
||||
framePlanId));
|
||||
snapshot.SetStageSnapshot(
|
||||
BuildPassQueueStageSnapshot(
|
||||
CameraFrameStage.MainScene,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing,
|
||||
framePlanId));
|
||||
snapshot.SetStageSnapshot(
|
||||
BuildPassQueueStageSnapshot(
|
||||
CameraFrameStage.PostProcess,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing,
|
||||
framePlanId));
|
||||
snapshot.SetStageSnapshot(
|
||||
BuildPassQueueStageSnapshot(
|
||||
CameraFrameStage.FinalOutput,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing,
|
||||
framePlanId));
|
||||
|
||||
PassQueueStageSnapshot stageSnapshot;
|
||||
snapshot.manifest = new PassQueueStageManifest
|
||||
{
|
||||
shadowCaster =
|
||||
HasPassQueueStage(
|
||||
snapshot.TryGetStageSnapshot(
|
||||
CameraFrameStage.ShadowCaster,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing),
|
||||
out stageSnapshot) &&
|
||||
HasRendererStageBlocks(
|
||||
CameraFrameStage.ShadowCaster,
|
||||
stageSnapshot.rendererBlocks),
|
||||
depthOnly =
|
||||
HasPassQueueStage(
|
||||
snapshot.TryGetStageSnapshot(
|
||||
CameraFrameStage.DepthOnly,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing),
|
||||
out stageSnapshot) &&
|
||||
HasRendererStageBlocks(
|
||||
CameraFrameStage.DepthOnly,
|
||||
stageSnapshot.rendererBlocks),
|
||||
postProcess =
|
||||
HasPassQueueStage(
|
||||
snapshot.TryGetStageSnapshot(
|
||||
CameraFrameStage.PostProcess,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing),
|
||||
out stageSnapshot) &&
|
||||
HasRendererStageBlocks(
|
||||
CameraFrameStage.PostProcess,
|
||||
stageSnapshot.rendererBlocks),
|
||||
finalOutput =
|
||||
HasPassQueueStage(
|
||||
snapshot.TryGetStageSnapshot(
|
||||
CameraFrameStage.FinalOutput,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing)
|
||||
out stageSnapshot) &&
|
||||
HasRendererStageBlocks(
|
||||
CameraFrameStage.FinalOutput,
|
||||
stageSnapshot.rendererBlocks)
|
||||
};
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
private bool HasPassQueueStage(
|
||||
private PassQueueStageSnapshot BuildPassQueueStageSnapshot(
|
||||
CameraFrameStage stage,
|
||||
int rendererIndex,
|
||||
bool finalColorRequiresProcessing)
|
||||
bool finalColorRequiresProcessing,
|
||||
ulong framePlanId)
|
||||
{
|
||||
BuildPassQueue(
|
||||
RenderingData.CreatePlanning(
|
||||
stage,
|
||||
rendererIndex,
|
||||
finalColorRequiresProcessing));
|
||||
return HasRendererStageBlocks(stage);
|
||||
finalColorRequiresProcessing,
|
||||
framePlanId));
|
||||
|
||||
List<ScriptableRenderPass> activePassQueue =
|
||||
new List<ScriptableRenderPass>(
|
||||
m_activePassQueue);
|
||||
RendererBlocks rendererBlocks =
|
||||
new RendererBlocks();
|
||||
rendererBlocks.Build(activePassQueue);
|
||||
return new PassQueueStageSnapshot(
|
||||
stage,
|
||||
activePassQueue,
|
||||
rendererBlocks);
|
||||
}
|
||||
|
||||
private static void ApplyPassQueueStageManifest(
|
||||
@@ -631,6 +828,129 @@ namespace XCEngine.Rendering.Universal
|
||||
return true;
|
||||
}
|
||||
|
||||
private void StorePassQueueFrameSnapshot(
|
||||
PassQueueFrameSnapshot snapshot)
|
||||
{
|
||||
if (snapshot == null ||
|
||||
snapshot.framePlanId == 0UL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_framePlanSnapshots.ContainsKey(
|
||||
snapshot.framePlanId) &&
|
||||
m_framePlanSnapshots.Count >=
|
||||
kMaxFramePlanSnapshotCount)
|
||||
{
|
||||
ulong oldestFramePlanId = 0UL;
|
||||
bool hasOldestFramePlanId = false;
|
||||
foreach (ulong framePlanId in
|
||||
m_framePlanSnapshots.Keys)
|
||||
{
|
||||
oldestFramePlanId = framePlanId;
|
||||
hasOldestFramePlanId = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasOldestFramePlanId)
|
||||
{
|
||||
m_framePlanSnapshots.Remove(
|
||||
oldestFramePlanId);
|
||||
}
|
||||
}
|
||||
|
||||
m_framePlanSnapshots[snapshot.framePlanId] =
|
||||
snapshot;
|
||||
}
|
||||
|
||||
private bool TryGetPassQueueStageSnapshot(
|
||||
RendererRecordingContext context,
|
||||
out PassQueueStageSnapshot stageSnapshot)
|
||||
{
|
||||
stageSnapshot = null;
|
||||
if (context == null ||
|
||||
context.framePlanId == 0UL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PassQueueFrameSnapshot frameSnapshot;
|
||||
if (!m_framePlanSnapshots.TryGetValue(
|
||||
context.framePlanId,
|
||||
out frameSnapshot) ||
|
||||
frameSnapshot == null ||
|
||||
frameSnapshot.rendererIndex !=
|
||||
context.rendererIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return frameSnapshot.TryGetStageSnapshot(
|
||||
context.stage,
|
||||
out stageSnapshot);
|
||||
}
|
||||
|
||||
private bool SupportsRendererRecordingFromSnapshot(
|
||||
RendererRecordingContext context,
|
||||
PassQueueStageSnapshot snapshot)
|
||||
{
|
||||
LoadPassQueueStageSnapshot(snapshot);
|
||||
try
|
||||
{
|
||||
return SupportsRendererStage(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ClearPassQueue();
|
||||
}
|
||||
}
|
||||
|
||||
private bool RecordRendererFromSnapshot(
|
||||
RendererRecordingContext context,
|
||||
PassQueueStageSnapshot snapshot)
|
||||
{
|
||||
LoadPassQueueStageSnapshot(snapshot);
|
||||
try
|
||||
{
|
||||
bool recorded;
|
||||
using (ContextContainer frameData =
|
||||
ScriptableRenderPass.BuildRenderGraphFrameData(
|
||||
context.renderingData))
|
||||
{
|
||||
recorded =
|
||||
RecordRendererStage(
|
||||
context,
|
||||
new RenderGraph(context.renderContext),
|
||||
frameData);
|
||||
}
|
||||
if (recorded)
|
||||
{
|
||||
FinishCameraStackRendering();
|
||||
}
|
||||
|
||||
return recorded;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ClearPassQueue();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadPassQueueStageSnapshot(
|
||||
PassQueueStageSnapshot snapshot)
|
||||
{
|
||||
ClearPassQueue();
|
||||
if (snapshot == null ||
|
||||
snapshot.activePassQueue == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_activePassQueue.AddRange(
|
||||
snapshot.activePassQueue);
|
||||
m_rendererBlocks.Build(m_activePassQueue);
|
||||
}
|
||||
|
||||
private void BuildPassQueue(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user