refactor(rendering): retain managed pipeline asset runtime per native asset

This commit is contained in:
2026-04-17 23:54:04 +08:00
parent 6838b00d97
commit fa9a5ffb00
6 changed files with 395 additions and 214 deletions

View File

@@ -272,10 +272,11 @@ bool SupportsManagedRenderPipelineStageGraphRecording(
} // namespace
class MonoManagedRenderPipelineStageRecorder final
: public Rendering::RenderPipelineStageRecorder {
class MonoManagedRenderPipelineAssetRuntime final
: public Rendering::Pipelines::ManagedRenderPipelineAssetRuntime
, public std::enable_shared_from_this<MonoManagedRenderPipelineAssetRuntime> {
public:
MonoManagedRenderPipelineStageRecorder(
MonoManagedRenderPipelineAssetRuntime(
MonoScriptRuntime* runtime,
std::weak_ptr<void> runtimeLifetime,
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor)
@@ -284,6 +285,56 @@ public:
, m_descriptor(std::move(descriptor)) {
}
~MonoManagedRenderPipelineAssetRuntime() override {
ReleaseManagedAsset();
}
std::unique_ptr<Rendering::RenderPipelineStageRecorder> CreateStageRecorder() const override;
void ConfigureCameraFramePlan(
Rendering::CameraFramePlan& plan) const override;
MonoScriptRuntime* GetRuntime() const {
return m_runtime;
}
bool IsRuntimeAlive() const {
return m_runtime != nullptr &&
!m_runtimeLifetime.expired() &&
m_runtime->m_initialized;
}
bool CreateManagedPipeline(uint32_t& outPipelineHandle) const;
private:
bool EnsureManagedAsset() const;
void ReleaseManagedAsset() const;
MonoObject* GetManagedAssetObject() const;
MonoMethod* ResolveCreatePipelineMethod(MonoObject* assetObject) const;
MonoMethod* ResolveConfigureCameraFramePlanMethod(
MonoObject* assetObject) const;
MonoScriptRuntime* m_runtime = nullptr;
std::weak_ptr<void> m_runtimeLifetime;
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor m_descriptor;
mutable uint32_t m_assetHandle = 0;
mutable MonoMethod* m_createPipelineMethod = nullptr;
mutable MonoMethod* m_configureCameraFramePlanMethod = nullptr;
mutable bool m_assetCreationAttempted = false;
};
class MonoManagedRenderPipelineStageRecorder final
: public Rendering::RenderPipelineStageRecorder {
public:
explicit MonoManagedRenderPipelineStageRecorder(
std::shared_ptr<const MonoManagedRenderPipelineAssetRuntime> assetRuntime)
: m_assetRuntime(std::move(assetRuntime))
, m_runtime(
m_assetRuntime != nullptr
? m_assetRuntime->GetRuntime()
: nullptr) {
}
~MonoManagedRenderPipelineStageRecorder() override {
Shutdown();
}
@@ -389,91 +440,27 @@ public:
private:
bool IsRuntimeAlive() const {
return m_runtime != nullptr &&
!m_runtimeLifetime.expired() &&
m_runtime->m_initialized;
return m_assetRuntime != nullptr &&
m_assetRuntime->IsRuntimeAlive() &&
m_runtime != nullptr;
}
bool EnsureManagedPipeline() const {
if (m_pipelineHandle != 0) {
return true;
}
if (m_pipelineCreationAttempted || !IsRuntimeAlive() ||
!m_descriptor.IsValid()) {
if (m_pipelineCreationAttempted || !IsRuntimeAlive()) {
return false;
}
m_pipelineCreationAttempted = true;
MonoClass* assetClass = nullptr;
if (!m_runtime->ResolveManagedClass(
m_descriptor.assemblyName,
m_descriptor.namespaceName,
m_descriptor.className,
assetClass) ||
assetClass == nullptr) {
return false;
}
if (!IsMonoClassOrSubclass(
assetClass,
m_runtime->m_scriptableRenderPipelineAssetClass)) {
m_runtime->SetError(
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
m_descriptor.GetFullName() + ".");
return false;
}
uint32_t assetHandle = 0;
if (!m_runtime->CreateExternalManagedObject(assetClass, assetHandle) ||
assetHandle == 0) {
return false;
}
MonoObject* const assetObject = m_runtime->GetManagedObject(assetHandle);
MonoMethod* const createPipelineMethod =
m_runtime->ResolveManagedMethod(assetObject, "CreatePipeline", 0);
if (!assetObject || !createPipelineMethod) {
m_runtime->DestroyExternalManagedObject(assetHandle);
return false;
}
MonoObject* pipelineObject = nullptr;
if (!m_runtime->InvokeManagedMethod(
assetObject,
createPipelineMethod,
nullptr,
&pipelineObject) ||
pipelineObject == nullptr) {
m_runtime->DestroyExternalManagedObject(assetHandle);
return false;
}
if (!IsMonoClassOrSubclass(
mono_object_get_class(pipelineObject),
m_runtime->m_scriptableRenderPipelineClass)) {
m_runtime->SetError(
"Managed render pipeline asset returned a non-ScriptableRenderPipeline instance: " +
m_descriptor.GetFullName() + ".");
m_runtime->DestroyExternalManagedObject(assetHandle);
return false;
}
const uint32_t pipelineHandle =
m_runtime->RetainExternalManagedObject(pipelineObject);
if (pipelineHandle == 0) {
m_runtime->DestroyExternalManagedObject(assetHandle);
return false;
}
m_assetHandle = assetHandle;
m_pipelineHandle = pipelineHandle;
return true;
return m_assetRuntime->CreateManagedPipeline(m_pipelineHandle) &&
m_pipelineHandle != 0;
}
void ReleaseManagedObjects() {
if (!IsRuntimeAlive()) {
m_assetHandle = 0;
m_pipelineHandle = 0;
return;
}
@@ -482,10 +469,6 @@ private:
m_runtime->DestroyExternalManagedObject(m_pipelineHandle);
m_pipelineHandle = 0;
}
if (m_assetHandle != 0) {
m_runtime->DestroyExternalManagedObject(m_assetHandle);
m_assetHandle = 0;
}
}
MonoMethod* ResolveSupportsStageMethod(MonoObject* pipelineObject) const {
@@ -546,10 +529,8 @@ private:
passes);
}
std::shared_ptr<const MonoManagedRenderPipelineAssetRuntime> m_assetRuntime;
MonoScriptRuntime* m_runtime = nullptr;
std::weak_ptr<void> m_runtimeLifetime;
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor m_descriptor;
mutable uint32_t m_assetHandle = 0;
mutable uint32_t m_pipelineHandle = 0;
mutable MonoMethod* m_supportsStageMethod = nullptr;
mutable MonoMethod* m_recordStageMethod = nullptr;
@@ -559,6 +540,172 @@ private:
Rendering::Pipelines::BuiltinForwardPipeline m_builtinForwardPipeline;
};
std::unique_ptr<Rendering::RenderPipelineStageRecorder>
MonoManagedRenderPipelineAssetRuntime::CreateStageRecorder() const {
if (!IsRuntimeAlive() || !m_descriptor.IsValid()) {
return nullptr;
}
return std::make_unique<MonoManagedRenderPipelineStageRecorder>(
shared_from_this());
}
void MonoManagedRenderPipelineAssetRuntime::ConfigureCameraFramePlan(
Rendering::CameraFramePlan& plan) const {
if (!EnsureManagedAsset()) {
return;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const method =
ResolveConfigureCameraFramePlanMethod(assetObject);
if (assetObject == nullptr || method == nullptr) {
return;
}
ManagedScriptableRenderPipelinePlanningContextState planningContextState = {};
planningContextState.plan = &plan;
const uint64_t planningContextHandle =
RegisterManagedScriptableRenderPipelinePlanningContextState(
planningContextState);
MonoObject* const planningContextObject =
m_runtime->CreateManagedScriptableRenderPipelinePlanningContext(
planningContextHandle);
if (planningContextObject == nullptr) {
UnregisterManagedScriptableRenderPipelinePlanningContextState(
planningContextHandle);
return;
}
void* args[1] = { planningContextObject };
m_runtime->InvokeManagedMethod(
assetObject,
method,
args,
nullptr);
UnregisterManagedScriptableRenderPipelinePlanningContextState(
planningContextHandle);
}
bool MonoManagedRenderPipelineAssetRuntime::CreateManagedPipeline(
uint32_t& outPipelineHandle) const {
outPipelineHandle = 0;
if (!EnsureManagedAsset()) {
return false;
}
MonoObject* const assetObject = GetManagedAssetObject();
MonoMethod* const createPipelineMethod =
ResolveCreatePipelineMethod(assetObject);
if (assetObject == nullptr || createPipelineMethod == nullptr) {
return false;
}
MonoObject* pipelineObject = nullptr;
if (!m_runtime->InvokeManagedMethod(
assetObject,
createPipelineMethod,
nullptr,
&pipelineObject) ||
pipelineObject == nullptr) {
return false;
}
if (!IsMonoClassOrSubclass(
mono_object_get_class(pipelineObject),
m_runtime->m_scriptableRenderPipelineClass)) {
m_runtime->SetError(
"Managed render pipeline asset returned a non-ScriptableRenderPipeline instance: " +
m_descriptor.GetFullName() + ".");
return false;
}
outPipelineHandle = m_runtime->RetainExternalManagedObject(pipelineObject);
return outPipelineHandle != 0;
}
bool MonoManagedRenderPipelineAssetRuntime::EnsureManagedAsset() const {
if (m_assetHandle != 0) {
return true;
}
if (m_assetCreationAttempted || !IsRuntimeAlive() || !m_descriptor.IsValid()) {
return false;
}
m_assetCreationAttempted = true;
MonoClass* assetClass = nullptr;
if (!m_runtime->ResolveManagedClass(
m_descriptor.assemblyName,
m_descriptor.namespaceName,
m_descriptor.className,
assetClass) ||
assetClass == nullptr) {
return false;
}
if (!IsMonoClassOrSubclass(
assetClass,
m_runtime->m_scriptableRenderPipelineAssetClass)) {
m_runtime->SetError(
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
m_descriptor.GetFullName() + ".");
return false;
}
return m_runtime->CreateExternalManagedObject(assetClass, m_assetHandle) &&
m_assetHandle != 0;
}
void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const {
m_createPipelineMethod = nullptr;
m_configureCameraFramePlanMethod = nullptr;
m_assetCreationAttempted = false;
if (!IsRuntimeAlive()) {
m_assetHandle = 0;
return;
}
if (m_assetHandle != 0) {
m_runtime->DestroyExternalManagedObject(m_assetHandle);
m_assetHandle = 0;
}
}
MonoObject* MonoManagedRenderPipelineAssetRuntime::GetManagedAssetObject() const {
return m_assetHandle != 0
? m_runtime->GetManagedObject(m_assetHandle)
: nullptr;
}
MonoMethod* MonoManagedRenderPipelineAssetRuntime::ResolveCreatePipelineMethod(
MonoObject* assetObject) const {
if (m_createPipelineMethod == nullptr) {
m_createPipelineMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"CreatePipeline",
0);
}
return m_createPipelineMethod;
}
MonoMethod*
MonoManagedRenderPipelineAssetRuntime::ResolveConfigureCameraFramePlanMethod(
MonoObject* assetObject) const {
if (m_configureCameraFramePlanMethod == nullptr) {
m_configureCameraFramePlanMethod =
m_runtime->ResolveManagedMethod(
assetObject,
"ConfigureCameraFramePlan",
1);
}
return m_configureCameraFramePlanMethod;
}
class MonoManagedRenderPipelineBridge final
: public Rendering::Pipelines::ManagedRenderPipelineBridge {
public:
@@ -569,71 +716,20 @@ public:
, m_runtimeLifetime(std::move(runtimeLifetime)) {
}
std::unique_ptr<Rendering::RenderPipelineStageRecorder> CreateStageRecorder(
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor) const override {
std::shared_ptr<const Rendering::Pipelines::ManagedRenderPipelineAssetRuntime>
CreateAssetRuntime(
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor)
const override {
if (!IsRuntimeAlive() || !descriptor.IsValid()) {
return nullptr;
}
return std::make_unique<MonoManagedRenderPipelineStageRecorder>(
return std::make_shared<MonoManagedRenderPipelineAssetRuntime>(
m_runtime,
m_runtimeLifetime,
descriptor);
}
void ConfigureCameraFramePlan(
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor,
Rendering::CameraFramePlan& plan) const override {
if (!IsRuntimeAlive() || !descriptor.IsValid()) {
return;
}
uint32_t assetHandle = 0;
MonoObject* const assetObject =
CreateManagedAssetInstance(descriptor, assetHandle);
if (assetObject == nullptr || assetHandle == 0) {
if (assetHandle != 0) {
m_runtime->DestroyExternalManagedObject(assetHandle);
}
return;
}
MonoMethod* const method =
m_runtime->ResolveManagedMethod(
assetObject,
"ConfigureCameraFramePlan",
1);
if (method == nullptr) {
m_runtime->DestroyExternalManagedObject(assetHandle);
return;
}
ManagedScriptableRenderPipelinePlanningContextState planningContextState = {};
planningContextState.plan = &plan;
const uint64_t planningContextHandle =
RegisterManagedScriptableRenderPipelinePlanningContextState(
planningContextState);
MonoObject* const planningContextObject =
m_runtime->CreateManagedScriptableRenderPipelinePlanningContext(
planningContextHandle);
if (planningContextObject == nullptr) {
UnregisterManagedScriptableRenderPipelinePlanningContextState(
planningContextHandle);
m_runtime->DestroyExternalManagedObject(assetHandle);
return;
}
void* args[1] = { planningContextObject };
m_runtime->InvokeManagedMethod(
assetObject,
method,
args,
nullptr);
UnregisterManagedScriptableRenderPipelinePlanningContextState(
planningContextHandle);
m_runtime->DestroyExternalManagedObject(assetHandle);
}
private:
bool IsRuntimeAlive() const {
return m_runtime != nullptr &&
@@ -641,38 +737,6 @@ private:
m_runtime->m_initialized;
}
MonoObject* CreateManagedAssetInstance(
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor,
uint32_t& outAssetHandle) const {
outAssetHandle = 0;
MonoClass* assetClass = nullptr;
if (!m_runtime->ResolveManagedClass(
descriptor.assemblyName,
descriptor.namespaceName,
descriptor.className,
assetClass) ||
assetClass == nullptr) {
return nullptr;
}
if (!IsMonoClassOrSubclass(
assetClass,
m_runtime->m_scriptableRenderPipelineAssetClass)) {
m_runtime->SetError(
"Managed render pipeline asset must derive from ScriptableRenderPipelineAsset: " +
descriptor.GetFullName() + ".");
return nullptr;
}
if (!m_runtime->CreateExternalManagedObject(assetClass, outAssetHandle) ||
outAssetHandle == 0) {
return nullptr;
}
return m_runtime->GetManagedObject(outAssetHandle);
}
MonoScriptRuntime* m_runtime = nullptr;
std::weak_ptr<void> m_runtimeLifetime;
};