feat(rendering): add managed fullscreen stage planning seam
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "Debug/Logger.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "Physics/PhysicsWorld.h"
|
||||
#include "Rendering/Execution/CameraFramePlan.h"
|
||||
#include "Rendering/Passes/BuiltinColorScalePostProcessPass.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardSceneRecorder.h"
|
||||
@@ -96,6 +97,11 @@ struct ManagedScriptableRenderContextState {
|
||||
std::vector<Math::Vector4> queuedBuiltinColorScaleFullscreenPasses = {};
|
||||
};
|
||||
|
||||
struct ManagedScriptableRenderPipelinePlanningContextState {
|
||||
uint64_t handle = 0;
|
||||
Rendering::CameraFramePlan* plan = nullptr;
|
||||
};
|
||||
|
||||
uint64_t& GetManagedScriptableRenderContextNextHandle() {
|
||||
static uint64_t nextHandle = 1;
|
||||
return nextHandle;
|
||||
@@ -135,6 +141,49 @@ void UnregisterManagedScriptableRenderContextState(uint64_t handle) {
|
||||
GetManagedScriptableRenderContextRegistry().erase(handle);
|
||||
}
|
||||
|
||||
uint64_t& GetManagedScriptableRenderPipelinePlanningContextNextHandle() {
|
||||
static uint64_t nextHandle = 1;
|
||||
return nextHandle;
|
||||
}
|
||||
|
||||
std::unordered_map<uint64_t, ManagedScriptableRenderPipelinePlanningContextState*>&
|
||||
GetManagedScriptableRenderPipelinePlanningContextRegistry() {
|
||||
static std::unordered_map<uint64_t, ManagedScriptableRenderPipelinePlanningContextState*>
|
||||
registry;
|
||||
return registry;
|
||||
}
|
||||
|
||||
ManagedScriptableRenderPipelinePlanningContextState*
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(
|
||||
uint64_t handle) {
|
||||
const auto it =
|
||||
GetManagedScriptableRenderPipelinePlanningContextRegistry().find(handle);
|
||||
return it != GetManagedScriptableRenderPipelinePlanningContextRegistry().end()
|
||||
? it->second
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
uint64_t RegisterManagedScriptableRenderPipelinePlanningContextState(
|
||||
ManagedScriptableRenderPipelinePlanningContextState& state) {
|
||||
uint64_t handle =
|
||||
GetManagedScriptableRenderPipelinePlanningContextNextHandle()++;
|
||||
if (handle == 0) {
|
||||
handle = GetManagedScriptableRenderPipelinePlanningContextNextHandle()++;
|
||||
}
|
||||
|
||||
state.handle = handle;
|
||||
GetManagedScriptableRenderPipelinePlanningContextRegistry()[handle] = &state;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void UnregisterManagedScriptableRenderPipelinePlanningContextState(uint64_t handle) {
|
||||
if (handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetManagedScriptableRenderPipelinePlanningContextRegistry().erase(handle);
|
||||
}
|
||||
|
||||
void CleanupMonoRootDomainAtExit() {
|
||||
MonoRootState& rootState = GetMonoRootState();
|
||||
if (!rootState.rootDomain) {
|
||||
@@ -522,9 +571,7 @@ public:
|
||||
|
||||
std::unique_ptr<Rendering::RenderPipelineStageRecorder> CreateStageRecorder(
|
||||
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor& descriptor) const override {
|
||||
if (m_runtime == nullptr ||
|
||||
m_runtimeLifetime.expired() ||
|
||||
!descriptor.IsValid()) {
|
||||
if (!IsRuntimeAlive() || !descriptor.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -534,7 +581,98 @@ public:
|
||||
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 &&
|
||||
!m_runtimeLifetime.expired() &&
|
||||
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;
|
||||
};
|
||||
@@ -2307,6 +2445,68 @@ InternalCall_Rendering_ScriptableRenderContext_RecordBuiltinColorScaleFullscreen
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearPostProcessStage(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedScriptableRenderPipelinePlanningContextState* const state =
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
|
||||
if (state == nullptr || state->plan == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->plan->ClearFullscreenStage(Rendering::CameraFrameStage::PostProcess);
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestPostProcessStage(
|
||||
uint64_t nativeHandle,
|
||||
int32_t source,
|
||||
mono_bool usesGraphManagedOutputColor) {
|
||||
ManagedScriptableRenderPipelinePlanningContextState* const state =
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->plan == nullptr ||
|
||||
source == static_cast<int32_t>(Rendering::CameraFrameColorSource::ExplicitSurface)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return state->plan->RequestFullscreenStage(
|
||||
Rendering::CameraFrameStage::PostProcess,
|
||||
static_cast<Rendering::CameraFrameColorSource>(source),
|
||||
usesGraphManagedOutputColor != 0)
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFinalOutputStage(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedScriptableRenderPipelinePlanningContextState* const state =
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
|
||||
if (state == nullptr || state->plan == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->plan->ClearFullscreenStage(Rendering::CameraFrameStage::FinalOutput);
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestFinalOutputStage(
|
||||
uint64_t nativeHandle,
|
||||
int32_t source) {
|
||||
ManagedScriptableRenderPipelinePlanningContextState* const state =
|
||||
FindManagedScriptableRenderPipelinePlanningContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->plan == nullptr ||
|
||||
source == static_cast<int32_t>(Rendering::CameraFrameColorSource::ExplicitSurface)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return state->plan->RequestFullscreenStage(
|
||||
Rendering::CameraFrameStage::FinalOutput,
|
||||
static_cast<Rendering::CameraFrameColorSource>(source))
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
void RegisterInternalCalls() {
|
||||
if (GetInternalCallRegistrationState()) {
|
||||
return;
|
||||
@@ -2440,6 +2640,10 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordBuiltinForwardScenePhase", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RecordBuiltinForwardScenePhase));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordBuiltinForwardInjectionPoint", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RecordBuiltinForwardInjectionPoint));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RecordBuiltinColorScaleFullscreenPass", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RecordBuiltinColorScaleFullscreenPass));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearPostProcessStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearPostProcessStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestPostProcessStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestPostProcessStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_ClearFinalOutputStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_ClearFinalOutputStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderPipelinePlanningContext_RequestFinalOutputStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderPipelinePlanningContext_RequestFinalOutputStage));
|
||||
|
||||
GetInternalCallRegistrationState() = true;
|
||||
}
|
||||
@@ -2494,6 +2698,8 @@ void MonoScriptRuntime::Shutdown() {
|
||||
Rendering::Pipelines::ClearManagedRenderPipelineBridge();
|
||||
GetManagedScriptableRenderContextRegistry().clear();
|
||||
GetManagedScriptableRenderContextNextHandle() = 1;
|
||||
GetManagedScriptableRenderPipelinePlanningContextRegistry().clear();
|
||||
GetManagedScriptableRenderPipelinePlanningContextNextHandle() = 1;
|
||||
ClearManagedInstances();
|
||||
ClearExternalManagedObjects();
|
||||
ClearClassCache();
|
||||
@@ -2509,9 +2715,11 @@ void MonoScriptRuntime::Shutdown() {
|
||||
m_scriptableRenderPipelineAssetClass = nullptr;
|
||||
m_scriptableRenderPipelineClass = nullptr;
|
||||
m_scriptableRenderContextClass = nullptr;
|
||||
m_scriptableRenderPipelinePlanningContextClass = nullptr;
|
||||
m_serializeFieldAttributeClass = nullptr;
|
||||
m_gameObjectConstructor = nullptr;
|
||||
m_scriptableRenderContextConstructor = nullptr;
|
||||
m_scriptableRenderPipelinePlanningContextConstructor = nullptr;
|
||||
m_managedGameObjectUUIDField = nullptr;
|
||||
m_gameObjectUUIDField = nullptr;
|
||||
m_scriptComponentUUIDField = nullptr;
|
||||
@@ -3143,6 +3351,27 @@ bool MonoScriptRuntime::DiscoverScriptClasses() {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_scriptableRenderPipelinePlanningContextClass = mono_class_from_name(
|
||||
m_coreImage,
|
||||
m_settings.baseNamespace.c_str(),
|
||||
"ScriptableRenderPipelinePlanningContext");
|
||||
if (!m_scriptableRenderPipelinePlanningContextClass) {
|
||||
SetError(
|
||||
"Failed to locate the managed ScriptableRenderPipelinePlanningContext type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_scriptableRenderPipelinePlanningContextConstructor =
|
||||
mono_class_get_method_from_name(
|
||||
m_scriptableRenderPipelinePlanningContextClass,
|
||||
".ctor",
|
||||
1);
|
||||
if (!m_scriptableRenderPipelinePlanningContextConstructor) {
|
||||
SetError(
|
||||
"Failed to locate the managed ScriptableRenderPipelinePlanningContext constructor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_serializeFieldAttributeClass = mono_class_from_name(
|
||||
m_coreImage,
|
||||
m_settings.baseNamespace.c_str(),
|
||||
@@ -3594,6 +3823,45 @@ MonoObject* MonoScriptRuntime::CreateManagedScriptableRenderContext(
|
||||
return contextObject;
|
||||
}
|
||||
|
||||
MonoObject* MonoScriptRuntime::CreateManagedScriptableRenderPipelinePlanningContext(
|
||||
uint64_t nativeHandle) {
|
||||
if (!m_initialized ||
|
||||
nativeHandle == 0 ||
|
||||
m_scriptableRenderPipelinePlanningContextClass == nullptr ||
|
||||
m_scriptableRenderPipelinePlanningContextConstructor == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SetCurrentDomain();
|
||||
|
||||
MonoObject* const contextObject =
|
||||
mono_object_new(
|
||||
m_appDomain,
|
||||
m_scriptableRenderPipelinePlanningContextClass);
|
||||
if (contextObject == nullptr) {
|
||||
SetError(
|
||||
"Mono failed to allocate a managed ScriptableRenderPipelinePlanningContext.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* args[1];
|
||||
uint64_t nativeHandleArgument = nativeHandle;
|
||||
args[0] = &nativeHandleArgument;
|
||||
|
||||
MonoObject* exception = nullptr;
|
||||
mono_runtime_invoke(
|
||||
m_scriptableRenderPipelinePlanningContextConstructor,
|
||||
contextObject,
|
||||
args,
|
||||
&exception);
|
||||
if (exception != nullptr) {
|
||||
RecordException(exception);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return contextObject;
|
||||
}
|
||||
|
||||
MonoScriptRuntime::InstanceData* MonoScriptRuntime::FindInstance(const ScriptRuntimeContext& context) {
|
||||
const auto it = m_instances.find(InstanceKey{context.gameObjectUUID, context.scriptComponentUUID});
|
||||
return it != m_instances.end() ? &it->second : nullptr;
|
||||
|
||||
Reference in New Issue
Block a user