From cac6e34fa5e1674a38fa4d85d8a41cf61aff28ac Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sat, 18 Apr 2026 16:52:59 +0800 Subject: [PATCH] fix(rendering): clear managed SRP selection on runtime stop --- .../src/Scripting/Mono/MonoScriptRuntime.cpp | 21 +++--- tests/scripting/test_mono_script_runtime.cpp | 71 +++++++++++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp index fd9a5b9e..c6566368 100644 --- a/engine/src/Scripting/Mono/MonoScriptRuntime.cpp +++ b/engine/src/Scripting/Mono/MonoScriptRuntime.cpp @@ -303,6 +303,16 @@ MonoScriptRuntime* GetActiveMonoScriptRuntime() { return dynamic_cast(ScriptEngine::Get().GetRuntime()); } +void ClearManagedRenderPipelineSelection(MonoScriptRuntime* runtime) { + const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor = + Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + if (runtime != nullptr && descriptor.managedAssetHandle != 0u) { + runtime->ReleaseExternalManagedObject(descriptor.managedAssetHandle); + } + + Rendering::Pipelines::ClearManagedRenderPipelineAssetDescriptor(); +} + bool TryUnboxManagedBoolean(MonoObject* boxedValue, bool& outValue) { outValue = false; if (!boxedValue) { @@ -2724,13 +2734,7 @@ void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) { Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); if (assetObject == nullptr) { - if (runtime != nullptr && - currentDescriptor.managedAssetHandle != 0u) { - runtime->ReleaseExternalManagedObject( - currentDescriptor.managedAssetHandle); - } - - Rendering::Pipelines::ClearManagedRenderPipelineAssetDescriptor(); + ClearManagedRenderPipelineSelection(runtime); return; } @@ -3173,7 +3177,7 @@ bool MonoScriptRuntime::Initialize() { void MonoScriptRuntime::Shutdown() { Rendering::Pipelines::ClearManagedRenderPipelineBridge(); - Rendering::Pipelines::ClearManagedRenderPipelineAssetDescriptor(); + ClearManagedRenderPipelineSelection(this); GetManagedScriptableRenderContextRegistry().clear(); GetManagedScriptableRenderContextNextHandle() = 1; GetManagedScriptableRenderPipelineCameraRequestContextRegistry().clear(); @@ -3386,6 +3390,7 @@ void MonoScriptRuntime::OnRuntimeStart(Components::Scene* scene) { void MonoScriptRuntime::OnRuntimeStop(Components::Scene* scene) { (void)scene; + ClearManagedRenderPipelineSelection(this); ClearManagedInstances(); m_activeScene = nullptr; GetInternalCallScene() = nullptr; diff --git a/tests/scripting/test_mono_script_runtime.cpp b/tests/scripting/test_mono_script_runtime.cpp index b1a89917..cfb08423 100644 --- a/tests/scripting/test_mono_script_runtime.cpp +++ b/tests/scripting/test_mono_script_runtime.cpp @@ -343,6 +343,77 @@ TEST_F(MonoScriptRuntimeTest, ManagedGraphicsSettingsRoundTripsRenderPipelineAss "Gameplay.RenderPipelineApiProbeAsset"); } +TEST_F( + MonoScriptRuntimeTest, + RuntimeStopClearsManagedGraphicsSettingsSelection) { + Scene* runtimeScene = CreateScene("ManagedRenderPipelineStopClearsSelectionScene"); + GameObject* scriptObject = runtimeScene->CreateGameObject("RenderPipelineProbe"); + ScriptComponent* script = + AddScript(scriptObject, "Gameplay", "RenderPipelineApiProbe"); + ASSERT_NE(script, nullptr); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + const XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptorBeforeStop = + XCEngine::Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + ASSERT_TRUE(descriptorBeforeStop.IsValid()); + ASSERT_NE(descriptorBeforeStop.managedAssetHandle, 0u); + ASSERT_NE( + runtime->GetExternalManagedObject( + descriptorBeforeStop.managedAssetHandle), + nullptr); + + engine->OnRuntimeStop(); + + const XCEngine::Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptorAfterStop = + XCEngine::Rendering::Pipelines::GetManagedRenderPipelineAssetDescriptor(); + EXPECT_FALSE(descriptorAfterStop.IsValid()); + EXPECT_EQ(descriptorAfterStop.managedAssetHandle, 0u); + EXPECT_EQ( + runtime->GetExternalManagedObject( + descriptorBeforeStop.managedAssetHandle), + nullptr); +} + +TEST_F( + MonoScriptRuntimeTest, + CameraRendererFallsBackAfterRuntimeStopClearsManagedSelection) { + Scene* runtimeScene = CreateScene("ManagedRenderPipelineStopFallbackScene"); + GameObject* selectionObject = + runtimeScene->CreateGameObject("ManagedRenderPipelineSelection"); + ScriptComponent* selectionScript = + AddScript( + selectionObject, + "Gameplay", + "ManagedRenderPipelineRuntimeSelectionProbe"); + ASSERT_NE(selectionScript, nullptr); + + engine->OnRuntimeStart(runtimeScene); + engine->OnUpdate(0.016f); + + XCEngine::Rendering::CameraRenderer renderer; + ASSERT_NE( + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()), + nullptr); + + engine->OnRuntimeStop(); + + EXPECT_EQ( + dynamic_cast< + const XCEngine::Rendering::Pipelines::ManagedScriptableRenderPipelineAsset*>( + renderer.GetPipelineAsset()), + nullptr); + + auto* host = + dynamic_cast( + renderer.GetPipeline()); + ASSERT_NE(host, nullptr); + EXPECT_EQ(host->GetStageRecorder(), nullptr); +} + TEST_F( MonoScriptRuntimeTest, DefaultCameraRendererUsesManagedGraphicsSelectionToRecordMainSceneGraph) {