refactor(rendering): formalize pipeline selection and engine asset discovery
This commit is contained in:
@@ -357,6 +357,14 @@ std::string TrimAssemblyName(const std::string& assemblyName) {
|
||||
return assemblyName;
|
||||
}
|
||||
|
||||
MonoScriptRuntime::ManagedAssemblyDescriptor BuildManagedAssemblyDescriptor(
|
||||
const std::string& assemblyName,
|
||||
const std::filesystem::path& assemblyPath) {
|
||||
return MonoScriptRuntime::ManagedAssemblyDescriptor{
|
||||
assemblyName,
|
||||
assemblyPath};
|
||||
}
|
||||
|
||||
bool IsMonoClassOrSubclass(MonoClass* monoClass, MonoClass* potentialBaseClass) {
|
||||
if (!monoClass || !potentialBaseClass) {
|
||||
return false;
|
||||
@@ -386,12 +394,14 @@ MonoScriptRuntime* GetActiveMonoScriptRuntime() {
|
||||
|
||||
void ClearManagedRenderPipelineSelection(MonoScriptRuntime* runtime) {
|
||||
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor =
|
||||
Rendering::GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor();
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.GetConfiguredRenderPipelineAssetDescriptor();
|
||||
if (runtime != nullptr && descriptor.managedAssetHandle != 0u) {
|
||||
runtime->ReleaseExternalManagedObject(descriptor.managedAssetHandle);
|
||||
}
|
||||
|
||||
Rendering::GetGraphicsSettingsState().ClearRenderPipelineAssetDescriptor();
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.ClearConfiguredRenderPipelineAssetDescriptor();
|
||||
}
|
||||
|
||||
bool TryUnboxManagedBoolean(MonoObject* boxedValue, bool& outValue) {
|
||||
@@ -2812,7 +2822,8 @@ mono_bool InternalCall_Physics_Raycast(
|
||||
void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) {
|
||||
MonoScriptRuntime* const runtime = GetActiveMonoScriptRuntime();
|
||||
const Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor currentDescriptor =
|
||||
Rendering::GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor();
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.GetConfiguredRenderPipelineAssetDescriptor();
|
||||
|
||||
if (assetObject == nullptr) {
|
||||
ClearManagedRenderPipelineSelection(runtime);
|
||||
@@ -2856,8 +2867,8 @@ void InternalCall_Rendering_SetRenderPipelineAsset(MonoObject* assetObject) {
|
||||
currentDescriptor.managedAssetHandle);
|
||||
}
|
||||
|
||||
Rendering::GetGraphicsSettingsState().SetRenderPipelineAssetDescriptor(
|
||||
descriptor);
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.SetConfiguredRenderPipelineAssetDescriptor(descriptor);
|
||||
}
|
||||
|
||||
MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() {
|
||||
@@ -2867,7 +2878,8 @@ MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() {
|
||||
}
|
||||
|
||||
Rendering::Pipelines::ManagedRenderPipelineAssetDescriptor descriptor =
|
||||
Rendering::GetGraphicsSettingsState().GetRenderPipelineAssetDescriptor();
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.GetConfiguredRenderPipelineAssetDescriptor();
|
||||
if (!descriptor.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -2877,8 +2889,8 @@ MonoObject* InternalCall_Rendering_GetRenderPipelineAsset() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rendering::GetGraphicsSettingsState().SetRenderPipelineAssetDescriptor(
|
||||
descriptor);
|
||||
Rendering::GetGraphicsSettingsState()
|
||||
.SetConfiguredRenderPipelineAssetDescriptor(descriptor);
|
||||
}
|
||||
|
||||
return runtime->GetExternalManagedObject(
|
||||
@@ -3838,6 +3850,7 @@ void MonoScriptRuntime::Shutdown() {
|
||||
m_appAssembly = nullptr;
|
||||
m_coreImage = nullptr;
|
||||
m_appImage = nullptr;
|
||||
m_loadedManagedAssemblies.clear();
|
||||
m_componentClass = nullptr;
|
||||
m_behaviourClass = nullptr;
|
||||
m_gameObjectClass = nullptr;
|
||||
@@ -4304,6 +4317,19 @@ void MonoScriptRuntime::ResolveSettings() {
|
||||
m_settings.corlibDirectory = m_settings.coreAssemblyPath.parent_path();
|
||||
}
|
||||
}
|
||||
|
||||
for (ManagedAssemblyDescriptor& assembly : m_settings.engineAssemblies) {
|
||||
if (assembly.name.empty() && !assembly.path.empty()) {
|
||||
assembly.name = assembly.path.stem().string();
|
||||
}
|
||||
|
||||
if (assembly.path.empty() &&
|
||||
!m_settings.assemblyDirectory.empty() &&
|
||||
!assembly.name.empty()) {
|
||||
assembly.path =
|
||||
m_settings.assemblyDirectory / (assembly.name + ".dll");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::InitializeRootDomain() {
|
||||
@@ -4387,42 +4413,95 @@ bool MonoScriptRuntime::LoadAssemblies() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(m_settings.coreAssemblyPath)) {
|
||||
SetError("Script core assembly does not exist: " + m_settings.coreAssemblyPath.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(m_settings.appAssemblyPath)) {
|
||||
SetError("Game scripts assembly does not exist: " + m_settings.appAssemblyPath.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
SetCurrentDomain();
|
||||
m_loadedManagedAssemblies.clear();
|
||||
|
||||
m_coreAssembly = mono_domain_assembly_open(m_appDomain, m_settings.coreAssemblyPath.string().c_str());
|
||||
if (!m_coreAssembly) {
|
||||
SetError("Failed to load script core assembly: " + m_settings.coreAssemblyPath.string());
|
||||
if (!LoadAssemblyImage(
|
||||
BuildManagedAssemblyDescriptor(
|
||||
m_settings.coreAssemblyName,
|
||||
m_settings.coreAssemblyPath),
|
||||
"script core",
|
||||
m_coreAssembly,
|
||||
m_coreImage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_coreImage = mono_assembly_get_image(m_coreAssembly);
|
||||
if (!m_coreImage) {
|
||||
SetError("Failed to access the script core image.");
|
||||
for (const ManagedAssemblyDescriptor& assembly :
|
||||
m_settings.engineAssemblies) {
|
||||
MonoAssembly* loadedAssembly = nullptr;
|
||||
MonoImage* loadedImage = nullptr;
|
||||
if (!LoadAssemblyImage(
|
||||
assembly,
|
||||
"engine",
|
||||
loadedAssembly,
|
||||
loadedImage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoadAssemblyImage(
|
||||
BuildManagedAssemblyDescriptor(
|
||||
m_settings.appAssemblyName,
|
||||
m_settings.appAssemblyPath),
|
||||
"game scripts",
|
||||
m_appAssembly,
|
||||
m_appImage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_appAssembly = mono_domain_assembly_open(m_appDomain, m_settings.appAssemblyPath.string().c_str());
|
||||
if (!m_appAssembly) {
|
||||
SetError("Failed to load game scripts assembly: " + m_settings.appAssemblyPath.string());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::LoadAssemblyImage(
|
||||
const ManagedAssemblyDescriptor& descriptor,
|
||||
const char* roleLabel,
|
||||
MonoAssembly*& outAssembly,
|
||||
MonoImage*& outImage) {
|
||||
outAssembly = nullptr;
|
||||
outImage = nullptr;
|
||||
|
||||
if (descriptor.name.empty() || descriptor.path.empty()) {
|
||||
SetError(
|
||||
"Managed " + std::string(roleLabel) +
|
||||
" assembly descriptor is incomplete.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_appImage = mono_assembly_get_image(m_appAssembly);
|
||||
if (!m_appImage) {
|
||||
SetError("Failed to access the game scripts image.");
|
||||
if (!std::filesystem::exists(descriptor.path)) {
|
||||
SetError(
|
||||
"Managed " + std::string(roleLabel) +
|
||||
" assembly does not exist: " + descriptor.path.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_loadedManagedAssemblies.contains(descriptor.name)) {
|
||||
SetError(
|
||||
"Managed assembly name is loaded more than once: " +
|
||||
descriptor.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
outAssembly = mono_domain_assembly_open(
|
||||
m_appDomain,
|
||||
descriptor.path.string().c_str());
|
||||
if (!outAssembly) {
|
||||
SetError(
|
||||
"Failed to load managed " + std::string(roleLabel) +
|
||||
" assembly: " + descriptor.path.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
outImage = mono_assembly_get_image(outAssembly);
|
||||
if (!outImage) {
|
||||
SetError(
|
||||
"Failed to access the managed " + std::string(roleLabel) +
|
||||
" image: " + descriptor.path.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_loadedManagedAssemblies.emplace(
|
||||
descriptor.name,
|
||||
LoadedManagedAssemblyData{outAssembly, outImage});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4568,6 +4647,15 @@ bool MonoScriptRuntime::DiscoverScriptClasses() {
|
||||
}
|
||||
|
||||
DiscoverScriptClassesInImage(m_settings.appAssemblyName, m_appImage);
|
||||
DiscoverRenderPipelineAssetClassesInImage(
|
||||
m_settings.coreAssemblyName,
|
||||
m_coreImage);
|
||||
for (const ManagedAssemblyDescriptor& assembly :
|
||||
m_settings.engineAssemblies) {
|
||||
DiscoverRenderPipelineAssetClassesInImage(
|
||||
assembly.name,
|
||||
FindLoadedAssemblyImage(assembly.name));
|
||||
}
|
||||
DiscoverRenderPipelineAssetClassesInImage(
|
||||
m_settings.appAssemblyName,
|
||||
m_appImage);
|
||||
@@ -4669,11 +4757,16 @@ void MonoScriptRuntime::DiscoverRenderPipelineAssetClassesInImage(
|
||||
continue;
|
||||
}
|
||||
|
||||
m_renderPipelineAssetClasses.push_back(
|
||||
ScriptClassDescriptor{
|
||||
assemblyName,
|
||||
SafeString(mono_class_get_namespace(monoClass)),
|
||||
SafeString(mono_class_get_name(monoClass))});
|
||||
const ScriptClassDescriptor descriptor{
|
||||
assemblyName,
|
||||
SafeString(mono_class_get_namespace(monoClass)),
|
||||
SafeString(mono_class_get_name(monoClass))};
|
||||
if (std::find(
|
||||
m_renderPipelineAssetClasses.begin(),
|
||||
m_renderPipelineAssetClasses.end(),
|
||||
descriptor) == m_renderPipelineAssetClasses.end()) {
|
||||
m_renderPipelineAssetClasses.push_back(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4899,13 +4992,7 @@ bool MonoScriptRuntime::ResolveManagedClass(
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoImage* image = nullptr;
|
||||
if (assemblyName == m_settings.coreAssemblyName) {
|
||||
image = m_coreImage;
|
||||
} else if (assemblyName == m_settings.appAssemblyName) {
|
||||
image = m_appImage;
|
||||
}
|
||||
|
||||
MonoImage* image = FindLoadedAssemblyImage(assemblyName);
|
||||
if (!image) {
|
||||
return false;
|
||||
}
|
||||
@@ -5875,6 +5962,14 @@ void MonoScriptRuntime::ClearClassCache() {
|
||||
m_renderPipelineAssetClasses.clear();
|
||||
}
|
||||
|
||||
MonoImage* MonoScriptRuntime::FindLoadedAssemblyImage(
|
||||
const std::string& assemblyName) const {
|
||||
const auto it = m_loadedManagedAssemblies.find(assemblyName);
|
||||
return it != m_loadedManagedAssemblies.end()
|
||||
? it->second.image
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::InvokeManagedMethod(
|
||||
MonoObject* instance,
|
||||
MonoMethod* method,
|
||||
|
||||
Reference in New Issue
Block a user