feat(srp): add renderer-driven pipeline backbone

Introduce renderer-driven and renderer-backed managed pipeline base types in the Universal package.

Move shared renderer-data/default-renderer ownership out of UniversalRenderPipelineAsset, migrate probe assets onto the generic seam, and expose renderer recording/request context types for future SRP expansion.

Update scripting API-surface expectations and validate with build, unit tests, scripting tests, and old editor smoke.
This commit is contained in:
2026-04-20 02:05:17 +08:00
parent 9e6c473186
commit cd29c8b2bc
12 changed files with 575 additions and 197 deletions

View File

@@ -0,0 +1,24 @@
using XCEngine;
namespace XCEngine.Rendering.Universal
{
public class RendererBackedRenderPipeline
: RendererDrivenRenderPipeline
{
private readonly RendererBackedRenderPipelineAsset m_asset;
public RendererBackedRenderPipeline(
RendererBackedRenderPipelineAsset asset)
{
m_asset = asset;
}
protected override ScriptableRenderer ResolveRenderer(
RendererRecordingContext context)
{
return m_asset != null
? m_asset.GetDefaultRenderer()
: null;
}
}
}

View File

@@ -0,0 +1,220 @@
using System;
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public abstract class RendererBackedRenderPipelineAsset
: ScriptableRenderPipelineAsset
{
public ScriptableRendererData[] rendererDataList =
Array.Empty<ScriptableRendererData>();
public int defaultRendererIndex = 0;
protected RendererBackedRenderPipelineAsset()
{
}
protected override ScriptableRenderPipeline CreatePipeline()
{
return CreateRendererBackedPipeline();
}
protected override void ConfigureCameraRenderRequest(
CameraRenderRequestContext context)
{
ConfigureRendererCameraRequest(
new RendererCameraRequestContext(context));
ScriptableRendererData resolvedRendererData =
GetDefaultRendererData();
if (resolvedRendererData != null)
{
resolvedRendererData
.ConfigureCameraRenderRequestInstance(
context);
}
}
protected override void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
ScriptableRendererData resolvedRendererData =
GetDefaultRendererData();
if (resolvedRendererData != null)
{
resolvedRendererData
.ConfigureCameraFramePlanInstance(
context);
}
}
protected override string GetPipelineRendererAssetKey()
{
ScriptableRendererData resolvedRendererData =
GetDefaultRendererData();
return resolvedRendererData != null
? resolvedRendererData
.GetPipelineRendererAssetKeyInstance()
: string.Empty;
}
protected override void ReleaseRuntimeResources()
{
ReleaseRendererDataRuntimeResources();
}
protected virtual ScriptableRenderPipeline
CreateRendererBackedPipeline()
{
return new RendererBackedRenderPipeline(this);
}
protected virtual void ConfigureRendererCameraRequest(
RendererCameraRequestContext context)
{
}
protected virtual ScriptableRendererData
CreateDefaultRendererData()
{
return null;
}
internal ScriptableRendererData GetDefaultRendererData()
{
return GetRendererData(defaultRendererIndex);
}
internal ScriptableRenderer GetDefaultRenderer()
{
return GetRenderer(defaultRendererIndex);
}
internal ScriptableRendererData GetRendererData(
int rendererIndex)
{
EnsureRendererDataList();
if (rendererDataList.Length == 0)
{
return null;
}
int resolvedRendererIndex =
ResolveRendererIndex(rendererIndex);
if (resolvedRendererIndex < 0)
{
return null;
}
if (rendererDataList[resolvedRendererIndex] == null)
{
rendererDataList[resolvedRendererIndex] =
CreateDefaultRendererData();
}
return rendererDataList[resolvedRendererIndex];
}
internal ScriptableRenderer GetRenderer(
int rendererIndex)
{
ScriptableRendererData rendererData =
GetRendererData(rendererIndex);
return rendererData != null
? rendererData.GetRendererInstance()
: null;
}
protected internal void ReleaseRendererDataRuntimeResources()
{
EnsureRendererDataList();
for (int i = 0; i < rendererDataList.Length; ++i)
{
ScriptableRendererData rendererData =
rendererDataList[i];
if (rendererData == null ||
WasRendererDataReleasedEarlier(i))
{
continue;
}
rendererData.ReleaseRuntimeResourcesInstance();
}
}
private void EnsureRendererDataList()
{
if (rendererDataList != null &&
rendererDataList.Length > 0)
{
return;
}
ScriptableRendererData defaultRendererData =
CreateDefaultRendererData();
rendererDataList =
defaultRendererData != null
? new ScriptableRendererData[]
{
defaultRendererData
}
: Array.Empty<ScriptableRendererData>();
defaultRendererIndex = 0;
}
private bool WasRendererDataReleasedEarlier(
int rendererDataIndex)
{
ScriptableRendererData rendererData =
rendererDataList[rendererDataIndex];
for (int i = 0; i < rendererDataIndex; ++i)
{
if (object.ReferenceEquals(
rendererDataList[i],
rendererData))
{
return true;
}
}
return false;
}
private int ResolveRendererIndex(
int rendererIndex)
{
EnsureRendererDataList();
if (rendererDataList.Length == 0)
{
return -1;
}
if (rendererIndex < 0 ||
rendererIndex >= rendererDataList.Length)
{
return ResolveDefaultRendererIndex();
}
return rendererIndex;
}
private int ResolveDefaultRendererIndex()
{
EnsureRendererDataList();
if (rendererDataList.Length == 0)
{
return -1;
}
if (defaultRendererIndex < 0 ||
defaultRendererIndex >= rendererDataList.Length)
{
defaultRendererIndex = 0;
}
return defaultRendererIndex;
}
}
}

