refactor(srp): unify managed pipeline instance ownership

Move shared managed ScriptableRenderPipeline instance ownership into MonoManagedRenderPipelineAssetRuntime.

Make stage recorders borrow the runtime-owned pipeline instead of creating and destroying private handles.

Add a regression test that locks one CreatePipeline call across multiple stage recorders.
This commit is contained in:
2026-04-20 00:44:09 +08:00
parent cbc0ddbd42
commit beaf5809d5
4 changed files with 272 additions and 37 deletions

View File

@@ -731,10 +731,11 @@ public:
m_runtime->m_initialized;
}
bool CreateManagedPipeline(uint32_t& outPipelineHandle) const;
bool AcquireManagedPipelineHandle(uint32_t& outPipelineHandle) const;
private:
bool EnsureManagedAsset() const;
void ReleaseManagedPipeline() const;
void ReleaseManagedAsset() const;
MonoObject* GetManagedAssetObject() const;
MonoMethod* ResolveCreatePipelineMethod(MonoObject* assetObject) const;
@@ -755,6 +756,8 @@ private:
mutable MonoMethod* m_getPipelineRendererAssetKeyMethod = nullptr;
mutable bool m_ownsManagedAssetHandle = false;
mutable bool m_assetCreationAttempted = false;
mutable uint32_t m_pipelineHandle = 0;
mutable bool m_pipelineCreationAttempted = false;
mutable bool m_pipelineRendererAssetResolved = false;
mutable std::shared_ptr<const Rendering::RenderPipelineAsset>
m_pipelineRendererAsset = nullptr;
@@ -777,7 +780,7 @@ public:
}
bool Initialize(const Rendering::RenderContext&) override {
return EnsureManagedPipeline();
return GetManagedPipelineObject() != nullptr;
}
void Shutdown() override {
@@ -791,10 +794,8 @@ public:
if (m_ownedSceneRenderer != nullptr) {
m_ownedSceneRenderer->Shutdown();
}
ReleaseManagedObjects();
m_supportsStageMethod = nullptr;
m_recordStageMethod = nullptr;
m_pipelineCreationAttempted = false;
m_boundSceneRenderer = nullptr;
}
@@ -806,12 +807,11 @@ public:
bool SupportsStageRenderGraph(Rendering::CameraFrameStage stage) const override {
if (!SupportsManagedRenderPipelineStageGraphRecording(stage) ||
!EnsureManagedPipeline()) {
!IsRuntimeAlive()) {
return false;
}
MonoObject* const pipelineObject =
m_runtime->GetManagedObject(m_pipelineHandle);
MonoObject* const pipelineObject = GetManagedPipelineObject();
MonoMethod* const method = ResolveSupportsStageMethod(pipelineObject);
if (!pipelineObject || !method) {
return false;
@@ -834,12 +834,11 @@ public:
bool RecordStageRenderGraph(
const Rendering::RenderPipelineStageRenderGraphContext& context) override {
if (!EnsureManagedPipeline()) {
if (!IsRuntimeAlive()) {
return false;
}
MonoObject* const pipelineObject =
m_runtime->GetManagedObject(m_pipelineHandle);
MonoObject* const pipelineObject = GetManagedPipelineObject();
MonoMethod* const method = ResolveRecordStageMethod(pipelineObject);
if (!pipelineObject || !method) {
return false;
@@ -895,30 +894,18 @@ private:
m_runtime != nullptr;
}
bool EnsureManagedPipeline() const {
if (m_pipelineHandle != 0) {
return true;
}
if (m_pipelineCreationAttempted || !IsRuntimeAlive()) {
return false;
}
m_pipelineCreationAttempted = true;
return m_assetRuntime->CreateManagedPipeline(m_pipelineHandle) &&
m_pipelineHandle != 0;
}
void ReleaseManagedObjects() {
MonoObject* GetManagedPipelineObject() const {
if (!IsRuntimeAlive()) {
m_pipelineHandle = 0;
return;
return nullptr;
}
if (m_pipelineHandle != 0) {
m_runtime->DestroyExternalManagedObject(m_pipelineHandle);
m_pipelineHandle = 0;
uint32_t pipelineHandle = 0;
if (!m_assetRuntime->AcquireManagedPipelineHandle(pipelineHandle) ||
pipelineHandle == 0) {
return nullptr;
}
return m_runtime->GetManagedObject(pipelineHandle);
}
MonoMethod* ResolveSupportsStageMethod(MonoObject* pipelineObject) const {
@@ -998,10 +985,8 @@ private:
std::shared_ptr<const MonoManagedRenderPipelineAssetRuntime> m_assetRuntime;
MonoScriptRuntime* m_runtime = nullptr;
mutable uint32_t m_pipelineHandle = 0;
mutable MonoMethod* m_supportsStageMethod = nullptr;
mutable MonoMethod* m_recordStageMethod = nullptr;
mutable bool m_pipelineCreationAttempted = false;
std::vector<std::unique_ptr<Rendering::RenderPass>> m_fullscreenPassPool = {};
Rendering::NativeSceneRenderer* m_boundSceneRenderer = nullptr;
std::unique_ptr<Rendering::NativeSceneRenderer> m_ownedSceneRenderer =
@@ -1131,17 +1116,28 @@ MonoManagedRenderPipelineAssetRuntime::GetPipelineRendererAsset() const {
return m_pipelineRendererAsset;
}
bool MonoManagedRenderPipelineAssetRuntime::CreateManagedPipeline(
bool MonoManagedRenderPipelineAssetRuntime::AcquireManagedPipelineHandle(
uint32_t& outPipelineHandle) const {
outPipelineHandle = 0;
if (!EnsureManagedAsset()) {
if (m_pipelineHandle != 0) {
outPipelineHandle = m_pipelineHandle;
return true;
}
if (m_pipelineCreationAttempted) {
outPipelineHandle = 0;
return false;
}
if (!EnsureManagedAsset()) {
outPipelineHandle = 0;
return false;
}
m_pipelineCreationAttempted = true;
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const createPipelineMethod =
ResolveCreatePipelineMethod(assetObject);
if (assetObject == nullptr || createPipelineMethod == nullptr) {
outPipelineHandle = 0;
return false;
}
@@ -1152,6 +1148,7 @@ bool MonoManagedRenderPipelineAssetRuntime::CreateManagedPipeline(
nullptr,
&pipelineObject) ||
pipelineObject == nullptr) {
outPipelineHandle = 0;
return false;
}
@@ -1161,11 +1158,13 @@ bool MonoManagedRenderPipelineAssetRuntime::CreateManagedPipeline(
m_runtime->SetError(
"Managed render pipeline asset returned a non-ScriptableRenderPipeline instance: " +
m_descriptor.GetFullName() + ".");
outPipelineHandle = 0;
return false;
}
outPipelineHandle = m_runtime->RetainExternalManagedObject(pipelineObject);
return outPipelineHandle != 0;
m_pipelineHandle = m_runtime->RetainExternalManagedObject(pipelineObject);
outPipelineHandle = m_pipelineHandle;
return m_pipelineHandle != 0;
}
bool MonoManagedRenderPipelineAssetRuntime::EnsureManagedAsset() const {
@@ -1232,7 +1231,22 @@ bool MonoManagedRenderPipelineAssetRuntime::EnsureManagedAsset() const {
return m_ownsManagedAssetHandle;
}
void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedPipeline() const {
m_pipelineCreationAttempted = false;
if (!IsRuntimeAlive()) {
m_pipelineHandle = 0;
return;
}
if (m_pipelineHandle != 0) {
m_runtime->DestroyExternalManagedObject(m_pipelineHandle);
m_pipelineHandle = 0;
}
}
void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const {
ReleaseManagedPipeline();
m_createPipelineMethod = nullptr;
m_configureCameraRenderRequestMethod = nullptr;
m_getDefaultFinalColorSettingsMethod = nullptr;