diff --git a/docs/used/SRP_RendererDataPipelineBackendSeamNarrowingPlan_完成归档_2026-04-21.md b/docs/used/SRP_RendererDataPipelineBackendSeamNarrowingPlan_完成归档_2026-04-21.md new file mode 100644 index 00000000..1fcc1ad3 --- /dev/null +++ b/docs/used/SRP_RendererDataPipelineBackendSeamNarrowingPlan_完成归档_2026-04-21.md @@ -0,0 +1,59 @@ +# SRP RendererData Pipeline Backend Seam Narrowing Plan 2026-04-21 + +## Goal + +Remove the last public native-backend seam from `ScriptableRendererData` by hiding renderer-data-level pipeline renderer key selection and moving project probe-only backend overrides to the renderer-backed asset layer. + +## Why This Stage + +After the previous SRP cleanup stages, the main remaining user-visible native seam is: + +1. `ScriptableRendererData.GetPipelineRendererAssetKey()` + +This is still the wrong layer for external customization: + +1. ordinary URP renderer-data authors should not choose native scene renderer backend keys directly; +2. the backend family should be a first-party URP / engine concern; +3. current external usage is mostly project probe code in `managed/GameScripts`. + +At the same time, most builtin-forward probe renderer data already derive from `UniversalRendererData` through `ProbeRendererData`, so they can inherit first-party backend binding behavior without overriding the seam directly. + +## Scope + +Included: + +1. tighten `ScriptableRendererData.GetPipelineRendererAssetKey()` visibility to package-private override scope; +2. tighten `UniversalRendererData`'s override accordingly; +3. remove project probe renderer-data overrides of that seam where first-party inheritance is sufficient; +4. move project probe-only special backend choices such as `MissingBackend` / alias cases to asset-level contextual key overrides; +5. rebuild `XCEditor` and run old editor smoke. + +Not included: + +1. hiding `RendererBackedRenderPipelineAsset.GetPipelineRendererAssetKeyContextual(...)` yet; +2. replacing backend key resolution with a non-string registry; +3. Mono bridge method-name changes; +4. deferred renderer work. + +## Acceptance + +This stage is complete when: + +1. external renderer-data subclasses no longer see `GetPipelineRendererAssetKey()` as a normal override point; +2. first-party `UniversalRendererData` still provides builtin forward backend binding; +3. project probe assets still express their special backend selection behavior through asset-level overrides where needed; +4. `XCEditor` builds successfully; +5. old editor smoke passes and `editor.log` contains a fresh `SceneReady`. + +## Validation + +Validated on 2026-04-21: + +1. built old editor target with `cmake --build . --config Debug --target XCEditor` from `build/`; +2. launched `editor/bin/Debug/XCEngine.exe`; +3. let it run for about 12 seconds; +4. verified a fresh `SceneReady` entry in `editor/bin/Debug/editor.log`. + +Observed log line: + +`[2026-04-21 14:25:41] [INFO] [General] [SceneLoadTrace] SceneReady elapsed_ms=5084 first_frame_ms=568 peak_pending_async=9` diff --git a/managed/GameScripts/RenderPipelineApiProbe.cs b/managed/GameScripts/RenderPipelineApiProbe.cs index b0b4e479..795a4086 100644 --- a/managed/GameScripts/RenderPipelineApiProbe.cs +++ b/managed/GameScripts/RenderPipelineApiProbe.cs @@ -519,9 +519,9 @@ namespace Gameplay } internal sealed class ManagedFeaturePassOrderProbeRendererData - : ScriptableRendererData + : ProbeRendererData { - protected override ScriptableRenderer CreateRenderer() + protected override ScriptableRenderer CreateProbeRenderer() { return new ManagedFeaturePassOrderProbeRenderer(); } @@ -534,11 +534,6 @@ namespace Gameplay new ManagedFeaturePassOrderCustomFeature("CustomB") }; } - - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForward"; - } } internal sealed class CameraDataObservationPass @@ -1034,11 +1029,6 @@ namespace Gameplay { return new ManagedRenderPipelineProbe(); } - - protected override string GetPipelineRendererAssetKey() - { - return "MissingBackend"; - } } internal sealed class ManagedBuiltinForwardAliasProbeRendererData @@ -1048,11 +1038,6 @@ namespace Gameplay { return new ManagedRenderPipelineProbe(); } - - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForwardAlias"; - } } internal sealed class ManagedRendererSelectionInactiveRenderer @@ -1072,9 +1057,9 @@ namespace Gameplay } internal sealed class ManagedRendererSelectionActiveRendererData - : ScriptableRendererData + : ProbeRendererData { - protected override ScriptableRenderer CreateRenderer() + protected override ScriptableRenderer CreateProbeRenderer() { return new ProbeSceneRenderer(); } @@ -1102,11 +1087,6 @@ namespace Gameplay CameraFrameStage.PostProcess, CameraFrameColorSource.MainSceneColor); } - - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForward"; - } } internal sealed class ManagedRendererSelectionInactiveRendererData @@ -1116,11 +1096,6 @@ namespace Gameplay { return new ManagedRendererSelectionInactiveRenderer(); } - - protected override string GetPipelineRendererAssetKey() - { - return "MissingBackend"; - } } internal sealed class ManagedRendererReuseProbeRendererData @@ -1434,9 +1409,9 @@ namespace Gameplay } internal sealed class ManagedLifecycleProbeRendererData - : ScriptableRendererData + : ProbeRendererData { - protected override ScriptableRenderer CreateRenderer() + protected override ScriptableRenderer CreateProbeRenderer() { ManagedLifecycleProbeState.CreateRendererCallCount++; return new ManagedLifecycleProbeRenderer(); @@ -1458,11 +1433,6 @@ namespace Gameplay }; } - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForward"; - } - protected override void ReleaseRuntimeResources() { ManagedLifecycleProbeState.ReleaseRendererDataRuntimeResourcesCallCount++; @@ -1512,6 +1482,60 @@ namespace Gameplay } } + internal abstract class ProbePipelineRendererKeyAsset + : RendererBackedRenderPipelineAsset + { + protected sealed override string + GetPipelineRendererAssetKeyContextual( + int rendererIndex) + { + int resolvedRendererIndex = + ResolvePipelineRendererProbeIndex( + rendererIndex); + string overrideAssetKey = + ResolveProbePipelineRendererAssetKey( + resolvedRendererIndex); + return !string.IsNullOrEmpty(overrideAssetKey) + ? overrideAssetKey + : base.GetPipelineRendererAssetKeyContextual( + resolvedRendererIndex); + } + + protected virtual string ResolveProbePipelineRendererAssetKey( + int resolvedRendererIndex) + { + return string.Empty; + } + + private int ResolvePipelineRendererProbeIndex( + int rendererIndex) + { + if (rendererDataList != null && + rendererIndex >= 0 && + rendererIndex < rendererDataList.Length) + { + return rendererIndex; + } + + if (rendererDataList == null || + rendererDataList.Length == 0) + { + return -1; + } + + int resolvedDefaultRendererIndex = + defaultRendererIndex; + if (resolvedDefaultRendererIndex < 0 || + resolvedDefaultRendererIndex >= + rendererDataList.Length) + { + resolvedDefaultRendererIndex = 0; + } + + return resolvedDefaultRendererIndex; + } + } + public sealed class ManagedUniversalLifecycleProbeAsset : UniversalRenderPipelineAsset { @@ -1570,7 +1594,7 @@ namespace Gameplay } public sealed class ManagedUnknownBackendRenderPipelineProbeAsset - : RendererBackedRenderPipelineAsset + : ProbePipelineRendererKeyAsset { public ManagedUnknownBackendRenderPipelineProbeAsset() { @@ -1579,10 +1603,16 @@ namespace Gameplay new ManagedUnknownBackendProbeRendererData() }; } + + protected override string ResolveProbePipelineRendererAssetKey( + int resolvedRendererIndex) + { + return "MissingBackend"; + } } public sealed class ManagedBuiltinForwardAliasRenderPipelineProbeAsset - : RendererBackedRenderPipelineAsset + : ProbePipelineRendererKeyAsset { public ManagedBuiltinForwardAliasRenderPipelineProbeAsset() { @@ -1591,6 +1621,12 @@ namespace Gameplay new ManagedBuiltinForwardAliasProbeRendererData() }; } + + protected override string ResolveProbePipelineRendererAssetKey( + int resolvedRendererIndex) + { + return "BuiltinForwardAlias"; + } } public sealed class ManagedUniversalRenderPipelineProbeAsset @@ -1622,7 +1658,7 @@ namespace Gameplay } public sealed class ManagedDefaultRendererSelectionProbeAsset - : RendererBackedRenderPipelineAsset + : ProbePipelineRendererKeyAsset { public ManagedDefaultRendererSelectionProbeAsset() { @@ -1633,10 +1669,18 @@ namespace Gameplay }; defaultRendererIndex = 1; } + + protected override string ResolveProbePipelineRendererAssetKey( + int resolvedRendererIndex) + { + return resolvedRendererIndex == 0 + ? "MissingBackend" + : string.Empty; + } } public sealed class ManagedInvalidDefaultRendererSelectionProbeAsset - : RendererBackedRenderPipelineAsset + : ProbePipelineRendererKeyAsset { public ManagedInvalidDefaultRendererSelectionProbeAsset() { @@ -1647,10 +1691,18 @@ namespace Gameplay }; defaultRendererIndex = 5; } + + protected override string ResolveProbePipelineRendererAssetKey( + int resolvedRendererIndex) + { + return resolvedRendererIndex == 1 + ? "MissingBackend" + : string.Empty; + } } public sealed class ManagedFallbackRendererSelectionConsistencyProbeAsset - : RendererBackedRenderPipelineAsset + : ProbePipelineRendererKeyAsset { public ManagedFallbackRendererSelectionConsistencyProbeAsset() { @@ -1661,6 +1713,14 @@ namespace Gameplay }; defaultRendererIndex = 7; } + + protected override string ResolveProbePipelineRendererAssetKey( + int resolvedRendererIndex) + { + return resolvedRendererIndex == 1 + ? "MissingBackend" + : string.Empty; + } } public sealed class ManagedRendererReuseProbeAsset diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs index 1e83f7f1..57262aa7 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs @@ -166,7 +166,7 @@ namespace XCEngine.Rendering.Universal { } - protected virtual string GetPipelineRendererAssetKey() + private protected virtual string GetPipelineRendererAssetKey() { return string.Empty; } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs index c546cc74..190d2a35 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs @@ -27,7 +27,7 @@ namespace XCEngine.Rendering.Universal Array.Empty(); } - protected override string GetPipelineRendererAssetKey() + private protected override string GetPipelineRendererAssetKey() { return "BuiltinForward"; } diff --git a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs index 0b1b1b74..0bcfc589 100644 --- a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs +++ b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs @@ -204,15 +204,21 @@ namespace ProjectScripts { return new ProjectCustomRenderer(); } + } - protected override string GetPipelineRendererAssetKey() + public abstract class ProjectBuiltinForwardRendererBackedAsset + : RendererBackedRenderPipelineAsset + { + protected sealed override string + GetPipelineRendererAssetKeyContextual( + int rendererIndex) { return "BuiltinForward"; } } public sealed class ProjectCustomRendererPipelineAsset - : RendererBackedRenderPipelineAsset + : ProjectBuiltinForwardRendererBackedAsset { public ProjectCustomRendererPipelineAsset() { @@ -333,11 +339,6 @@ namespace ProjectScripts }; } - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForward"; - } - public void InvalidateForTest() { ProjectRendererInvalidationProbeState @@ -347,7 +348,7 @@ namespace ProjectScripts } public sealed class ProjectRendererInvalidationProbeAsset - : RendererBackedRenderPipelineAsset + : ProjectBuiltinForwardRendererBackedAsset { private readonly ProjectRendererInvalidationProbeRendererData m_rendererData; @@ -461,11 +462,6 @@ namespace ProjectScripts }; } - protected override string GetPipelineRendererAssetKey() - { - return "BuiltinForward"; - } - public void InvalidateForTest() { ProjectPersistentFeatureProbeState @@ -475,7 +471,7 @@ namespace ProjectScripts } public sealed class ProjectPersistentFeatureProbeAsset - : RendererBackedRenderPipelineAsset + : ProjectBuiltinForwardRendererBackedAsset { private readonly ProjectPersistentFeatureProbeRendererData m_rendererData;