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:
161
docs/used/SRP_RendererDrivenPipeline执行接缝计划_2026-04-20.md
Normal file
161
docs/used/SRP_RendererDrivenPipeline执行接缝计划_2026-04-20.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# SRP Renderer-Driven Pipeline 执行接缝计划 2026-04-20
|
||||
|
||||
## 1. 阶段目标
|
||||
|
||||
上一阶段已经把 `CameraFramePlan` 的 managed 规划接缝接进来了:
|
||||
|
||||
1. `ScriptableRenderPipelineAsset -> ConfigureCameraFramePlan`
|
||||
2. `UniversalRenderPipelineAsset -> ScriptableRendererData -> ScriptableRendererFeature`
|
||||
|
||||
但执行层还有一个明显没收干净的问题:
|
||||
|
||||
1. `UniversalRenderPipelineAsset` 仍然自己持有一套 rendererData/defaultRenderer/runtime cleanup 逻辑
|
||||
2. `UniversalRenderPipeline` 仍然自己做一层很薄的 renderer forwarding
|
||||
3. managed renderer 虽然已经存在,但还没有被提炼成正式的 renderer-driven pipeline 骨架
|
||||
|
||||
这一阶段的目标就是把这层骨架正式抽出来:
|
||||
|
||||
1. 增加通用的 `RendererDrivenRenderPipeline`
|
||||
2. 增加通用的 `RendererBackedRenderPipelineAsset`
|
||||
3. 增加 `RendererBackedRenderPipeline`
|
||||
4. 给 Universal 正式迁移到这套骨架
|
||||
5. 补上 renderer execution 侧的上下文类型,给后续 SRP/URP 继续扩张留出稳定接口
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前问题
|
||||
|
||||
### 2.1 Universal 还在重复持有“通用 renderer 资产”逻辑
|
||||
|
||||
当前 `UniversalRenderPipelineAsset` 里同时承担了:
|
||||
|
||||
1. `rendererDataList/defaultRendererIndex`
|
||||
2. `GetRendererData/GetRenderer`
|
||||
3. `ConfigureCameraRenderRequest`
|
||||
4. `ConfigureCameraFramePlan`
|
||||
5. `GetPipelineRendererAssetKey`
|
||||
6. `ReleaseRendererDataRuntimeResources`
|
||||
|
||||
这些其实已经不是 `Universal` 特有逻辑,而是“renderer-backed pipeline asset”的通用职责。
|
||||
|
||||
### 2.2 Pipeline 执行骨架还没有提升成可复用抽象
|
||||
|
||||
当前 `UniversalRenderPipeline` 本质上只是:
|
||||
|
||||
1. 拿默认 renderer
|
||||
2. 转发 `SupportsStageRenderGraph`
|
||||
3. 转发 `RecordStageRenderGraph`
|
||||
|
||||
这层 forwarding 逻辑应该收成通用的 renderer-driven pipeline 基类,而不是继续散落在首方包里。
|
||||
|
||||
### 2.3 缺少 renderer execution 层自己的正式上下文对象
|
||||
|
||||
当前 renderer 执行时主要直接吃:
|
||||
|
||||
1. `ScriptableRenderContext`
|
||||
2. `RenderingData`
|
||||
|
||||
这能工作,但在 API 组织上还缺一个更明确的“renderer 正在做执行决策”的上下文层。
|
||||
|
||||
这一阶段先补最小集合:
|
||||
|
||||
1. `RendererRecordingContext`
|
||||
2. `RendererCameraRequestContext`
|
||||
|
||||
不扩 raw native API,只做 managed 组织骨架。
|
||||
|
||||
---
|
||||
|
||||
## 3. 实施方案
|
||||
|
||||
### 3.1 Universal 包新增通用 renderer-driven 基类
|
||||
|
||||
新增:
|
||||
|
||||
1. `RendererDrivenRenderPipeline`
|
||||
2. `RendererBackedRenderPipeline`
|
||||
3. `RendererBackedRenderPipelineAsset`
|
||||
|
||||
职责边界:
|
||||
|
||||
1. `RendererDrivenRenderPipeline` 负责 pipeline -> renderer execution delegation
|
||||
2. `RendererBackedRenderPipeline` 负责从 asset 解析默认 renderer
|
||||
3. `RendererBackedRenderPipelineAsset` 负责 rendererData 列表、默认选择、request/plan/backend key/runtime cleanup
|
||||
|
||||
### 3.2 Universal 迁移到通用骨架
|
||||
|
||||
重构:
|
||||
|
||||
1. `UniversalRenderPipelineAsset : RendererBackedRenderPipelineAsset`
|
||||
2. `UniversalRenderPipeline : RendererBackedRenderPipeline`
|
||||
3. `UniversalRenderPipelineAsset` 只保留 Universal 自己的默认 rendererData 初始化
|
||||
|
||||
### 3.3 补 execution context 类型
|
||||
|
||||
新增:
|
||||
|
||||
1. `RendererRecordingContext`
|
||||
2. `RendererCameraRequestContext`
|
||||
|
||||
这一步先做到:
|
||||
|
||||
1. 类型正式存在
|
||||
2. pipeline / renderer 内部可以开始用它们组织 execution seam
|
||||
3. 不强行扩大 public raw recording surface
|
||||
|
||||
### 3.4 用测试锁住新骨架
|
||||
|
||||
验证点:
|
||||
|
||||
1. API probe 能看到新类型
|
||||
2. Universal 行为不回退
|
||||
3. 通用 renderer-backed 骨架至少被现有 Universal 主链真实经过
|
||||
|
||||
---
|
||||
|
||||
## 4. 实施步骤
|
||||
|
||||
### Step 1:新增 renderer-driven 基类
|
||||
|
||||
目标:
|
||||
|
||||
1. 新增 `RendererDrivenRenderPipeline`
|
||||
2. 新增 `RendererBackedRenderPipeline`
|
||||
3. 新增 `RendererBackedRenderPipelineAsset`
|
||||
|
||||
### Step 2:迁移 Universal
|
||||
|
||||
目标:
|
||||
|
||||
1. `UniversalRenderPipelineAsset` 下放通用逻辑
|
||||
2. `UniversalRenderPipeline` 改成继承通用基类
|
||||
3. 保持现有 runtime / cleanup / default renderer 行为一致
|
||||
|
||||
### Step 3:补 execution context 类型
|
||||
|
||||
目标:
|
||||
|
||||
1. 新增 `RendererRecordingContext`
|
||||
2. 新增 `RendererCameraRequestContext`
|
||||
3. 在 renderer-driven 骨架里用起来
|
||||
|
||||
### Step 4:补测试与验证
|
||||
|
||||
目标:
|
||||
|
||||
1. 更新 `ScriptableRenderContextApiSurfaceProbe`
|
||||
2. 更新 `test_mono_script_runtime.cpp`
|
||||
3. 编译 `rendering_unit_tests`、`scripting_tests`、`XCEditor`
|
||||
4. 运行 old editor 10s 冒烟并检查新的 `SceneReady`
|
||||
|
||||
---
|
||||
|
||||
## 5. 验收标准
|
||||
|
||||
完成后应满足:
|
||||
|
||||
1. `Universal` 不再自己持有整套通用 renderer-backed asset 逻辑
|
||||
2. 存在正式的 `RendererDrivenRenderPipeline / RendererBackedRenderPipeline / RendererBackedRenderPipelineAsset`
|
||||
3. 存在正式的 `RendererRecordingContext / RendererCameraRequestContext`
|
||||
4. `Universal` 现有 request / plan / record 行为不回退
|
||||
5. `scripting_tests`、`rendering_unit_tests`、`XCEditor`、old editor 冒烟全部通过
|
||||
@@ -199,6 +199,11 @@ set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RenderClearFlags.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RenderEnvironmentMode.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RenderPassEvent.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RendererBackedRenderPipeline.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RendererBackedRenderPipelineAsset.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RendererCameraRequestContext.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RendererDrivenRenderPipeline.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RendererRecordingContext.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RenderingData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/RenderingDataResolver.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Universal/ShadowData.cs
|
||||
|
||||
@@ -1115,7 +1115,7 @@ namespace Gameplay
|
||||
}
|
||||
|
||||
public sealed class ManagedRenderPipelineProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
: RendererBackedRenderPipelineAsset
|
||||
{
|
||||
public static int CreatePipelineCallCount;
|
||||
|
||||
@@ -1135,7 +1135,7 @@ namespace Gameplay
|
||||
}
|
||||
|
||||
public sealed class ManagedPostProcessRenderPipelineProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
: RendererBackedRenderPipelineAsset
|
||||
{
|
||||
public ManagedPostProcessRenderPipelineProbeAsset()
|
||||
{
|
||||
@@ -1148,7 +1148,7 @@ namespace Gameplay
|
||||
}
|
||||
|
||||
public sealed class ManagedUnknownBackendRenderPipelineProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
: RendererBackedRenderPipelineAsset
|
||||
{
|
||||
public ManagedUnknownBackendRenderPipelineProbeAsset()
|
||||
{
|
||||
@@ -1188,7 +1188,7 @@ namespace Gameplay
|
||||
}
|
||||
|
||||
public sealed class ManagedDefaultRendererSelectionProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
: RendererBackedRenderPipelineAsset
|
||||
{
|
||||
public ManagedDefaultRendererSelectionProbeAsset()
|
||||
{
|
||||
@@ -1202,7 +1202,7 @@ namespace Gameplay
|
||||
}
|
||||
|
||||
public sealed class ManagedInvalidDefaultRendererSelectionProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
: RendererBackedRenderPipelineAsset
|
||||
{
|
||||
public ManagedInvalidDefaultRendererSelectionProbeAsset()
|
||||
{
|
||||
@@ -1216,7 +1216,7 @@ namespace Gameplay
|
||||
}
|
||||
|
||||
public sealed class ManagedRendererReuseProbeAsset
|
||||
: UniversalRenderPipelineAsset
|
||||
: RendererBackedRenderPipelineAsset
|
||||
{
|
||||
public ManagedRendererReuseProbeAsset()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1315,11 +1315,11 @@ TEST_F(
|
||||
EXPECT_TRUE(hasPublicPipelineAssetConfigureCameraFramePlan);
|
||||
EXPECT_TRUE(hasPlanningContextType);
|
||||
EXPECT_TRUE(hasRendererFeatureConfigureCameraFramePlan);
|
||||
EXPECT_FALSE(hasRendererRecordingContextType);
|
||||
EXPECT_FALSE(hasRendererCameraRequestContextType);
|
||||
EXPECT_FALSE(hasRendererBackedRenderPipelineAssetType);
|
||||
EXPECT_FALSE(hasRendererBackedRenderPipelineType);
|
||||
EXPECT_FALSE(hasRendererDrivenRenderPipelineType);
|
||||
EXPECT_TRUE(hasRendererRecordingContextType);
|
||||
EXPECT_TRUE(hasRendererCameraRequestContextType);
|
||||
EXPECT_TRUE(hasRendererBackedRenderPipelineAssetType);
|
||||
EXPECT_TRUE(hasRendererBackedRenderPipelineType);
|
||||
EXPECT_TRUE(hasRendererDrivenRenderPipelineType);
|
||||
EXPECT_FALSE(hasPublicRendererSupportsStageRenderGraph);
|
||||
EXPECT_FALSE(hasPublicRendererRecordStageRenderGraph);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user