feat(rendering): add scriptable render context v1
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "Debug/Logger.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "Physics/PhysicsWorld.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Scripting/ScriptComponent.h"
|
||||
@@ -83,6 +84,52 @@ bool& GetInternalCallRegistrationState() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
struct ManagedScriptableRenderContextState {
|
||||
uint64_t handle = 0;
|
||||
Rendering::CameraFrameStage stage = Rendering::CameraFrameStage::MainScene;
|
||||
const Rendering::RenderPipelineStageRenderGraphContext* graphContext = nullptr;
|
||||
Rendering::Pipelines::BuiltinForwardPipeline builtinForwardPipeline;
|
||||
};
|
||||
|
||||
uint64_t& GetManagedScriptableRenderContextNextHandle() {
|
||||
static uint64_t nextHandle = 1;
|
||||
return nextHandle;
|
||||
}
|
||||
|
||||
std::unordered_map<uint64_t, ManagedScriptableRenderContextState*>&
|
||||
GetManagedScriptableRenderContextRegistry() {
|
||||
static std::unordered_map<uint64_t, ManagedScriptableRenderContextState*> registry;
|
||||
return registry;
|
||||
}
|
||||
|
||||
ManagedScriptableRenderContextState* FindManagedScriptableRenderContextState(
|
||||
uint64_t handle) {
|
||||
const auto it = GetManagedScriptableRenderContextRegistry().find(handle);
|
||||
return it != GetManagedScriptableRenderContextRegistry().end()
|
||||
? it->second
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
uint64_t RegisterManagedScriptableRenderContextState(
|
||||
ManagedScriptableRenderContextState& state) {
|
||||
uint64_t handle = GetManagedScriptableRenderContextNextHandle()++;
|
||||
if (handle == 0) {
|
||||
handle = GetManagedScriptableRenderContextNextHandle()++;
|
||||
}
|
||||
|
||||
state.handle = handle;
|
||||
GetManagedScriptableRenderContextRegistry()[handle] = &state;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void UnregisterManagedScriptableRenderContextState(uint64_t handle) {
|
||||
if (handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetManagedScriptableRenderContextRegistry().erase(handle);
|
||||
}
|
||||
|
||||
void CleanupMonoRootDomainAtExit() {
|
||||
MonoRootState& rootState = GetMonoRootState();
|
||||
if (!rootState.rootDomain) {
|
||||
@@ -233,14 +280,27 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t managedStage = static_cast<int32_t>(context.stage);
|
||||
void* args[1] = { &managedStage };
|
||||
ManagedScriptableRenderContextState managedContextState = {};
|
||||
managedContextState.stage = context.stage;
|
||||
managedContextState.graphContext = &context;
|
||||
const uint64_t managedContextHandle =
|
||||
RegisterManagedScriptableRenderContextState(managedContextState);
|
||||
MonoObject* const managedContextObject =
|
||||
m_runtime->CreateManagedScriptableRenderContext(managedContextHandle);
|
||||
if (managedContextObject == nullptr) {
|
||||
UnregisterManagedScriptableRenderContextState(managedContextHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
void* args[1] = { managedContextObject };
|
||||
MonoObject* result = nullptr;
|
||||
if (!m_runtime->InvokeManagedMethod(
|
||||
const bool invokeSucceeded = m_runtime->InvokeManagedMethod(
|
||||
pipelineObject,
|
||||
method,
|
||||
args,
|
||||
&result)) {
|
||||
&result);
|
||||
UnregisterManagedScriptableRenderContextState(managedContextHandle);
|
||||
if (!invokeSucceeded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2100,6 +2160,31 @@ MonoString* InternalCall_Rendering_GetRenderPipelineAssetTypeName() {
|
||||
return mono_string_new(mono_domain_get(), assemblyQualifiedName.c_str());
|
||||
}
|
||||
|
||||
int32_t InternalCall_Rendering_ScriptableRenderContext_GetStage(
|
||||
uint64_t nativeHandle) {
|
||||
const ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
return state != nullptr
|
||||
? static_cast<int32_t>(state->stage)
|
||||
: static_cast<int32_t>(Rendering::CameraFrameStage::MainScene);
|
||||
}
|
||||
|
||||
mono_bool InternalCall_Rendering_ScriptableRenderContext_RenderBuiltinForwardMainScene(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->graphContext == nullptr ||
|
||||
state->stage != Rendering::CameraFrameStage::MainScene) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return state->builtinForwardPipeline.RecordStageRenderGraph(
|
||||
*state->graphContext)
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
void RegisterInternalCalls() {
|
||||
if (GetInternalCallRegistrationState()) {
|
||||
return;
|
||||
@@ -2228,6 +2313,8 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Physics_Raycast", reinterpret_cast<const void*>(&InternalCall_Physics_Raycast));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_SetRenderPipelineAssetType", reinterpret_cast<const void*>(&InternalCall_Rendering_SetRenderPipelineAssetType));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_GetRenderPipelineAssetTypeName", reinterpret_cast<const void*>(&InternalCall_Rendering_GetRenderPipelineAssetTypeName));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_GetStage", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_GetStage));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_RenderBuiltinForwardMainScene", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_RenderBuiltinForwardMainScene));
|
||||
|
||||
GetInternalCallRegistrationState() = true;
|
||||
}
|
||||
@@ -2280,6 +2367,8 @@ bool MonoScriptRuntime::Initialize() {
|
||||
|
||||
void MonoScriptRuntime::Shutdown() {
|
||||
Rendering::Pipelines::ClearManagedRenderPipelineBridge();
|
||||
GetManagedScriptableRenderContextRegistry().clear();
|
||||
GetManagedScriptableRenderContextNextHandle() = 1;
|
||||
ClearManagedInstances();
|
||||
ClearExternalManagedObjects();
|
||||
ClearClassCache();
|
||||
@@ -2294,8 +2383,10 @@ void MonoScriptRuntime::Shutdown() {
|
||||
m_monoBehaviourClass = nullptr;
|
||||
m_scriptableRenderPipelineAssetClass = nullptr;
|
||||
m_scriptableRenderPipelineClass = nullptr;
|
||||
m_scriptableRenderContextClass = nullptr;
|
||||
m_serializeFieldAttributeClass = nullptr;
|
||||
m_gameObjectConstructor = nullptr;
|
||||
m_scriptableRenderContextConstructor = nullptr;
|
||||
m_managedGameObjectUUIDField = nullptr;
|
||||
m_gameObjectUUIDField = nullptr;
|
||||
m_scriptComponentUUIDField = nullptr;
|
||||
@@ -2908,6 +2999,25 @@ bool MonoScriptRuntime::DiscoverScriptClasses() {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_scriptableRenderContextClass = mono_class_from_name(
|
||||
m_coreImage,
|
||||
m_settings.baseNamespace.c_str(),
|
||||
"ScriptableRenderContext");
|
||||
if (!m_scriptableRenderContextClass) {
|
||||
SetError("Failed to locate the managed ScriptableRenderContext type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_scriptableRenderContextConstructor = mono_class_get_method_from_name(
|
||||
m_scriptableRenderContextClass,
|
||||
".ctor",
|
||||
1);
|
||||
if (!m_scriptableRenderContextConstructor) {
|
||||
SetError(
|
||||
"Failed to locate the managed ScriptableRenderContext constructor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_serializeFieldAttributeClass = mono_class_from_name(
|
||||
m_coreImage,
|
||||
m_settings.baseNamespace.c_str(),
|
||||
@@ -3322,6 +3432,43 @@ void MonoScriptRuntime::DestroyExternalManagedObject(uint32_t gcHandle) {
|
||||
m_externalManagedObjects.erase(it);
|
||||
}
|
||||
|
||||
MonoObject* MonoScriptRuntime::CreateManagedScriptableRenderContext(
|
||||
uint64_t nativeHandle) {
|
||||
if (!m_initialized ||
|
||||
nativeHandle == 0 ||
|
||||
m_scriptableRenderContextClass == nullptr ||
|
||||
m_scriptableRenderContextConstructor == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SetCurrentDomain();
|
||||
|
||||
MonoObject* const contextObject =
|
||||
mono_object_new(m_appDomain, m_scriptableRenderContextClass);
|
||||
if (contextObject == nullptr) {
|
||||
SetError(
|
||||
"Mono failed to allocate a managed ScriptableRenderContext.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* args[1];
|
||||
uint64_t nativeHandleArgument = nativeHandle;
|
||||
args[0] = &nativeHandleArgument;
|
||||
|
||||
MonoObject* exception = nullptr;
|
||||
mono_runtime_invoke(
|
||||
m_scriptableRenderContextConstructor,
|
||||
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