fix(rendering): clear managed SRP selection on runtime stop

This commit is contained in:
2026-04-18 16:52:59 +08:00
parent 30ee70a4d1
commit cac6e34fa5
2 changed files with 84 additions and 8 deletions

View File

@@ -303,6 +303,16 @@ MonoScriptRuntime* GetActiveMonoScriptRuntime() {
return dynamic_cast<MonoScriptRuntime*>(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;

View File

@@ -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<XCEngine::Rendering::Pipelines::ScriptableRenderPipelineHost*>(
renderer.GetPipeline());
ASSERT_NE(host, nullptr);
EXPECT_EQ(host->GetStageRecorder(), nullptr);
}
TEST_F(
MonoScriptRuntimeTest,
DefaultCameraRendererUsesManagedGraphicsSelectionToRecordMainSceneGraph) {