diff --git a/docs/used/SRP_UniversalManagedCameraFrameBaselineSignalPlan_完成归档_2026-04-21.md b/docs/used/SRP_UniversalManagedCameraFrameBaselineSignalPlan_完成归档_2026-04-21.md new file mode 100644 index 00000000..76fb7e51 --- /dev/null +++ b/docs/used/SRP_UniversalManagedCameraFrameBaselineSignalPlan_完成归档_2026-04-21.md @@ -0,0 +1,58 @@ +# SRP Universal Managed Camera Frame Baseline Signal Plan 2026-04-21 + +## Goal + +Stop renderer-backed managed pipelines from acquiring native camera-frame baseline behavior through camera-frame plan policy keys, and replace that path with an explicit managed capability signal. + +## Why This Stage + +The previous stage split a native managed baseline policy from the old default camera-frame plan policy, but renderer-backed managed pipelines still reach that baseline indirectly: + +1. managed asset runtime asks for a camera-frame plan policy key; +2. renderer-backed managed asset selects a builtin baseline key; +3. native host resolves that key back into baseline behavior. + +That is still string-driven indirection in the core SRP path. The cleaner ownership model is: + +1. managed asset says whether it needs native camera-frame baseline preparation; +2. native host applies that baseline directly; +3. managed renderer data / renderer / features continue the actual frame planning. + +## Scope + +Included: + +1. add a managed asset runtime capability signal for native camera-frame baseline usage; +2. make `ManagedScriptableRenderPipelineAsset` apply native baseline directly from that signal; +3. remove renderer-backed managed reliance on camera-frame plan policy key selection for this path; +4. remove renderer-data-level camera-frame plan policy key plumbing if it is no longer used; +5. rebuild `XCEditor` and run old editor smoke. + +Not included: + +1. deleting generic camera-frame plan policy key support for all possible managed assets; +2. moving final-color policy resolution fully into managed code; +3. deleting the legacy native default frame-plan policy for non-managed pipelines; +4. deferred renderer work. + +## Acceptance + +This stage is complete when: + +1. renderer-backed managed pipelines request native baseline through an explicit capability signal instead of a camera-frame plan policy key; +2. `ManagedScriptableRenderPipelineAsset` applies baseline directly for that path; +3. renderer-data-level camera-frame policy key plumbing is removed if unused; +4. `XCEditor` build passes; +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` for about 12 seconds; +3. verified fresh `editor/bin/Debug/editor.log` contains `SceneReady`. + +Observed log line: + +`[2026-04-21 13:34:54] [INFO] [General] [SceneLoadTrace] SceneReady elapsed_ms=6190 first_frame_ms=746 peak_pending_async=9` diff --git a/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h b/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h index dcb9627b..1917aaad 100644 --- a/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h +++ b/engine/include/XCEngine/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h @@ -104,6 +104,14 @@ public: (void)rendererIndex; return GetCameraFramePlanPolicyAssetKey(); } + virtual bool UsesNativeCameraFramePlanBaseline() const { + return false; + } + virtual bool UsesNativeCameraFramePlanBaseline( + int32_t rendererIndex) const { + (void)rendererIndex; + return UsesNativeCameraFramePlanBaseline(); + } virtual std::string GetRenderSceneSetupPolicyAssetKey() const { return {}; } diff --git a/engine/src/Rendering/Internal/RenderPipelineFactory.cpp b/engine/src/Rendering/Internal/RenderPipelineFactory.cpp index 2aee2666..b906ce84 100644 --- a/engine/src/Rendering/Internal/RenderPipelineFactory.cpp +++ b/engine/src/Rendering/Internal/RenderPipelineFactory.cpp @@ -220,18 +220,8 @@ void EnsureBuiltinCameraFramePlanPolicyRegistryInitialized() { plan, defaultFinalColorSettings); }); - registry.emplace( - "BuiltinManagedCameraFramePlanBaseline", - [](CameraFramePlan& plan, - const FinalColorSettings& defaultFinalColorSettings) { - ApplyDefaultRenderPipelineAssetCameraFramePlanBaselinePolicy( - plan, - defaultFinalColorSettings); - }); GetBuiltinCameraFramePlanPolicyKeys().insert( "BuiltinDefaultCameraFramePlan"); - GetBuiltinCameraFramePlanPolicyKeys().insert( - "BuiltinManagedCameraFramePlanBaseline"); return true; }(); (void)initialized; diff --git a/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp b/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp index b835db66..5ae756f9 100644 --- a/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp +++ b/engine/src/Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.cpp @@ -179,11 +179,20 @@ void ManagedScriptableRenderPipelineAsset::ConfigureCameraFramePlan( if (const std::shared_ptr runtime = ResolveManagedAssetRuntime(); runtime != nullptr) { + const FinalColorSettings defaultFinalColorSettings = + GetDefaultFinalColorSettings(); + if (runtime->UsesNativeCameraFramePlanBaseline( + plan.request.rendererIndex)) { + ApplyDefaultRenderPipelineAssetCameraFramePlanBaselinePolicy( + plan, + defaultFinalColorSettings); + } else { ApplyManagedCameraFramePlanPolicyOrDefault( runtime->GetCameraFramePlanPolicyAssetKey( plan.request.rendererIndex), plan, - GetDefaultFinalColorSettings()); + defaultFinalColorSettings); + } runtime->ConfigureCameraFramePlan(plan); return; } diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index fc220985..476ea594 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -1370,6 +1370,9 @@ public: override; std::string GetCameraFramePlanPolicyAssetKey( int32_t rendererIndex) const override; + bool UsesNativeCameraFramePlanBaseline() const override; + bool UsesNativeCameraFramePlanBaseline( + int32_t rendererIndex) const override; std::string GetRenderSceneSetupPolicyAssetKey() const override; std::string GetRenderSceneSetupPolicyAssetKey( @@ -1423,6 +1426,10 @@ private: MonoObject* assetObject) const; MonoMethod* ResolveGetCameraFramePlanPolicyAssetKeyContextualMethod( MonoObject* assetObject) const; + MonoMethod* ResolveUsesNativeCameraFramePlanBaselineMethod( + MonoObject* assetObject) const; + MonoMethod* ResolveUsesNativeCameraFramePlanBaselineContextualMethod( + MonoObject* assetObject) const; MonoMethod* ResolveGetRenderSceneSetupPolicyAssetKeyMethod( MonoObject* assetObject) const; MonoMethod* ResolveGetRenderSceneSetupPolicyAssetKeyContextualMethod( @@ -1460,6 +1467,11 @@ private: mutable MonoMethod* m_getCameraFramePlanPolicyAssetKeyContextualMethod = nullptr; + mutable MonoMethod* m_usesNativeCameraFramePlanBaselineMethod = + nullptr; + mutable MonoMethod* + m_usesNativeCameraFramePlanBaselineContextualMethod = + nullptr; mutable MonoMethod* m_getRenderSceneSetupPolicyAssetKeyMethod = nullptr; mutable MonoMethod* @@ -2178,6 +2190,66 @@ std::string MonoManagedRenderPipelineAssetRuntime:: reinterpret_cast(managedKeyObject)); } +bool MonoManagedRenderPipelineAssetRuntime::UsesNativeCameraFramePlanBaseline() + const { + return UsesNativeCameraFramePlanBaseline(-1); +} + +bool MonoManagedRenderPipelineAssetRuntime::UsesNativeCameraFramePlanBaseline( + int32_t rendererIndex) const { + if (!SyncManagedAssetRuntimeState()) { + return false; + } + + MonoObject* const assetObject = GetManagedAssetObject(); + if (assetObject == nullptr) { + return false; + } + + MonoMethod* const contextualMethod = + ResolveUsesNativeCameraFramePlanBaselineContextualMethod( + assetObject); + if (contextualMethod != nullptr) { + void* args[1] = { &rendererIndex }; + MonoObject* managedValueObject = nullptr; + if (!m_runtime->InvokeManagedMethod( + assetObject, + contextualMethod, + args, + &managedValueObject)) { + return false; + } + + bool usesBaseline = false; + return TryUnboxManagedBoolean( + managedValueObject, + usesBaseline) && + usesBaseline; + } + + MonoMethod* const method = + ResolveUsesNativeCameraFramePlanBaselineMethod( + assetObject); + if (method == nullptr) { + return false; + } + + MonoObject* managedValueObject = nullptr; + if (!m_runtime->InvokeManagedMethod( + assetObject, + method, + nullptr, + &managedValueObject)) { + return false; + } + + bool usesBaseline = false; + return TryUnboxManagedBoolean( + managedValueObject, + usesBaseline) && + usesBaseline; +} + std::string MonoManagedRenderPipelineAssetRuntime:: GetRenderSceneSetupPolicyAssetKey() const { return GetRenderSceneSetupPolicyAssetKey(-1); @@ -2594,6 +2666,8 @@ void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const { m_getPipelineRendererAssetKeyContextualMethod = nullptr; m_getCameraFramePlanPolicyAssetKeyMethod = nullptr; m_getCameraFramePlanPolicyAssetKeyContextualMethod = nullptr; + m_usesNativeCameraFramePlanBaselineMethod = nullptr; + m_usesNativeCameraFramePlanBaselineContextualMethod = nullptr; m_getRenderSceneSetupPolicyAssetKeyMethod = nullptr; m_getRenderSceneSetupPolicyAssetKeyContextualMethod = nullptr; m_getDirectionalShadowPlanningPolicyAssetKeyMethod = nullptr; @@ -2781,6 +2855,37 @@ MonoManagedRenderPipelineAssetRuntime:: return m_getCameraFramePlanPolicyAssetKeyContextualMethod; } +MonoMethod* +MonoManagedRenderPipelineAssetRuntime:: + ResolveUsesNativeCameraFramePlanBaselineMethod( + MonoObject* assetObject) const { + if (m_usesNativeCameraFramePlanBaselineMethod == nullptr) { + m_usesNativeCameraFramePlanBaselineMethod = + m_runtime->ResolveManagedMethod( + assetObject, + "UsesNativeCameraFramePlanBaseline", + 0); + } + + return m_usesNativeCameraFramePlanBaselineMethod; +} + +MonoMethod* +MonoManagedRenderPipelineAssetRuntime:: + ResolveUsesNativeCameraFramePlanBaselineContextualMethod( + MonoObject* assetObject) const { + if (m_usesNativeCameraFramePlanBaselineContextualMethod == + nullptr) { + m_usesNativeCameraFramePlanBaselineContextualMethod = + m_runtime->ResolveManagedMethod( + assetObject, + "UsesNativeCameraFramePlanBaselineContextual", + 1); + } + + return m_usesNativeCameraFramePlanBaselineContextualMethod; +} + MonoMethod* MonoManagedRenderPipelineAssetRuntime:: ResolveGetRenderSceneSetupPolicyAssetKeyMethod( diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs index f8876854..2c5af238 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs @@ -88,34 +88,6 @@ namespace XCEngine.Rendering.Universal : string.Empty; } - protected override string GetCameraFramePlanPolicyAssetKeyContextual( - int rendererIndex) - { - ScriptableRendererData resolvedRendererData = - GetRendererData(rendererIndex); - if (resolvedRendererData != null) - { - string assetKey = - resolvedRendererData - .GetCameraFramePlanPolicyAssetKeyInstance(); - if (!string.IsNullOrEmpty(assetKey)) - { - return assetKey; - } - } - - string contextualAssetKey = - base.GetCameraFramePlanPolicyAssetKeyContextual( - rendererIndex); - if (!string.IsNullOrEmpty(contextualAssetKey)) - { - return contextualAssetKey; - } - - return GetRendererBackedCameraFramePlanPolicyAssetKey( - rendererIndex); - } - protected override string GetRenderSceneSetupPolicyAssetKeyContextual( int rendererIndex) @@ -238,20 +210,17 @@ namespace XCEngine.Rendering.Universal return null; } - protected virtual string - GetRendererBackedCameraFramePlanPolicyAssetKey( - int rendererIndex) - { - return UsesExplicitFullscreenStagePlanning() - ? "BuiltinManagedCameraFramePlanBaseline" - : string.Empty; - } - protected virtual bool UsesExplicitFullscreenStagePlanning() { return true; } + protected override bool UsesNativeCameraFramePlanBaselineContextual( + int rendererIndex) + { + return UsesExplicitFullscreenStagePlanning(); + } + internal ScriptableRendererData GetDefaultRendererData() { return ResolveSelectedRendererData(); diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs index 1cb908b7..0ed5ea9e 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs @@ -61,11 +61,6 @@ namespace XCEngine.Rendering.Universal return GetPipelineRendererAssetKey(); } - internal string GetCameraFramePlanPolicyAssetKeyInstance() - { - return GetCameraFramePlanPolicyAssetKey(); - } - internal string GetRenderSceneSetupPolicyAssetKeyInstance() { return GetRenderSceneSetupPolicyAssetKey(); @@ -176,11 +171,6 @@ namespace XCEngine.Rendering.Universal return string.Empty; } - protected virtual string GetCameraFramePlanPolicyAssetKey() - { - return string.Empty; - } - protected virtual string GetRenderSceneSetupPolicyAssetKey() { return string.Empty; diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs index 53148e43..08439fd8 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderPipelineAsset.cs @@ -69,6 +69,17 @@ namespace XCEngine.Rendering return GetCameraFramePlanPolicyAssetKey(); } + protected virtual bool UsesNativeCameraFramePlanBaseline() + { + return false; + } + + protected virtual bool UsesNativeCameraFramePlanBaselineContextual( + int rendererIndex) + { + return UsesNativeCameraFramePlanBaseline(); + } + protected virtual string GetRenderSceneSetupPolicyAssetKey() { return string.Empty;