Introduce a formal ScriptableRendererData setup seam so renderer feature attachment is owned by renderer data instead of renderer constructors pulling feature caches. Route lifecycle and reuse probes through the new setup path, lock the non-public setup seam in the API surface probe, and update scripting expectations accordingly.
200 lines
5.2 KiB
C#
200 lines
5.2 KiB
C#
using System.Collections.Generic;
|
|
using XCEngine;
|
|
using XCEngine.Rendering;
|
|
|
|
namespace XCEngine.Rendering.Universal
|
|
{
|
|
public abstract class ScriptableRenderer
|
|
{
|
|
private readonly List<ScriptableRendererFeature> m_features =
|
|
new List<ScriptableRendererFeature>();
|
|
private readonly List<ScriptableRenderPass> m_activePassQueue =
|
|
new List<ScriptableRenderPass>();
|
|
private bool m_disposed;
|
|
|
|
protected ScriptableRenderer()
|
|
{
|
|
}
|
|
|
|
internal void ReleaseRuntimeResourcesInstance()
|
|
{
|
|
if (m_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ReleaseRuntimeResources();
|
|
|
|
for (int i = 0; i < m_features.Count; ++i)
|
|
{
|
|
ScriptableRendererFeature feature = m_features[i];
|
|
if (feature != null)
|
|
{
|
|
feature.ReleaseRuntimeResourcesInstance();
|
|
}
|
|
}
|
|
|
|
m_features.Clear();
|
|
m_activePassQueue.Clear();
|
|
m_disposed = true;
|
|
}
|
|
|
|
public void EnqueuePass(
|
|
ScriptableRenderPass renderPass)
|
|
{
|
|
if (renderPass == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int insertIndex = m_activePassQueue.Count;
|
|
while (insertIndex > 0 &&
|
|
m_activePassQueue[insertIndex - 1].renderPassEvent >
|
|
renderPass.renderPassEvent)
|
|
{
|
|
insertIndex--;
|
|
}
|
|
|
|
m_activePassQueue.Insert(
|
|
insertIndex,
|
|
renderPass);
|
|
}
|
|
|
|
protected void AddFeature(
|
|
ScriptableRendererFeature feature)
|
|
{
|
|
if (feature == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_features.Add(feature);
|
|
feature.Create();
|
|
}
|
|
|
|
protected virtual void AddRenderPasses(
|
|
RenderingData renderingData)
|
|
{
|
|
}
|
|
|
|
internal void AddFeatureInstance(
|
|
ScriptableRendererFeature feature)
|
|
{
|
|
AddFeature(feature);
|
|
}
|
|
|
|
internal bool SupportsRendererRecordingInstance(
|
|
RendererRecordingContext context)
|
|
{
|
|
return SupportsRendererRecording(context);
|
|
}
|
|
|
|
internal bool RecordRendererInstance(
|
|
RendererRecordingContext context)
|
|
{
|
|
return RecordRenderer(context);
|
|
}
|
|
|
|
protected virtual bool SupportsRendererRecording(
|
|
RendererRecordingContext context)
|
|
{
|
|
if (context == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
RenderingData renderingData =
|
|
context.renderingData;
|
|
BuildPassQueue(renderingData);
|
|
for (int i = 0; i < m_activePassQueue.Count; ++i)
|
|
{
|
|
ScriptableRenderPass renderPass = m_activePassQueue[i];
|
|
if (renderPass != null &&
|
|
renderPass.SupportsStage(context.stage))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected virtual bool RecordRenderer(
|
|
RendererRecordingContext context)
|
|
{
|
|
if (context == null ||
|
|
context.renderContext == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
RenderingData renderingData =
|
|
context.renderingData;
|
|
BuildPassQueue(renderingData);
|
|
|
|
bool recordedAnyPass = false;
|
|
for (int i = 0; i < m_activePassQueue.Count; ++i)
|
|
{
|
|
ScriptableRenderPass renderPass = m_activePassQueue[i];
|
|
if (renderPass == null ||
|
|
!renderPass.SupportsStage(renderingData.stage))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!renderPass.Record(
|
|
context.renderContext,
|
|
renderingData))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
recordedAnyPass = true;
|
|
}
|
|
|
|
return recordedAnyPass;
|
|
}
|
|
|
|
protected internal virtual bool SupportsStageRenderGraph(
|
|
CameraFrameStage stage)
|
|
{
|
|
return SupportsRendererRecording(
|
|
new RendererRecordingContext(stage));
|
|
}
|
|
|
|
protected internal virtual bool RecordStageRenderGraph(
|
|
ScriptableRenderContext context)
|
|
{
|
|
return context != null &&
|
|
RecordRenderer(
|
|
new RendererRecordingContext(context));
|
|
}
|
|
|
|
private void BuildPassQueue(
|
|
RenderingData renderingData)
|
|
{
|
|
m_activePassQueue.Clear();
|
|
|
|
for (int i = 0; i < m_features.Count; ++i)
|
|
{
|
|
ScriptableRendererFeature feature = m_features[i];
|
|
if (feature == null || !feature.isActive)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
feature.AddRenderPasses(
|
|
this,
|
|
renderingData);
|
|
}
|
|
|
|
AddRenderPasses(renderingData);
|
|
}
|
|
|
|
protected virtual void ReleaseRuntimeResources()
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|