View File

@@ -0,0 +1,28 @@
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public sealed class RendererCameraRequestContext
{
private readonly CameraRenderRequestContext m_requestContext;
internal RendererCameraRequestContext(
CameraRenderRequestContext requestContext)
{
m_requestContext = requestContext;
}
public int renderedBaseCameraCount =>
m_requestContext != null
? m_requestContext.renderedBaseCameraCount
: 0;
public int renderedRequestCount =>
m_requestContext != null
? m_requestContext.renderedRequestCount
: 0;
internal CameraRenderRequestContext requestContext =>
m_requestContext;
}
}

View File

@@ -0,0 +1,53 @@
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public abstract class RendererDrivenRenderPipeline
: ScriptableRenderPipeline
{
protected RendererDrivenRenderPipeline()
{
}
protected sealed override bool SupportsStageRenderGraph(
CameraFrameStage stage)
{
return SupportsRendererRecording(
new RendererRecordingContext(stage));
}
protected sealed override bool RecordStageRenderGraph(
ScriptableRenderContext context)
{
if (context == null)
{
return false;
}
return RecordRenderer(
new RendererRecordingContext(context));
}
protected virtual bool SupportsRendererRecording(
RendererRecordingContext context)
{
ScriptableRenderer renderer =
ResolveRenderer(context);
return renderer != null &&
renderer.SupportsRendererRecording(context);
}
protected virtual bool RecordRenderer(
RendererRecordingContext context)
{
ScriptableRenderer renderer =
ResolveRenderer(context);
return renderer != null &&
renderer.RecordRenderer(context);
}
protected abstract ScriptableRenderer ResolveRenderer(
RendererRecordingContext context);
}
}

View File

@@ -0,0 +1,48 @@
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public sealed class RendererRecordingContext
{
private readonly ScriptableRenderContext m_renderContext;
private readonly RenderingData m_renderingData;
internal RendererRecordingContext(
CameraFrameStage stage)
: this(
null,
new RenderingData(stage))
{
}
internal RendererRecordingContext(
ScriptableRenderContext renderContext)
: this(
renderContext,
renderContext != null
? new RenderingData(renderContext)
: new RenderingData(CameraFrameStage.MainScene))
{
}
private RendererRecordingContext(
ScriptableRenderContext renderContext,
RenderingData renderingData)
{
m_renderContext = renderContext;
m_renderingData =
renderingData ??
new RenderingData(CameraFrameStage.MainScene);
}
public CameraFrameStage stage =>
m_renderingData.stage;
public RenderingData renderingData =>
m_renderingData;
internal ScriptableRenderContext renderContext =>
m_renderContext;
}
}

View File

@@ -77,6 +77,22 @@ namespace XCEngine.Rendering.Universal
{
}
internal bool SupportsRendererRecording(
RendererRecordingContext context)
{
return context != null &&
SupportsStageRenderGraph(context.stage);
}
internal bool RecordRenderer(
RendererRecordingContext context)
{
return context != null &&
context.renderContext != null &&
RecordStageRenderGraph(
context.renderContext);
}
protected internal virtual bool SupportsStageRenderGraph(
CameraFrameStage stage)
{

View File

@@ -4,37 +4,12 @@ using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
internal sealed class UniversalRenderPipeline
: ScriptableRenderPipeline
: RendererBackedRenderPipeline
{
private readonly UniversalRenderPipelineAsset m_asset;
public UniversalRenderPipeline(
UniversalRenderPipelineAsset asset)
: base(asset)
{
m_asset = asset;
}
protected override bool SupportsStageRenderGraph(
CameraFrameStage stage)
{
ScriptableRenderer renderer = GetDefaultRenderer();
return renderer != null &&
renderer.SupportsStageRenderGraph(stage);
}
protected override bool RecordStageRenderGraph(
ScriptableRenderContext context)
{
ScriptableRenderer renderer = GetDefaultRenderer();
return renderer != null &&
renderer.RecordStageRenderGraph(context);
}
private ScriptableRenderer GetDefaultRenderer()
{
return m_asset != null
? m_asset.GetDefaultRenderer()
: null;
}
}
}

