refactor(rendering): retain managed pipeline asset runtime per native asset
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user