View File

@@ -4,170 +4,18 @@ using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public class UniversalRenderPipelineAsset
: ScriptableRenderPipelineAsset
: RendererBackedRenderPipelineAsset
{
public ScriptableRendererData[] rendererDataList =
new ScriptableRendererData[]
{
new UniversalRendererData()
};
public int defaultRendererIndex = 0;
protected override ScriptableRenderPipeline CreatePipeline()
protected override ScriptableRenderPipeline
CreateRendererBackedPipeline()
{
return GetDefaultRendererData() != null
? new UniversalRenderPipeline(this)
: null;
return new UniversalRenderPipeline(this);
}
protected override void ConfigureCameraRenderRequest(
CameraRenderRequestContext context)
protected override ScriptableRendererData
CreateDefaultRendererData()
{
ScriptableRendererData resolvedRendererData =
GetDefaultRendererData();
if (resolvedRendererData != null)
{
resolvedRendererData.ConfigureCameraRenderRequestInstance(
context);
}
}
protected override void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
ScriptableRendererData resolvedRendererData =
GetDefaultRendererData();
if (resolvedRendererData != null)
{
resolvedRendererData.ConfigureCameraFramePlanInstance(
context);
}
}
protected override string GetPipelineRendererAssetKey()
{
ScriptableRendererData resolvedRendererData =
GetDefaultRendererData();
return resolvedRendererData != null
? resolvedRendererData.GetPipelineRendererAssetKeyInstance()
: string.Empty;
}
protected override void ReleaseRuntimeResources()
{
ReleaseRendererDataRuntimeResources();
}
internal ScriptableRendererData GetDefaultRendererData()
{
return GetRendererData(defaultRendererIndex);
}
internal ScriptableRenderer GetDefaultRenderer()
{
return GetRenderer(defaultRendererIndex);
}
internal ScriptableRendererData GetRendererData(
int rendererIndex)
{
EnsureRendererDataList();
int resolvedRendererIndex =
ResolveRendererIndex(rendererIndex);
if (rendererDataList[resolvedRendererIndex] == null)
{
rendererDataList[resolvedRendererIndex] =
new UniversalRendererData();
}
return rendererDataList[resolvedRendererIndex];
}
internal ScriptableRenderer GetRenderer(
int rendererIndex)
{
ScriptableRendererData rendererData =
GetRendererData(rendererIndex);
return rendererData != null
? rendererData.GetRendererInstance()
: null;
}
private void EnsureRendererDataList()
{
if (rendererDataList != null &&
rendererDataList.Length > 0)
{
return;
}
rendererDataList =
new ScriptableRendererData[]
{
new UniversalRendererData()
};
defaultRendererIndex = 0;
}
protected void ReleaseRendererDataRuntimeResources()
{
EnsureRendererDataList();
for (int i = 0; i < rendererDataList.Length; ++i)
{
ScriptableRendererData rendererData =
rendererDataList[i];
if (rendererData == null ||
WasRendererDataReleasedEarlier(i))
{
continue;
}
rendererData.ReleaseRuntimeResourcesInstance();
}
}
private bool WasRendererDataReleasedEarlier(
int rendererDataIndex)
{
ScriptableRendererData rendererData =
rendererDataList[rendererDataIndex];
for (int i = 0; i < rendererDataIndex; ++i)
{
if (object.ReferenceEquals(
rendererDataList[i],
rendererData))
{
return true;
}
}
return false;
}
private int ResolveRendererIndex(
int rendererIndex)
{
EnsureRendererDataList();
if (rendererIndex < 0 ||
rendererIndex >= rendererDataList.Length)
{
return ResolveDefaultRendererIndex();
}
return rendererIndex;
}
private int ResolveDefaultRendererIndex()
{
EnsureRendererDataList();
if (defaultRendererIndex < 0 ||
defaultRendererIndex >= rendererDataList.Length)
{
defaultRendererIndex = 0;
}
return defaultRendererIndex;
return new UniversalRendererData();
}
}
}