diff --git a/src/common/functions.hpp b/src/common/functions.hpp index dde2d021..f3365084 100644 --- a/src/common/functions.hpp +++ b/src/common/functions.hpp @@ -84,11 +84,6 @@ T ceil_divide(T dividend, T divisor) { return (dividend + divisor - 1) / divisor; } -template -T random() { - return rand() & all_ones(); -} - inline constexpr u32 make_magic4(const char c0, const char c1, const char c2, const char c3) { return static_cast(c0) | static_cast(c1) << 8 | diff --git a/src/common/macros.hpp b/src/common/macros.hpp index 46079f8e..f0bbdcc4 100644 --- a/src/common/macros.hpp +++ b/src/common/macros.hpp @@ -21,22 +21,6 @@ #define PASS(...) __VA_ARGS__ #define PASS_VA_ARGS(...) , ##__VA_ARGS__ -#define SINGLETON_DEFINE_GET_INSTANCE(type, logging_class) \ - static type* g_instance = nullptr; \ - type& type::GetInstance() { \ - ASSERT_DEBUG(g_instance, logging_class, \ - #type " hasn't been instantiated"); \ - return *g_instance; \ - } - -#define SINGLETON_SET_INSTANCE(type, logging_class) \ - { \ - ASSERT(!g_instance, logging_class, #type " already exists"); \ - g_instance = this; \ - } - -#define SINGLETON_UNSET_INSTANCE() g_instance = nullptr - #define BIT(n) (1u << (n)) #define BITL(n) (1ul << (n)) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0df8b0f0..9bbf4059 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -200,7 +200,6 @@ add_library(hydra-core horizon/services/am/global_state_controller.hpp horizon/services/am/application_creator.cpp horizon/services/am/application_creator.hpp - horizon/services/am/library_applet_controller.hpp horizon/services/am/library_applet_creator.cpp horizon/services/am/library_applet_creator.hpp horizon/services/am/library_applet_accessor.cpp @@ -233,6 +232,7 @@ add_library(hydra-core horizon/services/am/storage_accessor.hpp horizon/services/am/session.cpp horizon/services/am/session.hpp + horizon/services/am/internal/library_applet_controller.hpp horizon/services/visrv/display_service_base.cpp horizon/services/visrv/display_service_base.hpp horizon/services/visrv/system_display_service.cpp @@ -414,6 +414,8 @@ add_library(hydra-core horizon/services/ins/receiver_manager.hpp horizon/services/irsensor/ir_sensor_server.cpp horizon/services/irsensor/ir_sensor_server.hpp + horizon/services/irsensor/internal/ir_sensor_manager.cpp + horizon/services/irsensor/internal/ir_sensor_manager.hpp horizon/services/ro/detail/ro_interface.cpp horizon/services/ro/detail/ro_interface.hpp horizon/applets/const.hpp @@ -450,7 +452,6 @@ add_library(hydra-core hw/tegra_x1/cpu/mmu.hpp hw/tegra_x1/cpu/thread.cpp hw/tegra_x1/cpu/thread.hpp - hw/tegra_x1/cpu/cpu.cpp hw/tegra_x1/cpu/cpu.hpp hw/tegra_x1/cpu/dynarmic/const.hpp hw/tegra_x1/cpu/dynarmic/memory.hpp @@ -577,7 +578,7 @@ add_library(hydra-core hw/tegra_x1/gpu/renderer/pipeline_cache.hpp hw/tegra_x1/gpu/renderer/index_cache.cpp hw/tegra_x1/gpu/renderer/index_cache.hpp - hw/tegra_x1/gpu/renderer/renderer_base.hpp + hw/tegra_x1/gpu/renderer/renderer.hpp hw/tegra_x1/gpu/renderer/metal/const.hpp hw/tegra_x1/gpu/renderer/metal/maxwell_to_mtl.cpp hw/tegra_x1/gpu/renderer/metal/maxwell_to_mtl.hpp @@ -635,8 +636,8 @@ add_library(hydra-core debugger/debugger.hpp debugger/debugger_manager.cpp debugger/debugger_manager.hpp - emulation_context.cpp - emulation_context.hpp + system.cpp + system.hpp title.hpp c_api.cpp c_api.h diff --git a/src/core/c_api.cpp b/src/core/c_api.cpp index dee67c03..af4d56f0 100644 --- a/src/core/c_api.cpp +++ b/src/core/c_api.cpp @@ -1,7 +1,6 @@ #include "core/c_api.h" #include "core/debugger/debugger_manager.hpp" -#include "core/emulation_context.hpp" #include "core/horizon/filesystem/content_archive.hpp" #include "core/horizon/filesystem/disk_file.hpp" #include "core/horizon/firmware.hpp" @@ -10,6 +9,7 @@ #include "core/horizon/ui/handler_base.hpp" #include "core/hw/tegra_x1/gpu/gpu.hpp" #include "core/hw/tegra_x1/gpu/renderer/texture.hpp" +#include "core/system.hpp" #define HYDRA_EXPORT extern "C" __attribute__((visibility("default"))) @@ -311,71 +311,6 @@ HYDRA_EXPORT bool* hydra_config_get_gdb_wait_for_client() { return &hydra::CONFIG_INSTANCE.GetGdbWaitForClient(); } -// Loader plugins - -// Manager -HYDRA_EXPORT void hydra_loader_plugin_manager_refresh() { - hydra::horizon::loader::plugins::Manager::GetInstance().Refresh(); -} - -// Plugin -HYDRA_EXPORT void* hydra_create_loader_plugin(hydra_string path) { - try { - return new hydra::horizon::loader::plugins::Plugin( - std::string(string_view_from_hydra_string(path))); - } catch (...) { - // TODO: return an error - return nullptr; - } -} - -HYDRA_EXPORT void hydra_loader_plugin_destroy(void* plugin) { - delete reinterpret_cast(plugin); -} - -HYDRA_EXPORT hydra_string hydra_loader_plugin_get_name(const void* plugin) { - return hydra_string_from_string_view( - reinterpret_cast(plugin) - ->GetName()); -} - -HYDRA_EXPORT hydra_string -hydra_loader_plugin_get_display_version(const void* plugin) { - return hydra_string_from_string_view( - reinterpret_cast(plugin) - ->GetDisplayVersion()); -} - -HYDRA_EXPORT uint32_t -hydra_loader_plugin_get_supported_format_count(const void* plugin) { - return static_cast( - reinterpret_cast(plugin) - ->GetSupportedFormats() - .size()); -} - -HYDRA_EXPORT hydra_string -hydra_loader_plugin_get_supported_format(const void* plugin, uint32_t index) { - return hydra_string_from_string_view( - reinterpret_cast(plugin) - ->GetSupportedFormats()[index]); -} - -HYDRA_EXPORT uint32_t -hydra_loader_plugin_get_option_config_count(const void* plugin) { - return static_cast( - reinterpret_cast(plugin) - ->GetOptionConfigs() - .size()); -} - -HYDRA_EXPORT const void* -hydra_loader_plugin_get_option_config(const void* plugin, uint32_t index) { - return &reinterpret_cast( - plugin) - ->GetOptionConfigs()[index]; -} - // Option config HYDRA_EXPORT void* hydra_loader_plugin_option_config_copy(const void* config) { return new hydra::horizon::loader::plugins::OptionConfig( @@ -475,10 +410,13 @@ hydra_content_archive_get_content_type(void* content_archive) { } // Loader -HYDRA_EXPORT void* hydra_create_loader_from_path(hydra_string path) { +HYDRA_EXPORT void* hydra_create_loader_from_path(hydra_string path, + void* plugin_manager) { try { return hydra::horizon::loader::LoaderBase::CreateFromPath( - string_view_from_hydra_string(path)); + string_view_from_hydra_string(path), + reinterpret_cast( + plugin_manager)); } catch (...) { // TODO: return an error return nullptr; @@ -551,6 +489,80 @@ HYDRA_EXPORT hydra_string hydra_nca_loader_get_name(void* nca_loader) { ->GetName()); } +// Plugins + +// Manager +HYDRA_EXPORT void* hydra_create_loader_plugin_manager() { + return new hydra::horizon::loader::plugins::Manager(); +} + +HYDRA_EXPORT void hydra_loader_plugin_manager_destroy(void* manager) { + delete reinterpret_cast(manager); +} + +HYDRA_EXPORT void hydra_loader_plugin_manager_refresh(void* manager) { + reinterpret_cast(manager) + ->Refresh(); +} + +// Plugin +HYDRA_EXPORT void* hydra_create_loader_plugin(hydra_string path) { + try { + return new hydra::horizon::loader::plugins::Plugin( + std::string(string_view_from_hydra_string(path))); + } catch (...) { + // TODO: return an error + return nullptr; + } +} + +HYDRA_EXPORT void hydra_loader_plugin_destroy(void* plugin) { + delete reinterpret_cast(plugin); +} + +HYDRA_EXPORT hydra_string hydra_loader_plugin_get_name(const void* plugin) { + return hydra_string_from_string_view( + reinterpret_cast(plugin) + ->GetName()); +} + +HYDRA_EXPORT hydra_string +hydra_loader_plugin_get_display_version(const void* plugin) { + return hydra_string_from_string_view( + reinterpret_cast(plugin) + ->GetDisplayVersion()); +} + +HYDRA_EXPORT uint32_t +hydra_loader_plugin_get_supported_format_count(const void* plugin) { + return static_cast( + reinterpret_cast(plugin) + ->GetSupportedFormats() + .size()); +} + +HYDRA_EXPORT hydra_string +hydra_loader_plugin_get_supported_format(const void* plugin, uint32_t index) { + return hydra_string_from_string_view( + reinterpret_cast(plugin) + ->GetSupportedFormats()[index]); +} + +HYDRA_EXPORT uint32_t +hydra_loader_plugin_get_option_config_count(const void* plugin) { + return static_cast( + reinterpret_cast(plugin) + ->GetOptionConfigs() + .size()); +} + +HYDRA_EXPORT const void* +hydra_loader_plugin_get_option_config(const void* plugin, uint32_t index) { + return &reinterpret_cast( + plugin) + ->GetOptionConfigs()[index]; +} + // NACP HYDRA_EXPORT void hydra_nacp_destroy(void* nacp) { delete reinterpret_cast< @@ -733,70 +745,102 @@ class UiHandler : public hydra::horizon::ui::IHandler { } }; -HYDRA_EXPORT void* hydra_create_emulation_context() { - return new hydra::EmulationContext(*(new UiHandler())); +HYDRA_EXPORT void* hydra_create_system() { + return new hydra::System(*(new UiHandler())); } -HYDRA_EXPORT void hydra_emulation_context_destroy(void* ctx) { +HYDRA_EXPORT void hydra_system_destroy(void* system) { // TODO: also destroy the UI handler - delete reinterpret_cast(ctx); + delete reinterpret_cast(system); } -HYDRA_EXPORT void hydra_emulation_context_set_surface(void* ctx, - void* surface) { - reinterpret_cast(ctx)->SetSurface(surface); +HYDRA_EXPORT void hydra_system_set_surface(void* system, void* surface) { + reinterpret_cast(system)->SetSurface(surface); } -HYDRA_EXPORT void hydra_emulation_context_load_and_start(void* ctx, - void* loader) { - reinterpret_cast(ctx)->LoadAndStart( +HYDRA_EXPORT void hydra_system_load_and_start(void* system, void* loader) { + reinterpret_cast(system)->LoadAndStart( reinterpret_cast(loader)); } -HYDRA_EXPORT void hydra_emulation_context_request_stop(void* ctx) { - reinterpret_cast(ctx)->RequestStop(); +HYDRA_EXPORT void hydra_system_request_stop(void* system) { + reinterpret_cast(system)->RequestStop(); } -HYDRA_EXPORT void hydra_emulation_context_force_stop(void* ctx) { - reinterpret_cast(ctx)->ForceStop(); +HYDRA_EXPORT void hydra_system_force_stop(void* system) { + reinterpret_cast(system)->ForceStop(); } -HYDRA_EXPORT void hydra_emulation_context_pause(void* ctx) { - reinterpret_cast(ctx)->Pause(); +HYDRA_EXPORT void hydra_system_pause(void* system) { + reinterpret_cast(system)->Pause(); } -HYDRA_EXPORT void hydra_emulation_context_resume(void* ctx) { - reinterpret_cast(ctx)->Resume(); +HYDRA_EXPORT void hydra_system_resume(void* system) { + reinterpret_cast(system)->Resume(); } -HYDRA_EXPORT void -hydra_emulation_context_notify_operation_mode_changed(void* ctx) { - reinterpret_cast(ctx) - ->NotifyOperationModeChanged(); +HYDRA_EXPORT void hydra_system_notify_operation_mode_changed(void* system) { + reinterpret_cast(system)->NotifyOperationModeChanged(); } -HYDRA_EXPORT void hydra_emulation_context_progress_frame( - void* ctx, uint32_t width, uint32_t height, bool* out_dt_average_updated) { - reinterpret_cast(ctx)->ProgressFrame( +HYDRA_EXPORT void hydra_system_progress_frame(void* system, uint32_t width, + uint32_t height, + bool* out_dt_average_updated) { + reinterpret_cast(system)->ProgressFrame( width, height, *out_dt_average_updated); } -HYDRA_EXPORT bool hydra_emulation_context_is_running(void* ctx) { - return reinterpret_cast(ctx)->IsRunning(); +HYDRA_EXPORT bool hydra_system_is_running(void* system) { + return reinterpret_cast(system)->IsRunning(); +} + +HYDRA_EXPORT float hydra_system_get_last_delta_time_average(void* system) { + return reinterpret_cast(system)->GetLastDeltaTimeAverage(); +} + +HYDRA_EXPORT void hydra_system_take_screenshot(void* system) { + reinterpret_cast(system)->TakeScreenshot(); } -HYDRA_EXPORT float -hydra_emulation_context_get_last_delta_time_average(void* ctx) { - return reinterpret_cast(ctx) - ->GetLastDeltaTimeAverage(); +HYDRA_EXPORT void hydra_system_capture_gpu_frame(void* system) { + reinterpret_cast(system)->CaptureGpuFrame(); } -HYDRA_EXPORT void hydra_emulation_context_take_screenshot(void* ctx) { - reinterpret_cast(ctx)->TakeScreenshot(); +HYDRA_EXPORT void hydra_system_texture_cache_lock(void* system) { + reinterpret_cast(system) + ->GetGpu() + .GetRenderer() + .GetTextureCache() + .GetMutex() + .lock(); } -HYDRA_EXPORT void hydra_emulation_context_capture_gpu_frame(void* ctx) { - reinterpret_cast(ctx)->CaptureGpuFrame(); +HYDRA_EXPORT void hydra_system_texture_cache_unlock(void* system) { + reinterpret_cast(system) + ->GetGpu() + .GetRenderer() + .GetTextureCache() + .GetMutex() + .unlock(); +} + +HYDRA_EXPORT uint32_t +hydra_system_texture_cache_get_texture_memory_count(void* system) { + // HACK + return static_cast(reinterpret_cast(system) + ->GetGpu() + .GetRenderer() + .GetTextureCache() + .GetMemoryCount()); +} + +HYDRA_EXPORT const void* +hydra_system_texture_cache_get_texture_memory(void* system, uint32_t index) { + return &reinterpret_cast(system) + ->GetGpu() + .GetRenderer() + .GetTextureCache() + .GetMemory(index); } // Debugger @@ -994,26 +1038,6 @@ HYDRA_EXPORT uint64_t hydra_debugger_resolved_stack_frame_get_address( // Texture cache -// Texture cache -HYDRA_EXPORT void hydra_texture_cache_lock() { - hydra::RENDERER_INSTANCE.GetTextureCache().GetMutex().lock(); -} - -HYDRA_EXPORT void hydra_texture_cache_unlock() { - hydra::RENDERER_INSTANCE.GetTextureCache().GetMutex().unlock(); -} - -HYDRA_EXPORT uint32_t hydra_texture_cache_get_texture_memory_count() { - // HACK - return static_cast( - hydra::RENDERER_INSTANCE.GetTextureCache().GetMemoryCount()); -} - -HYDRA_EXPORT const void* -hydra_texture_cache_get_texture_memory(uint32_t index) { - return &hydra::RENDERER_INSTANCE.GetTextureCache().GetMemory(index); -} - // Texture memory HYDRA_EXPORT uint32_t hydra_texture_memory_get_texture_group_count(const void* mem) { diff --git a/src/core/c_api.h b/src/core/c_api.h index 69dca5be..bbfefbfe 100644 --- a/src/core/c_api.h +++ b/src/core/c_api.h @@ -200,23 +200,6 @@ bool* hydra_config_get_gdb_enabled(); uint16_t* hydra_config_get_gdb_port(); bool* hydra_config_get_gdb_wait_for_client(); -// Loader plugins - -// Manager -void hydra_loader_plugin_manager_refresh(); - -// Plugin -void* hydra_create_loader_plugin(hydra_string path); -void hydra_loader_plugin_destroy(void* plugin); -hydra_string hydra_loader_plugin_get_name(const void* plugin); -hydra_string hydra_loader_plugin_get_display_version(const void* plugin); -uint32_t hydra_loader_plugin_get_supported_format_count(const void* plugin); -hydra_string hydra_loader_plugin_get_supported_format(const void* plugin, - uint32_t index); -uint32_t hydra_loader_plugin_get_option_config_count(const void* plugin); -const void* hydra_loader_plugin_get_option_config(const void* plugin, - uint32_t index); - // Option config typedef enum HydraLoaderPluginOptionType : uint32_t { HYDRA_LOADER_PLUGIN_OPTION_TYPE_BOOLEAN = 0, @@ -253,7 +236,7 @@ HydraContentArchiveContentType hydra_content_archive_get_content_type(void* content_archive); // Loader -void* hydra_create_loader_from_path(hydra_string path); +void* hydra_create_loader_from_path(hydra_string path, void* plugin_manager); void hydra_loader_destroy(void* loader); uint64_t hydra_loader_get_title_id(void* loader); void* hydra_loader_load_nacp(void* loader); @@ -268,6 +251,25 @@ void hydra_loader_extract_romfs(const void* loader, hydra_string path); void* hydra_create_nca_loader_from_content_archive(void* content_archive); hydra_string hydra_nca_loader_get_name(void* nca_loader); +// Plugins + +// Manager +void* hydra_create_loader_plugin_manager(); +void hydra_loader_plugin_manager_destroy(void* manager); +void hydra_loader_plugin_manager_refresh(void* manager); + +// Plugin +void* hydra_create_loader_plugin(hydra_string path); +void hydra_loader_plugin_destroy(void* plugin); +hydra_string hydra_loader_plugin_get_name(const void* plugin); +hydra_string hydra_loader_plugin_get_display_version(const void* plugin); +uint32_t hydra_loader_plugin_get_supported_format_count(const void* plugin); +hydra_string hydra_loader_plugin_get_supported_format(const void* plugin, + uint32_t index); +uint32_t hydra_loader_plugin_get_option_config_count(const void* plugin); +const void* hydra_loader_plugin_get_option_config(const void* plugin, + uint32_t index); + // NACP void hydra_nacp_destroy(void* nacp); const void* hydra_nacp_get_title(void* nacp); @@ -300,30 +302,35 @@ void hydra_user_set_avatar_bg_color(void* user, hydra_uchar3 color); hydra_string hydra_user_get_avatar_path(void* user); void hydra_user_set_avatar_path(void* user, hydra_string path); -// Emulation context -void* hydra_create_emulation_context(); -void hydra_emulation_context_destroy(void* ctx); +// System +void* hydra_create_system(); +void hydra_system_destroy(void* system); + +void hydra_system_set_surface(void* system, void* surface); -void hydra_emulation_context_set_surface(void* ctx, void* surface); +void hydra_system_load_and_start(void* system, void* loader); +void hydra_system_request_stop(void* system); +void hydra_system_force_stop(void* system); -void hydra_emulation_context_load_and_start(void* ctx, void* loader); -void hydra_emulation_context_request_stop(void* ctx); -void hydra_emulation_context_force_stop(void* ctx); +void hydra_system_pause(void* system); +void hydra_system_resume(void* system); -void hydra_emulation_context_pause(void* ctx); -void hydra_emulation_context_resume(void* ctx); +void hydra_system_notify_operation_mode_changed(void* system); -void hydra_emulation_context_notify_operation_mode_changed(void* ctx); +void hydra_system_progress_frame(void* system, uint32_t width, uint32_t height, + bool* out_dt_average_updated); -void hydra_emulation_context_progress_frame(void* ctx, uint32_t width, - uint32_t height, - bool* out_dt_average_updated); +bool hydra_system_is_running(void* system); +float hydra_system_get_last_delta_time_average(void* system); -bool hydra_emulation_context_is_running(void* ctx); -float hydra_emulation_context_get_last_delta_time_average(void* ctx); +void hydra_system_take_screenshot(void* system); +void hydra_system_capture_gpu_frame(void* system); -void hydra_emulation_context_take_screenshot(void* ctx); -void hydra_emulation_context_capture_gpu_frame(void* ctx); +void hydra_system_texture_cache_lock(void* system); +void hydra_system_texture_cache_unlock(void* system); +uint32_t hydra_system_texture_cache_get_texture_memory_count(void* system); +const void* hydra_system_texture_cache_get_texture_memory(void* system, + uint32_t index); // Input // TODO @@ -385,12 +392,6 @@ uint64_t hydra_debugger_resolved_stack_frame_get_address( // Texture cache -// Texture cache -void hydra_texture_cache_lock(); -void hydra_texture_cache_unlock(); -uint32_t hydra_texture_cache_get_texture_memory_count(); -const void* hydra_texture_cache_get_texture_memory(uint32_t index); - // Texture memory uint32_t hydra_texture_memory_get_texture_group_count(const void* mem); const void* hydra_texture_memory_get_texture_group(const void* mem, diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index dde707ec..8a39176d 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -73,7 +73,9 @@ void Debugger::UnregisterGuestThreadForThisThread() { thread.guest_thread = nullptr; } -void Debugger::ActivateGdbServer() { gdb_server = new GdbServer(*this); } +void Debugger::ActivateGdbServer(System& system) { + gdb_server = new GdbServer(system, *this); +} void Debugger::NotifySupervisorPaused(horizon::kernel::GuestThread* thread, Signal signal) { diff --git a/src/core/debugger/debugger.hpp b/src/core/debugger/debugger.hpp index 0ad23f1c..199bcde4 100644 --- a/src/core/debugger/debugger.hpp +++ b/src/core/debugger/debugger.hpp @@ -2,6 +2,10 @@ #include "core/debugger/const.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { class GuestThread; class Process; @@ -156,7 +160,7 @@ class Debugger { SymbolTable& GetFunctionTable() { return function_table; } // GDB - void ActivateGdbServer(); + void ActivateGdbServer(System& system); void NotifySupervisorPaused(horizon::kernel::GuestThread* thread, Signal signal); void BreakpointHit(horizon::kernel::GuestThread* thread); diff --git a/src/core/debugger/gdb_server.cpp b/src/core/debugger/gdb_server.cpp index 0dd608d0..d3be7273 100644 --- a/src/core/debugger/gdb_server.cpp +++ b/src/core/debugger/gdb_server.cpp @@ -18,6 +18,7 @@ #include "core/hw/tegra_x1/cpu/cpu.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" #include "core/hw/tegra_x1/cpu/thread.hpp" +#include "core/system.hpp" #define GET_THREAD_ID(thread) reinterpret_cast(thread) #define GET_THREAD_FROM_ID(id) \ @@ -228,7 +229,8 @@ ENABLE_ENUM_FORMATTING(hydra::debugger::BreakpointType, Software, "software", namespace hydra::debugger { -GdbServer::GdbServer(Debugger& debugger_) : debugger{debugger_} { +GdbServer::GdbServer(System& system_, Debugger& debugger_) + : system{system_}, debugger{debugger_} { const u16 port = CONFIG_INSTANCE.GetGdbPort(); // Create the socket @@ -289,7 +291,7 @@ void GdbServer::NotifySupervisorPaused(horizon::kernel::GuestThread* thread, } void GdbServer::RegisterThread(Thread& thread) { - if (CPU_INSTANCE.GetFeatures().supports_native_breakpoints) { + if (system.GetCpu().GetFeatures().supports_native_breakpoints) { std::lock_guard lock(mutex); for (const auto addr : breakpoint_addresses) thread.guest_thread->GetThread()->InsertBreakpoint(addr); @@ -475,7 +477,7 @@ void GdbServer::HandleVCont(std::string_view command) { crnt_thread = thread; thread->GetThread()->SingleStep(); - if (CPU_INSTANCE.GetFeatures().supports_synchronous_single_step) { + if (system.GetCpu().GetFeatures().supports_synchronous_single_step) { // Single-stepping already finished NotifySupervisorPausedImpl(thread, Signal::SigTrap); } else { @@ -601,7 +603,7 @@ void GdbServer::HandleInsertBreakpoint(std::string_view command) { ASSERT_DEBUG(size == 4, Debugger, "Invalid software breakpoint size 0x{:x}", size); - if (CPU_INSTANCE.GetFeatures().supports_native_breakpoints) { + if (system.GetCpu().GetFeatures().supports_native_breakpoints) { breakpoint_addresses.push_back(addr); for (const auto& [_, thread] : debugger.threads) thread.guest_thread->GetThread()->InsertBreakpoint(addr); @@ -635,7 +637,7 @@ void GdbServer::HandleRemoveBreakpoint(std::string_view command) { ASSERT_DEBUG(size == 4, Debugger, "Invalid software breakpoint size 0x{:x}", size); - if (CPU_INSTANCE.GetFeatures().supports_native_breakpoints) { + if (system.GetCpu().GetFeatures().supports_native_breakpoints) { breakpoint_addresses.erase(std::find(breakpoint_addresses.begin(), breakpoint_addresses.end(), addr)); diff --git a/src/core/debugger/gdb_server.hpp b/src/core/debugger/gdb_server.hpp index 83141c62..360126f8 100644 --- a/src/core/debugger/gdb_server.hpp +++ b/src/core/debugger/gdb_server.hpp @@ -2,6 +2,10 @@ #include "core/debugger/const.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { class GuestThread; } // namespace hydra::horizon::kernel @@ -13,7 +17,7 @@ class Debugger; class GdbServer { public: - GdbServer(Debugger& debugger_); + GdbServer(System& system_, Debugger& debugger_); ~GdbServer(); void RegisterThread(Thread& thread); @@ -23,6 +27,7 @@ class GdbServer { void BreakpointHit(horizon::kernel::GuestThread* thread); private: + System& system; Debugger& debugger; std::mutex mutex; diff --git a/src/core/horizon/applets/applet_base.cpp b/src/core/horizon/applets/applet_base.cpp index 4f4696c7..0f0f66dc 100644 --- a/src/core/horizon/applets/applet_base.cpp +++ b/src/core/horizon/applets/applet_base.cpp @@ -5,7 +5,7 @@ namespace hydra::horizon::applets { -void AppletBase::Start() { +void AppletBase::Start(System& system) { // TODO: not every applet uses common args (for instance // LibraryAppletMiiEdit) const auto common_args = PopInData(); @@ -18,7 +18,7 @@ void AppletBase::Start() { thread = new std::thread([&]() { GET_CURRENT_PROCESS_DEBUGGER().RegisterThisThread("Applet"); - result = Run(); + result = Run(system); controller.GetStateChangedEvent()->Signal(); GET_CURRENT_PROCESS_DEBUGGER().UnregisterThisThread(); }); diff --git a/src/core/horizon/applets/applet_base.hpp b/src/core/horizon/applets/applet_base.hpp index 03a516ab..de0d03ce 100644 --- a/src/core/horizon/applets/applet_base.hpp +++ b/src/core/horizon/applets/applet_base.hpp @@ -1,13 +1,13 @@ #pragma once #include "core/horizon/kernel/kernel.hpp" -#include "core/horizon/services/am/library_applet_controller.hpp" +#include "core/horizon/services/am/internal/library_applet_controller.hpp" namespace hydra::horizon::applets { class AppletBase { public: - AppletBase(services::am::LibraryAppletController& controller_) + AppletBase(services::am::internal::LibraryAppletController& controller_) : controller{controller_} {} virtual ~AppletBase() { if (thread) { @@ -17,12 +17,12 @@ class AppletBase { } } - void Start(); + void Start(System& system); result_t GetResult() const { return result; } protected: - virtual result_t Run() = 0; + virtual result_t Run(System& system) = 0; // Helpers @@ -81,7 +81,7 @@ class AppletBase { } private: - services::am::LibraryAppletController& controller; + services::am::internal::LibraryAppletController& controller; std::thread* thread{nullptr}; result_t result{RESULT_SUCCESS}; diff --git a/src/core/horizon/applets/controller/applet.cpp b/src/core/horizon/applets/controller/applet.cpp index c34a782d..5ce6f24b 100644 --- a/src/core/horizon/applets/controller/applet.cpp +++ b/src/core/horizon/applets/controller/applet.cpp @@ -2,7 +2,7 @@ namespace hydra::horizon::applets::controller { -result_t Applet::Run() { +result_t Applet::Run(System& system) { const auto arg_private = PopInData(); // Mode @@ -20,9 +20,9 @@ result_t Applet::Run() { // Run with the correct args switch (arg_private.controller_support_arg_size) { case sizeof(SupportArg<4>): - return RunControllerSupport<4>(); + return RunControllerSupport<4>(system); case sizeof(SupportArg<8>): - return RunControllerSupport<8>(); + return RunControllerSupport<8>(system); default: LOG_ERROR(Applets, "Invalid controller support argument size 0x{:x}", arg_private.controller_support_arg_size); diff --git a/src/core/horizon/applets/controller/applet.hpp b/src/core/horizon/applets/controller/applet.hpp index 25edfebe..286964c3 100644 --- a/src/core/horizon/applets/controller/applet.hpp +++ b/src/core/horizon/applets/controller/applet.hpp @@ -12,13 +12,14 @@ class Applet : public AppletBase { using AppletBase::AppletBase; protected: - result_t Run() override; + result_t Run(System& system) override; private: template - result_t RunControllerSupport() { + result_t RunControllerSupport(System& system) { const auto arg = PopInData>(); + (void)system; LOG_FUNC_WITH_ARGS_STUBBED( Applets, "player count min: {}, player count max: {}, single mode: {}, " diff --git a/src/core/horizon/applets/error/applet.cpp b/src/core/horizon/applets/error/applet.cpp index 39f96ae3..1db06cec 100644 --- a/src/core/horizon/applets/error/applet.cpp +++ b/src/core/horizon/applets/error/applet.cpp @@ -1,12 +1,12 @@ #include "core/horizon/applets/error/applet.hpp" #include "core/horizon/applets/error/const.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/ui/handler_base.hpp" +#include "core/system.hpp" namespace hydra::horizon::applets::error { -result_t Applet::Run() { +result_t Applet::Run(System& system) { // TODO: PopInData auto param_reader = PopInDataRaw(); const auto param_common = param_reader.Read(); @@ -19,7 +19,7 @@ result_t Applet::Run() { const auto param = param_reader.Read(); // TODO: handle empty messages - OS_INSTANCE.GetUIHandler().ShowMessageDialog( + system.GetUIHandler().ShowMessageDialog( ui::MessageDialogType::Error, fmt::format("Error (0x{:x})", param.error_code_number), fmt::format("{}\n{}", param.dialog_message, diff --git a/src/core/horizon/applets/error/applet.hpp b/src/core/horizon/applets/error/applet.hpp index 4f82fb6a..13495499 100644 --- a/src/core/horizon/applets/error/applet.hpp +++ b/src/core/horizon/applets/error/applet.hpp @@ -9,7 +9,7 @@ class Applet : public AppletBase { using AppletBase::AppletBase; protected: - result_t Run() override; + result_t Run(System& system) override; }; } // namespace hydra::horizon::applets::error diff --git a/src/core/horizon/applets/player_select/applet.cpp b/src/core/horizon/applets/player_select/applet.cpp index d3444296..69097d2d 100644 --- a/src/core/horizon/applets/player_select/applet.cpp +++ b/src/core/horizon/applets/player_select/applet.cpp @@ -1,11 +1,11 @@ #include "core/horizon/applets/player_select/applet.hpp" #include "core/horizon/applets/player_select/const.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::applets::player_select { -result_t Applet::Run() { +result_t Applet::Run(System& system) { auto settings_reader = PopInDataRaw(); const auto settings = settings_reader.Read(); (void)settings; @@ -15,7 +15,8 @@ result_t Applet::Run() { // return that UiReturnArg ret{ .result = RESULT_SUCCESS, - .selected_user = USER_MANAGER_INSTANCE + .selected_user = system.GetOS() + .GetUserManager() .GetUserIDs()[0], // TODO: use the active user ID }; diff --git a/src/core/horizon/applets/player_select/applet.hpp b/src/core/horizon/applets/player_select/applet.hpp index 77cc704f..a72185ef 100644 --- a/src/core/horizon/applets/player_select/applet.hpp +++ b/src/core/horizon/applets/player_select/applet.hpp @@ -9,7 +9,7 @@ class Applet : public AppletBase { using AppletBase::AppletBase; protected: - result_t Run() override; + result_t Run(System& system) override; }; } // namespace hydra::horizon::applets::player_select diff --git a/src/core/horizon/applets/software_keyboard/applet.cpp b/src/core/horizon/applets/software_keyboard/applet.cpp index 11b2c8d6..25249ba9 100644 --- a/src/core/horizon/applets/software_keyboard/applet.cpp +++ b/src/core/horizon/applets/software_keyboard/applet.cpp @@ -1,7 +1,7 @@ #include "core/horizon/applets/software_keyboard/applet.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/ui/handler_base.hpp" +#include "core/system.hpp" namespace hydra::horizon::applets::software_keyboard { @@ -15,7 +15,7 @@ enum class TextCheckResult : u32 { } // namespace -result_t Applet::Run() { +result_t Applet::Run(System& system) { const auto config = PopInData(); // TODO: work buffer @@ -26,7 +26,7 @@ result_t Applet::Run() { while (true) { // Text input std::string output_text_utf8; - result = OS_INSTANCE.GetUIHandler().ShowSoftwareKeyboard( + result = system.GetUIHandler().ShowSoftwareKeyboard( utf16_to_utf8(std::u16string(config.header_text)), utf16_to_utf8(std::u16string(config.sub_text)), utf16_to_utf8(std::u16string(config.guide_text)), output_text_utf8); @@ -50,7 +50,7 @@ result_t Applet::Run() { // Dialog std::u16string msg = reader.ReadPtr(); - OS_INSTANCE.GetUIHandler().ShowMessageDialog( + system.GetUIHandler().ShowMessageDialog( (res == TextCheckResult::ShowFailureDialog ? ui::MessageDialogType::Error : ui::MessageDialogType::Info), diff --git a/src/core/horizon/applets/software_keyboard/applet.hpp b/src/core/horizon/applets/software_keyboard/applet.hpp index c3866cf1..d09675a7 100644 --- a/src/core/horizon/applets/software_keyboard/applet.hpp +++ b/src/core/horizon/applets/software_keyboard/applet.hpp @@ -10,7 +10,7 @@ class Applet : public AppletBase { using AppletBase::AppletBase; protected: - result_t Run() override; + result_t Run(System& system) override; }; } // namespace hydra::horizon::applets::software_keyboard diff --git a/src/core/horizon/display/binder.cpp b/src/core/horizon/display/binder.cpp index 6bd8cc0c..039b50bd 100644 --- a/src/core/horizon/display/binder.cpp +++ b/src/core/horizon/display/binder.cpp @@ -1,6 +1,6 @@ #include "core/horizon/display/binder.hpp" -#include "core/hw/tegra_x1/gpu/gpu.hpp" +#include "core/system.hpp" namespace hydra::horizon::display { @@ -42,7 +42,7 @@ i32 Binder::GetAvailableSlot() { return slot; } -void Binder::QueueBuffer(i32 slot, const BqBufferInput& input) { +void Binder::QueueBuffer(System& system, i32 slot, const BqBufferInput& input) { { std::lock_guard lock(queue_mutex); queued_buffers.push({slot, input}); @@ -58,7 +58,7 @@ void Binder::QueueBuffer(i32 slot, const BqBufferInput& input) { // Debug // TODO: only do this for the main process - RENDERER_INSTANCE.NotifyDebugFrameBoundary(); + system.GetGpu().GetRenderer().NotifyDebugFrameBoundary(); } i32 Binder::ConsumeBuffer(BqBufferInput& out_input) { diff --git a/src/core/horizon/display/binder.hpp b/src/core/horizon/display/binder.hpp index 60e8e2e2..866cd86c 100644 --- a/src/core/horizon/display/binder.hpp +++ b/src/core/horizon/display/binder.hpp @@ -116,7 +116,7 @@ struct Binder { // Buffers void AddBuffer(i32 slot, const GraphicBuffer& buff); i32 GetAvailableSlot(); - void QueueBuffer(i32 slot, const BqBufferInput& input); + void QueueBuffer(System& system, i32 slot, const BqBufferInput& input); i32 ConsumeBuffer(BqBufferInput& out_input); void UnqueueAllBuffers(); diff --git a/src/core/horizon/display/driver.cpp b/src/core/horizon/display/driver.cpp index 15c0c9c0..f8dc0568 100644 --- a/src/core/horizon/display/driver.cpp +++ b/src/core/horizon/display/driver.cpp @@ -1,10 +1,12 @@ #include "core/horizon/display/driver.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::display { -Driver::Driver() { display_pool.Add(new Display()); } +Driver::Driver(System& system_) : system{system_} { + display_pool.Add(new Display()); +} bool Driver::AcquirePresentTextures( hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer) { @@ -50,7 +52,7 @@ void Driver::Present( } // Viewport - const auto src_size = float2(OS_INSTANCE.GetDisplayResolution()); + const auto src_size = float2(system.GetOS().GetDisplayResolution()); auto scale_x = static_cast(width) / src_size.x(); auto scale_y = static_cast(height) / src_size.y(); diff --git a/src/core/horizon/display/driver.hpp b/src/core/horizon/display/driver.hpp index 3ab2cdf9..36c1c9d8 100644 --- a/src/core/horizon/display/driver.hpp +++ b/src/core/horizon/display/driver.hpp @@ -7,7 +7,7 @@ namespace hydra::horizon::display { class Driver { public: - Driver(); + Driver(System& system_); // Displays Display& GetDisplay(handle_id_t id) { @@ -29,7 +29,7 @@ class Driver { // Layers u32 CreateLayer(kernel::Process* process, u32 binder_id) { std::lock_guard lock(layer_mutex); - return layer_pool.Add(new Layer(process, binder_id)); + return layer_pool.Add(new Layer(system, process, binder_id)); } void DestroyLayer(u32 id) { @@ -71,6 +71,8 @@ class Driver { Layer* GetFirstLayerForProcess(kernel::Process* process); private: + System& system; + std::mutex display_mutex; StaticPool display_pool; std::mutex layer_mutex; diff --git a/src/core/horizon/display/layer.cpp b/src/core/horizon/display/layer.cpp index 6bd06f5e..745980d3 100644 --- a/src/core/horizon/display/layer.cpp +++ b/src/core/horizon/display/layer.cpp @@ -6,13 +6,14 @@ #include "core/hw/tegra_x1/gpu/renderer/surface_compositor.hpp" #include "core/hw/tegra_x1/gpu/renderer/texture.hpp" #include "core/hw/tegra_x1/gpu/renderer/texture_view.hpp" +#include "core/system.hpp" namespace hydra::horizon::display { bool Layer::AcquirePresentTexture( hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer) { // Get the buffer to present - auto& binder = OS_INSTANCE.GetDisplayDriver().GetBinder(binder_id); + auto& binder = system.GetOS().GetDisplayDriver().GetBinder(binder_id); BqBufferInput input; i32 slot = binder.ConsumeBuffer(input); @@ -21,8 +22,8 @@ bool Layer::AcquirePresentTexture( const auto& buffer = binder.GetBuffer(slot); // Texture - present_texture = GPU_INSTANCE.GetTexture(command_buffer, process->GetMmu(), - buffer.nv_buffer); + present_texture = system.GetGpu().GetTexture( + command_buffer, process->GetMmu(), buffer.nv_buffer); // Rect src_rect = {}; @@ -76,7 +77,8 @@ void Layer::Present(hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer, } AccumulatedTime Layer::GetAccumulatedDT() { - return OS_INSTANCE.GetDisplayDriver() + return system.GetOS() + .GetDisplayDriver() .GetBinder(binder_id) .GetAccumulatedDT(); } diff --git a/src/core/horizon/display/layer.hpp b/src/core/horizon/display/layer.hpp index 410aa683..92c4e62c 100644 --- a/src/core/horizon/display/layer.hpp +++ b/src/core/horizon/display/layer.hpp @@ -10,13 +10,15 @@ class ISurfaceCompositor; namespace hydra::horizon::display { +class Driver; + #define LAYER_SIZE_AUTO \ uint2 { 0, 0 } class Layer { public: - Layer(kernel::Process* process_, u32 binder_id_) - : process{process_}, binder_id{binder_id_} {} + Layer(System& system_, kernel::Process* process_, u32 binder_id_) + : system{system_}, process{process_}, binder_id{binder_id_} {} // TODO void Open() {} @@ -32,6 +34,7 @@ class Layer { AccumulatedTime GetAccumulatedDT(); private: + System& system; kernel::Process* process; u32 binder_id; diff --git a/src/core/horizon/kernel/applet_resource.hpp b/src/core/horizon/kernel/applet_resource.hpp index 5c85379d..e11fd003 100644 --- a/src/core/horizon/kernel/applet_resource.hpp +++ b/src/core/horizon/kernel/applet_resource.hpp @@ -1,5 +1,9 @@ #pragma once +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { using AppletResourceUserId = u64; @@ -37,6 +41,8 @@ class AppletResourcePool { AruidAlreadyTaken, }; + AppletResourcePool(System& system_) : system{system_} {} + typename ResourceArray::iterator begin() { return resources.begin(); } typename ResourceArray::const_iterator begin() const { @@ -58,7 +64,7 @@ class AppletResourcePool { ASSERT_THROWING_DEBUG(!resource.has_value(), Kernel, Error::AruidAlreadyTaken, "Aruid {:#x} already taken", aruid); - resource.emplace(); + resource.emplace(system); return *resource; } @@ -84,6 +90,7 @@ class AppletResourcePool { } private: + System& system; ResourceArray resources{}; // Helpers diff --git a/src/core/horizon/kernel/applet_state.cpp b/src/core/horizon/kernel/applet_state.cpp index f3886b57..8024bea8 100644 --- a/src/core/horizon/kernel/applet_state.cpp +++ b/src/core/horizon/kernel/applet_state.cpp @@ -5,13 +5,13 @@ namespace hydra::horizon::kernel { -AppletState::AppletState() - : aruid{KERNEL_INSTANCE.AllocateAppletResourceUserId()}, +AppletState::AppletState(Kernel& kernel_) + : kernel{kernel_}, aruid{kernel.AllocateAppletResourceUserId()}, msg_event{new Event(false, "Message event")} {} AppletState::~AppletState() { msg_event->Release(); - KERNEL_INSTANCE.ReleaseAppletResourceUserId(aruid); + kernel.ReleaseAppletResourceUserId(aruid); } void AppletState::SendMessage(AppletMessage msg) { diff --git a/src/core/horizon/kernel/applet_state.hpp b/src/core/horizon/kernel/applet_state.hpp index c30f6d68..40275f49 100644 --- a/src/core/horizon/kernel/applet_state.hpp +++ b/src/core/horizon/kernel/applet_state.hpp @@ -6,6 +6,7 @@ namespace hydra::horizon::kernel { class Event; +class Kernel; #pragma pack(push, 1) struct AccountHeader { @@ -18,7 +19,7 @@ struct AccountHeader { class AppletState { public: - AppletState(); + AppletState(Kernel& kernel_); ~AppletState(); // Send @@ -37,6 +38,8 @@ class AppletState { sized_ptr PopLaunchParameter(const LaunchParameterKind kind); private: + Kernel& kernel; + std::mutex mutex; AppletResourceUserId aruid; diff --git a/src/core/horizon/kernel/guest_thread.cpp b/src/core/horizon/kernel/guest_thread.cpp index 65bc9b19..50fd9ee7 100644 --- a/src/core/horizon/kernel/guest_thread.cpp +++ b/src/core/horizon/kernel/guest_thread.cpp @@ -6,12 +6,15 @@ #include "core/hw/tegra_x1/cpu/cpu.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" #include "core/hw/tegra_x1/cpu/thread.hpp" +#include "core/system.hpp" namespace hydra::horizon::kernel { -GuestThread::GuestThread(Process* process, vaddr_t stack_top_addr_, - i32 priority, const std::string_view debug_name) - : IThread(process, priority, debug_name), stack_top_addr{stack_top_addr_} { +GuestThread::GuestThread(System& system_, Process* process, + vaddr_t stack_top_addr_, i32 priority, + const std::string_view debug_name) + : IThread(process, priority, debug_name), system{system_}, + stack_top_addr{stack_top_addr_} { tls_mem = process->CreateTlsMemory(tls_addr); } @@ -22,10 +25,11 @@ uptr GuestThread::GetTlsPtr() const { return tls_mem->GetPtr(); } void GuestThread::Run() { // Create ASSERT(entry_point != invalid(), Kernel, "Invalid entry point"); - thread = CPU_INSTANCE.CreateThread( - process->GetMmu(), + thread = system.GetCpu().CreateThread( + system.GetWallClock(), process->GetMmu(), {[this](hw::tegra_x1::cpu::IThread* hw_thread, u64 id) { - KERNEL_INSTANCE.SupervisorCall(process, this, hw_thread, id); + system.GetOS().GetKernel().SupervisorCall(process, this, hw_thread, + id); }, [this]() { ProcessMessages(); diff --git a/src/core/horizon/kernel/guest_thread.hpp b/src/core/horizon/kernel/guest_thread.hpp index ffb3bf12..3baee98c 100644 --- a/src/core/horizon/kernel/guest_thread.hpp +++ b/src/core/horizon/kernel/guest_thread.hpp @@ -2,6 +2,10 @@ #include "core/horizon/kernel/thread.hpp" +namespace hydra { +class System; +} + namespace hydra::hw::tegra_x1::cpu { class IMemory; class IThread; @@ -11,7 +15,8 @@ namespace hydra::horizon::kernel { class GuestThread : public IThread { public: - GuestThread(Process* process, vaddr_t stack_top_addr_, i32 priority, + GuestThread(System& system_, Process* process, vaddr_t stack_top_addr_, + i32 priority, const std::string_view debug_name = "Guest thread"); ~GuestThread() override; @@ -35,6 +40,8 @@ class GuestThread : public IThread { void Run() override; private: + System& system; + hw::tegra_x1::cpu::IMemory* tls_mem; vaddr_t tls_addr; vaddr_t stack_top_addr; diff --git a/src/core/horizon/kernel/kernel.cpp b/src/core/horizon/kernel/kernel.cpp index 0771b525..965037e0 100644 --- a/src/core/horizon/kernel/kernel.cpp +++ b/src/core/horizon/kernel/kernel.cpp @@ -12,15 +12,11 @@ #include "core/hw/tegra_x1/cpu/cpu.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" #include "core/hw/tegra_x1/cpu/thread.hpp" -#include "core/hw/wall_clock.hpp" +#include "core/system.hpp" namespace hydra::horizon::kernel { -SINGLETON_DEFINE_GET_INSTANCE(Kernel, Kernel) - -Kernel::Kernel() { SINGLETON_SET_INSTANCE(Kernel, Kernel); } - -Kernel::~Kernel() { SINGLETON_UNSET_INSTANCE(); } +Kernel::Kernel(System& system_) : system{system_}, process_manager(system) {} void Kernel::SupervisorCall(Process* crnt_process, IThread* crnt_thread, hw::tegra_x1::cpu::IThread* guest_thread, u64 id) { @@ -369,7 +365,7 @@ result_t Kernel::SetHeapSize(Process* crnt_process, usize size, // TODO: handle this more cleanly? auto& heap_mem = crnt_process->GetHeapMemory(); if (!heap_mem) { - heap_mem = CPU_INSTANCE.AllocateMemory(size); + heap_mem = system.GetCpu().AllocateMemory(size); crnt_process->GetMmu()->Map(HEAP_REGION.GetBegin(), heap_mem, {MemoryType::Normal_1_0_0, MemoryAttribute::None, @@ -474,7 +470,8 @@ result_t Kernel::CreateThread(Process* crnt_process, vaddr_t entry_point, // Thread // TODO: processor ID (void)processor_id; - auto thread = new GuestThread(crnt_process, stack_top_addr, priority); + auto thread = + new GuestThread(system, crnt_process, stack_top_addr, priority); thread->SetEntryPoint(entry_point); thread->SetArg(0, args_addr); @@ -738,7 +735,7 @@ result_t Kernel::ArbitrateLock(IThread* crnt_thread, IThread* owner_thread, owner_thread->self_handle_for_mutex = owner_handle; { - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); if (atomic_load(reinterpret_cast(mutex_addr)) != (owner_thread->self_handle_for_mutex | MUTEX_WAIT_MASK)) @@ -769,7 +766,7 @@ result_t Kernel::ArbitrateUnlock(IThread* crnt_thread, uptr mutex_addr) { LOG_DEBUG(Kernel, "ArbitrateUnlock called (mutex: 0x{:08x})", mutex_addr); { - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); UnlockMutex(crnt_thread, mutex_addr); } @@ -794,7 +791,7 @@ result_t Kernel::WaitProcessWideKeyAtomic(Process* crnt_process, crnt_thread->Pause(); { - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); cond_var_waiters.AddLast(crnt_thread); UnlockMutex(crnt_thread, mutex_addr); } @@ -814,7 +811,7 @@ result_t Kernel::WaitProcessWideKeyAtomic(Process* crnt_process, // Remove this thread from the wait list { - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); // Cond var cond_var_waiters.Remove(crnt_thread); @@ -834,7 +831,7 @@ result_t Kernel::SignalProcessWideKey(Process* crnt_process, uptr addr, LOG_DEBUG(Kernel, "SignalProcessWideKey called (addr: 0x{:08x}, count: {})", addr, count); - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); if (count == -1) count = static_cast(cond_var_waiters.GetSize()); @@ -859,7 +856,7 @@ result_t Kernel::SignalProcessWideKey(Process* crnt_process, uptr addr, void Kernel::GetSystemTick(u64& out_tick) { LOG_DEBUG(Kernel, "GetSystemTick called"); - out_tick = hw::WallClock::GetInstance().GetCntpct(); // TODO: correct? + out_tick = system.GetWallClock().GetCntpct(); // TODO: correct? } result_t Kernel::ConnectToNamedPort(const std::string_view name, @@ -1088,7 +1085,7 @@ result_t Kernel::MapPhysicalMemory(Process* crnt_process, vaddr_t addr, if (!ALIAS_REGION.Contains(Range::FromSize(addr, size))) return MAKE_RESULT(Svc, 110); // Invalid memory region - auto mem = CPU_INSTANCE.AllocateMemory(size); + auto mem = system.GetCpu().AllocateMemory(size); // TODO: keep track of the memory crnt_process->GetMmu()->Map(addr, mem, {MemoryType::Alias, MemoryAttribute::None, @@ -1131,7 +1128,7 @@ result_t Kernel::WaitForAddress(IThread* crnt_thread, uptr addr, bool wait; { - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); auto value_ptr = reinterpret_cast(addr); u32 current_value; @@ -1177,7 +1174,7 @@ result_t Kernel::WaitForAddress(IThread* crnt_thread, uptr addr, // Removal is done by the signalling thread /* { - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); arbiters.Remove(crnt_thread); } */ @@ -1201,7 +1198,7 @@ result_t Kernel::SignalToAddress(uptr addr, SignalType signal_type, u32 value, (void)value; (void)count; - CriticalSectionLock cs_lock; + CriticalSectionLock cs_lock(*this); for (auto waiter_node = arbiters.GetHead(); waiter_node != nullptr;) { auto waiter = waiter_node->Get(); if (waiter->mutex_wait_addr != addr) { diff --git a/src/core/horizon/kernel/kernel.hpp b/src/core/horizon/kernel/kernel.hpp index e8d94df9..519b11f8 100644 --- a/src/core/horizon/kernel/kernel.hpp +++ b/src/core/horizon/kernel/kernel.hpp @@ -1,6 +1,5 @@ #pragma once -#include "core/horizon/filesystem/filesystem.hpp" #include "core/horizon/kernel/applet_resource.hpp" #include "core/horizon/kernel/event.hpp" #include "core/horizon/kernel/hipc/service_manager.hpp" @@ -8,8 +7,6 @@ #include "core/horizon/kernel/shared_memory.hpp" #include "core/horizon/kernel/transfer_memory.hpp" -#define KERNEL_INSTANCE hydra::horizon::kernel::Kernel::GetInstance() - namespace hydra::hw::tegra_x1::cpu { class IMmu; class IThread; @@ -35,10 +32,7 @@ class CodeMemory; class Kernel { public: - static Kernel& GetInstance(); - - Kernel(); - ~Kernel(); + Kernel(System& system_); void SupervisorCall(Process* crnt_process, IThread* crnt_thread, hw::tegra_x1::cpu::IThread* guest_thread, u64 id); @@ -162,7 +156,8 @@ class Kernel { vaddr_t src_addr, u64 size); private: - filesystem::Filesystem filesystem; + System& system; + ProcessManager process_manager; hipc::ServiceManager service_manager; @@ -182,7 +177,6 @@ class Kernel { void UnlockMutex(IThread* thread, uptr mutex_addr); public: - REF_GETTER(filesystem, GetFilesystem); REF_GETTER(process_manager, GetProcessManager); REF_GETTER(service_manager, GetServiceManager); REF_GETTER(critical_section_mutex, GetCriticalSectionMutex); @@ -190,11 +184,14 @@ class Kernel { class CriticalSectionLock { public: - CriticalSectionLock() { KERNEL_INSTANCE.GetCriticalSectionMutex().lock(); } - - ~CriticalSectionLock() { - KERNEL_INSTANCE.GetCriticalSectionMutex().unlock(); + CriticalSectionLock(Kernel& kernel_) : kernel{kernel_} { + kernel.GetCriticalSectionMutex().lock(); } + + ~CriticalSectionLock() { kernel.GetCriticalSectionMutex().unlock(); } + + private: + Kernel& kernel; }; } // namespace hydra::horizon::kernel diff --git a/src/core/horizon/kernel/process.cpp b/src/core/horizon/kernel/process.cpp index af62552c..24d84a0e 100644 --- a/src/core/horizon/kernel/process.cpp +++ b/src/core/horizon/kernel/process.cpp @@ -6,12 +6,15 @@ #include "core/hw/tegra_x1/cpu/cpu.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" #include "core/hw/tegra_x1/gpu/gmmu.hpp" +#include "core/system.hpp" namespace hydra::horizon::kernel { -Process::Process(const std::string_view debug_name) - : SynchronizationObject(false, debug_name), mmu{CPU_INSTANCE.CreateMmu()}, - gmmu{new hw::tegra_x1::gpu::GMmu(mmu)} { +Process::Process(System& system_, const std::string_view debug_name) + : SynchronizationObject(false, debug_name), system{system_}, + mmu{system.GetCpu().CreateMmu(system)}, gmmu{new hw::tegra_x1::gpu::GMmu( + mmu)}, + applet_state(system.GetOS().GetKernel()) { // TODO: use title ID and name as debugger name? DEBUGGER_MANAGER_INSTANCE.AttachDebugger( this, @@ -34,7 +37,7 @@ uptr Process::CreateMemory(Range region, usize size, MemoryType type, out_base = mmu->FindFreeMemory(region, size); ASSERT(out_base != 0x0, Kernel, "Failed to find free memory"); - auto mem = CPU_INSTANCE.AllocateMemory(size); + auto mem = system.GetCpu().AllocateMemory(size); mmu->Map(out_base, mem, {type, MemoryAttribute::None, perm}); executable_mems.push_back(mem); @@ -74,7 +77,7 @@ uptr Process::CreateExecutableMemory(const std::string_view module_name, } hw::tegra_x1::cpu::IMemory* Process::CreateTlsMemory(vaddr_t& base) { - auto mem = CPU_INSTANCE.AllocateMemory(TLS_SIZE); + auto mem = system.GetCpu().AllocateMemory(TLS_SIZE); base = tls_mem_base; mmu->Map(base, mem, {MemoryType::ThreadLocal, MemoryAttribute::None, @@ -88,7 +91,7 @@ void Process::CreateStackMemory(usize stack_size) { // main_thread = new GuestThread(this, STACK_REGION.begin + stack_size - // 0x10, priority); auto handle_id = AddHandle(main_thread); - main_thread_stack_mem = CPU_INSTANCE.AllocateMemory(stack_size); + main_thread_stack_mem = system.GetCpu().AllocateMemory(stack_size); mmu->Map(STACK_REGION.GetBegin(), main_thread_stack_mem, {MemoryType::Stack, MemoryAttribute::None, MemoryPermission::ReadWrite}); diff --git a/src/core/horizon/kernel/process.hpp b/src/core/horizon/kernel/process.hpp index 36b93fde..54af5072 100644 --- a/src/core/horizon/kernel/process.hpp +++ b/src/core/horizon/kernel/process.hpp @@ -38,7 +38,7 @@ struct CodeSet { class Process : public SynchronizationObject { public: - Process(const std::string_view debug_name = "Process"); + Process(System& system_, const std::string_view debug_name = "Process"); ~Process() override; // Memory @@ -136,6 +136,8 @@ class Process : public SynchronizationObject { } private: + System& system; + hw::tegra_x1::cpu::IMmu* mmu; hw::tegra_x1::gpu::GMmu* gmmu; diff --git a/src/core/horizon/kernel/process_manager.cpp b/src/core/horizon/kernel/process_manager.cpp index 5ec9bd3e..873314ef 100644 --- a/src/core/horizon/kernel/process_manager.cpp +++ b/src/core/horizon/kernel/process_manager.cpp @@ -18,7 +18,7 @@ ProcessManager::~ProcessManager() { Process* ProcessManager::CreateProcess(const std::string_view name) { std::lock_guard lock(mutex); - Process* process = new Process(name); + Process* process = new Process(system, name); processes.push_back(process); return process; } diff --git a/src/core/horizon/kernel/process_manager.hpp b/src/core/horizon/kernel/process_manager.hpp index a7bccf5b..447622a6 100644 --- a/src/core/horizon/kernel/process_manager.hpp +++ b/src/core/horizon/kernel/process_manager.hpp @@ -1,11 +1,16 @@ #pragma once +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { class Process; class ProcessManager { public: + ProcessManager(System& system_) : system{system_} {} ~ProcessManager(); Process* CreateProcess(const std::string_view name); @@ -17,6 +22,8 @@ class ProcessManager { std::vector::iterator End() { return processes.end(); } private: + System& system; + std::mutex mutex; std::vector processes; }; diff --git a/src/core/horizon/kernel/shared_memory.cpp b/src/core/horizon/kernel/shared_memory.cpp index 4bc839ff..cb5f4afa 100644 --- a/src/core/horizon/kernel/shared_memory.cpp +++ b/src/core/horizon/kernel/shared_memory.cpp @@ -4,9 +4,10 @@ namespace hydra::horizon::kernel { -SharedMemory::SharedMemory(usize size, const std::string_view debug_name) +SharedMemory::SharedMemory(hw::tegra_x1::cpu::ICpu& cpu, usize size, + const std::string_view debug_name) : AutoObject(debug_name) { - memory = CPU_INSTANCE.AllocateMemory(size); + memory = cpu.AllocateMemory(size); // Clear memset(reinterpret_cast(GetPtr()), 0, size); diff --git a/src/core/horizon/kernel/shared_memory.hpp b/src/core/horizon/kernel/shared_memory.hpp index 1b4fa691..f2a06204 100644 --- a/src/core/horizon/kernel/shared_memory.hpp +++ b/src/core/horizon/kernel/shared_memory.hpp @@ -5,6 +5,7 @@ #include "core/hw/tegra_x1/cpu/mmu.hpp" namespace hydra::hw::tegra_x1::cpu { +class ICpu; class IMmu; } // namespace hydra::hw::tegra_x1::cpu @@ -12,7 +13,7 @@ namespace hydra::horizon::kernel { class SharedMemory : public AutoObject { public: - SharedMemory(usize size, + SharedMemory(hw::tegra_x1::cpu::ICpu& cpu, usize size, const std::string_view debug_name = "SharedMemory"); ~SharedMemory() override; diff --git a/src/core/horizon/loader/homebrew_loader.cpp b/src/core/horizon/loader/homebrew_loader.cpp index 0e2c4e8d..e0dc4dc8 100644 --- a/src/core/horizon/loader/homebrew_loader.cpp +++ b/src/core/horizon/loader/homebrew_loader.cpp @@ -6,8 +6,7 @@ #include "core/horizon/const.hpp" #include "core/horizon/filesystem/disk_file.hpp" #include "core/horizon/filesystem/file_view.hpp" -#include "core/horizon/filesystem/filesystem.hpp" -#include "core/horizon/kernel/kernel.hpp" +#include "core/system.hpp" namespace hydra::horizon::loader { @@ -48,12 +47,13 @@ struct ConfigEntry { class HomebrewThread : public kernel::GuestThread { public: // TODO: don't hardcode priority - HomebrewThread(kernel::Process* process, std::string_view path_) - : kernel::GuestThread(process, + HomebrewThread(System& system_, kernel::Process* process, + std::string_view path_) + : kernel::GuestThread(system_, process, kernel::STACK_REGION.GetBegin() + STACK_MEMORY_SIZE - 0x10, 0x2c, "Homebrew thread"), - path{path_} {} + system{system_}, path{path_} {} protected: void Run() override { @@ -124,15 +124,14 @@ class HomebrewThread : public kernel::GuestThread { // File filesystem::IFile* file; - const auto res = - KERNEL_INSTANCE.GetFilesystem().GetFile(path, file); + const auto res = system.GetOS().GetFilesystem().GetFile(path, file); ASSERT(res == filesystem::FsResult::Success, Loader, "Failed to get Homebrew file: {}", res); // NRO loader { NroLoader nro_loader(file, false); - nro_loader.LoadProcess(process); + nro_loader.LoadProcess(system, process); const auto executable_ptr = nro_loader.GetExecutablePtr(); // Random @@ -220,7 +219,9 @@ class HomebrewThread : public kernel::GuestThread { } private: + System& system; std::string path; + handle_id_t self_handle{INVALID_HANDLE_ID}; public: @@ -236,7 +237,7 @@ HomebrewLoader::HomebrewLoader(filesystem::IFile* file_) TryLoadAssetSection(new filesystem::FileView(file, asset_begin)); } -void HomebrewLoader::LoadProcess(kernel::Process* process) { +void HomebrewLoader::LoadProcess(System& system, kernel::Process* process) { // Get name auto stream = nacp_file->Open(filesystem::FileOpenFlags::Read); @@ -250,7 +251,7 @@ void HomebrewLoader::LoadProcess(kernel::Process* process) { std::string mapped_path = fmt::format(FS_SD_MOUNT "/switch/{}/{}.nro", title_name, title_name); const auto res = - KERNEL_INSTANCE.GetFilesystem().AddEntry(mapped_path, file, true); + system.GetOS().GetFilesystem().AddEntry(mapped_path, file, true); ASSERT(res == filesystem::FsResult::Success, Loader, "Failed to map Homebrew file: {}", res); @@ -258,7 +259,7 @@ void HomebrewLoader::LoadProcess(kernel::Process* process) { process->CreateStackMemory(STACK_MEMORY_SIZE); // Main thread - auto main_thread = new HomebrewThread(process, mapped_path); + auto main_thread = new HomebrewThread(system, process, mapped_path); const auto main_thread_handle_id = process->SetMainThread(main_thread); main_thread->SetSelfHandle(main_thread_handle_id); } diff --git a/src/core/horizon/loader/homebrew_loader.hpp b/src/core/horizon/loader/homebrew_loader.hpp index 7104cfa3..ce91b09e 100644 --- a/src/core/horizon/loader/homebrew_loader.hpp +++ b/src/core/horizon/loader/homebrew_loader.hpp @@ -2,16 +2,21 @@ #include "core/horizon/loader/nro_loader.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::loader { class HomebrewLoader : public LoaderBase { public: HomebrewLoader(filesystem::IFile* file_); - void LoadProcess(kernel::Process* process) override; + void LoadProcess(System& system, kernel::Process* process) override; private: filesystem::IFile* file; + NroLoader nro_loader; void TryLoadAssetSection(filesystem::IFile* asset_file); diff --git a/src/core/horizon/loader/loader_base.cpp b/src/core/horizon/loader/loader_base.cpp index c1507d97..780348c4 100644 --- a/src/core/horizon/loader/loader_base.cpp +++ b/src/core/horizon/loader/loader_base.cpp @@ -74,7 +74,8 @@ uchar4* LoadGIF(filesystem::IFile* file, } // namespace -LoaderBase* LoaderBase::CreateFromPath(std::string_view path) { +LoaderBase* LoaderBase::CreateFromPath(std::string_view path, + plugins::Manager* plugin_manager) { while (path.back() == '/') { path.remove_suffix(1); } @@ -100,14 +101,21 @@ LoaderBase* LoaderBase::CreateFromPath(std::string_view path) { } else if (ext == ".nca") { loader = new horizon::loader::NcaLoader(file); } else { + // Check if we need to create a temporary plugin manager + bool has_plugin_manager = (plugin_manager != nullptr); + if (!has_plugin_manager) + plugin_manager = new plugins::Manager(); + // First, check if any of the loader plugins supports this format - auto plugin = plugins::Manager::GetInstance().FindPluginForFormat( - ext.substr(1)); + auto plugin = plugin_manager->FindPluginForFormat(ext.substr(1)); ASSERT_THROWING( plugin, Loader, CreateFromPathError::UnsupportedExtension, "Unsupported extension \"{}\" (path: \"{}\")", ext, path); loader = plugin->Load(path); + + if (!has_plugin_manager) + delete plugin_manager; } } diff --git a/src/core/horizon/loader/loader_base.hpp b/src/core/horizon/loader/loader_base.hpp index f04f0310..1ea5c32e 100644 --- a/src/core/horizon/loader/loader_base.hpp +++ b/src/core/horizon/loader/loader_base.hpp @@ -4,21 +4,35 @@ #include "core/horizon/kernel/process.hpp" #include "core/horizon/services/ns/const.hpp" +namespace hydra { +class System; +} + +namespace hydra::horizon::filesystem { +class Filesystem; +} + namespace hydra::horizon::loader { +namespace plugins { +class Manager; +} + class LoaderBase { public: enum class CreateFromPathError { DoesNotExist, UnsupportedExtension, }; - static LoaderBase* CreateFromPath(std::string_view path); + static LoaderBase* + CreateFromPath(std::string_view path, + plugins::Manager* plugin_manager = nullptr); virtual ~LoaderBase() = default; virtual u64 GetTitleID() const { return invalid(); } - virtual void LoadProcess(kernel::Process* process) = 0; + virtual void LoadProcess(System& system, kernel::Process* process) = 0; enum class LoadNacpError { InvalidSize, }; diff --git a/src/core/horizon/loader/nca_loader.cpp b/src/core/horizon/loader/nca_loader.cpp index 4558f970..94c23083 100644 --- a/src/core/horizon/loader/nca_loader.cpp +++ b/src/core/horizon/loader/nca_loader.cpp @@ -4,6 +4,7 @@ #include "core/horizon/kernel/kernel.hpp" #include "core/horizon/loader/npdm.hpp" #include "core/horizon/loader/nso_loader.hpp" +#include "core/system.hpp" #define NINTENDO_LOGO_PATH "logo/NintendoLogo.png" #define STARTUP_MOVIE_PATH "logo/StartupMovie.gif" @@ -80,21 +81,22 @@ NcaLoader::NcaLoader(const filesystem::ContentArchive& content_archive_) romfs_entry = romfs_file; } -void NcaLoader::LoadProcess(kernel::Process* process) { +void NcaLoader::LoadProcess(System& system, kernel::Process* process) { // Title ID process->SetTitleID(content_archive.GetTitleID()); // ExeFS - LoadCode(process, exefs_dir); + LoadCode(system, process, exefs_dir); // RomFS - const auto res = KERNEL_INSTANCE.GetFilesystem().AddEntry( + const auto res = system.GetOS().GetFilesystem().AddEntry( FS_SD_MOUNT "/rom/romFS", romfs_entry, true); ASSERT(res == filesystem::FsResult::Success, Loader, "Failed to add romFS file: {}", res); } -void NcaLoader::LoadCode(kernel::Process* process, filesystem::Directory* dir) { +void NcaLoader::LoadCode(System& system, kernel::Process* process, + filesystem::Directory* dir) { // HACK: if rtld is not present, use main as the entry point std::string entry_point = "rtld"; filesystem::IEntry* e; @@ -112,7 +114,7 @@ void NcaLoader::LoadCode(kernel::Process* process, filesystem::Directory* dir) { loader.SetMainThreadParams(main_thread_priority, main_thread_core_number, main_thread_stack_size); - loader.LoadProcess(process); + loader.LoadProcess(system, process); } } diff --git a/src/core/horizon/loader/nca_loader.hpp b/src/core/horizon/loader/nca_loader.hpp index 475edf4e..b6b78876 100644 --- a/src/core/horizon/loader/nca_loader.hpp +++ b/src/core/horizon/loader/nca_loader.hpp @@ -3,6 +3,10 @@ #include "core/horizon/filesystem/content_archive.hpp" #include "core/horizon/loader/loader_base.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::loader { class NcaLoader : public LoaderBase { @@ -19,7 +23,7 @@ class NcaLoader : public LoaderBase { const std::string& GetName() const { return name; } - void LoadProcess(kernel::Process* process) override; + void LoadProcess(System& system, kernel::Process* process) override; private: filesystem::ContentArchive content_archive; @@ -31,7 +35,8 @@ class NcaLoader : public LoaderBase { u32 system_resource_size; // Helpers - void LoadCode(kernel::Process* process, filesystem::Directory* dir); + void LoadCode(System& system, kernel::Process* process, + filesystem::Directory* dir); }; } // namespace hydra::horizon::loader diff --git a/src/core/horizon/loader/nro_loader.cpp b/src/core/horizon/loader/nro_loader.cpp index 8a844883..25de6675 100644 --- a/src/core/horizon/loader/nro_loader.cpp +++ b/src/core/horizon/loader/nro_loader.cpp @@ -64,7 +64,7 @@ NroLoader::NroLoader(filesystem::IFile* file_, const bool is_entry_point_) delete stream; } -void NroLoader::LoadProcess(kernel::Process* process) { +void NroLoader::LoadProcess(System& system, kernel::Process* process) { auto stream = file->Open(filesystem::FileOpenFlags::Read); // Create executable memory @@ -87,6 +87,7 @@ void NroLoader::LoadProcess(kernel::Process* process) { // Main thread if (is_entry_point) { + (void)system; // TODO: implement? LOG_FATAL(Loader, "NRO loading not implemented"); /* diff --git a/src/core/horizon/loader/nro_loader.hpp b/src/core/horizon/loader/nro_loader.hpp index 95f6c14a..a6a2b9b0 100644 --- a/src/core/horizon/loader/nro_loader.hpp +++ b/src/core/horizon/loader/nro_loader.hpp @@ -17,7 +17,7 @@ class NroLoader : public LoaderBase { NroLoader(filesystem::IFile* file_, const bool is_entry_point_); - void LoadProcess(kernel::Process* process) override; + void LoadProcess(System& system, kernel::Process* process) override; vaddr_t GetEntryPoint() const; diff --git a/src/core/horizon/loader/nso_loader.cpp b/src/core/horizon/loader/nso_loader.cpp index c9ccaddd..b3d52406 100644 --- a/src/core/horizon/loader/nso_loader.cpp +++ b/src/core/horizon/loader/nso_loader.cpp @@ -126,7 +126,7 @@ NsoLoader::NsoLoader(filesystem::IFile* file_, const std::string_view name_, delete stream; } -void NsoLoader::LoadProcess(kernel::Process* process) { +void NsoLoader::LoadProcess(System& system, kernel::Process* process) { // Register executable DEBUGGER_MANAGER_INSTANCE.GetDebugger(process).RegisterExecutable(name, file); @@ -222,7 +222,7 @@ void NsoLoader::LoadProcess(kernel::Process* process) { // Main thread auto main_thread = new kernel::GuestThread( - process, + system, process, kernel::STACK_REGION.GetBegin() + main_thread_stack_size - 0x10, main_thread_priority); const auto main_thread_handle_id = process->SetMainThread(main_thread); diff --git a/src/core/horizon/loader/nso_loader.hpp b/src/core/horizon/loader/nso_loader.hpp index 67315ef9..4b1d9296 100644 --- a/src/core/horizon/loader/nso_loader.hpp +++ b/src/core/horizon/loader/nso_loader.hpp @@ -25,7 +25,7 @@ class NsoLoader : public LoaderBase { main_thread_stack_size = stack_size; } - void LoadProcess(kernel::Process* process) override; + void LoadProcess(System& system, kernel::Process* process) override; private: filesystem::IFile* file; diff --git a/src/core/horizon/loader/nsp_loader.hpp b/src/core/horizon/loader/nsp_loader.hpp index 95ab0ad3..a6706646 100644 --- a/src/core/horizon/loader/nsp_loader.hpp +++ b/src/core/horizon/loader/nsp_loader.hpp @@ -17,8 +17,8 @@ class NspLoader : public LoaderBase { return invalid(); // program_nca_loader->GetTitleID(); } - void LoadProcess(kernel::Process* process) override { - /*program_nca_loader*/ nso_loader->LoadProcess(process); + void LoadProcess(System& system, kernel::Process* process) override { + /*program_nca_loader*/ nso_loader->LoadProcess(system, process); } private: diff --git a/src/core/horizon/loader/nx_loader.cpp b/src/core/horizon/loader/nx_loader.cpp index 0656a309..d3485a12 100644 --- a/src/core/horizon/loader/nx_loader.cpp +++ b/src/core/horizon/loader/nx_loader.cpp @@ -4,6 +4,7 @@ #include "core/horizon/kernel/kernel.hpp" #include "core/horizon/loader/npdm.hpp" #include "core/horizon/loader/nso_loader.hpp" +#include "core/system.hpp" #define NACP_PATH "meta/control.nacp" #define ICON_PATH "meta/icons/AmericanEnglish.jpg" @@ -55,12 +56,12 @@ NxLoader::NxLoader(const filesystem::Directory& dir_) : dir{dir_} { "Failed to get RomFS entry: {}", res); } -void NxLoader::LoadProcess(kernel::Process* process) { +void NxLoader::LoadProcess(System& system, kernel::Process* process) { // Title ID process->SetTitleID(title_id); // ExeFS - LoadCode(process, exefs_dir); + LoadCode(system, process, exefs_dir); // RomFS filesystem::IFile* romfs_file; @@ -75,7 +76,7 @@ void NxLoader::LoadProcess(kernel::Process* process) { ASSERT(romfs_file, Loader, "Failed to build romFS"); } - const auto res = KERNEL_INSTANCE.GetFilesystem().AddEntry( + const auto res = system.GetOS().GetFilesystem().AddEntry( FS_SD_MOUNT "/rom/romFS", romfs_file, true); ASSERT(res == filesystem::FsResult::Success, Loader, "Failed to add romFS file: {}", res); @@ -140,7 +141,7 @@ void NxLoader::ParseNpdm() { system_resource_size = meta.system_resource_size; } -void NxLoader::LoadCode(kernel::Process* process, +void NxLoader::LoadCode(System& system, kernel::Process* process, filesystem::Directory* exefs_dir) { // HACK: if rtld is not present, use main as the entry point std::string entry_point = "rtld"; @@ -159,7 +160,7 @@ void NxLoader::LoadCode(kernel::Process* process, loader.SetMainThreadParams(main_thread_priority, main_thread_core_number, main_thread_stack_size); - loader.LoadProcess(process); + loader.LoadProcess(system, process); } } diff --git a/src/core/horizon/loader/nx_loader.hpp b/src/core/horizon/loader/nx_loader.hpp index 100d2750..5b713915 100644 --- a/src/core/horizon/loader/nx_loader.hpp +++ b/src/core/horizon/loader/nx_loader.hpp @@ -3,6 +3,10 @@ #include "core/horizon/filesystem/directory.hpp" #include "core/horizon/loader/loader_base.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::loader { class NxLoader : public LoaderBase { @@ -17,7 +21,7 @@ class NxLoader : public LoaderBase { const std::string& GetName() const { return title_name; } - void LoadProcess(kernel::Process* process) override; + void LoadProcess(System& system, kernel::Process* process) override; private: const filesystem::Directory& dir; @@ -33,7 +37,8 @@ class NxLoader : public LoaderBase { // Helpers void ParseInfo(); void ParseNpdm(); - void LoadCode(kernel::Process* process, filesystem::Directory* exefs_dir); + void LoadCode(System& system, kernel::Process* process, + filesystem::Directory* exefs_dir); }; } // namespace hydra::horizon::loader diff --git a/src/core/horizon/loader/plugins/manager.hpp b/src/core/horizon/loader/plugins/manager.hpp index a2dcaa3c..581024d7 100644 --- a/src/core/horizon/loader/plugins/manager.hpp +++ b/src/core/horizon/loader/plugins/manager.hpp @@ -6,11 +6,6 @@ namespace hydra::horizon::loader::plugins { class Manager { public: - static Manager& GetInstance() { - static Manager instance; - return instance; - } - void Refresh(); Plugin* FindPluginForFormat(std::string_view format); diff --git a/src/core/horizon/loader/plugins/plugin.hpp b/src/core/horizon/loader/plugins/plugin.hpp index 992bb509..f5d73a61 100644 --- a/src/core/horizon/loader/plugins/plugin.hpp +++ b/src/core/horizon/loader/plugins/plugin.hpp @@ -4,6 +4,10 @@ #include "core/horizon/loader/plugins/api.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::filesystem { class Directory; } diff --git a/src/core/horizon/os.cpp b/src/core/horizon/os.cpp index 8491906c..a9ef2f0d 100644 --- a/src/core/horizon/os.cpp +++ b/src/core/horizon/os.cpp @@ -107,7 +107,7 @@ void RegisterServiceToPort(services::Server* server, service_manager.RegisterPort(port_name, client_port); } -uint2 round_up_to_nearest_standard_resolution(uint2 surface_resolution) { +uint2 RoundUpToNearestStandardResolution(uint2 surface_resolution) { // TODO: constexpr static uint2 standard_resolutions[] = { {1280, 720}, {1920, 1080}, {2560, 1440}, {3840, 2160}, {7680, 4320}}; @@ -123,26 +123,25 @@ uint2 round_up_to_nearest_standard_resolution(uint2 surface_resolution) { } // namespace -SINGLETON_DEFINE_GET_INSTANCE(OS, Horizon) - -OS::OS(audio::ICore& audio_core_, ui::IHandler& ui_handler_) - : audio_core{audio_core_}, ui_handler{ui_handler_} { - SINGLETON_SET_INSTANCE(OS, Horizon); - +OS::OS(System& system_) + : system{system_}, kernel(system), nvservices_server(system), + others_server(system), display_driver(system), + hid_resource_manager(system), shared_font_manager(system), + time_manager(system), ir_sensor_manager(system) { // Firmware - try_install_firmware_to_filesystem(kernel.GetFilesystem()); + try_install_firmware_to_filesystem(filesystem); // Sysmodules const auto& sysmodules_path = CONFIG_INSTANCE.GetSysmodulesPath(); if (std::filesystem::exists(sysmodules_path)) { - auto res = KERNEL_INSTANCE.GetFilesystem().AddEntry( - FS_SYSMODULES_PATH, sysmodules_path, true); + auto res = + filesystem.AddEntry(FS_SYSMODULES_PATH, sysmodules_path, true); ASSERT(res == horizon::filesystem::FsResult::Success, Other, "Failed to add sysmodules", res); } // System avatars - user_manager.LoadSystemAvatars(kernel.GetFilesystem()); + user_manager.LoadSystemAvatars(filesystem); // Shared font shared_font_manager.LoadFonts(); @@ -334,14 +333,12 @@ OS::OS(audio::ICore& audio_core_, ui::IHandler& ui_handler_) // TODO: get title ID from toolbox.json auto process = kernel.GetProcessManager().CreateProcess("Sysmodule"); - loader.LoadProcess(process); + loader.LoadProcess(system, process); process->Start(); } } } -OS::~OS() { SINGLETON_UNSET_INSTANCE(); } - void OS::NotifyOperationModeChanged() { // Disconnect and connect npads // TODO: update supported style sets? @@ -366,7 +363,7 @@ uint2 OS::GetDisplayResolution() const { } else { switch (CONFIG_INSTANCE.GetDisplayResolution()) { case Resolution::Auto: - return round_up_to_nearest_standard_resolution(surface_resolution); + return RoundUpToNearestStandardResolution(surface_resolution); case Resolution::_720p: return {1280, 720}; case Resolution::_1080p: diff --git a/src/core/horizon/os.hpp b/src/core/horizon/os.hpp index 303221e4..5dd2ea7c 100644 --- a/src/core/horizon/os.hpp +++ b/src/core/horizon/os.hpp @@ -1,17 +1,15 @@ #pragma once #include "core/horizon/display/driver.hpp" +#include "core/horizon/filesystem/filesystem.hpp" #include "core/horizon/services/account/internal/user_manager.hpp" +#include "core/horizon/services/am/internal/library_applet_controller.hpp" #include "core/horizon/services/hid/internal/resource_manager.hpp" +#include "core/horizon/services/irsensor/internal/ir_sensor_manager.hpp" #include "core/horizon/services/pl/internal/shared_font_manager.hpp" #include "core/horizon/services/server.hpp" #include "core/horizon/services/timesrv/internal/time_manager.hpp" -#define OS_INSTANCE horizon::OS::GetInstance() -#define USER_MANAGER_INSTANCE OS_INSTANCE.GetUserManager() -#define SHARED_FONT_MANAGER_INSTANCE OS_INSTANCE.GetSharedFontManager() -#define TIME_MANAGER_INSTANCE OS_INSTANCE.GetTimeManager() - namespace hydra::audio { class ICore; } @@ -28,10 +26,7 @@ class IHandler; class OS { public: - static OS& GetInstance(); - - OS(audio::ICore& audio_core_, ui::IHandler& ui_handler_); - ~OS(); + OS(System& system_); void NotifyOperationModeChanged(); @@ -39,10 +34,10 @@ class OS { uint2 GetDisplayResolution() const; private: - audio::ICore& audio_core; - ui::IHandler& ui_handler; + System& system; kernel::Kernel kernel; + filesystem::Filesystem filesystem; // Services kernel::hipc::ServiceManager service_manager; @@ -55,23 +50,24 @@ class OS { services::account::internal::UserManager user_manager; services::pl::internal::SharedFontManager shared_font_manager; services::timesrv::internal::TimeManager time_manager; + services::irsensor::internal::IrSensorManager ir_sensor_manager; - services::am::LibraryAppletController* library_applet_self_controller{ - nullptr}; + services::am::internal::LibraryAppletController* + library_applet_self_controller{nullptr}; // Display uint2 surface_resolution; public: - REF_GETTER(audio_core, GetAudioCore); - REF_GETTER(ui_handler, GetUIHandler); REF_GETTER(kernel, GetKernel); + REF_GETTER(filesystem, GetFilesystem); REF_GETTER(service_manager, GetServiceManager); REF_GETTER(display_driver, GetDisplayDriver); REF_GETTER(hid_resource_manager, GetHidResourceManager); REF_GETTER(user_manager, GetUserManager); REF_GETTER(shared_font_manager, GetSharedFontManager); REF_GETTER(time_manager, GetTimeManager); + REF_GETTER(ir_sensor_manager, GetIrSensorManager); GETTER_AND_SETTER(library_applet_self_controller, GetLibraryAppletSelfController, SetLibraryAppletSelfController); diff --git a/src/core/horizon/services/account/account_service.cpp b/src/core/horizon/services/account/account_service.cpp index 994715b8..abe0b67e 100644 --- a/src/core/horizon/services/account/account_service.cpp +++ b/src/core/horizon/services/account/account_service.cpp @@ -1,29 +1,32 @@ #include "core/horizon/services/account/account_service_for_application.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/services/account/profile.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::account { -result_t IAccountService::GetUserCount(i32* out_count) { - *out_count = static_cast(USER_MANAGER_INSTANCE.GetUserCount()); +result_t IAccountService::GetUserCount(System* system, i32* out_count) { + *out_count = + static_cast(system->GetOS().GetUserManager().GetUserCount()); return RESULT_SUCCESS; } -result_t IAccountService::GetUserExistence(uuid_t user_id, bool* out_exists) { +result_t IAccountService::GetUserExistence(System* system, uuid_t user_id, + bool* out_exists) { LOG_DEBUG(Services, "User ID: 0x{:08x}", user_id); - *out_exists = USER_MANAGER_INSTANCE.UserExists(user_id); + *out_exists = system->GetOS().GetUserManager().UserExists(user_id); return RESULT_SUCCESS; } result_t -IAccountService::ListAllUsers(OutBuffer out_buffer) { +IAccountService::ListAllUsers(System* system, + OutBuffer out_buffer) { // Clear buffer std::memset(out_buffer.stream->GetPtr(), 0, out_buffer.stream->GetSize()); // Write user IDs - for (const auto user_id : USER_MANAGER_INSTANCE.GetUserIDs()) { + for (const auto user_id : system->GetOS().GetUserManager().GetUserIDs()) { // Check if we cen fit the entry in the buffer if (out_buffer.stream->GetSeek() + sizeof(uuid_t) > out_buffer.stream->GetSize()) @@ -38,14 +41,15 @@ IAccountService::ListAllUsers(OutBuffer out_buffer) { // TODO: how is this different from ListAllUsers? Or a better question: what is // the difference between an opened user and a closed user? result_t -IAccountService::ListOpenUsers(OutBuffer out_buffer) { +IAccountService::ListOpenUsers(System* system, + OutBuffer out_buffer) { LOG_FUNC_STUBBED(Services); // Clear buffer std::memset(out_buffer.stream->GetPtr(), 0, out_buffer.stream->GetSize()); // Write user IDs - for (const auto user_id : USER_MANAGER_INSTANCE.GetUserIDs()) { + for (const auto user_id : system->GetOS().GetUserManager().GetUserIDs()) { // Check if we cen fit the entry in the buffer if (out_buffer.stream->GetSeek() + sizeof(uuid_t) > out_buffer.stream->GetSize()) @@ -59,11 +63,12 @@ IAccountService::ListOpenUsers(OutBuffer out_buffer) { return RESULT_SUCCESS; } -result_t IAccountService::GetLastOpenedUser(uuid_t* out_user_id) { +result_t IAccountService::GetLastOpenedUser(System* system, + uuid_t* out_user_id) { LOG_FUNC_STUBBED(Services); // HACK: return the first user - *out_user_id = USER_MANAGER_INSTANCE.GetUserIDs()[0]; + *out_user_id = system->GetOS().GetUserManager().GetUserIDs()[0]; return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/account/account_service.hpp b/src/core/horizon/services/account/account_service.hpp index 40f6d901..e9532500 100644 --- a/src/core/horizon/services/account/account_service.hpp +++ b/src/core/horizon/services/account/account_service.hpp @@ -17,12 +17,14 @@ class IAccountService : public IService { protected: // Commands - result_t GetUserCount(i32* out_count); - result_t GetUserExistence(uuid_t user_id, bool* out_exists); - result_t ListAllUsers(OutBuffer out_buffer); + result_t GetUserCount(System* system, i32* out_count); + result_t GetUserExistence(System* system, uuid_t user_id, bool* out_exists); + result_t ListAllUsers(System* system, + OutBuffer out_buffer); // TODO: correct? - result_t ListOpenUsers(OutBuffer out_buffer); - result_t GetLastOpenedUser(uuid_t* out_user_id); + result_t ListOpenUsers(System* system, + OutBuffer out_buffer); + result_t GetLastOpenedUser(System* system, uuid_t* out_user_id); result_t GetProfile(RequestContext* ctx, uuid_t user_id); // TODO: PID and PID reserved result_t IsUserRegistrationRequestPermitted(bool* out_permitted); diff --git a/src/core/horizon/services/account/profile.cpp b/src/core/horizon/services/account/profile.cpp index cacee71e..590ebe95 100644 --- a/src/core/horizon/services/account/profile.cpp +++ b/src/core/horizon/services/account/profile.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/account/profile.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::account { @@ -8,40 +8,41 @@ DEFINE_SERVICE_COMMAND_TABLE(IProfile, 0, Get, 1, GetBase, 10, GetImageSize, 11, LoadImage) result_t -IProfile::Get(ProfileBase* out_base, +IProfile::Get(System* system, ProfileBase* out_base, OutBuffer out_user_data_buffer) { - const auto& user = USER_MANAGER_INSTANCE.GetUser(user_id); + const auto& user = system->GetOS().GetUserManager().GetUser(user_id); *out_base = user.GetBase(); out_user_data_buffer.stream->Write(user.GetData()); return RESULT_SUCCESS; } -result_t IProfile::GetBase(ProfileBase* out_base) { - const auto& user = USER_MANAGER_INSTANCE.GetUser(user_id); +result_t IProfile::GetBase(System* system, ProfileBase* out_base) { + const auto& user = system->GetOS().GetUserManager().GetUser(user_id); *out_base = user.GetBase(); return RESULT_SUCCESS; } // TODO: get the size without loading the whole image? -result_t IProfile::GetImageSize(u32* out_size) { - const auto& user = USER_MANAGER_INSTANCE.GetUser(user_id); +result_t IProfile::GetImageSize(System* system, u32* out_size) { + const auto& user = system->GetOS().GetUserManager().GetUser(user_id); std::vector data; - USER_MANAGER_INSTANCE.LoadAvatarImageAsJpeg(user.GetAvatarPath(), - user.GetAvatarBgColor(), data); + system->GetOS().GetUserManager().LoadAvatarImageAsJpeg( + user.GetAvatarPath(), user.GetAvatarBgColor(), data); *out_size = static_cast(data.size()); return RESULT_SUCCESS; } -result_t IProfile::LoadImage(OutBuffer out_buffer, +result_t IProfile::LoadImage(System* system, + OutBuffer out_buffer, u32* out_size) { - const auto& user = USER_MANAGER_INSTANCE.GetUser(user_id); + const auto& user = system->GetOS().GetUserManager().GetUser(user_id); // Load image std::vector data; - USER_MANAGER_INSTANCE.LoadAvatarImageAsJpeg(user.GetAvatarPath(), - user.GetAvatarBgColor(), data); + system->GetOS().GetUserManager().LoadAvatarImageAsJpeg( + user.GetAvatarPath(), user.GetAvatarBgColor(), data); out_buffer.stream->WriteSpan(std::span(data)); diff --git a/src/core/horizon/services/account/profile.hpp b/src/core/horizon/services/account/profile.hpp index 64800362..f1d4091c 100644 --- a/src/core/horizon/services/account/profile.hpp +++ b/src/core/horizon/services/account/profile.hpp @@ -16,11 +16,12 @@ class IProfile : public IService { uuid_t user_id; // Commands - result_t Get(ProfileBase* out_base, + result_t Get(System* system, ProfileBase* out_base, OutBuffer out_user_data_buffer); - result_t GetBase(ProfileBase* out_base); - result_t GetImageSize(u32* out_size); - result_t LoadImage(OutBuffer out_buffer, + result_t GetBase(System* system, ProfileBase* out_base); + result_t GetImageSize(System* system, u32* out_size); + result_t LoadImage(System* system, + OutBuffer out_buffer, u32* out_size); }; diff --git a/src/core/horizon/services/am/common_state_getter.cpp b/src/core/horizon/services/am/common_state_getter.cpp index bab06c34..f76e8ba2 100644 --- a/src/core/horizon/services/am/common_state_getter.cpp +++ b/src/core/horizon/services/am/common_state_getter.cpp @@ -1,7 +1,7 @@ #include "core/horizon/services/am/common_state_getter.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::am { @@ -37,9 +37,10 @@ result_t ICommonStateGetter::GetOperationMode(OperationMode* out_mode) { return RESULT_SUCCESS; } -result_t ICommonStateGetter::GetDefaultDisplayResolution(i32* out_width, +result_t ICommonStateGetter::GetDefaultDisplayResolution(System* system, + i32* out_width, i32* out_height) { - const auto res = OS_INSTANCE.GetDisplayResolution(); + const auto res = system->GetOS().GetDisplayResolution(); *out_width = static_cast(res.x()); *out_height = static_cast(res.y()); return RESULT_SUCCESS; diff --git a/src/core/horizon/services/am/common_state_getter.hpp b/src/core/horizon/services/am/common_state_getter.hpp index 6b9e1ee3..43fd8be8 100644 --- a/src/core/horizon/services/am/common_state_getter.hpp +++ b/src/core/horizon/services/am/common_state_getter.hpp @@ -33,7 +33,8 @@ class ICommonStateGetter : public IService { STUB_REQUEST_COMMAND(DisallowToEnterSleep); result_t GetOperationMode(OperationMode* out_mode); STUB_REQUEST_COMMAND(GetPerformanceMode); - result_t GetDefaultDisplayResolution(i32* out_width, i32* out_height); + result_t GetDefaultDisplayResolution(System* system, i32* out_width, + i32* out_height); result_t GetDefaultDisplayResolutionChangeEvent( kernel::Process* process, OutHandle out_handle); result_t GetCurrentFocusState(kernel::Process* process, diff --git a/src/core/horizon/services/am/library_applet_controller.hpp b/src/core/horizon/services/am/internal/library_applet_controller.hpp similarity index 95% rename from src/core/horizon/services/am/library_applet_controller.hpp rename to src/core/horizon/services/am/internal/library_applet_controller.hpp index 2aa1c6c5..1b2469c5 100644 --- a/src/core/horizon/services/am/library_applet_controller.hpp +++ b/src/core/horizon/services/am/internal/library_applet_controller.hpp @@ -4,7 +4,7 @@ #include "core/horizon/kernel/kernel.hpp" #include "core/horizon/services/am/storage.hpp" -namespace hydra::horizon::services::am { +namespace hydra::horizon::services::am::internal { class StorageQueue { public: @@ -89,4 +89,4 @@ class LibraryAppletController { StorageQueue interactive_out_data; }; -} // namespace hydra::horizon::services::am +} // namespace hydra::horizon::services::am::internal diff --git a/src/core/horizon/services/am/library_applet_accessor.cpp b/src/core/horizon/services/am/library_applet_accessor.cpp index a81bf024..e72a1a3b 100644 --- a/src/core/horizon/services/am/library_applet_accessor.cpp +++ b/src/core/horizon/services/am/library_applet_accessor.cpp @@ -46,8 +46,8 @@ result_t ILibraryAppletAccessor::GetAppletStateChangedEvent( return RESULT_SUCCESS; } -result_t ILibraryAppletAccessor::Start() { - applet->Start(); +result_t ILibraryAppletAccessor::Start(System* system) { + applet->Start(*system); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/am/library_applet_accessor.hpp b/src/core/horizon/services/am/library_applet_accessor.hpp index d7fdee95..b9295e11 100644 --- a/src/core/horizon/services/am/library_applet_accessor.hpp +++ b/src/core/horizon/services/am/library_applet_accessor.hpp @@ -1,7 +1,7 @@ #pragma once #include "core/horizon/const.hpp" -#include "core/horizon/services/am/library_applet_controller.hpp" +#include "core/horizon/services/am/internal/library_applet_controller.hpp" #include "core/horizon/services/const.hpp" namespace hydra::horizon::applets { @@ -22,13 +22,13 @@ class ILibraryAppletAccessor : public IService { u32 id) override; private: - LibraryAppletController controller; + internal::LibraryAppletController controller; applets::AppletBase* applet; // Commands result_t GetAppletStateChangedEvent(kernel::Process* process, OutHandle out_handle); - result_t Start(); + result_t Start(System* system); result_t GetResult(); result_t PushInData(IService* storage_); result_t PopOutData(RequestContext* ctx); diff --git a/src/core/horizon/services/am/library_applet_self_accessor.cpp b/src/core/horizon/services/am/library_applet_self_accessor.cpp index cea5b9c0..730d8cda 100644 --- a/src/core/horizon/services/am/library_applet_self_accessor.cpp +++ b/src/core/horizon/services/am/library_applet_self_accessor.cpp @@ -1,10 +1,10 @@ #include "core/horizon/services/am/library_applet_self_accessor.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" -#include "core/horizon/services/am/library_applet_controller.hpp" +#include "core/horizon/services/am/internal/library_applet_controller.hpp" +#include "core/system.hpp" -#define CONTROLLER OS_INSTANCE.GetLibraryAppletSelfController() +#define CONTROLLER system->GetOS().GetLibraryAppletSelfController() namespace hydra::horizon::services::am { @@ -14,17 +14,14 @@ DEFINE_SERVICE_COMMAND_TABLE(ILibraryAppletSelfAccessor, 0, PopInData, 1, 11, GetLibraryAppletInfo, 14, GetCallerAppletIdentityInfo) -ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor() { - // Verify that we have a library applet self controller available - ASSERT(CONTROLLER, Services, "No library applet self controller"); -} - -result_t ILibraryAppletSelfAccessor::PopInData(RequestContext* ctx) { +result_t ILibraryAppletSelfAccessor::PopInData(RequestContext* ctx, + System* system) { AddService(*ctx, CONTROLLER->PopInData()->Retain()); return RESULT_SUCCESS; } -result_t ILibraryAppletSelfAccessor::PushOutData(IService* storage_) { +result_t ILibraryAppletSelfAccessor::PushOutData(System* system, + IService* storage_) { auto storage = dynamic_cast(storage_); ASSERT_DEBUG(storage, Services, "Storage is not of type IStorage"); @@ -32,13 +29,15 @@ result_t ILibraryAppletSelfAccessor::PushOutData(IService* storage_) { return RESULT_SUCCESS; } -result_t ILibraryAppletSelfAccessor::PopInteractiveInData(RequestContext* ctx) { +result_t ILibraryAppletSelfAccessor::PopInteractiveInData(RequestContext* ctx, + System* system) { AddService(*ctx, CONTROLLER->PopInteractiveInData()->Retain()); return RESULT_SUCCESS; } result_t -ILibraryAppletSelfAccessor::PushInteractiveOutData(IService* storage_) { +ILibraryAppletSelfAccessor::PushInteractiveOutData(System* system, + IService* storage_) { auto storage = dynamic_cast(storage_); ASSERT_DEBUG(storage, Services, "Storage is not of type IStorage"); diff --git a/src/core/horizon/services/am/library_applet_self_accessor.hpp b/src/core/horizon/services/am/library_applet_self_accessor.hpp index 4762e48d..72381e57 100644 --- a/src/core/horizon/services/am/library_applet_self_accessor.hpp +++ b/src/core/horizon/services/am/library_applet_self_accessor.hpp @@ -17,19 +17,16 @@ struct AppletIdentityInfo { }; class ILibraryAppletSelfAccessor : public IService { - public: - ILibraryAppletSelfAccessor(); - protected: result_t RequestImpl([[maybe_unused]] RequestContext& context, u32 id) override; private: // Commands - result_t PopInData(RequestContext* ctx); - result_t PushOutData(IService* storage_); - result_t PopInteractiveInData(RequestContext* ctx); - result_t PushInteractiveOutData(IService* storage_); + result_t PopInData(RequestContext* ctx, System* system); + result_t PushOutData(System* system, IService* storage_); + result_t PopInteractiveInData(RequestContext* ctx, System* system); + result_t PushInteractiveOutData(System* system, IService* storage_); result_t ExitProcessAndReturn(kernel::Process* process); result_t GetLibraryAppletInfo(LibraryAppletInfo* out_info); result_t GetCallerAppletIdentityInfo(AppletIdentityInfo* out_info); diff --git a/src/core/horizon/services/am/self_controller.cpp b/src/core/horizon/services/am/self_controller.cpp index b610cfd1..43ffd5b3 100644 --- a/src/core/horizon/services/am/self_controller.cpp +++ b/src/core/horizon/services/am/self_controller.cpp @@ -1,7 +1,7 @@ #include "core/horizon/services/am/self_controller.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::am { @@ -44,23 +44,24 @@ result_t ISelfController::GetLibraryAppletLaunchableEvent( return RESULT_SUCCESS; } -result_t ISelfController::CreateManagedDisplayLayer(kernel::Process* process, +result_t ISelfController::CreateManagedDisplayLayer(System* system, + kernel::Process* process, u64* out_layer_id) { - u32 binder_id = OS_INSTANCE.GetDisplayDriver().CreateBinder(); + u32 binder_id = system->GetOS().GetDisplayDriver().CreateBinder(); *out_layer_id = - OS_INSTANCE.GetDisplayDriver().CreateLayer(process, binder_id); + system->GetOS().GetDisplayDriver().CreateLayer(process, binder_id); return RESULT_SUCCESS; } result_t ISelfController::CreateManagedDisplaySeparableLayer( - kernel::Process* process, u64* out_display_layer_id, + System* system, kernel::Process* process, u64* out_display_layer_id, u64* out_recording_layer_id) { - u32 binder_id = OS_INSTANCE.GetDisplayDriver().CreateBinder(); + u32 binder_id = system->GetOS().GetDisplayDriver().CreateBinder(); *out_display_layer_id = - OS_INSTANCE.GetDisplayDriver().CreateLayer(process, binder_id); + system->GetOS().GetDisplayDriver().CreateLayer(process, binder_id); // TODO: what is a recording layer? *out_recording_layer_id = - OS_INSTANCE.GetDisplayDriver().CreateLayer(process, binder_id); + system->GetOS().GetDisplayDriver().CreateLayer(process, binder_id); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/am/self_controller.hpp b/src/core/horizon/services/am/self_controller.hpp index 58939843..50076ca4 100644 --- a/src/core/horizon/services/am/self_controller.hpp +++ b/src/core/horizon/services/am/self_controller.hpp @@ -37,9 +37,10 @@ class ISelfController : public IService { STUB_REQUEST_COMMAND(SetRestartMessageEnabled); STUB_REQUEST_COMMAND(SetOutOfFocusSuspendingEnabled); STUB_REQUEST_COMMAND(SetAlbumImageOrientation); - result_t CreateManagedDisplayLayer(kernel::Process* process, + result_t CreateManagedDisplayLayer(System* system, kernel::Process* process, u64* out_layer_id); - result_t CreateManagedDisplaySeparableLayer(kernel::Process* process, + result_t CreateManagedDisplaySeparableLayer(System* system, + kernel::Process* process, u64* out_display_layer_id, u64* out_recording_layer_id); STUB_REQUEST_COMMAND(SetHandlesRequestToDisplay); diff --git a/src/core/horizon/services/audio/audio_out.cpp b/src/core/horizon/services/audio/audio_out.cpp index 6c1b45c6..42a41d9e 100644 --- a/src/core/horizon/services/audio/audio_out.cpp +++ b/src/core/horizon/services/audio/audio_out.cpp @@ -1,8 +1,8 @@ #include "core/horizon/services/audio/audio_out.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::audio { @@ -12,9 +12,10 @@ DEFINE_SERVICE_COMMAND_TABLE(IAudioOut, 0, GetAudioOutState, 1, Start, 2, Stop, AppendAudioOutBufferAuto, 8, GetReleasedAudioOutBuffersAuto) -IAudioOut::IAudioOut(PcmFormat format, u32 sample_rate, u16 channel_count) +IAudioOut::IAudioOut(System& system, PcmFormat format, u32 sample_rate, + u16 channel_count) : buffer_event{new kernel::Event(false, "IAudioOut buffer event")} { - stream = OS_INSTANCE.GetAudioCore().CreateStream( + stream = system.GetAudioCore().CreateStream( format, sample_rate, channel_count, [&](buffer_id_t buffer_id) { { std::unique_lock lock(buffer_mutex); diff --git a/src/core/horizon/services/audio/audio_out.hpp b/src/core/horizon/services/audio/audio_out.hpp index f9a926b2..427daac5 100644 --- a/src/core/horizon/services/audio/audio_out.hpp +++ b/src/core/horizon/services/audio/audio_out.hpp @@ -20,7 +20,8 @@ struct Buffer { class IAudioOut : public IService { public: - IAudioOut(PcmFormat format, u32 sample_rate, u16 channel_count); + IAudioOut(System& system, PcmFormat format, u32 sample_rate, + u16 channel_count); protected: result_t RequestImpl([[maybe_unused]] RequestContext& context, diff --git a/src/core/horizon/services/audio/audio_out_manager.cpp b/src/core/horizon/services/audio/audio_out_manager.cpp index 5482a1ca..c0f74f8d 100644 --- a/src/core/horizon/services/audio/audio_out_manager.cpp +++ b/src/core/horizon/services/audio/audio_out_manager.cpp @@ -86,7 +86,8 @@ result_t IAudioOutManager::OpenAudioOutImpl( std::string device_name_out = "Hydra audio device"; out_device_name_stream->WriteNullTerminatedString(device_name_out); - AddService(*ctx, new IAudioOut(format, sample_rate, channel_count)); + AddService(*ctx, + new IAudioOut(ctx->system, format, sample_rate, channel_count)); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/const.hpp b/src/core/horizon/services/const.hpp index e5af1e66..f0d4c2b6 100644 --- a/src/core/horizon/services/const.hpp +++ b/src/core/horizon/services/const.hpp @@ -24,7 +24,11 @@ return RESULT_SUCCESS; \ } -// TODO: remove +namespace hydra { +class System; +} + +// TODO: remove? namespace hydra::horizon::kernel { class Event; class SharedMemory; @@ -103,6 +107,7 @@ class OutHandle { enum class ArgumentType { Context, + System, Process, InData, OutData, @@ -122,6 +127,11 @@ struct arg_traits { static constexpr ArgumentType type = ArgumentType::Context; }; +template <> +struct arg_traits { + static constexpr ArgumentType type = ArgumentType::System; +}; + template <> struct arg_traits { static constexpr ArgumentType type = ArgumentType::Process; @@ -183,6 +193,13 @@ void read_arg(RequestContext& context, Class& instance, if constexpr (traits::type == ArgumentType::Context) { arg = &context; + // Next + read_arg(context, instance, args); + return; + } else if constexpr (traits::type == ArgumentType::System) { + arg = &context.system; + // Next read_arg(context, instance, args); diff --git a/src/core/horizon/services/fssrv/filesystem.cpp b/src/core/horizon/services/fssrv/filesystem.cpp index 36a4671c..2570d7f1 100644 --- a/src/core/horizon/services/fssrv/filesystem.cpp +++ b/src/core/horizon/services/fssrv/filesystem.cpp @@ -3,9 +3,9 @@ #include "core/horizon/filesystem/directory.hpp" #include "core/horizon/filesystem/file.hpp" #include "core/horizon/filesystem/filesystem.hpp" -#include "core/horizon/kernel/kernel.hpp" #include "core/horizon/services/fssrv/directory.hpp" #include "core/horizon/services/fssrv/file.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::fssrv { @@ -26,7 +26,7 @@ DEFINE_SERVICE_COMMAND_TABLE(IFileSystem, 0, CreateFile, 1, DeleteFile, 2, // TODO: flags result_t -IFileSystem::CreateFile(CreateOption flags, u64 size, +IFileSystem::CreateFile(System* system, CreateOption flags, u64 size, InBuffer in_path_buffer) { (void)flags; @@ -38,7 +38,7 @@ IFileSystem::CreateFile(CreateOption flags, u64 size, size = 16_MiB; } - const auto res = KERNEL_INSTANCE.GetFilesystem().CreateFile( + const auto res = system->GetOS().GetFilesystem().CreateFile( path, size, true); // TODO: should create_intermediate be true? if (res == filesystem::FsResult::AlreadyExists) LOG_WARN(Services, "File \"{}\" already exists", path); @@ -50,10 +50,11 @@ IFileSystem::CreateFile(CreateOption flags, u64 size, } result_t -IFileSystem::DeleteFile(InBuffer in_path_buffer) { +IFileSystem::DeleteFile(System* system, + InBuffer in_path_buffer) { READ_PATH(); - const auto res = KERNEL_INSTANCE.GetFilesystem().DeleteEntry(path); + const auto res = system->GetOS().GetFilesystem().DeleteEntry(path); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Failed to delete file \"{}\": {}", path, res); return MAKE_RESULT(Fs, 1); @@ -63,10 +64,11 @@ IFileSystem::DeleteFile(InBuffer in_path_buffer) { } result_t -IFileSystem::CreateDirectory(InBuffer in_path_buffer) { +IFileSystem::CreateDirectory(System* system, + InBuffer in_path_buffer) { READ_PATH(); - const auto res = KERNEL_INSTANCE.GetFilesystem().CreateDirectory( + const auto res = system->GetOS().GetFilesystem().CreateDirectory( path, true); // TODO: should create_intermediate be true? if (res == filesystem::FsResult::AlreadyExists) LOG_WARN(Services, "Directory \"{}\" already exists", path); @@ -78,10 +80,11 @@ IFileSystem::CreateDirectory(InBuffer in_path_buffer) { } result_t -IFileSystem::DeleteDirectory(InBuffer in_path_buffer) { +IFileSystem::DeleteDirectory(System* system, + InBuffer in_path_buffer) { READ_PATH(); - const auto res = KERNEL_INSTANCE.GetFilesystem().DeleteEntry(path); + const auto res = system->GetOS().GetFilesystem().DeleteEntry(path); ASSERT(res == filesystem::FsResult::Success, Services, "Failed to delete directory \"{}\": {}", path, res); @@ -89,10 +92,10 @@ IFileSystem::DeleteDirectory(InBuffer in_path_buffer) { } result_t IFileSystem::DeleteDirectoryRecursively( - InBuffer in_path_buffer) { + System* system, InBuffer in_path_buffer) { READ_PATH(); - const auto res = KERNEL_INSTANCE.GetFilesystem().DeleteEntry(path, true); + const auto res = system->GetOS().GetFilesystem().DeleteEntry(path, true); ASSERT(res == filesystem::FsResult::Success, Services, "Failed to delete directory recursively \"{}\": {}", path, res); @@ -111,12 +114,13 @@ IFileSystem::RenameFile(InBuffer in_path_buffer, } result_t -IFileSystem::GetEntryType(InBuffer in_path_buffer, +IFileSystem::GetEntryType(System* system, + InBuffer in_path_buffer, EntryType* out_entry_type) { READ_PATH(); filesystem::IEntry* entry; - const auto res = KERNEL_INSTANCE.GetFilesystem().GetEntry(path, entry); + const auto res = system->GetOS().GetFilesystem().GetEntry(path, entry); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Error getting entry \"{}\": {}", path, res); return MAKE_RESULT(Fs, 1); @@ -128,14 +132,15 @@ IFileSystem::GetEntryType(InBuffer in_path_buffer, } result_t -IFileSystem::OpenFile(RequestContext* ctx, filesystem::FileOpenFlags flags, +IFileSystem::OpenFile(RequestContext* ctx, System* system, + filesystem::FileOpenFlags flags, InBuffer in_path_buffer) { READ_PATH(); LOG_DEBUG(Services, "Flags: {}", flags); filesystem::IFile* file; - const auto res = KERNEL_INSTANCE.GetFilesystem().GetFile(path, file); + const auto res = system->GetOS().GetFilesystem().GetFile(path, file); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Error opening file \"{}\": {}", path, res); return MAKE_RESULT(Fs, 1); @@ -146,7 +151,7 @@ IFileSystem::OpenFile(RequestContext* ctx, filesystem::FileOpenFlags flags, } result_t -IFileSystem::OpenDirectory(RequestContext* ctx, +IFileSystem::OpenDirectory(RequestContext* ctx, System* system, DirectoryFilterFlags filter_flags, InBuffer in_path_buffer) { READ_PATH(); @@ -155,7 +160,7 @@ IFileSystem::OpenDirectory(RequestContext* ctx, filesystem::Directory* directory; const auto res = - KERNEL_INSTANCE.GetFilesystem().GetDirectory(path, directory); + system->GetOS().GetFilesystem().GetDirectory(path, directory); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Error opening directory \"{}\": {}", path, res); return MAKE_RESULT(Fs, 1); @@ -190,14 +195,14 @@ IFileSystem::GetTotalSpaceSize(InBuffer in_path_buffer, } result_t IFileSystem::GetFileTimeStampRaw( - InBuffer in_path_buffer, + System* system, InBuffer in_path_buffer, TimeStampRaw* out_timestamp) { LOG_FUNC_STUBBED(Services); READ_PATH(); filesystem::IFile* file; - const auto res = KERNEL_INSTANCE.GetFilesystem().GetFile(path, file); + const auto res = system->GetOS().GetFilesystem().GetFile(path, file); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Error opening file \"{}\": {}", path, res); // TODO: set is_valid to false? diff --git a/src/core/horizon/services/fssrv/filesystem.hpp b/src/core/horizon/services/fssrv/filesystem.hpp index 221f8309..8ab9410a 100644 --- a/src/core/horizon/services/fssrv/filesystem.hpp +++ b/src/core/horizon/services/fssrv/filesystem.hpp @@ -32,20 +32,25 @@ class IFileSystem : public IService { std::string mount; // Commands - result_t CreateFile(CreateOption flags, u64 size, + result_t CreateFile(System* system, CreateOption flags, u64 size, InBuffer in_path_buffer); - result_t DeleteFile(InBuffer in_path_buffer); - result_t CreateDirectory(InBuffer in_path_buffer); - result_t DeleteDirectory(InBuffer in_path_buffer); + result_t DeleteFile(System* system, + InBuffer in_path_buffer); + result_t CreateDirectory(System* system, + InBuffer in_path_buffer); + result_t DeleteDirectory(System* system, + InBuffer in_path_buffer); result_t DeleteDirectoryRecursively( - InBuffer in_path_buffer); + System* system, InBuffer in_path_buffer); result_t RenameFile(InBuffer in_path_buffer, InBuffer in_new_path_buffer); - result_t GetEntryType(InBuffer in_path_buffer, + result_t GetEntryType(System* system, + InBuffer in_path_buffer, EntryType* out_entry_type); - result_t OpenFile(RequestContext* ctx, filesystem::FileOpenFlags flags, + result_t OpenFile(RequestContext* ctx, System* system, + filesystem::FileOpenFlags flags, InBuffer in_path_buffer); - result_t OpenDirectory(RequestContext* ctx, + result_t OpenDirectory(RequestContext* ctx, System* system, DirectoryFilterFlags filter_flags, InBuffer in_path_buffer); STUB_REQUEST_COMMAND(Commit); @@ -54,7 +59,8 @@ class IFileSystem : public IService { result_t GetTotalSpaceSize(InBuffer in_path_buffer, u64* out_size); result_t - GetFileTimeStampRaw(InBuffer in_path_buffer, + GetFileTimeStampRaw(System* system, + InBuffer in_path_buffer, TimeStampRaw* out_timestamp); // 3.0.0+ }; diff --git a/src/core/horizon/services/fssrv/filesystem_proxy.cpp b/src/core/horizon/services/fssrv/filesystem_proxy.cpp index cb7da03b..00a1e074 100644 --- a/src/core/horizon/services/fssrv/filesystem_proxy.cpp +++ b/src/core/horizon/services/fssrv/filesystem_proxy.cpp @@ -2,12 +2,12 @@ #include "core/horizon/filesystem/content_archive.hpp" #include "core/horizon/filesystem/filesystem.hpp" -#include "core/horizon/kernel/kernel.hpp" #include "core/horizon/kernel/process.hpp" #include "core/horizon/services/fssrv/file.hpp" #include "core/horizon/services/fssrv/filesystem.hpp" #include "core/horizon/services/fssrv/save_data_info_reader.hpp" #include "core/horizon/services/fssrv/storage.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::fssrv { @@ -98,14 +98,14 @@ result_t IFileSystemProxy::OpenSdCardFileSystem(RequestContext* ctx) { // TODO: creation and meta info result_t IFileSystemProxy::CreateSaveDataFileSystem( - kernel::Process* process, SaveDataAttribute attr, + System* system, kernel::Process* process, SaveDataAttribute attr, SaveDataCreationInfo creation_info, SaveDataMetaInfo meta_info) { (void)creation_info; (void)meta_info; std::string mount = get_save_data_mount(process, attr); const auto res = - KERNEL_INSTANCE.GetFilesystem().CreateDirectory(mount, true); + system->GetOS().GetFilesystem().CreateDirectory(mount, true); ASSERT(res == filesystem::FsResult::Success || res == filesystem::FsResult::AlreadyExists, Services, "Failed to create save data directory: {}", res); @@ -128,15 +128,17 @@ result_t IFileSystemProxy::ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( } result_t IFileSystemProxy::OpenSaveDataFileSystem( - RequestContext* ctx, kernel::Process* process, + RequestContext* ctx, System* system, kernel::Process* process, aligned space_id, SaveDataAttribute attr) { - return OpenSaveDataFileSystemImpl(ctx, process, space_id, attr, false); + return OpenSaveDataFileSystemImpl(ctx, system, process, space_id, attr, + false); } result_t IFileSystemProxy::OpenReadOnlySaveDataFileSystem( - RequestContext* ctx, kernel::Process* process, + RequestContext* ctx, System* system, kernel::Process* process, aligned space_id, SaveDataAttribute attr) { - return OpenSaveDataFileSystemImpl(ctx, process, space_id, attr, true); + return OpenSaveDataFileSystemImpl(ctx, system, process, space_id, attr, + true); } // TODO: space ID @@ -148,13 +150,13 @@ result_t IFileSystemProxy::OpenSaveDataInfoReaderBySaveDataSpaceId( return RESULT_SUCCESS; } -result_t -IFileSystemProxy::OpenDataStorageByCurrentProcess(RequestContext* ctx, - kernel::Process* process) { - return OpenDataStorageByProgramId(ctx, process->GetTitleID()); +result_t IFileSystemProxy::OpenDataStorageByCurrentProcess( + RequestContext* ctx, System* system, kernel::Process* process) { + return OpenDataStorageByProgramId(ctx, system, process->GetTitleID()); } result_t IFileSystemProxy::OpenDataStorageByProgramId(RequestContext* ctx, + System* system, u64 program_id) { LOG_DEBUG(Services, "Program ID: 0x{:016x}", program_id); @@ -163,7 +165,7 @@ result_t IFileSystemProxy::OpenDataStorageByProgramId(RequestContext* ctx, filesystem::IFile* file = nullptr; const auto res = - KERNEL_INSTANCE.GetFilesystem().GetFile(FS_SD_MOUNT "/rom/romFS", file); + system->GetOS().GetFilesystem().GetFile(FS_SD_MOUNT "/rom/romFS", file); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Data storage does not exist"); return MAKE_RESULT(Fs, res); @@ -174,8 +176,10 @@ result_t IFileSystemProxy::OpenDataStorageByProgramId(RequestContext* ctx, return RESULT_SUCCESS; } -result_t IFileSystemProxy::OpenDataStorageByDataId( - RequestContext* ctx, aligned storage_id, u64 data_id) { +result_t +IFileSystemProxy::OpenDataStorageByDataId(RequestContext* ctx, System* system, + aligned storage_id, + u64 data_id) { LOG_FUNC_NOT_IMPLEMENTED(Services); LOG_DEBUG(Services, "Storage ID: {}, data ID: 0x{:016x}", storage_id, @@ -185,7 +189,7 @@ result_t IFileSystemProxy::OpenDataStorageByDataId( switch (storage_id.Get()) { case ncm::StorageID::BuiltInSystem: { // TODO: correct? - const auto res = KERNEL_INSTANCE.GetFilesystem().GetFile( + const auto res = system->GetOS().GetFilesystem().GetFile( fmt::format(FS_FIRMWARE_PATH "/{:016x}/public data", data_id), file); ASSERT(res == filesystem::FsResult::Success, Services, @@ -212,13 +216,14 @@ result_t IFileSystemProxy::OpenDataStorageByDataId( } result_t -IFileSystemProxy::OpenPatchDataStorageByCurrentProcess(RequestContext* ctx) { +IFileSystemProxy::OpenPatchDataStorageByCurrentProcess(RequestContext* ctx, + System* system) { LOG_NOT_IMPLEMENTED(Services, "OpenPatchDataStorageByCurrentProcess"); // HACK filesystem::IFile* file = nullptr; const auto res = - KERNEL_INSTANCE.GetFilesystem().GetFile(FS_SD_MOUNT "/rom/romFS", file); + system->GetOS().GetFilesystem().GetFile(FS_SD_MOUNT "/rom/romFS", file); if (res != filesystem::FsResult::Success) { LOG_WARN(Services, "Data storage does not exist"); return MAKE_RESULT(Fs, res); @@ -242,11 +247,9 @@ result_t IFileSystemProxy::GetGlobalAccessLogMode(u32* out_log_mode) { return RESULT_SUCCESS; } -result_t IFileSystemProxy::OpenSaveDataFileSystemImpl(RequestContext* ctx, - kernel::Process* process, - SaveDataSpaceId space_id, - SaveDataAttribute attr, - bool read_only) { +result_t IFileSystemProxy::OpenSaveDataFileSystemImpl( + RequestContext* ctx, System* system, kernel::Process* process, + SaveDataSpaceId space_id, SaveDataAttribute attr, bool read_only) { (void)space_id; (void)read_only; @@ -257,7 +260,7 @@ result_t IFileSystemProxy::OpenSaveDataFileSystemImpl(RequestContext* ctx, // TODO: correct? const auto res = - KERNEL_INSTANCE.GetFilesystem().CreateDirectory(mount, true); + system->GetOS().GetFilesystem().CreateDirectory(mount, true); ASSERT_DEBUG(res == filesystem::FsResult::Success || res == filesystem::FsResult::AlreadyExists, Services, "Failed to create save data directory: {}", res); diff --git a/src/core/horizon/services/fssrv/filesystem_proxy.hpp b/src/core/horizon/services/fssrv/filesystem_proxy.hpp index 308d41d3..49f8f1f9 100644 --- a/src/core/horizon/services/fssrv/filesystem_proxy.hpp +++ b/src/core/horizon/services/fssrv/filesystem_proxy.hpp @@ -34,7 +34,7 @@ enum BisPartitionId : u32 { CalibrationFile = 28, SafeMode = 29, User = 30, - System = 31, + System_ = 31, SystemProperEncryption = 32, SystemProperPartition = 33, SignedSystemPartitionOnSafeMode = 34, @@ -117,34 +117,37 @@ class IFileSystemProxy : public IService { OpenBisFileSystem(BisPartitionId partition_id, InBuffer unknown_buffer); result_t OpenSdCardFileSystem(RequestContext* ctx); - result_t CreateSaveDataFileSystem(kernel::Process* process, + result_t CreateSaveDataFileSystem(System* system, kernel::Process* process, SaveDataAttribute attr, SaveDataCreationInfo creation_info, SaveDataMetaInfo meta_info); result_t ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( aligned space_id, u64 save_id, OutBuffer out_buffer); - result_t OpenSaveDataFileSystem(RequestContext* ctx, + result_t OpenSaveDataFileSystem(RequestContext* ctx, System* system, kernel::Process* process, aligned space_id, SaveDataAttribute attr); result_t OpenReadOnlySaveDataFileSystem( - RequestContext* ctx, kernel::Process* process, + RequestContext* ctx, System* system, kernel::Process* process, aligned space_id, SaveDataAttribute attr); result_t OpenSaveDataInfoReaderBySaveDataSpaceId(RequestContext* ctx, SaveDataSpaceId space_id); result_t OpenDataStorageByCurrentProcess(RequestContext* ctx, + System* system, kernel::Process* process); - result_t OpenDataStorageByProgramId(RequestContext* ctx, u64 program_id); - result_t OpenDataStorageByDataId(RequestContext* ctx, + result_t OpenDataStorageByProgramId(RequestContext* ctx, System* system, + u64 program_id); + result_t OpenDataStorageByDataId(RequestContext* ctx, System* system, aligned storage_id, u64 data_id); - result_t OpenPatchDataStorageByCurrentProcess(RequestContext* ctx); + result_t OpenPatchDataStorageByCurrentProcess(RequestContext* ctx, + System* system); result_t DisableAutoSaveDataCreation(); result_t GetGlobalAccessLogMode(u32* out_log_mode); // Impl - result_t OpenSaveDataFileSystemImpl(RequestContext* ctx, + result_t OpenSaveDataFileSystemImpl(RequestContext* ctx, System* system, kernel::Process* process, SaveDataSpaceId space_id, SaveDataAttribute attr, bool read_only); @@ -169,7 +172,7 @@ ENABLE_ENUM_FORMATTING( "boot config and package 2 part 5", BootConfigAndPackage2Part6, "boot config and package 2 part 6", CalibrationBinary, "calibration binary", CalibrationFile, "calibration file", SafeMode, "safe mode", User, "user", - System, "system", SystemProperEncryption, "system proper encryption", + System_, "system", SystemProperEncryption, "system proper encryption", SystemProperPartition, "system proper partition", SignedSystemPartitionOnSafeMode, "signed system partition on safe mode", DeviceTreeBlob, "device tree blob", System0, "system 0") diff --git a/src/core/horizon/services/hid/applet_resource.cpp b/src/core/horizon/services/hid/applet_resource.cpp index f9c9d235..ea959411 100644 --- a/src/core/horizon/services/hid/applet_resource.cpp +++ b/src/core/horizon/services/hid/applet_resource.cpp @@ -1,19 +1,19 @@ #include "core/horizon/services/hid/applet_resource.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::hid { DEFINE_SERVICE_COMMAND_TABLE(IAppletResource, 0, GetSharedMemoryHandle) -IAppletResource::IAppletResource(kernel::AppletResourceUserId aruid_) - : aruid{aruid_}, resource{ - OS_INSTANCE.GetHidResourceManager().CreateResource( - aruid)} {} +IAppletResource::IAppletResource(System& system_, + kernel::AppletResourceUserId aruid_) + : system{system_}, aruid{aruid_}, + resource{system.GetOS().GetHidResourceManager().CreateResource(aruid)} {} IAppletResource::~IAppletResource() { - OS_INSTANCE.GetHidResourceManager().DestroyResource(aruid); + system.GetOS().GetHidResourceManager().DestroyResource(aruid); } result_t diff --git a/src/core/horizon/services/hid/applet_resource.hpp b/src/core/horizon/services/hid/applet_resource.hpp index 14aab795..db63cfa2 100644 --- a/src/core/horizon/services/hid/applet_resource.hpp +++ b/src/core/horizon/services/hid/applet_resource.hpp @@ -11,7 +11,7 @@ class AppletResource; class IAppletResource : public IService { public: - IAppletResource(kernel::AppletResourceUserId aruid_); + IAppletResource(System& system_, kernel::AppletResourceUserId aruid_); ~IAppletResource(); protected: @@ -19,6 +19,7 @@ class IAppletResource : public IService { u32 id) override; private: + System& system; kernel::AppletResourceUserId aruid; internal::AppletResource& resource; diff --git a/src/core/horizon/services/hid/hid_server.cpp b/src/core/horizon/services/hid/hid_server.cpp index 92f98dcc..3f8d7a94 100644 --- a/src/core/horizon/services/hid/hid_server.cpp +++ b/src/core/horizon/services/hid/hid_server.cpp @@ -1,12 +1,12 @@ #include "core/horizon/services/hid/hid_server.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/services/hid/active_vibration_device_list.hpp" #include "core/horizon/services/hid/applet_resource.hpp" +#include "core/system.hpp" #define APPLET_RESOURCE(aruid) \ - OS_INSTANCE.GetHidResourceManager().GetResource(aruid) + system->GetOS().GetHidResourceManager().GetResource(aruid) namespace hydra::horizon::services::hid { @@ -28,26 +28,28 @@ DEFINE_SERVICE_COMMAND_TABLE( result_t IHidServer::CreateAppletResource(RequestContext* ctx, kernel::AppletResourceUserId aruid) { - AddService(*ctx, new IAppletResource(aruid)); + AddService(*ctx, new IAppletResource(ctx->system, aruid)); return RESULT_SUCCESS; } result_t -IHidServer::SetSupportedNpadStyleSet(aligned style_set, +IHidServer::SetSupportedNpadStyleSet(System* system, + aligned style_set, kernel::AppletResourceUserId aruid) { APPLET_RESOURCE(aruid).SetSupportedStyleSet(style_set); return RESULT_SUCCESS; } result_t -IHidServer::GetSupportedNpadStyleSet(kernel::AppletResourceUserId aruid, +IHidServer::GetSupportedNpadStyleSet(System* system, + kernel::AppletResourceUserId aruid, NpadStyleSet* out_style_set) { *out_style_set = APPLET_RESOURCE(aruid).GetSupportedStyleSet(); return RESULT_SUCCESS; } result_t IHidServer::SetSupportedNpadIdType( - kernel::AppletResourceUserId aruid, + System* system, kernel::AppletResourceUserId aruid, InBuffer in_types_buffer) { while (in_types_buffer.stream->GetSeek() < in_types_buffer.stream->GetSize()) { @@ -58,13 +60,14 @@ result_t IHidServer::SetSupportedNpadIdType( return RESULT_SUCCESS; } -result_t IHidServer::ActivateNpad(kernel::AppletResourceUserId aruid) { +result_t IHidServer::ActivateNpad(System* system, + kernel::AppletResourceUserId aruid) { APPLET_RESOURCE(aruid).ActivateNpads(NpadRevision::Revision0); return RESULT_SUCCESS; } result_t IHidServer::AcquireNpadStyleSetUpdateEventHandle( - kernel::Process* process, aligned type, + System* system, kernel::Process* process, aligned type, kernel::AppletResourceUserId aruid, u64 event_ptr, OutHandle out_handle) { (void)event_ptr; @@ -82,7 +85,7 @@ result_t IHidServer::AcquireNpadStyleSetUpdateEventHandle( return RESULT_SUCCESS; } -result_t IHidServer::DisconnectNpad(aligned type, +result_t IHidServer::DisconnectNpad(System* system, aligned type, kernel::AppletResourceUserId aruid) { APPLET_RESOURCE(aruid).DisconnectNpad(internal::ToNpadIndex(type)); return RESULT_SUCCESS; @@ -131,20 +134,23 @@ result_t IHidServer::GetPlayerLedPattern(NpadIdType npad_id_type, } result_t -IHidServer::ActivateNpadWithRevision(aligned revision, +IHidServer::ActivateNpadWithRevision(System* system, + aligned revision, kernel::AppletResourceUserId aruid) { LOG_DEBUG(Services, "Revision: {}", revision); APPLET_RESOURCE(aruid).ActivateNpads(revision); return RESULT_SUCCESS; } -result_t IHidServer::SetNpadJoyHoldType(kernel::AppletResourceUserId aruid, +result_t IHidServer::SetNpadJoyHoldType(System* system, + kernel::AppletResourceUserId aruid, NpadJoyHoldType type) { APPLET_RESOURCE(aruid).SetJoyHoldType(type); return RESULT_SUCCESS; } -result_t IHidServer::GetNpadJoyHoldType(kernel::AppletResourceUserId aruid, +result_t IHidServer::GetNpadJoyHoldType(System* system, + kernel::AppletResourceUserId aruid, aligned* out_type) { out_type->ZeroOutPadding(); *out_type = APPLET_RESOURCE(aruid).GetJoyHoldType(); diff --git a/src/core/horizon/services/hid/hid_server.hpp b/src/core/horizon/services/hid/hid_server.hpp index 16e3b85b..33bf766e 100644 --- a/src/core/horizon/services/hid/hid_server.hpp +++ b/src/core/horizon/services/hid/hid_server.hpp @@ -37,28 +37,33 @@ class IHidServer : public IService { STUB_REQUEST_COMMAND(EnableSixAxisSensorFusion); STUB_REQUEST_COMMAND(SetGyroscopeZeroDriftMode); STUB_REQUEST_COMMAND(ActivateGesture); - result_t SetSupportedNpadStyleSet(aligned style_set, + result_t SetSupportedNpadStyleSet(System* system, + aligned style_set, kernel::AppletResourceUserId aruid); - result_t GetSupportedNpadStyleSet(kernel::AppletResourceUserId aruid, + result_t GetSupportedNpadStyleSet(System* system, + kernel::AppletResourceUserId aruid, NpadStyleSet* out_style_set); result_t - SetSupportedNpadIdType(kernel::AppletResourceUserId aruid, + SetSupportedNpadIdType(System* system, kernel::AppletResourceUserId aruid, InBuffer in_types_buffer); - result_t ActivateNpad(kernel::AppletResourceUserId aruid); + result_t ActivateNpad(System* system, kernel::AppletResourceUserId aruid); result_t AcquireNpadStyleSetUpdateEventHandle( - kernel::Process* process, aligned type, + System* system, kernel::Process* process, aligned type, kernel::AppletResourceUserId aruid, u64 event_ptr, OutHandle out_handle); - result_t DisconnectNpad(aligned type, + result_t DisconnectNpad(System* system, aligned type, kernel::AppletResourceUserId aruid); result_t GetPlayerLedPattern(NpadIdType npad_id_type, u64* out_pattern); - result_t ActivateNpadWithRevision(aligned revision, + result_t ActivateNpadWithRevision(System* system, + aligned revision, kernel::AppletResourceUserId aruid); // TODO: PID descriptor - result_t SetNpadJoyHoldType(kernel::AppletResourceUserId aruid, + result_t SetNpadJoyHoldType(System* system, + kernel::AppletResourceUserId aruid, NpadJoyHoldType type); // TODO: PID descriptor - result_t GetNpadJoyHoldType(kernel::AppletResourceUserId aruid, + result_t GetNpadJoyHoldType(System* system, + kernel::AppletResourceUserId aruid, aligned* out_type); STUB_REQUEST_COMMAND(SetNpadJoyAssignmentModeSingleByDefault); STUB_REQUEST_COMMAND(SetNpadJoyAssignmentModeDual); diff --git a/src/core/horizon/services/hid/internal/applet_resource.cpp b/src/core/horizon/services/hid/internal/applet_resource.cpp index d82816c2..007f4783 100644 --- a/src/core/horizon/services/hid/internal/applet_resource.cpp +++ b/src/core/horizon/services/hid/internal/applet_resource.cpp @@ -1,6 +1,7 @@ #include "core/horizon/services/hid/internal/applet_resource.hpp" #include "core/horizon/kernel/shared_memory.hpp" +#include "core/system.hpp" #define SHARED_MEMORY (*reinterpret_cast(shared_mem->GetPtr())) @@ -8,8 +9,8 @@ namespace hydra::horizon::services::hid::internal { #define NPAD_INTERNAL_STATE(i) SHARED_MEMORY.npad.entries[i].internal_state -AppletResource::AppletResource() - : shared_mem{new kernel::SharedMemory(sizeof(SharedMemory), +AppletResource::AppletResource(System& system) + : shared_mem{new kernel::SharedMemory(system.GetCpu(), sizeof(SharedMemory), "HID shared memory")}, npads{{NPAD_INTERNAL_STATE(0), NPAD_INTERNAL_STATE(1), NPAD_INTERNAL_STATE(2), NPAD_INTERNAL_STATE(3), diff --git a/src/core/horizon/services/hid/internal/applet_resource.hpp b/src/core/horizon/services/hid/internal/applet_resource.hpp index 765e4803..5ab9ef03 100644 --- a/src/core/horizon/services/hid/internal/applet_resource.hpp +++ b/src/core/horizon/services/hid/internal/applet_resource.hpp @@ -4,6 +4,10 @@ #include "core/horizon/services/hid/internal/npad.hpp" #include "core/horizon/services/hid/internal/npad_index.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { class SharedMemory; } @@ -12,7 +16,7 @@ namespace hydra::horizon::services::hid::internal { class AppletResource { public: - AppletResource(); + AppletResource(System& system); ~AppletResource(); // Npad setup diff --git a/src/core/horizon/services/hid/internal/resource_manager.cpp b/src/core/horizon/services/hid/internal/resource_manager.cpp index d78d28b8..7487cd51 100644 --- a/src/core/horizon/services/hid/internal/resource_manager.cpp +++ b/src/core/horizon/services/hid/internal/resource_manager.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/hid/internal/resource_manager.hpp" -#include "core/input/device_manager.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::hid::internal { @@ -19,7 +19,7 @@ void ResourceManager::Update() { const auto index = static_cast(i); // Poll - const auto state = INPUT_DEVICE_MANAGER_INSTANCE.PollNpad(index); + const auto state = system.GetInputDeviceManager().PollNpad(index); // Update for (auto& resource : resource_pool) { @@ -31,7 +31,7 @@ void ResourceManager::Update() { } // Touch - const auto touch_state = INPUT_DEVICE_MANAGER_INSTANCE.PollTouch(); + const auto touch_state = system.GetInputDeviceManager().PollTouch(); for (auto& resource : resource_pool) { if (!resource.has_value()) continue; diff --git a/src/core/horizon/services/hid/internal/resource_manager.hpp b/src/core/horizon/services/hid/internal/resource_manager.hpp index bebfa50c..3288ec86 100644 --- a/src/core/horizon/services/hid/internal/resource_manager.hpp +++ b/src/core/horizon/services/hid/internal/resource_manager.hpp @@ -11,6 +11,8 @@ class ResourceManager { AruidAlreadyTaken, }; + ResourceManager(System& system_) : system{system_}, resource_pool(system) {} + void SetupNpads(); void Update(); @@ -27,6 +29,8 @@ class ResourceManager { } private: + System& system; + kernel::AppletResourcePool resource_pool; }; diff --git a/src/core/horizon/services/hosbinder/hos_binder_driver.cpp b/src/core/horizon/services/hosbinder/hos_binder_driver.cpp index 43921f1b..7ef1315d 100644 --- a/src/core/horizon/services/hosbinder/hos_binder_driver.cpp +++ b/src/core/horizon/services/hosbinder/hos_binder_driver.cpp @@ -1,9 +1,9 @@ #include "core/horizon/services/hosbinder/hos_binder_driver.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/services/hosbinder/parcel.hpp" #include "core/hw/tegra_x1/gpu/const.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::hosbinder { @@ -73,19 +73,19 @@ DEFINE_SERVICE_COMMAND_TABLE(IHOSBinderDriver, 0, TransactParcel, 1, TransactParcelAuto) result_t IHOSBinderDriver::TransactParcel( - i32 binder_id, TransactCode code, u32 flags, + System* system, i32 binder_id, TransactCode code, u32 flags, InBuffer in_parcel_buffer, OutBuffer out_parcel_buffer) { LOG_DEBUG(Services, "Code: {}", code); - TransactParcelImpl(binder_id, code, flags, in_parcel_buffer.stream, + TransactParcelImpl(*system, binder_id, code, flags, in_parcel_buffer.stream, out_parcel_buffer.stream); return RESULT_SUCCESS; } -result_t IHOSBinderDriver::AdjustRefcount(i32 binder_id, i32 add_value, - BinderType type) { - auto& binder = OS::GetInstance().GetDisplayDriver().GetBinder( +result_t IHOSBinderDriver::AdjustRefcount(System* system, i32 binder_id, + i32 add_value, BinderType type) { + auto& binder = system->GetOS().GetDisplayDriver().GetBinder( static_cast(binder_id)); switch (type) { case BinderType::Weak: @@ -103,12 +103,12 @@ result_t IHOSBinderDriver::AdjustRefcount(i32 binder_id, i32 add_value, // TODO: code result_t -IHOSBinderDriver::GetNativeHandle(kernel::Process* process, i32 binder_id, - u32 code, +IHOSBinderDriver::GetNativeHandle(System* system, kernel::Process* process, + i32 binder_id, u32 code, OutHandle out_handle) { (void)code; - out_handle = process->AddHandle(OS::GetInstance() + out_handle = process->AddHandle(system->GetOS() .GetDisplayDriver() .GetBinder(static_cast(binder_id)) .GetEvent()); @@ -116,19 +116,19 @@ IHOSBinderDriver::GetNativeHandle(kernel::Process* process, i32 binder_id, } result_t IHOSBinderDriver::TransactParcelAuto( - i32 binder_id, TransactCode code, u32 flags, + System* system, i32 binder_id, TransactCode code, u32 flags, InBuffer in_parcel_buffer, OutBuffer out_parcel_buffer) { LOG_DEBUG(Services, "Code: {}", code); - TransactParcelImpl(binder_id, code, flags, in_parcel_buffer.stream, + TransactParcelImpl(*system, binder_id, code, flags, in_parcel_buffer.stream, out_parcel_buffer.stream); return RESULT_SUCCESS; } // TODO: flags -void IHOSBinderDriver::TransactParcelImpl(i32 binder_id, TransactCode code, - u32 flags, +void IHOSBinderDriver::TransactParcelImpl(System& system, i32 binder_id, + TransactCode code, u32 flags, io::MemoryStream* in_stream, io::MemoryStream* out_stream) { (void)flags; @@ -137,7 +137,7 @@ void IHOSBinderDriver::TransactParcelImpl(i32 binder_id, TransactCode code, ParcelWriter parcel_writer(out_stream); // Binder - auto& binder = OS::GetInstance().GetDisplayDriver().GetBinder( + auto& binder = system.GetOS().GetDisplayDriver().GetBinder( static_cast(binder_id)); // Interface token @@ -181,10 +181,10 @@ void IHOSBinderDriver::TransactParcelImpl(i32 binder_id, TransactCode code, const auto& input = *parcel_reader.ReadFlattenedObject(); - binder.QueueBuffer(slot, input); + binder.QueueBuffer(system, slot, input); // Buffer output - const auto res = OS_INSTANCE.GetDisplayResolution(); + const auto res = system.GetOS().GetDisplayResolution(); parcel_writer.Write({ .width = res.x(), .height = res.y(), @@ -201,10 +201,10 @@ void IHOSBinderDriver::TransactParcelImpl(i32 binder_id, TransactCode code, u32 value = 0; switch (what) { case NativeWindowAttribute::Width: - value = OS_INSTANCE.GetDisplayResolution().x(); + value = system.GetOS().GetDisplayResolution().x(); break; case NativeWindowAttribute::Height: - value = OS_INSTANCE.GetDisplayResolution().y(); + value = system.GetOS().GetDisplayResolution().y(); break; case NativeWindowAttribute::Format: value = static_cast(PixelFormat::RGBA8888); // RGBA8888 @@ -219,7 +219,7 @@ void IHOSBinderDriver::TransactParcelImpl(i32 binder_id, TransactCode code, break; } case TransactCode::Connect: { - const auto res = OS_INSTANCE.GetDisplayResolution(); + const auto res = system.GetOS().GetDisplayResolution(); parcel_writer.Write({ .width = res.x(), .height = res.y(), diff --git a/src/core/horizon/services/hosbinder/hos_binder_driver.hpp b/src/core/horizon/services/hosbinder/hos_binder_driver.hpp index a12b0ee1..c575a7fc 100644 --- a/src/core/horizon/services/hosbinder/hos_binder_driver.hpp +++ b/src/core/horizon/services/hosbinder/hos_binder_driver.hpp @@ -36,21 +36,25 @@ class IHOSBinderDriver : public IService { private: // Commands - result_t TransactParcel(i32 binder_id, TransactCode code, u32 flags, + result_t TransactParcel(System* system, i32 binder_id, TransactCode code, + u32 flags, InBuffer in_parcel_buffer, OutBuffer out_parcel_buffer); - result_t AdjustRefcount(i32 binder_id, i32 add_value, BinderType type); + result_t AdjustRefcount(System* system, i32 binder_id, i32 add_value, + BinderType type); result_t - GetNativeHandle(kernel::Process* process, i32 binder_id, u32 code, + GetNativeHandle(System* system, kernel::Process* process, i32 binder_id, + u32 code, OutHandle out_handle); // TODO: should code be TransactCode? result_t - TransactParcelAuto(i32 binder_id, TransactCode code, u32 flags, + TransactParcelAuto(System* system, i32 binder_id, TransactCode code, + u32 flags, InBuffer in_parcel_buffer, OutBuffer out_parcel_buffer); - void TransactParcelImpl(i32 binder_id, TransactCode code, u32 flags, - io::MemoryStream* in_stream, + void TransactParcelImpl(System& system, i32 binder_id, TransactCode code, + u32 flags, io::MemoryStream* in_stream, io::MemoryStream* out_stream); }; diff --git a/src/core/horizon/services/irsensor/internal/ir_sensor_manager.cpp b/src/core/horizon/services/irsensor/internal/ir_sensor_manager.cpp new file mode 100644 index 00000000..76de2067 --- /dev/null +++ b/src/core/horizon/services/irsensor/internal/ir_sensor_manager.cpp @@ -0,0 +1,11 @@ +#include "core/horizon/services/irsensor/internal/ir_sensor_manager.hpp" + +#include "core/horizon/kernel/shared_memory.hpp" +#include "core/system.hpp" + +namespace hydra::horizon::services::irsensor::internal { + +IrSensorManager::IrSensorManager(System& system) + : shared_mem{new kernel::SharedMemory(system.GetCpu(), 0x8000)} {} + +} // namespace hydra::horizon::services::irsensor::internal diff --git a/src/core/horizon/services/irsensor/internal/ir_sensor_manager.hpp b/src/core/horizon/services/irsensor/internal/ir_sensor_manager.hpp new file mode 100644 index 00000000..69ca2517 --- /dev/null +++ b/src/core/horizon/services/irsensor/internal/ir_sensor_manager.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "core/horizon/services/const.hpp" + +namespace hydra::horizon::services::irsensor::internal { + +class IrSensorManager { + public: + IrSensorManager(System& system); + + private: + kernel::SharedMemory* shared_mem; + + public: + GETTER(shared_mem, GetSharedMemory); +}; + +} // namespace hydra::horizon::services::irsensor::internal diff --git a/src/core/horizon/services/irsensor/ir_sensor_server.cpp b/src/core/horizon/services/irsensor/ir_sensor_server.cpp index e4844650..51148228 100644 --- a/src/core/horizon/services/irsensor/ir_sensor_server.cpp +++ b/src/core/horizon/services/irsensor/ir_sensor_server.cpp @@ -2,6 +2,7 @@ #include "core/horizon/kernel/process.hpp" #include "core/horizon/kernel/shared_memory.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::irsensor { @@ -10,14 +11,12 @@ DEFINE_SERVICE_COMMAND_TABLE(IIrSensorServer, 303, DeactivateIrsensor, 304, GetNpadIrCameraHandle, 319, ActivateIrsensorWithFunctionLevel) -IIrSensorServer::IIrSensorServer() - : shared_mem{new kernel::SharedMemory(0x8000)} {} - result_t IIrSensorServer::GetIrsensorSharedMemoryHandle( - kernel::Process* process, u64 aruid, + System* system, kernel::Process* process, u64 aruid, OutHandle out_handle) { (void)aruid; - out_handle = process->AddHandle(shared_mem); + out_handle = process->AddHandle( + system->GetOS().GetIrSensorManager().GetSharedMemory()); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/irsensor/ir_sensor_server.hpp b/src/core/horizon/services/irsensor/ir_sensor_server.hpp index a75e7b66..97ab5144 100644 --- a/src/core/horizon/services/irsensor/ir_sensor_server.hpp +++ b/src/core/horizon/services/irsensor/ir_sensor_server.hpp @@ -25,21 +25,17 @@ struct PackedFunctionLevel { }; class IIrSensorServer : public IService { - public: - IIrSensorServer(); - protected: result_t RequestImpl([[maybe_unused]] RequestContext& context, u32 id) override; private: - kernel::SharedMemory* shared_mem; // TODO: make this global - // Commands STUB_REQUEST_COMMAND(DeactivateIrsensor); // TODO: PID descriptor result_t - GetIrsensorSharedMemoryHandle(kernel::Process* process, u64 aruid, + GetIrsensorSharedMemoryHandle(System* system, kernel::Process* process, + u64 aruid, OutHandle out_handle); result_t GetNpadIrCameraHandle(hid::NpadIdType npad_id, IrCameraHandle* out_handle); diff --git a/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp b/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp index 5d9763f2..314090e3 100644 --- a/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/channel_base.hpp @@ -17,7 +17,8 @@ struct UnmapCmdBufferHandle { class ChannelBase : public FdBase { public: - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; protected: u64 user_data; @@ -39,7 +40,8 @@ class ChannelBase : public FdBase { NvResult SetNvMapFd(u32 fd_id); NvResult SetTimeout(u32 timeout); virtual NvResult - SubmitGpfifo([[maybe_unused]] kernel::Process* process, u64 gpfifo, + SubmitGpfifo([[maybe_unused]] System* system, + [[maybe_unused]] kernel::Process* process, u64 gpfifo, u32 num_entries, InOut inout_flags_and_detailed_error, diff --git a/src/core/horizon/services/nvdrv/ioctl/const.hpp b/src/core/horizon/services/nvdrv/ioctl/const.hpp index 18cb21a0..71e7560b 100644 --- a/src/core/horizon/services/nvdrv/ioctl/const.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/const.hpp @@ -26,8 +26,8 @@ DEFINE_IOCTL_TABLE_ENTRY_IMPL(fd, 3, type, __VA_ARGS__) #define DEFINE_IOCTL_TABLE_IMPL(fd, ioctl_suffix, ...) \ - NvResult fd::Ioctl##ioctl_suffix([[maybe_unused]] IoctlContext& context, u32 type, \ - u32 nr) { \ + NvResult fd::Ioctl##ioctl_suffix([[maybe_unused]] IoctlContext& context, \ + u32 type, u32 nr) { \ switch (type) { \ __VA_ARGS__ \ default: \ @@ -41,6 +41,10 @@ #define DEFINE_IOCTL2_TABLE(fd, ...) DEFINE_IOCTL_TABLE_IMPL(fd, 2, __VA_ARGS__) #define DEFINE_IOCTL3_TABLE(fd, ...) DEFINE_IOCTL_TABLE_IMPL(fd, 3, __VA_ARGS__) +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { class Process; } @@ -48,6 +52,7 @@ class Process; namespace hydra::horizon::services::nvdrv::ioctl { struct IoctlContext { + System& system; kernel::Process* process; io::MemoryStream* in_stream; io::MemoryStream* in_buffer_stream; @@ -79,6 +84,7 @@ struct InOutSingle { enum class ArgumentType { Context, + System, Process, In, Out, @@ -95,6 +101,11 @@ struct arg_traits { static constexpr ArgumentType type = ArgumentType::Context; }; +template <> +struct arg_traits { + static constexpr ArgumentType type = ArgumentType::System; +}; + template <> struct arg_traits { static constexpr ArgumentType type = ArgumentType::Process; @@ -143,6 +154,12 @@ void read_arg(IoctlContext& context, CommandArguments& args) { if constexpr (traits::type == ArgumentType::Context) { arg = &context; + // Next + read_arg(context, args); + return; + } else if constexpr (traits::type == ArgumentType::System) { + arg = &context.system; + // Next read_arg(context, args); return; diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp index fa6036e4..a527bb5c 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.cpp @@ -2,7 +2,7 @@ #include "core/horizon/kernel/process.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" -#include "core/hw/tegra_x1/gpu/gpu.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::nvdrv::ioctl { @@ -47,7 +47,7 @@ NvResult NvHostAsGpu::UnmapBuffer(gpu_vaddr_t addr) { } // TODO: kind -NvResult NvHostAsGpu::MapBufferEX(kernel::Process* process, +NvResult NvHostAsGpu::MapBufferEX(System* system, kernel::Process* process, MapBufferFlags flags, hw::tegra_x1::gpu::NvKind kind, handle_id_t nvmap_handle_id, @@ -63,7 +63,7 @@ NvResult NvHostAsGpu::MapBufferEX(kernel::Process* process, return NvResult::Success; } - const auto& map = GPU_INSTANCE.GetMap(nvmap_handle_id); + const auto& map = system->GetGpu().GetMap(nvmap_handle_id); usize size = mapping_size; if (size == 0x0) diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp index 33115420..59f87058 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_as_gpu.hpp @@ -40,8 +40,10 @@ struct RemapOp { class NvHostAsGpu : public FdBase { public: - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; - NvResult Ioctl3([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; + NvResult Ioctl3([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; private: // Ioctls @@ -51,8 +53,8 @@ class NvHostAsGpu : public FdBase { InOut align_and_offset); NvResult FreeSpace(vaddr_t offset, u32 pages, u32 page_size); NvResult UnmapBuffer(gpu_vaddr_t addr); - NvResult MapBufferEX(kernel::Process* process, MapBufferFlags flags, - hw::tegra_x1::gpu::NvKind kind, + NvResult MapBufferEX(System* system, kernel::Process* process, + MapBufferFlags flags, hw::tegra_x1::gpu::NvKind kind, handle_id_t nvmap_handle_id, [[maybe_unused]] u32 reserved, u64 buffer_offset, u64 mapping_size, InOutSingle inout_addr); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.cpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.cpp index 611ad31f..1f6507c8 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.hpp" -#include "core/hw/wall_clock.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::nvdrv::ioctl { @@ -159,9 +159,9 @@ NvResult NvHostCtrlGpu::PmuGetGpuLoad(u32* out_load) { return NvResult::Success; } -NvResult NvHostCtrlGpu::GetGpuTime(u64* out_timestamp, +NvResult NvHostCtrlGpu::GetGpuTime(System* system, u64* out_timestamp, [[maybe_unused]] u64* _out_reserved) { - *out_timestamp = hw::WallClock::GetInstance().GetGpuTick(); + *out_timestamp = system->GetWallClock().GetGpuTick(); return NvResult::Success; } diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.hpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.hpp index 7b684741..193e3ba3 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_ctrl_gpu.hpp @@ -64,8 +64,10 @@ class NvHostCtrlGpu : public FdBase { unknown_event{ new kernel::Event(false, "NvHostCtrlGpu unknown event")} {} - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; - NvResult Ioctl3([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; + NvResult Ioctl3([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; NvResult QueryEvent(u32 event_id_u32, kernel::Event*& out_event) override; private: @@ -87,7 +89,7 @@ class NvHostCtrlGpu : public FdBase { u64* out_mask_buffer); NvResult ZbcGetActiveSlotMask(u32* out_slot, u32* out_mask); NvResult PmuGetGpuLoad(u32* out_load); - NvResult GetGpuTime(u64* out_timestamp, + NvResult GetGpuTime(System* system, u64* out_timestamp, [[maybe_unused]] u64* _out_reserved); NvResult GetCharacteristics3(IoctlContext* ctx, diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp index 84e04d73..d8d34f59 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp @@ -2,7 +2,7 @@ #include "core/horizon/kernel/process.hpp" #include "core/hw/tegra_x1/gpu/const.hpp" -#include "core/hw/tegra_x1/gpu/gpu.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::nvdrv::ioctl { @@ -40,13 +40,13 @@ NvResult NvHostGpu::QueryEvent(u32 event_id_u32, kernel::Event*& out_event) { // TODO: gpfifo NvResult NvHostGpu::SubmitGpfifo( - kernel::Process* process, u64 gpfifo, u32 num_entries, + System* system, kernel::Process* process, u64 gpfifo, u32 num_entries, InOut inout_flags_and_detailed_error, InOutSingle inout_fence, const hw::tegra_x1::gpu::GpfifoEntry* entries) { (void)gpfifo; - GPU_INSTANCE.GetPfifo().SubmitEntries( + system->GetGpu().GetPfifo().SubmitEntries( *process->GetGMmu(), std::span(entries, num_entries), inout_flags_and_detailed_error); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.hpp b/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.hpp index f9e35a56..525ff7ba 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.hpp @@ -15,7 +15,8 @@ class NvHostGpu : public ChannelBase { error_notifier_event{ new kernel::Event(false, "NvHostGpu error notifier event")} {} - NvResult Ioctl2([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl2([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; NvResult QueryEvent(u32 event_id_u32, kernel::Event*& out_event) override; private: @@ -25,29 +26,33 @@ class NvHostGpu : public ChannelBase { // Ioctls NvResult - SubmitGpfifo(kernel::Process* process, u64 gpfifo, u32 num_entries, + SubmitGpfifo(System* system, kernel::Process* process, u64 gpfifo, + u32 num_entries, InOut inout_flags_and_detailed_error, InOutSingle inout_fence, const hw::tegra_x1::gpu::GpfifoEntry* entries) override; NvResult AllocObjCtx(u32 class_num, u32 flags, u64* out_obj_id) override; - NvResult ZCullBind(gpu_vaddr_t addr, u32 mode, [[maybe_unused]] u32 reserved) override; + NvResult ZCullBind(gpu_vaddr_t addr, u32 mode, + [[maybe_unused]] u32 reserved) override; NvResult SetErrorNotifier(u64 offset, u64 size, u32 mem, [[maybe_unused]] u32 reserved) override; NvResult GetErrorNotification(u64* out_timestamp, u32* out_info32, u16* out_info16, u64* out_status) override; - NvResult AllocGpfifoEX(u32 num_entries, u32 num_jobs, u32 flags, - hw::tegra_x1::gpu::Fence* out_fence, - [[maybe_unused]] std::array reserved) override; + NvResult + AllocGpfifoEX(u32 num_entries, u32 num_jobs, u32 flags, + hw::tegra_x1::gpu::Fence* out_fence, + [[maybe_unused]] std::array reserved) override; - NvResult SubmitGpfifo2(IoctlContext* ctx, kernel::Process* process, - u64 gpfifo, u32 num_entries, + NvResult SubmitGpfifo2(IoctlContext* ctx, System* system, + kernel::Process* process, u64 gpfifo, + u32 num_entries, InOut inout_flags_and_detailed_error, InOutSingle inout_fence) { return SubmitGpfifo( - process, gpfifo, num_entries, inout_flags_and_detailed_error, - inout_fence, + system, process, gpfifo, num_entries, + inout_flags_and_detailed_error, inout_fence, ctx->in_buffer_stream->ReadPtr()); } }; diff --git a/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp b/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp index 71e7832d..ecf8e058 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvmap.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/nvdrv/ioctl/nvmap.hpp" -#include "core/hw/tegra_x1/gpu/gpu.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::nvdrv::ioctl { @@ -9,8 +9,8 @@ DEFINE_IOCTL_TABLE(NvMap, FromId, 0x04, Alloc, 0x05, Free, 0x09, Param, 0x0e, GetId)) -NvResult NvMap::Create(u32 size, handle_id_t* out_handle_id) { - *out_handle_id = GPU_INSTANCE.CreateMap(size); +NvResult NvMap::Create(System* system, u32 size, handle_id_t* out_handle_id) { + *out_handle_id = system->GetGpu().CreateMap(size); return NvResult::Success; } @@ -21,22 +21,22 @@ NvResult NvMap::FromId(u32 id, handle_id_t* out_handle_id) { } // TODO: heap mask, kind -NvResult NvMap::Alloc(handle_id_t handle_id, u32 heap_mask, u32 flags, - InOutSingle inout_alignment, aligned kind, - gpu_vaddr_t addr) { +NvResult NvMap::Alloc(System* system, handle_id_t handle_id, u32 heap_mask, + u32 flags, InOutSingle inout_alignment, + aligned kind, gpu_vaddr_t addr) { (void)heap_mask; (void)kind; // TODO: flags? - GPU_INSTANCE.AllocateMap(handle_id, addr, flags == 1); + system->GetGpu().AllocateMap(handle_id, addr, flags == 1); inout_alignment = hw::tegra_x1::gpu::GPU_PAGE_SIZE; // TODO: correct? return NvResult::Success; } -NvResult NvMap::Free(aligned handle_id, gpu_vaddr_t* out_addr, - u64* out_size, u32* out_flags) { - auto map = GPU_INSTANCE.GetMap(handle_id); - GPU_INSTANCE.FreeMap(handle_id); +NvResult NvMap::Free(System* system, aligned handle_id, + gpu_vaddr_t* out_addr, u64* out_size, u32* out_flags) { + auto map = system->GetGpu().GetMap(handle_id); + system->GetGpu().FreeMap(handle_id); *out_addr = map.addr; *out_size = map.size; @@ -44,9 +44,9 @@ NvResult NvMap::Free(aligned handle_id, gpu_vaddr_t* out_addr, return NvResult::Success; } -NvResult NvMap::Param(handle_id_t handle_id, NvMapParamType type, - u32* out_value) { - auto map = GPU_INSTANCE.GetMap(handle_id); +NvResult NvMap::Param(System* system, handle_id_t handle_id, + NvMapParamType type, u32* out_value) { + auto map = system->GetGpu().GetMap(handle_id); switch (type) { case NvMapParamType::Size: *out_value = static_cast(map.size); diff --git a/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp b/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp index 4959d861..b63acd93 100644 --- a/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp +++ b/src/core/horizon/services/nvdrv/ioctl/nvmap.hpp @@ -15,18 +15,20 @@ enum class NvMapParamType : u32 { class NvMap : public FdBase { public: - NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, u32 nr) override; + NvResult Ioctl([[maybe_unused]] IoctlContext& context, u32 type, + u32 nr) override; private: // Ioctls - NvResult Create(u32 size, handle_id_t* out_handle_id); + NvResult Create(System* system, u32 size, handle_id_t* out_handle_id); NvResult FromId(u32 id, handle_id_t* out_handle_id); - NvResult Alloc(handle_id_t handle_id, u32 heap_mask, u32 flags, - InOutSingle inout_alignment, aligned kind, - gpu_vaddr_t addr); - NvResult Free(aligned handle_id, gpu_vaddr_t* out_addr, - u64* out_size, u32* out_flags); - NvResult Param(handle_id_t handle_id, NvMapParamType type, u32* out_value); + NvResult Alloc(System* system, handle_id_t handle_id, u32 heap_mask, + u32 flags, InOutSingle inout_alignment, + aligned kind, gpu_vaddr_t addr); + NvResult Free(System* system, aligned handle_id, + gpu_vaddr_t* out_addr, u64* out_size, u32* out_flags); + NvResult Param(System* system, handle_id_t handle_id, NvMapParamType type, + u32* out_value); NvResult GetId(u32* out_id, handle_id_t handle_id); }; diff --git a/src/core/horizon/services/nvdrv/nvdrv_services.cpp b/src/core/horizon/services/nvdrv/nvdrv_services.cpp index 4a49c386..6ac0b972 100644 --- a/src/core/horizon/services/nvdrv/nvdrv_services.cpp +++ b/src/core/horizon/services/nvdrv/nvdrv_services.cpp @@ -63,12 +63,12 @@ result_t INvDrvServices::Open(InBuffer path_buffer, return RESULT_SUCCESS; } -result_t INvDrvServices::Ioctl(kernel::Process* process, handle_id_t fd_id, - u32 code, +result_t INvDrvServices::Ioctl(System* system, kernel::Process* process, + handle_id_t fd_id, u32 code, InBuffer in_buffer, NvResult* out_result, OutBuffer out_buffer) { - return IoctlImpl(&ioctl::FdBase::Ioctl, process, fd_id, code, + return IoctlImpl(&ioctl::FdBase::Ioctl, *system, process, fd_id, code, in_buffer.stream, nullptr, out_buffer.stream, nullptr, out_result); } @@ -115,24 +115,24 @@ result_t INvDrvServices::QueryEvent(kernel::Process* process, handle_id_t fd_id, } } -result_t INvDrvServices::Ioctl2(kernel::Process* process, handle_id_t fd_id, - u32 code, +result_t INvDrvServices::Ioctl2(System* system, kernel::Process* process, + handle_id_t fd_id, u32 code, InBuffer in_buffer1, InBuffer in_buffer2, NvResult* out_result, OutBuffer out_buffer) { - return IoctlImpl(&ioctl::FdBase::Ioctl2, process, fd_id, code, + return IoctlImpl(&ioctl::FdBase::Ioctl2, *system, process, fd_id, code, in_buffer1.stream, in_buffer2.stream, out_buffer.stream, nullptr, out_result); } -result_t INvDrvServices::Ioctl3(kernel::Process* process, handle_id_t fd_id, - u32 code, +result_t INvDrvServices::Ioctl3(System* system, kernel::Process* process, + handle_id_t fd_id, u32 code, InBuffer in_buffer, NvResult* out_result, OutBuffer out_buffer1, OutBuffer out_buffer2) { - return IoctlImpl(&ioctl::FdBase::Ioctl3, process, fd_id, code, + return IoctlImpl(&ioctl::FdBase::Ioctl3, *system, process, fd_id, code, in_buffer.stream, nullptr, out_buffer1.stream, out_buffer2.stream, out_result); } @@ -140,7 +140,7 @@ result_t INvDrvServices::Ioctl3(kernel::Process* process, handle_id_t fd_id, result_t INvDrvServices::IoctlImpl( NvResult (ioctl::FdBase::*func)(ioctl::IoctlContext& context, u32 type, u32 nr), - kernel::Process* process, handle_id_t fd_id, u32 code, + System& system, kernel::Process* process, handle_id_t fd_id, u32 code, io::MemoryStream* in_stream, io::MemoryStream* in_buffer_stream, io::MemoryStream* out_stream, io::MemoryStream* out_buffer_stream, NvResult* out_result) { @@ -151,7 +151,8 @@ result_t INvDrvServices::IoctlImpl( u32 nr = code & 0xff; ioctl::IoctlContext context{ - process, in_stream, in_buffer_stream, out_stream, out_buffer_stream, + system, process, in_stream, + in_buffer_stream, out_stream, out_buffer_stream, }; NvResult result = (fd->*func)(context, type, nr); diff --git a/src/core/horizon/services/nvdrv/nvdrv_services.hpp b/src/core/horizon/services/nvdrv/nvdrv_services.hpp index 33f7f0eb..cfbbef59 100644 --- a/src/core/horizon/services/nvdrv/nvdrv_services.hpp +++ b/src/core/horizon/services/nvdrv/nvdrv_services.hpp @@ -24,8 +24,8 @@ class INvDrvServices : public IService { // Commands result_t Open(InBuffer path_buffer, u32* out_fd_id, u32* out_error); - result_t Ioctl(kernel::Process* process, handle_id_t fd_id, u32 code, - InBuffer in_buffer, + result_t Ioctl(System* system, kernel::Process* process, handle_id_t fd_id, + u32 code, InBuffer in_buffer, NvResult* out_result, OutBuffer out_buffer); result_t Close(u32 fd_id, u32* out_err); @@ -34,13 +34,13 @@ class INvDrvServices : public IService { u32 event_id, NvResult* out_result, OutHandle out_handle); STUB_REQUEST_COMMAND(SetAruid); - result_t Ioctl2(kernel::Process* process, handle_id_t fd_id, u32 code, - InBuffer in_buffer1, + result_t Ioctl2(System* system, kernel::Process* process, handle_id_t fd_id, + u32 code, InBuffer in_buffer1, InBuffer in_buffer2, NvResult* out_result, OutBuffer out_buffer); - result_t Ioctl3(kernel::Process* process, handle_id_t fd_id, u32 code, - InBuffer in_buffer, + result_t Ioctl3(System* system, kernel::Process* process, handle_id_t fd_id, + u32 code, InBuffer in_buffer, NvResult* out_result, OutBuffer out_buffer1, OutBuffer out_buffer2); @@ -49,10 +49,10 @@ class INvDrvServices : public IService { result_t IoctlImpl(NvResult (ioctl::FdBase::*func)(ioctl::IoctlContext& context, u32 type, u32 nr), - kernel::Process* process, handle_id_t fd_id, u32 code, - io::MemoryStream* in_stream, io::MemoryStream* in_buffer_stream, - io::MemoryStream* out_stream, io::MemoryStream* out_buffer_stream, - NvResult* out_result); + System& system, kernel::Process* process, handle_id_t fd_id, + u32 code, io::MemoryStream* in_stream, + io::MemoryStream* in_buffer_stream, io::MemoryStream* out_stream, + io::MemoryStream* out_buffer_stream, NvResult* out_result); }; } // namespace hydra::horizon::services::nvdrv diff --git a/src/core/horizon/services/pl/internal/shared_font_manager.cpp b/src/core/horizon/services/pl/internal/shared_font_manager.cpp index 428fb933..181b8b1e 100644 --- a/src/core/horizon/services/pl/internal/shared_font_manager.cpp +++ b/src/core/horizon/services/pl/internal/shared_font_manager.cpp @@ -5,6 +5,7 @@ #include "core/horizon/filesystem/filesystem.hpp" #include "core/horizon/filesystem/partition_filesystem.hpp" #include "core/horizon/filesystem/romfs/romfs.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::pl::internal { @@ -37,12 +38,13 @@ constexpr SharedFontName shared_font_names[] = { #undef SHARED_FONT_ENTRY -filesystem::IFile* GetSharedFontFile(SharedFontType font_type) { +filesystem::IFile* GetSharedFontFile(filesystem::Filesystem& filesystem, + SharedFontType font_type) { const auto& name = shared_font_names[static_cast(font_type)]; // NCA filesystem::IFile* file; - auto res = KERNEL_INSTANCE.GetFilesystem().GetFile( + auto res = filesystem.GetFile( fmt::format(FS_FIRMWARE_PATH "/{}", name.name), file); if (res != filesystem::FsResult::Success) { LOG_ERROR(Services, "Failed to get shared font {} file: {}", font_type, @@ -99,8 +101,9 @@ result_t DecryptBFTTF(io::IStream* in_stream, io::IStream* out_stream) { } // namespace -SharedFontManager::SharedFontManager() - : shared_memory{new kernel::SharedMemory(SHARED_MEMORY_SIZE)} {} +SharedFontManager::SharedFontManager(System& system_) + : system{system_}, shared_memory{new kernel::SharedMemory( + system.GetCpu(), SHARED_MEMORY_SIZE)} {} SharedFontManager::~SharedFontManager() { delete shared_memory; } @@ -111,7 +114,7 @@ void SharedFontManager::LoadFonts() { } void SharedFontManager::LoadFont(const SharedFontType type) { - auto file = GetSharedFontFile(type); + auto file = GetSharedFontFile(system.GetOS().GetFilesystem(), type); if (!file) return; diff --git a/src/core/horizon/services/pl/internal/shared_font_manager.hpp b/src/core/horizon/services/pl/internal/shared_font_manager.hpp index 3a2d7af9..ceb1e652 100644 --- a/src/core/horizon/services/pl/internal/shared_font_manager.hpp +++ b/src/core/horizon/services/pl/internal/shared_font_manager.hpp @@ -14,12 +14,14 @@ struct FontState { class SharedFontManager { public: - SharedFontManager(); + SharedFontManager(System& system_); ~SharedFontManager(); void LoadFonts(); private: + System& system; + kernel::SharedMemory* shared_memory; u32 shared_memory_offset{0}; FontState states[u32(SharedFontType::Total)]{}; diff --git a/src/core/horizon/services/pl/shared_font_manager.cpp b/src/core/horizon/services/pl/shared_font_manager.cpp index 7469f890..02340481 100644 --- a/src/core/horizon/services/pl/shared_font_manager.cpp +++ b/src/core/horizon/services/pl/shared_font_manager.cpp @@ -1,7 +1,7 @@ #include "core/horizon/services/pl/shared_font_manager.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::pl { @@ -20,29 +20,32 @@ result_t ISharedFontManager::GetLoadState(SharedFontType font_type, return RESULT_SUCCESS; } -result_t ISharedFontManager::GetSize(SharedFontType font_type, u32* out_size) { - *out_size = - static_cast(SHARED_FONT_MANAGER_INSTANCE.GetState(font_type).size); +result_t ISharedFontManager::GetSize(System* system, SharedFontType font_type, + u32* out_size) { + *out_size = static_cast( + system->GetOS().GetSharedFontManager().GetState(font_type).size); return RESULT_SUCCESS; } -result_t -ISharedFontManager::GetSharedMemoryAddressOffset(SharedFontType font_type, - u32* out_address_offset) { - *out_address_offset = - SHARED_FONT_MANAGER_INSTANCE.GetState(font_type).shared_memory_offset; +result_t ISharedFontManager::GetSharedMemoryAddressOffset( + System* system, SharedFontType font_type, u32* out_address_offset) { + *out_address_offset = system->GetOS() + .GetSharedFontManager() + .GetState(font_type) + .shared_memory_offset; return RESULT_SUCCESS; } result_t ISharedFontManager::GetSharedMemoryNativeHandle( - kernel::Process* process, OutHandle out_handle) { - out_handle = - process->AddHandle(SHARED_FONT_MANAGER_INSTANCE.GetSharedMemory()); + System* system, kernel::Process* process, + OutHandle out_handle) { + out_handle = process->AddHandle( + system->GetOS().GetSharedFontManager().GetSharedMemory()); return RESULT_SUCCESS; } result_t ISharedFontManager::GetSharedFontInOrderOfPriority( - LanguageCode language_code, u8* out_loaded, u32* out_count, + System* system, LanguageCode language_code, u8* out_loaded, u32* out_count, OutBuffer out_types_buffer, OutBuffer out_offsets_buffer, OutBuffer out_sizes_buffer) { @@ -53,7 +56,8 @@ result_t ISharedFontManager::GetSharedFontInOrderOfPriority( (void)language_code; for (SharedFontType type = SharedFontType::JapanUsEurope; type < SharedFontType::Total; type++) { - const auto& state = SHARED_FONT_MANAGER_INSTANCE.GetState(type); + const auto& state = + system->GetOS().GetSharedFontManager().GetState(type); out_types_buffer.stream->Write(type); out_offsets_buffer.stream->Write(state.shared_memory_offset); out_sizes_buffer.stream->Write(static_cast(state.size)); diff --git a/src/core/horizon/services/pl/shared_font_manager.hpp b/src/core/horizon/services/pl/shared_font_manager.hpp index 00a05801..412a7647 100644 --- a/src/core/horizon/services/pl/shared_font_manager.hpp +++ b/src/core/horizon/services/pl/shared_font_manager.hpp @@ -12,17 +12,18 @@ class ISharedFontManager : public IService { // Commands result_t RequestLoad(SharedFontType font_type); result_t GetLoadState(SharedFontType font_type, LoadState* out_state); - result_t GetSize(SharedFontType font_type, u32* out_size); - result_t GetSharedMemoryAddressOffset(SharedFontType font_type, + result_t GetSize(System* system, SharedFontType font_type, u32* out_size); + result_t GetSharedMemoryAddressOffset(System* system, + SharedFontType font_type, u32* out_address_offset); result_t - GetSharedMemoryNativeHandle(kernel::Process* process, + GetSharedMemoryNativeHandle(System* system, kernel::Process* process, OutHandle out_handle); // TODO: buffer attr // TODO: should out_loaded be a bool? result_t GetSharedFontInOrderOfPriority( - LanguageCode language_code, u8* out_loaded, u32* out_count, - OutBuffer out_types_buffer, + System* system, LanguageCode language_code, u8* out_loaded, + u32* out_count, OutBuffer out_types_buffer, OutBuffer out_offsets_buffer, OutBuffer out_sizes_buffer); }; diff --git a/src/core/horizon/services/server.cpp b/src/core/horizon/services/server.cpp index ac8bc6c2..3577fea8 100644 --- a/src/core/horizon/services/server.cpp +++ b/src/core/horizon/services/server.cpp @@ -2,7 +2,7 @@ #include "core/horizon/kernel/hipc/server_port.hpp" #include "core/horizon/kernel/hipc/service_manager.hpp" -#include "core/horizon/kernel/kernel.hpp" +#include "core/system.hpp" namespace hydra::horizon::services { @@ -47,7 +47,7 @@ void Server::MainLoop(kernel::should_stop_fn_t should_stop) { sync_objs.insert(sync_objs.end(), sessions.begin(), sessions.end()); u32 signalled_index; - const auto res = KERNEL_INSTANCE.ReplyAndReceive( + const auto res = system.GetOS().GetKernel().ReplyAndReceive( thread, sync_objs, reply_target_session, kernel::INFINITE_TIMEOUT, signalled_index); switch (res) { @@ -67,7 +67,8 @@ void Server::MainLoop(kernel::should_stop_fn_t should_stop) { auto session = sessions[session_index]; auto service = session_services.at(session); - service->HandleRequest(session->GetActiveRequestClientProcess(), + service->HandleRequest(system, + session->GetActiveRequestClientProcess(), thread->GetTlsPtr()); // Set the reply target @@ -93,7 +94,8 @@ void Server::MainLoop(kernel::should_stop_fn_t should_stop) { // Handle all requests while (session->HasRequests()) { session->Receive(thread); - service->HandleRequest(session->GetActiveRequestClientProcess(), + service->HandleRequest(system, + session->GetActiveRequestClientProcess(), thread->GetTlsPtr()); session->Reply(thread->GetTlsPtr()); } diff --git a/src/core/horizon/services/server.hpp b/src/core/horizon/services/server.hpp index 792b5869..6c8e4834 100644 --- a/src/core/horizon/services/server.hpp +++ b/src/core/horizon/services/server.hpp @@ -7,6 +7,10 @@ #include "core/horizon/kernel/host_thread.hpp" #include "core/horizon/services/service.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::kernel::hipc { class ServerPort; class ServerSession; @@ -18,6 +22,7 @@ typedef std::function create_service_fn_t; class Server { public: + Server(System& system_) : system{system_} {} ~Server() { Stop(); } void Start(); @@ -33,6 +38,8 @@ class Server { } private: + System& system; + kernel::HostThread* thread{nullptr}; std::map diff --git a/src/core/horizon/services/service.cpp b/src/core/horizon/services/service.cpp index 47e51b8e..2bec748f 100644 --- a/src/core/horizon/services/service.cpp +++ b/src/core/horizon/services/service.cpp @@ -14,7 +14,8 @@ IService::~IService() { delete subservice_pool; } -void IService::HandleRequest(kernel::Process* caller_process, uptr ptr) { +void IService::HandleRequest(System& system, kernel::Process* caller_process, + uptr ptr) { // HIPC header auto hipc_in = kernel::hipc::parse_request(reinterpret_cast(ptr)); auto command_type = @@ -37,6 +38,7 @@ void IService::HandleRequest(kernel::Process* caller_process, uptr ptr) { scratch_buffer_copy_handles, scratch_buffer_move_handles); RequestContext context{ + system, caller_process, streams, }; diff --git a/src/core/horizon/services/service.hpp b/src/core/horizon/services/service.hpp index fadef484..b578bd20 100644 --- a/src/core/horizon/services/service.hpp +++ b/src/core/horizon/services/service.hpp @@ -2,6 +2,10 @@ #include "core/horizon/kernel/hipc/const.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::kernel { class Process; } @@ -14,13 +18,15 @@ class Server; class IService; struct RequestContext { + System& system; kernel::Process* process; kernel::hipc::Streams& streams; }; class IService { public: - void HandleRequest(kernel::Process* caller_process, uptr ptr); + void HandleRequest(System& system, kernel::Process* caller_process, + uptr ptr); void AddService(RequestContext& context, IService* service); IService* GetService(RequestContext& context, handle_id_t handle_id); diff --git a/src/core/horizon/services/sm/user_interface.cpp b/src/core/horizon/services/sm/user_interface.cpp index 9f0e530c..17b3226b 100644 --- a/src/core/horizon/services/sm/user_interface.cpp +++ b/src/core/horizon/services/sm/user_interface.cpp @@ -4,7 +4,7 @@ #include "core/horizon/kernel/hipc/port.hpp" #include "core/horizon/kernel/hipc/server_port.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::sm { @@ -13,11 +13,12 @@ DEFINE_SERVICE_COMMAND_TABLE(IUserInterface, 0, RegisterClient, 1, AtmosphereHasService, 65101, AtmosphereWaitService) result_t -IUserInterface::GetServiceHandle(kernel::Process* process, u64 name, +IUserInterface::GetServiceHandle(System* system, kernel::Process* process, + u64 name, OutHandle out_handle) { LOG_DEBUG(Services, "Service name: \"{}\"", u64_to_str(name)); - auto client_port = OS_INSTANCE.GetServiceManager().GetPort(name); + auto client_port = system->GetOS().GetServiceManager().GetPort(name); if (!client_port) { LOG_WARN(Services, "Unknown service name \"{}\"", u64_to_str(name)); return MAKE_RESULT(Svc, kernel::Error::NotFound); // TODO: module @@ -33,8 +34,8 @@ IUserInterface::GetServiceHandle(kernel::Process* process, u64 name, } result_t -IUserInterface::RegisterService(kernel::Process* process, u64 name, - bool is_light, i32 max_sessions, +IUserInterface::RegisterService(System* system, kernel::Process* process, + u64 name, bool is_light, i32 max_sessions, OutHandle out_port_handle) { (void)is_light; (void)max_sessions; @@ -56,15 +57,16 @@ IUserInterface::RegisterService(kernel::Process* process, u64 name, out_port_handle = process->AddHandle(server_port); // Register client side - OS_INSTANCE.GetServiceManager().RegisterPort(name, client_port); + system->GetOS().GetServiceManager().RegisterPort(name, client_port); return RESULT_SUCCESS; } -result_t IUserInterface::AtmosphereHasService(u64 name, bool* out_has_service) { +result_t IUserInterface::AtmosphereHasService(System* system, u64 name, + bool* out_has_service) { LOG_DEBUG(Services, "Service name: \"{}\"", u64_to_str(name)); - auto client_port = OS_INSTANCE.GetServiceManager().GetPort(name); + auto client_port = system->GetOS().GetServiceManager().GetPort(name); *out_has_service = (client_port != nullptr); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/sm/user_interface.hpp b/src/core/horizon/services/sm/user_interface.hpp index 356b1744..0e2a2a6f 100644 --- a/src/core/horizon/services/sm/user_interface.hpp +++ b/src/core/horizon/services/sm/user_interface.hpp @@ -12,14 +12,15 @@ class IUserInterface : public IService { private: // Commands STUB_REQUEST_COMMAND(RegisterClient); - result_t GetServiceHandle(kernel::Process* process, u64 name, - OutHandle out_handle); - result_t RegisterService(kernel::Process* process, u64 name, bool is_light, - i32 max_sessions, + result_t GetServiceHandle(System* system, kernel::Process* process, + u64 name, OutHandle out_handle); + result_t RegisterService(System* system, kernel::Process* process, u64 name, + bool is_light, i32 max_sessions, OutHandle out_port_handle); // Atmosphere commands - result_t AtmosphereHasService(u64 name, bool* out_has_service); + result_t AtmosphereHasService(System* system, u64 name, + bool* out_has_service); result_t AtmosphereWaitService(u64 name); }; diff --git a/src/core/horizon/services/timesrv/internal/time_manager.cpp b/src/core/horizon/services/timesrv/internal/time_manager.cpp index fb7642de..82e6c86a 100644 --- a/src/core/horizon/services/timesrv/internal/time_manager.cpp +++ b/src/core/horizon/services/timesrv/internal/time_manager.cpp @@ -1,5 +1,7 @@ #include "core/horizon/services/timesrv/internal/time_manager.hpp" +#include "core/system.hpp" + namespace hydra::horizon::services::timesrv::internal { namespace { @@ -14,8 +16,9 @@ constexpr u32 CONTINUOUS_ADJUSTMENT_TIME_POINT_OFFSET = 0xd0; } // namespace -TimeManager::TimeManager() - : shared_memory{new kernel::SharedMemory(SHARED_MEMORY_SIZE)} { +TimeManager::TimeManager(System& system) + : shared_memory{ + new kernel::SharedMemory(system.GetCpu(), SHARED_MEMORY_SIZE)} { std::memset(reinterpret_cast(shared_memory->GetPtr()), 0, SHARED_MEMORY_SIZE); diff --git a/src/core/horizon/services/timesrv/internal/time_manager.hpp b/src/core/horizon/services/timesrv/internal/time_manager.hpp index d40c7aec..9097779c 100644 --- a/src/core/horizon/services/timesrv/internal/time_manager.hpp +++ b/src/core/horizon/services/timesrv/internal/time_manager.hpp @@ -2,6 +2,10 @@ #include "core/horizon/kernel/shared_memory.hpp" +namespace hydra { +class System; +} + namespace hydra::horizon::services::timesrv::internal { struct SteadyClockTimePoint { @@ -28,7 +32,7 @@ struct ContinuousAdjustmentTimePoint { class TimeManager { public: - TimeManager(); + TimeManager(System& system); private: kernel::SharedMemory* shared_memory; diff --git a/src/core/horizon/services/timesrv/static_service.cpp b/src/core/horizon/services/timesrv/static_service.cpp index 831667d8..07057386 100644 --- a/src/core/horizon/services/timesrv/static_service.cpp +++ b/src/core/horizon/services/timesrv/static_service.cpp @@ -1,10 +1,10 @@ #include "core/horizon/services/timesrv/static_service.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/services/timesrv/steady_clock.hpp" #include "core/horizon/services/timesrv/system_clock.hpp" #include "core/horizon/services/timesrv/time_zone_service.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::timesrv { @@ -47,8 +47,10 @@ result_t IStaticService::GetEphemeralNetworkSystemClock(RequestContext* ctx) { } result_t IStaticService::GetSharedMemoryNativeHandle( - kernel::Process* process, OutHandle out_handle) { - out_handle = process->AddHandle(TIME_MANAGER_INSTANCE.GetSharedMemory()); + System* system, kernel::Process* process, + OutHandle out_handle) { + out_handle = + process->AddHandle(system->GetOS().GetTimeManager().GetSharedMemory()); return RESULT_SUCCESS; } diff --git a/src/core/horizon/services/timesrv/static_service.hpp b/src/core/horizon/services/timesrv/static_service.hpp index eb1dde57..5c2f9911 100644 --- a/src/core/horizon/services/timesrv/static_service.hpp +++ b/src/core/horizon/services/timesrv/static_service.hpp @@ -19,7 +19,7 @@ class IStaticService : public IService { result_t GetStandardLocalSystemClock(RequestContext* ctx); result_t GetEphemeralNetworkSystemClock(RequestContext* ctx); result_t - GetSharedMemoryNativeHandle(kernel::Process* process, + GetSharedMemoryNativeHandle(System* system, kernel::Process* process, OutHandle out_handle); STUB_REQUEST_COMMAND(CalculateMonotonicSystemClockBaseTimePoint); }; diff --git a/src/core/horizon/services/visrv/application_display_service.cpp b/src/core/horizon/services/visrv/application_display_service.cpp index ba1c1416..cde683bc 100644 --- a/src/core/horizon/services/visrv/application_display_service.cpp +++ b/src/core/horizon/services/visrv/application_display_service.cpp @@ -1,10 +1,10 @@ #include "core/horizon/services/visrv/application_display_service.hpp" #include "core/horizon/kernel/process.hpp" -#include "core/horizon/os.hpp" #include "core/horizon/services/hosbinder/parcel.hpp" #include "core/horizon/services/visrv/manager_display_service.hpp" #include "core/horizon/services/visrv/system_display_service.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::visrv { @@ -29,13 +29,14 @@ DEFINE_SERVICE_COMMAND_TABLE( CloseLayer, 2030, CreateStrayLayer, 2031, DestroyStrayLayer, 2101, SetLayerScalingMode, 2102, ConvertScalingMode, 5202, GetDisplayVsyncEvent) -result_t IApplicationDisplayService::GetRelayService(RequestContext* ctx) { +result_t IApplicationDisplayService::GetRelayService(RequestContext* ctx, + System* system) { LOG_WARN(Services, "GetRelayService is not implemented properly"); // TODO: this should wrap dispdrv in a custom class const auto name = "dispdrv"_u64; - auto client_port = OS_INSTANCE.GetServiceManager().GetPort(name); + auto client_port = system->GetOS().GetServiceManager().GetPort(name); if (!client_port) { LOG_WARN(Services, "Unknown service name \"{}\"", u64_to_str(name)); return MAKE_RESULT(Svc, kernel::Error::NotFound); // TODO: module @@ -64,18 +65,19 @@ IApplicationDisplayService::GetManagerDisplayService(RequestContext* ctx) { } result_t IApplicationDisplayService::GetIndirectDisplayTransactionService( - RequestContext* ctx) { + RequestContext* ctx, System* system) { LOG_WARN( Services, "GetIndirectDisplayTransactionService is not implemented properly"); // HACK - return GetRelayService(ctx); + return GetRelayService(ctx, system); } result_t IApplicationDisplayService::ListDisplays( - u64* out_count, OutBuffer out_display_infos_buffer) { - const auto res = OS_INSTANCE.GetDisplayResolution(); + System* system, u64* out_count, + OutBuffer out_display_infos_buffer) { + const auto res = system->GetOS().GetDisplayResolution(); out_display_infos_buffer.stream->Write({ .name = "Default", .has_layer_limit = true, @@ -87,40 +89,43 @@ result_t IApplicationDisplayService::ListDisplays( return RESULT_SUCCESS; } -result_t IApplicationDisplayService::OpenDisplay(DisplayName display_name, +result_t IApplicationDisplayService::OpenDisplay(System* system, + DisplayName display_name, u64* out_display_id) { - auto display_id = - OS_INSTANCE.GetDisplayDriver().GetDisplayIDFromName(display_name.name); - auto& display = OS_INSTANCE.GetDisplayDriver().GetDisplay(display_id); + auto display_id = system->GetOS().GetDisplayDriver().GetDisplayIDFromName( + display_name.name); + auto& display = system->GetOS().GetDisplayDriver().GetDisplay(display_id); display.Open(); *out_display_id = display_id; return RESULT_SUCCESS; } -result_t IApplicationDisplayService::CloseDisplay(u64 display_id) { - auto& display = OS_INSTANCE.GetDisplayDriver().GetDisplay( +result_t IApplicationDisplayService::CloseDisplay(System* system, + u64 display_id) { + auto& display = system->GetOS().GetDisplayDriver().GetDisplay( static_cast(display_id)); display.Close(); return RESULT_SUCCESS; } -result_t IApplicationDisplayService::GetDisplayResolution(u64 display_id, +result_t IApplicationDisplayService::GetDisplayResolution(System* system, + u64 display_id, i64* out_width, i64* out_height) { - auto& display = OS_INSTANCE.GetDisplayDriver().GetDisplay( + auto& display = system->GetOS().GetDisplayDriver().GetDisplay( static_cast(display_id)); (void)display; // TODO: use the display - const auto res = OS_INSTANCE.GetDisplayResolution(); + const auto res = system->GetOS().GetDisplayResolution(); *out_width = res.x(); *out_height = res.y(); return RESULT_SUCCESS; } result_t IApplicationDisplayService::OpenLayer( - DisplayName display_name, u64 layer_id, u64 aruid, + System* system, DisplayName display_name, u64 layer_id, u64 aruid, u64* out_native_window_size, OutBuffer parcel_buffer) { (void)display_name; @@ -128,10 +133,10 @@ result_t IApplicationDisplayService::OpenLayer( // TODO: what's the display for? // auto& display = - // OS_INSTANCE.GetDisplayDriver().GetDisplayByName(display_name.name); + // system->GetOS().GetDisplayDriver().GetDisplayByName(display_name.name); auto& layer = - OS_INSTANCE.GetDisplayDriver().GetLayer(static_cast(layer_id)); + system->GetOS().GetDisplayDriver().GetLayer(static_cast(layer_id)); layer.Open(); // Parcel @@ -144,24 +149,25 @@ result_t IApplicationDisplayService::OpenLayer( return RESULT_SUCCESS; } -result_t IApplicationDisplayService::CloseLayer(u64 layer_id) { - OS_INSTANCE.GetDisplayDriver().DestroyLayer(static_cast(layer_id)); +result_t IApplicationDisplayService::CloseLayer(System* system, u64 layer_id) { + system->GetOS().GetDisplayDriver().DestroyLayer(static_cast(layer_id)); return RESULT_SUCCESS; } result_t IApplicationDisplayService::CreateStrayLayer( - kernel::Process* process, aligned flags, u64 display_id, - u64* out_layer_id, u64* out_native_window_size, + System* system, kernel::Process* process, aligned flags, + u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer) { - return CreateStrayLayerImpl(process, flags, display_id, out_layer_id, - out_native_window_size, + return CreateStrayLayerImpl(*system, process, flags, display_id, + out_layer_id, out_native_window_size, out_parcel_buffer.stream); } -result_t IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { +result_t IApplicationDisplayService::DestroyStrayLayer(System* system, + u64 layer_id) { // TODO: how is this different from CloseLayer? LOG_FUNC_NOT_IMPLEMENTED(Services); - CloseLayer(layer_id); + CloseLayer(system, layer_id); return RESULT_SUCCESS; } @@ -171,9 +177,9 @@ result_t IApplicationDisplayService::ConvertScalingMode() { } result_t IApplicationDisplayService::GetDisplayVsyncEvent( - kernel::Process* process, u64 display_id, + System* system, kernel::Process* process, u64 display_id, OutHandle out_handle) { - auto& display = OS_INSTANCE.GetDisplayDriver().GetDisplay( + auto& display = system->GetOS().GetDisplayDriver().GetDisplay( static_cast(display_id)); out_handle = process->AddHandle(display.GetVSyncEvent()); diff --git a/src/core/horizon/services/visrv/application_display_service.hpp b/src/core/horizon/services/visrv/application_display_service.hpp index 736d833a..aea812d3 100644 --- a/src/core/horizon/services/visrv/application_display_service.hpp +++ b/src/core/horizon/services/visrv/application_display_service.hpp @@ -19,33 +19,34 @@ class IApplicationDisplayService : public DisplayServiceBase { protected: // Commands - result_t GetRelayService(RequestContext* ctx); + result_t GetRelayService(RequestContext* ctx, System* system); result_t GetSystemDisplayService(RequestContext* ctx); result_t GetManagerDisplayService(RequestContext* ctx); - result_t GetIndirectDisplayTransactionService(RequestContext* ctx); + result_t GetIndirectDisplayTransactionService(RequestContext* ctx, + System* system); result_t - ListDisplays(u64* out_count, + ListDisplays(System* system, u64* out_count, OutBuffer out_display_infos_buffer); - result_t OpenDisplay(DisplayName display_name, u64* out_display_id); - result_t CloseDisplay(u64 display_id); - result_t GetDisplayResolution(u64 display_id, i64* out_width, - i64* out_height); - result_t OpenLayer(DisplayName display_name, u64 layer_id, u64 aruid, - u64* out_native_window_size, + result_t OpenDisplay(System* system, DisplayName display_name, + u64* out_display_id); + result_t CloseDisplay(System* system, u64 display_id); + result_t GetDisplayResolution(System* system, u64 display_id, + i64* out_width, i64* out_height); + result_t OpenLayer(System* system, DisplayName display_name, u64 layer_id, + u64 aruid, u64* out_native_window_size, OutBuffer parcel_buffer); - result_t CloseLayer(u64 layer_id); + result_t CloseLayer(System* system, u64 layer_id); result_t - CreateStrayLayer(kernel::Process* process, aligned flags, - u64 display_id, u64* out_layer_id, + CreateStrayLayer(System* system, kernel::Process* process, + aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer); - result_t DestroyStrayLayer(u64 layer_id); + result_t DestroyStrayLayer(System* system, u64 layer_id); STUB_REQUEST_COMMAND(SetLayerScalingMode); result_t ConvertScalingMode(); - result_t GetDisplayVsyncEvent(kernel::Process* process, u64 display_id, + result_t GetDisplayVsyncEvent(System* system, kernel::Process* process, + u64 display_id, OutHandle out_handle); - - private: }; } // namespace hydra::horizon::services::visrv diff --git a/src/core/horizon/services/visrv/display_service_base.cpp b/src/core/horizon/services/visrv/display_service_base.cpp index 01e21b3d..cec35884 100644 --- a/src/core/horizon/services/visrv/display_service_base.cpp +++ b/src/core/horizon/services/visrv/display_service_base.cpp @@ -1,22 +1,23 @@ #include "core/horizon/services/visrv/display_service_base.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::visrv { // TODO: flags, display ID result_t DisplayServiceBase::CreateStrayLayerImpl( - kernel::Process* process, u32 flags, u64 display_id, u64* out_layer_id, - u64* out_native_window_size, io::MemoryStream* out_parcel_stream) { + System& system, kernel::Process* process, u32 flags, u64 display_id, + u64* out_layer_id, u64* out_native_window_size, + io::MemoryStream* out_parcel_stream) { (void)flags; (void)display_id; - u32 binder_id = OS_INSTANCE.GetDisplayDriver().CreateBinder(); + u32 binder_id = system.GetOS().GetDisplayDriver().CreateBinder(); // TODO: what's the display for? - // auto& display = OS_INSTANCE.GetDisplayDriver().GetDisplay(display_id); + // auto& display = system.GetOS().GetDisplayDriver().GetDisplay(display_id); *out_layer_id = - OS_INSTANCE.GetDisplayDriver().CreateLayer(process, binder_id); + system.GetOS().GetDisplayDriver().CreateLayer(process, binder_id); // Parcel hosbinder::ParcelWriter parcel_writer(out_parcel_stream); diff --git a/src/core/horizon/services/visrv/display_service_base.hpp b/src/core/horizon/services/visrv/display_service_base.hpp index 740408ab..cc704d9b 100644 --- a/src/core/horizon/services/visrv/display_service_base.hpp +++ b/src/core/horizon/services/visrv/display_service_base.hpp @@ -7,8 +7,8 @@ namespace hydra::horizon::services::visrv { class DisplayServiceBase : public IService { protected: - result_t CreateStrayLayerImpl(kernel::Process* process, u32 flags, - u64 display_id, u64* out_layer_id, + result_t CreateStrayLayerImpl(System& system, kernel::Process* process, + u32 flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, io::MemoryStream* out_parcel_stream); result_t SetLayerVisibilityImpl(u64 layer_id, bool visible); diff --git a/src/core/horizon/services/visrv/manager_display_service.cpp b/src/core/horizon/services/visrv/manager_display_service.cpp index 3f843eb6..9df48e41 100644 --- a/src/core/horizon/services/visrv/manager_display_service.cpp +++ b/src/core/horizon/services/visrv/manager_display_service.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/visrv/manager_display_service.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::visrv { @@ -9,7 +9,8 @@ DEFINE_SERVICE_COMMAND_TABLE(IManagerDisplayService, 2010, CreateManagedLayer, 6000, AddToLayerStack, 6002, SetLayerVisibility) // TODO: flags, display ID -result_t IManagerDisplayService::CreateManagedLayer(kernel::Process* process, +result_t IManagerDisplayService::CreateManagedLayer(System* system, + kernel::Process* process, aligned flags, u64 display_id, u64 aruid, u64* out_layer_id) { @@ -17,26 +18,28 @@ result_t IManagerDisplayService::CreateManagedLayer(kernel::Process* process, (void)display_id; (void)aruid; - u32 binder_id = OS_INSTANCE.GetDisplayDriver().CreateBinder(); + u32 binder_id = system->GetOS().GetDisplayDriver().CreateBinder(); // TODO: what's the display for? - // auto& display = OS_INSTANCE.GetDisplayDriver().GetDisplay(display_id); + // auto& display = + // system->GetOS().GetDisplayDriver().GetDisplay(display_id); *out_layer_id = - OS_INSTANCE.GetDisplayDriver().CreateLayer(process, binder_id); + system->GetOS().GetDisplayDriver().CreateLayer(process, binder_id); return RESULT_SUCCESS; } -result_t IManagerDisplayService::DestroyManagedLayer(u64 layer_id) { - OS_INSTANCE.GetDisplayDriver().DestroyLayer(static_cast(layer_id)); +result_t IManagerDisplayService::DestroyManagedLayer(System* system, + u64 layer_id) { + system->GetOS().GetDisplayDriver().DestroyLayer(static_cast(layer_id)); return RESULT_SUCCESS; } result_t IManagerDisplayService::CreateStrayLayer( - kernel::Process* process, aligned flags, u64 display_id, - u64* out_layer_id, u64* out_native_window_size, + System* system, kernel::Process* process, aligned flags, + u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer) { - return CreateStrayLayerImpl(process, flags, display_id, out_layer_id, - out_native_window_size, + return CreateStrayLayerImpl(*system, process, flags, display_id, + out_layer_id, out_native_window_size, out_parcel_buffer.stream); } diff --git a/src/core/horizon/services/visrv/manager_display_service.hpp b/src/core/horizon/services/visrv/manager_display_service.hpp index 72f1b7e0..16ddf533 100644 --- a/src/core/horizon/services/visrv/manager_display_service.hpp +++ b/src/core/horizon/services/visrv/manager_display_service.hpp @@ -11,12 +11,13 @@ class IManagerDisplayService : public DisplayServiceBase { private: // Commands - result_t CreateManagedLayer(kernel::Process* process, aligned flags, - u64 display_id, u64 aruid, u64* out_layer_id); - result_t DestroyManagedLayer(u64 layer_id); + result_t CreateManagedLayer(System* system, kernel::Process* process, + aligned flags, u64 display_id, + u64 aruid, u64* out_layer_id); + result_t DestroyManagedLayer(System* system, u64 layer_id); result_t - CreateStrayLayer(kernel::Process* process, aligned flags, - u64 display_id, u64* out_layer_id, + CreateStrayLayer(System* system, kernel::Process* process, + aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer); result_t AddToLayerStack(u32 stack, u64 layer_id); diff --git a/src/core/horizon/services/visrv/system_display_service.cpp b/src/core/horizon/services/visrv/system_display_service.cpp index eb2d5241..adb9c109 100644 --- a/src/core/horizon/services/visrv/system_display_service.cpp +++ b/src/core/horizon/services/visrv/system_display_service.cpp @@ -1,6 +1,6 @@ #include "core/horizon/services/visrv/system_display_service.hpp" -#include "core/horizon/os.hpp" +#include "core/system.hpp" namespace hydra::horizon::services::visrv { @@ -18,32 +18,38 @@ result_t ISystemDisplayService::GetZOrderCountMax(u64 display_id, return RESULT_SUCCESS; } -result_t ISystemDisplayService::SetLayerPosition(f32 x, f32 y, u64 layer_id) { - OS_INSTANCE.GetDisplayDriver() +result_t ISystemDisplayService::SetLayerPosition(System* system, f32 x, f32 y, + u64 layer_id) { + system->GetOS() + .GetDisplayDriver() .GetLayer(static_cast(layer_id)) .SetPosition({x, y}); return RESULT_SUCCESS; } -result_t ISystemDisplayService::SetLayerSize(u64 layer_id, i64 width, - i64 height) { - OS_INSTANCE.GetDisplayDriver() +result_t ISystemDisplayService::SetLayerSize(System* system, u64 layer_id, + i64 width, i64 height) { + system->GetOS() + .GetDisplayDriver() .GetLayer(static_cast(layer_id)) .SetSize({u32(width), u32(height)}); return RESULT_SUCCESS; } -result_t ISystemDisplayService::SetLayerZ(u64 layer_id, i64 z) { - OS_INSTANCE.GetDisplayDriver().GetLayer(static_cast(layer_id)).SetZ(z); +result_t ISystemDisplayService::SetLayerZ(System* system, u64 layer_id, i64 z) { + system->GetOS() + .GetDisplayDriver() + .GetLayer(static_cast(layer_id)) + .SetZ(z); return RESULT_SUCCESS; } result_t ISystemDisplayService::CreateStrayLayer( - kernel::Process* process, aligned flags, u64 display_id, - u64* out_layer_id, u64* out_native_window_size, + System* system, kernel::Process* process, aligned flags, + u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer) { - return CreateStrayLayerImpl(process, flags, display_id, out_layer_id, - out_native_window_size, + return CreateStrayLayerImpl(*system, process, flags, display_id, + out_layer_id, out_native_window_size, out_parcel_buffer.stream); } @@ -51,13 +57,13 @@ result_t ISystemDisplayService::SetLayerVisibility(u64 layer_id, bool visible) { return SetLayerVisibilityImpl(layer_id, visible); } -result_t ISystemDisplayService::GetDisplayMode(u64 display_id, u32* out_width, - u32* out_height, +result_t ISystemDisplayService::GetDisplayMode(System* system, u64 display_id, + u32* out_width, u32* out_height, float* out_refresh_rate, i32* out_unknown) { LOG_FUNC_WITH_ARGS_STUBBED(Services, "display ID: {}", display_id); - const auto res = OS_INSTANCE.GetDisplayResolution(); + const auto res = system->GetOS().GetDisplayResolution(); *out_width = res.x(); *out_height = res.y(); *out_refresh_rate = 60.0f; diff --git a/src/core/horizon/services/visrv/system_display_service.hpp b/src/core/horizon/services/visrv/system_display_service.hpp index a95ef60c..f7763230 100644 --- a/src/core/horizon/services/visrv/system_display_service.hpp +++ b/src/core/horizon/services/visrv/system_display_service.hpp @@ -12,17 +12,18 @@ class ISystemDisplayService : public DisplayServiceBase { private: // Commands result_t GetZOrderCountMax(u64 display_id, i64* out_count); - result_t SetLayerPosition(f32 x, f32 y, u64 layer_id); - result_t SetLayerSize(u64 layer_id, i64 width, i64 height); - result_t SetLayerZ(u64 layer_id, i64 z); + result_t SetLayerPosition(System* system, f32 x, f32 y, u64 layer_id); + result_t SetLayerSize(System* system, u64 layer_id, i64 width, i64 height); + result_t SetLayerZ(System* system, u64 layer_id, i64 z); result_t - CreateStrayLayer(kernel::Process* process, aligned flags, - u64 display_id, u64* out_layer_id, + CreateStrayLayer(System* system, kernel::Process* process, + aligned flags, u64 display_id, u64* out_layer_id, u64* out_native_window_size, OutBuffer out_parcel_buffer); result_t SetLayerVisibility(u64 layer_id, bool visible); - result_t GetDisplayMode(u64 display_id, u32* out_width, u32* out_height, - float* out_refresh_rate, i32* out_unknown); + result_t GetDisplayMode(System* system, u64 display_id, u32* out_width, + u32* out_height, float* out_refresh_rate, + i32* out_unknown); }; } // namespace hydra::horizon::services::visrv diff --git a/src/core/hw/tegra_x1/cpu/cpu.cpp b/src/core/hw/tegra_x1/cpu/cpu.cpp deleted file mode 100644 index 2c4147d6..00000000 --- a/src/core/hw/tegra_x1/cpu/cpu.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "core/hw/tegra_x1/cpu/cpu.hpp" - -namespace hydra::hw::tegra_x1::cpu { - -SINGLETON_DEFINE_GET_INSTANCE(ICpu, Cpu) - -ICpu::ICpu() { SINGLETON_SET_INSTANCE(Cpu, Cpu); } - -ICpu::~ICpu() { SINGLETON_UNSET_INSTANCE(); } - -} // namespace hydra::hw::tegra_x1::cpu diff --git a/src/core/hw/tegra_x1/cpu/cpu.hpp b/src/core/hw/tegra_x1/cpu/cpu.hpp index e931b8a5..d02156df 100644 --- a/src/core/hw/tegra_x1/cpu/cpu.hpp +++ b/src/core/hw/tegra_x1/cpu/cpu.hpp @@ -2,7 +2,9 @@ #include "core/hw/tegra_x1/cpu/thread.hpp" -#define CPU_INSTANCE hw::tegra_x1::cpu::ICpu::GetInstance() +namespace hydra { +class System; +} namespace hydra::hw::tegra_x1::cpu { @@ -17,13 +19,11 @@ struct CpuFeatures { class ICpu { public: - static ICpu& GetInstance(); + virtual ~ICpu() = default; - ICpu(); - virtual ~ICpu(); - - virtual IMmu* CreateMmu() = 0; - virtual IThread* CreateThread(IMmu* mmu, const ThreadCallbacks& callbacks, + virtual IMmu* CreateMmu(System& system) = 0; + virtual IThread* CreateThread(WallClock& wall_clock, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, vaddr_t tls_mem_base) = 0; virtual IMemory* AllocateMemory(usize size) = 0; diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/cpu.cpp b/src/core/hw/tegra_x1/cpu/dynarmic/cpu.cpp index 0e391e24..e835cfe1 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/cpu.cpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/cpu.cpp @@ -12,11 +12,12 @@ Cpu::Cpu() { .supports_synchronous_single_step = true}; } -IMmu* Cpu::CreateMmu() { return new Mmu(); } +IMmu* Cpu::CreateMmu(System& system) { return new Mmu(system); } -IThread* Cpu::CreateThread(IMmu* mmu, const ThreadCallbacks& callbacks, - IMemory* tls_mem, vaddr_t tls_mem_base) { - return new Thread(mmu, callbacks, tls_mem, tls_mem_base); +IThread* Cpu::CreateThread(WallClock& wall_clock, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, + vaddr_t tls_mem_base) { + return new Thread(wall_clock, mmu, callbacks, tls_mem, tls_mem_base); } IMemory* Cpu::AllocateMemory(usize size) { diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/cpu.hpp b/src/core/hw/tegra_x1/cpu/dynarmic/cpu.hpp index 16565833..269ec9f0 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/cpu.hpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/cpu.hpp @@ -20,9 +20,10 @@ class Cpu : public ICpu { public: Cpu(); - IMmu* CreateMmu() override; - IThread* CreateThread(IMmu* mmu, const ThreadCallbacks& callbacks, - IMemory* tls_mem, vaddr_t tls_mem_base) override; + IMmu* CreateMmu(System& system) override; + IThread* CreateThread(WallClock& wall_clock, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, + vaddr_t tls_mem_base) override; IMemory* AllocateMemory(usize size) override; }; diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp b/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp index 22a3bf12..3bb307e4 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/mmu.hpp @@ -10,6 +10,8 @@ constexpr usize PAGE_COUNT = class Mmu : public IMmu { public: + using IMmu::IMmu; + void Map(vaddr_t dst_va, Range range, const horizon::kernel::MemoryState state) override; void Map(vaddr_t dst_va, Range range) override; diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp b/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp index cd94ca6e..e1061f50 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/thread.cpp @@ -25,9 +25,10 @@ namespace hydra::hw::tegra_x1::cpu::dynarmic { static Dynarmic::ExclusiveMonitor g_exclusive_monitor(4); // TODO: don't hardcode core count -Thread::Thread(IMmu* mmu, const ThreadCallbacks& callbacks, IMemory* tls_mem, +Thread::Thread(WallClock& wall_clock, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, vaddr_t tls_mem_base) - : IThread(mmu, callbacks, tls_mem) { + : IThread(wall_clock, mmu, callbacks, tls_mem) { tpidrro_el0 = tls_mem_base; // TODO: tpidr_el0? @@ -167,7 +168,7 @@ void Thread::ExceptionRaised([[maybe_unused]] u64 pc, jit->HaltExecution(); } -u64 Thread::GetCNTPCT() { return WallClock::GetInstance().GetCntpct(); } +u64 Thread::GetCNTPCT() { return wall_clock.GetCntpct(); } void Thread::SerializeState() { for (u32 i = 0; i < 29; i++) diff --git a/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp b/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp index d8483abb..7c788b5e 100644 --- a/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp +++ b/src/core/hw/tegra_x1/cpu/dynarmic/thread.hpp @@ -18,8 +18,8 @@ class Mmu; class Thread final : public IThread, private Dynarmic::A64::UserCallbacks { public: - Thread(IMmu* mmu, const ThreadCallbacks& callbacks, IMemory* tls_mem, - vaddr_t tls_mem_base); + Thread(WallClock& wall_clock, IMmu* mmu, const ThreadCallbacks& callbacks, + IMemory* tls_mem, vaddr_t tls_mem_base); ~Thread() override; void Run() override; diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp index da21fd56..aa36f163 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp @@ -88,11 +88,12 @@ Cpu::Cpu() Cpu::~Cpu() {} -IMmu* Cpu::CreateMmu() { return new Mmu(); } +IMmu* Cpu::CreateMmu(System& system) { return new Mmu(system); } -IThread* Cpu::CreateThread(IMmu* mmu, const ThreadCallbacks& callbacks, - IMemory* tls_mem, vaddr_t tls_mem_base) { - return new Thread(mmu, callbacks, tls_mem, tls_mem_base); +IThread* Cpu::CreateThread(WallClock& wall_clock, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, + vaddr_t tls_mem_base) { + return new Thread(wall_clock, *this, mmu, callbacks, tls_mem, tls_mem_base); } IMemory* Cpu::AllocateMemory(usize size) { return new Memory(size); } diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp index 66965339..d686c2a8 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.hpp @@ -28,9 +28,10 @@ class Cpu : public ICpu { Cpu(); ~Cpu(); - IMmu* CreateMmu() override; - IThread* CreateThread(IMmu* mmu, const ThreadCallbacks& callbacks, - IMemory* tls_mem, vaddr_t tls_mem_base) override; + IMmu* CreateMmu(System& system) override; + IThread* CreateThread(WallClock& wall_clock, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, + vaddr_t tls_mem_base) override; IMemory* AllocateMemory(usize size) override; private: diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp index eae8467c..b733ce99 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.cpp @@ -13,8 +13,6 @@ #define KERNEL_RANGE_MEM_SIZE 0x1000000 */ -#define CPU (*static_cast(&CPU_INSTANCE)) - namespace hydra::hw::tegra_x1::cpu::hypervisor { namespace { @@ -77,7 +75,8 @@ void ReleasePageTableRegion(paddr_t addr) { } // namespace -Mmu::Mmu() : user_page_table(FindFreePageTableRegion()) { +Mmu::Mmu(System& system) + : IMmu(system), user_page_table(FindFreePageTableRegion()) { // Loader return address // TODO: this should be done in a backend agnostic way (perhaps in the // kernel?) diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp index 21700548..4791a91d 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/mmu.hpp @@ -11,7 +11,7 @@ constexpr uptr KERNEL_REGION_BASE = class Mmu : public IMmu { public: - Mmu(); + Mmu(System& system); ~Mmu() override; void Map(vaddr_t dst_va, Range range, diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp index dbfecb30..e3d8099d 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp @@ -7,8 +7,6 @@ #include "core/hw/tegra_x1/cpu/hypervisor/cpu.hpp" #include "core/hw/tegra_x1/cpu/hypervisor/mmu.hpp" #include "core/hw/wall_clock.hpp" - -#define CPU (*static_cast(&CPU_INSTANCE)) #define MMU (*static_cast(mmu)) namespace hydra::hw::tegra_x1::cpu::hypervisor { @@ -98,9 +96,10 @@ ENABLE_ENUM_FORMATTING( namespace hydra::hw::tegra_x1::cpu::hypervisor { -Thread::Thread(IMmu* mmu, const ThreadCallbacks& callbacks, IMemory* tls_mem, +Thread::Thread(WallClock& wall_clock, Cpu& cpu_, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, vaddr_t tls_mem_base) - : IThread(mmu, callbacks, tls_mem) { + : IThread(wall_clock, mmu, callbacks, tls_mem), cpu{cpu_} { // Create HV_ASSERT_SUCCESS(hv_vcpu_create(&vcpu, &exit, NULL)); @@ -118,7 +117,7 @@ Thread::Thread(IMmu* mmu, const ThreadCallbacks& callbacks, IMemory* tls_mem, SetSysReg(HV_SYS_REG_VBAR_EL1, KERNEL_REGION_BASE); SetSysReg(HV_SYS_REG_TTBR0_EL1, MMU.GetUserPageTable().GetBase()); - SetSysReg(HV_SYS_REG_TTBR1_EL1, CPU.GetKernelPageTable().GetBase()); + SetSysReg(HV_SYS_REG_TTBR1_EL1, cpu.GetKernelPageTable().GetBase()); // Setup TLS pointer SetSysReg(HV_SYS_REG_TPIDRRO_EL0, tls_mem_base); @@ -150,7 +149,7 @@ void Thread::Run() { // Run DeserializeState(); HV_ASSERT_SUCCESS(hv_vcpu_run(vcpu)); - exception = (GetReg(HV_REG_PC) >= CPU.GetKernelPageTable().GetBase()); + exception = (GetReg(HV_REG_PC) >= cpu.GetKernelPageTable().GetBase()); SerializeState(); // Handle exit @@ -340,7 +339,7 @@ void Thread::InstructionTrap(u32 esr) { state.r[rt] = GUEST_CNTFRQ; break; case 0b11'001'011'1110'00000'0000: // CNTPCT_EL0 - state.r[rt] = WallClock::GetInstance().GetCntpct(); + state.r[rt] = wall_clock.GetCntpct(); break; default: LOG_FATAL(Hypervisor, diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp index 6b8e65b6..380237b2 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/thread.hpp @@ -41,7 +41,8 @@ struct ThreadMessage { class Thread : public IThread { public: - Thread(IMmu* mmu, const ThreadCallbacks& callbacks, IMemory* tls_mem, + Thread(WallClock& wall_clock, Cpu& cpu_, IMmu* mmu, + const ThreadCallbacks& callbacks, IMemory* tls_mem, vaddr_t tls_mem_base); ~Thread() override; @@ -63,6 +64,8 @@ class Thread : public IThread { void SingleStep() override { SendMessage({ThreadMessageType::SingleStep}); } private: + Cpu& cpu; + hv_vcpu_t vcpu; hv_vcpu_exit_t* exit; bool exception{false}; diff --git a/src/core/hw/tegra_x1/cpu/mmu.cpp b/src/core/hw/tegra_x1/cpu/mmu.cpp index 0c4a3ce3..7f7db183 100644 --- a/src/core/hw/tegra_x1/cpu/mmu.cpp +++ b/src/core/hw/tegra_x1/cpu/mmu.cpp @@ -1,6 +1,6 @@ #include "core/hw/tegra_x1/cpu/mmu.hpp" -#include "core/hw/tegra_x1/gpu/gpu.hpp" +#include "core/system.hpp" namespace hydra::hw::tegra_x1::cpu { @@ -75,7 +75,7 @@ bool IMmu::TrackWrite(Range range) { // Notify the GPU // TODO: what about non-contiguous regions? const auto ptr = UnmapAddr(aligned_range.GetBegin()); - RENDERER_INSTANCE.InvalidateMemory( + system.GetGpu().GetRenderer().InvalidateMemory( Range::FromSize(ptr, aligned_range.GetSize())); { diff --git a/src/core/hw/tegra_x1/cpu/mmu.hpp b/src/core/hw/tegra_x1/cpu/mmu.hpp index 80637a04..b726d48e 100644 --- a/src/core/hw/tegra_x1/cpu/mmu.hpp +++ b/src/core/hw/tegra_x1/cpu/mmu.hpp @@ -5,6 +5,10 @@ #include "core/horizon/kernel/const.hpp" #include "core/hw/tegra_x1/cpu/memory.hpp" +namespace hydra { +class System; +} + namespace hydra::hw::tegra_x1::cpu { struct MemoryRegion { @@ -17,6 +21,7 @@ struct MemoryRegion { // each process has its own class IMmu { public: + IMmu(System& system_) : system{system_} {} virtual ~IMmu() = default; virtual void Map(vaddr_t dst_va, Range range, @@ -103,6 +108,8 @@ class IMmu { virtual void ResumeWriteTracking(Range range) = 0; private: + System& system; + std::mutex write_tracking_mutex; std::vector> tracked_pages; }; diff --git a/src/core/hw/tegra_x1/cpu/thread.hpp b/src/core/hw/tegra_x1/cpu/thread.hpp index f4c1dbc8..c39ac210 100644 --- a/src/core/hw/tegra_x1/cpu/thread.hpp +++ b/src/core/hw/tegra_x1/cpu/thread.hpp @@ -2,6 +2,10 @@ #include "core/hw/tegra_x1/cpu/const.hpp" +namespace hydra::hw { +class WallClock; +} + namespace hydra::hw::tegra_x1::cpu { class IMemory; @@ -31,8 +35,10 @@ struct ThreadState { class IThread { public: - IThread(IMmu* mmu_, const ThreadCallbacks& callbacks_, IMemory* tls_mem_) - : mmu{mmu_}, callbacks{callbacks_}, tls_mem{tls_mem_} {} + IThread(WallClock& wall_clock_, IMmu* mmu_, + const ThreadCallbacks& callbacks_, IMemory* tls_mem_) + : wall_clock{wall_clock_}, mmu{mmu_}, callbacks{callbacks_}, + tls_mem{tls_mem_} {} virtual ~IThread() {} virtual void Run() = 0; @@ -51,6 +57,7 @@ class IThread { IMemory* GetTlsMemory() const { return tls_mem; } protected: + WallClock& wall_clock; IMmu* mmu; ThreadCallbacks callbacks; IMemory* tls_mem; diff --git a/src/core/hw/tegra_x1/gpu/engines/2d.cpp b/src/core/hw/tegra_x1/gpu/engines/2d.cpp index e0203501..7e060cbf 100644 --- a/src/core/hw/tegra_x1/gpu/engines/2d.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/2d.cpp @@ -27,13 +27,13 @@ void TwoD::Copy(const u32 index, const u32 pixels_from_memory_src_y0_int) { const auto src_width = static_cast(pixels.dst_width * dudx); const auto src_height = static_cast(pixels.dst_height * dvdy); - dst->BlitFrom(tls_crnt_command_buffer, src, - {static_cast(src_x0), static_cast(src_y0), 0.0f}, - {src_width, src_height, 1}, 0, regs.src.layer, - {static_cast(pixels.dst_x0), - static_cast(pixels.dst_y0), 0.0f}, - {pixels.dst_width, pixels.dst_height, 1}, 0, regs.dst.layer, - 1, 1); + gpu.GetRenderer().BlitTexture( + tls_crnt_command_buffer, src, + {static_cast(src_x0), static_cast(src_y0), 0.0f}, + {src_width, src_height, 1}, 0, regs.src.layer, dst, + {static_cast(pixels.dst_x0), static_cast(pixels.dst_y0), + 0.0f}, + {pixels.dst_width, pixels.dst_height, 1}, 0, regs.dst.layer, 1, 1); } #pragma GCC diagnostic pop @@ -48,7 +48,7 @@ renderer::ITextureView* TwoD::GetTexture(const Texture2DInfo& info, info.height, 1, 1, info.depth, 0x0, 0x0, 0x0 // HACK ); - return RENDERER_INSTANCE.GetTextureCache().Find(tls_crnt_command_buffer, + return gpu.GetRenderer().GetTextureCache().Find(tls_crnt_command_buffer, descriptor, usage); } diff --git a/src/core/hw/tegra_x1/gpu/engines/2d.hpp b/src/core/hw/tegra_x1/gpu/engines/2d.hpp index 936bc076..fc0a486a 100644 --- a/src/core/hw/tegra_x1/gpu/engines/2d.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/2d.hpp @@ -3,6 +3,10 @@ #include "core/hw/tegra_x1/gpu/engines/engine_base.hpp" #include "core/hw/tegra_x1/gpu/renderer/const.hpp" +namespace hydra::hw::tegra_x1::gpu { +class Gpu; +} + namespace hydra::hw::tegra_x1::gpu::renderer { class ITextureView; } @@ -71,15 +75,19 @@ struct Regs2D { class TwoD : public EngineWithRegsBase { public: + TwoD(Gpu& gpu_) : gpu{gpu_} {} + void Method(u32 method, u32 arg) override; private: + Gpu& gpu; + // Commands void Copy(const u32 index, const u32 pixels_from_memory_src_y0_int); // Helpers - static renderer::ITextureView* GetTexture(const Texture2DInfo& info, - renderer::TextureUsage usage); + renderer::ITextureView* GetTexture(const Texture2DInfo& info, + renderer::TextureUsage usage); }; } // namespace hydra::hw::tegra_x1::gpu::engines diff --git a/src/core/hw/tegra_x1/gpu/engines/3d.cpp b/src/core/hw/tegra_x1/gpu/engines/3d.cpp index 60b8cd0b..4f301663 100644 --- a/src/core/hw/tegra_x1/gpu/engines/3d.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/3d.cpp @@ -14,6 +14,11 @@ namespace hydra::hw::tegra_x1::gpu::engines { namespace { +macro::DriverBase* CreateMacroDriver(ThreeD& three_d) { + // TODO: choose based on Macro backend + return new macro::interpreter::Driver(three_d); +} + u32 get_image_handle(u32 handle) { return extract_bits(handle, 0, 20); } u32 get_sampler_handle(u32 handle) { return extract_bits(handle, 20, 12); } @@ -216,14 +221,7 @@ DEFINE_METHOD_TABLE(ThreeD, INLINE_ENGINE_TABLE, 0x45, 1, 1, FirmwareCall4, u32, 0x8e4, 16, LoadConstBuffer, u32, 0x900, 5 * 8, BindGroup, u32) -SINGLETON_DEFINE_GET_INSTANCE(ThreeD, Engines) - -ThreeD::ThreeD() { - SINGLETON_SET_INSTANCE(ThreeD, Engines); - - // TODO: choose based on Macro backend - { macro_driver = new macro::interpreter::Driver(this); } - +ThreeD::ThreeD(Gpu& gpu_) : gpu{gpu_}, macro_driver{CreateMacroDriver(*this)} { // Initialize default state // Viewports @@ -247,12 +245,6 @@ ThreeD::ThreeD() { true; } -ThreeD::~ThreeD() { - delete macro_driver; - - SINGLETON_UNSET_INSTANCE(); -} - void ThreeD::FlushMacro() { macro_driver->Execute(); } void ThreeD::Macro(u32 method, u32 arg) { @@ -293,27 +285,27 @@ void ThreeD::DrawVertexArray(const u32 index, u32 count) { auto index_type = IndexType::None; auto primitive_type = regs.begin.primitive_type; - const auto index_buffer = RENDERER_INSTANCE.GetIndexCache().Decode( + const auto index_buffer = gpu.GetRenderer().GetIndexCache().Decode( tls_crnt_command_buffer, {.type = index_type, .primitive_type = primitive_type, .count = count}, index_type, primitive_type, count); if (index_buffer.GetBase()) { // Bind index buffer - RENDERER_INSTANCE.BindIndexBuffer(index_buffer, index_type); + gpu.GetRenderer().BindIndexBuffer(index_buffer, index_type); // Draw // Vertex start is set as vertex base instead, as start is now index // start // TODO: instance count - RENDERER_INSTANCE.DrawIndexed(tls_crnt_command_buffer, primitive_type, + gpu.GetRenderer().DrawIndexed(tls_crnt_command_buffer, primitive_type, 0, count, regs.vertex_array_start, regs.base_instance, 1); } else { // Draw // TODO: instance count - RENDERER_INSTANCE.Draw(tls_crnt_command_buffer, primitive_type, + gpu.GetRenderer().Draw(tls_crnt_command_buffer, primitive_type, regs.vertex_array_start, count, regs.base_instance, 1); } @@ -336,7 +328,7 @@ void ThreeD::DrawVertexElements(const u32 index, u32 count) { auto index_type = regs.index_type; auto primitive_type = regs.begin.primitive_type; - const auto index_buffer = RENDERER_INSTANCE.GetIndexCache().Decode( + const auto index_buffer = gpu.GetRenderer().GetIndexCache().Decode( tls_crnt_command_buffer, {.type = index_type, .primitive_type = primitive_type, @@ -346,11 +338,11 @@ void ThreeD::DrawVertexElements(const u32 index, u32 count) { // Bind index buffer ASSERT_DEBUG(index_buffer.GetBase(), Gpu, "Index buffer not found"); - RENDERER_INSTANCE.BindIndexBuffer(index_buffer, index_type); + gpu.GetRenderer().BindIndexBuffer(index_buffer, index_type); // Draw // TODO: instance count - RENDERER_INSTANCE.DrawIndexed(tls_crnt_command_buffer, primitive_type, + gpu.GetRenderer().DrawIndexed(tls_crnt_command_buffer, primitive_type, regs.vertex_elements_start, count, regs.base_vertex, regs.base_instance, 1); } @@ -368,21 +360,21 @@ void ThreeD::ClearBuffer(const u32 index, const ClearBufferData data) { // Regular clear { std::lock_guard texture_cache_lock( - RENDERER_INSTANCE.GetTextureCache().GetMutex()); - RENDERER_INSTANCE.BindRenderPass(GetRenderPass()); + gpu.GetRenderer().GetTextureCache().GetMutex()); + gpu.GetRenderer().BindRenderPass(GetRenderPass()); } if (data.color_mask != 0x0) - RENDERER_INSTANCE.ClearColor(tls_crnt_command_buffer, data.target_id, + gpu.GetRenderer().ClearColor(tls_crnt_command_buffer, data.target_id, data.layer_id, data.color_mask, regs.clear_color); if (data.depth) - RENDERER_INSTANCE.ClearDepth(tls_crnt_command_buffer, data.layer_id, + gpu.GetRenderer().ClearDepth(tls_crnt_command_buffer, data.layer_id, regs.clear_depth); if (data.stencil) - RENDERER_INSTANCE.ClearStencil(tls_crnt_command_buffer, data.layer_id, + gpu.GetRenderer().ClearStencil(tls_crnt_command_buffer, data.layer_id, regs.clear_stencil); } @@ -412,7 +404,7 @@ void ThreeD::LoadConstBuffer(const u32 index, const u32 data) { // Invalidate // TODO: invalidate as a whole - RENDERER_INSTANCE.InvalidateMemory(Range::FromSize(ptr, sizeof(u32))); + gpu.GetRenderer().InvalidateMemory(Range::FromSize(ptr, sizeof(u32))); } void ThreeD::BindGroup(const u32 index, const u32 data) { @@ -496,7 +488,7 @@ ThreeD::GetColorTargetTexture(u32 render_target_index) const { render_target.tile_mode.depth, !is_linear ? render_target.layer_stride * 4 : 0); - return RENDERER_INSTANCE.GetTextureCache().Find( + return gpu.GetRenderer().GetTextureCache().Find( tls_crnt_command_buffer, descriptor, renderer::TextureUsage::Write); } @@ -520,7 +512,7 @@ renderer::ITextureView* ThreeD::GetDepthStencilTargetTexture() const { regs.depth_target_tile_mode.height, regs.depth_target_tile_mode.depth, regs.depth_target_layer_stride * 4); - return RENDERER_INSTANCE.GetTextureCache().Find( + return gpu.GetRenderer().GetTextureCache().Find( tls_crnt_command_buffer, descriptor, renderer::TextureUsage::Write); } @@ -541,18 +533,18 @@ renderer::RenderPassBase* ThreeD::GetRenderPass() const { : nullptr), }; - return RENDERER_INSTANCE.GetRenderPassCache().Find(descriptor); + return gpu.GetRenderer().GetRenderPassCache().Find(descriptor); } renderer::Viewport ThreeD::GetViewport(u32 index) { renderer::Viewport res; - const auto& extent = REGS_3D.viewports[index]; - const auto& transform = REGS_3D.viewport_transforms[index]; - if (/*REGS_3D.viewport_transform_enabled*/ true) { // HACK + const auto& extent = regs.viewports[index]; + const auto& transform = regs.viewport_transforms[index]; + if (/*regs.viewport_transform_enabled*/ true) { // HACK auto scale_x = transform.scale_x; auto scale_y = transform.scale_y; - if (any(REGS_3D.window_origin_flags & + if (any(regs.window_origin_flags & engines::WindowOriginFlags::LowerLeft)) scale_y = -scale_y; @@ -587,7 +579,7 @@ renderer::Viewport ThreeD::GetViewport(u32 index) { res.depth_near = extent.near; res.depth_far = extent.far; } else { - const auto& screen_scissor = REGS_3D.screen_scissor; + const auto& screen_scissor = regs.screen_scissor; res.rect.origin.x() = screen_scissor.horizontal.x; res.rect.origin.y() = screen_scissor.vertical.y; res.rect.size.x() = screen_scissor.horizontal.width; @@ -612,7 +604,7 @@ renderer::Viewport ThreeD::GetViewport(u32 index) { } renderer::Scissor ThreeD::GetScissor(u32 index) { - const auto& scissor = REGS_3D.scissors[index]; + const auto& scissor = regs.scissors[index]; if (scissor.enabled) { return renderer::Scissor( uint2({scissor.horizontal.min, scissor.vertical.min}), @@ -659,7 +651,7 @@ renderer::ShaderBase* ThreeD::GetShader(ShaderStage stage) { } auto& active_shader = active_shaders[u32(to_renderer_shader_type(stage))]; - active_shader = RENDERER_INSTANCE.GetShaderCache().Find(descriptor); + active_shader = gpu.GetRenderer().GetShaderCache().Find(descriptor); return active_shader; } @@ -750,7 +742,7 @@ renderer::PipelineBase* ThreeD::GetPipeline() { } } - return RENDERER_INSTANCE.GetPipelineCache().Find(descriptor); + return gpu.GetRenderer().GetPipelineCache().Find(descriptor); } renderer::BufferView ThreeD::GetVertexBuffer(u32 vertex_array_index) const { @@ -765,7 +757,7 @@ renderer::BufferView ThreeD::GetVertexBuffer(u32 vertex_array_index) const { const auto ptr = tls_crnt_gmmu->UnmapAddr(vertex_array.addr); const auto size = u64(regs.vertex_array_limits[vertex_array_index]) + 1 - u64(vertex_array.addr); - return RENDERER_INSTANCE.GetBufferCache().Get( + return gpu.GetRenderer().GetBufferCache().Get( tls_crnt_command_buffer, Range::FromSize(ptr, size)); } @@ -824,7 +816,7 @@ ThreeD::GetTexture(const TextureImageControl& tic) const { format, tic.format_word.swizzle_x, tic.format_word.swizzle_y, tic.format_word.swizzle_z, tic.format_word.swizzle_w)); - return RENDERER_INSTANCE.GetTextureCache().Find( + return gpu.GetRenderer().GetTextureCache().Find( tls_crnt_command_buffer, descriptor, view_descriptor, renderer::TextureUsage::Read); } @@ -848,7 +840,7 @@ ThreeD::GetSampler(const TextureSamplerControl& tsc) const { tsc.border_color_b, tsc.border_color_a}), }; - return RENDERER_INSTANCE.GetSamplerCache().Find(descriptor); + return gpu.GetRenderer().GetSamplerCache().Find(descriptor); } void ThreeD::ConfigureShaderStage( @@ -862,7 +854,7 @@ void ThreeD::ConfigureShaderStage( const auto& resource_mapping = shader->GetDescriptor().resource_mapping; // Uniform buffers - RENDERER_INSTANCE.UnbindUniformBuffers(shader_type); + gpu.GetRenderer().UnbindUniformBuffers(shader_type); for (u32 i = 0; i < CONST_BUFFER_BINDING_COUNT; i++) { const auto index = resource_mapping.uniform_buffers[i]; if (index == invalid()) @@ -875,16 +867,16 @@ void ThreeD::ConfigureShaderStage( continue; } - const auto buffer = RENDERER_INSTANCE.GetBufferCache().Get( + const auto buffer = gpu.GetRenderer().GetBufferCache().Get( tls_crnt_command_buffer, range); - RENDERER_INSTANCE.BindUniformBuffer(buffer, shader_type, index); + gpu.GetRenderer().BindUniformBuffer(buffer, shader_type, index); } // TODO: storage buffers // Textures if (tex_header_pool && tex_sampler_pool) { - RENDERER_INSTANCE.UnbindTextures(shader_type); + gpu.GetRenderer().UnbindTextures(shader_type); auto tex_const_buffer = reinterpret_cast( bound_const_buffers[stage_index] [regs.bindless_texture_const_buffer_slot] @@ -904,7 +896,7 @@ void ThreeD::ConfigureShaderStage( const auto sampler = GetSampler(tsc); if (texture && sampler) - RENDERER_INSTANCE.BindTexture(texture, sampler, shader_type, + gpu.GetRenderer().BindTexture(texture, sampler, shader_type, renderer_index); } } @@ -912,7 +904,7 @@ void ThreeD::ConfigureShaderStage( bool ThreeD::DrawInternal() { std::lock_guard texture_cache_lock( - RENDERER_INSTANCE.GetTextureCache().GetMutex()); + gpu.GetRenderer().GetTextureCache().GetMutex()); // Flush tracked pages tls_crnt_gmmu->GetMmu()->FlushTrackedPages(); @@ -924,26 +916,29 @@ bool ThreeD::DrawInternal() { return false; } - RENDERER_INSTANCE.BindRenderPass(GetRenderPass()); + gpu.GetRenderer().BindRenderPass(GetRenderPass()); + gpu.GetRenderer().BindPipeline(GetPipeline()); + + gpu.GetRenderer().SetDepthTestEnabled(regs.depth_test_enabled); + gpu.GetRenderer().SetDepthWriteEnabled(regs.depth_write_enabled); + gpu.GetRenderer().SetDepthCompareOp(regs.depth_compare_op); for (u32 i = 0; i < VIEWPORT_COUNT; i++) { - RENDERER_INSTANCE.SetViewport(i, GetViewport(i)); - RENDERER_INSTANCE.SetScissor(i, GetScissor(i)); + gpu.GetRenderer().SetViewport(i, GetViewport(i)); + gpu.GetRenderer().SetScissor(i, GetScissor(i)); } - RENDERER_INSTANCE.BindPipeline(GetPipeline()); - for (u32 i = 0; i < VERTEX_ARRAY_COUNT; i++) { const auto& vertex_array = regs.vertex_arrays[i]; // HACK: Super Meat Boy contains invalid vertex arrays with address 4096 if (!vertex_array.config.enable || (vertex_array.addr.hi == 0 && vertex_array.addr.lo == 4096)) { - RENDERER_INSTANCE.BindVertexBuffer(renderer::BufferView(), i); + gpu.GetRenderer().BindVertexBuffer(renderer::BufferView(), i); continue; } const auto buffer = GetVertexBuffer(i); - RENDERER_INSTANCE.BindVertexBuffer(buffer, i); + gpu.GetRenderer().BindVertexBuffer(buffer, i); } // Configure stages diff --git a/src/core/hw/tegra_x1/gpu/engines/3d.hpp b/src/core/hw/tegra_x1/gpu/engines/3d.hpp index 275d68d6..5aa17939 100644 --- a/src/core/hw/tegra_x1/gpu/engines/3d.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/3d.hpp @@ -1,14 +1,9 @@ #pragma once #include "core/hw/tegra_x1/gpu/engines/inline_base.hpp" +#include "core/hw/tegra_x1/gpu/macro/driver_base.hpp" #include "core/hw/tegra_x1/gpu/renderer/buffer_view.hpp" -#define REGS_3D engines::ThreeD::GetInstance().GetRegs() - -namespace hydra::hw::tegra_x1::gpu::macro { -class DriverBase; -} - namespace hydra::hw::tegra_x1::gpu::renderer { class ITextureView; class SamplerBase; @@ -553,10 +548,7 @@ struct Regs3D { class ThreeD : public EngineWithRegsBase, public InlineBase { public: - static ThreeD& GetInstance(); - - ThreeD(); - ~ThreeD() override; + ThreeD(Gpu& gpu_); void Method(u32 method, u32 arg) override; @@ -569,8 +561,10 @@ class ThreeD : public EngineWithRegsBase, public InlineBase { void Macro(u32 method, u32 arg) override; private: + Gpu& gpu; + // Macros - macro::DriverBase* macro_driver; + std::unique_ptr macro_driver; // Active state (for quick access) renderer::ShaderBase* active_shaders[static_cast( diff --git a/src/core/hw/tegra_x1/gpu/engines/compute.hpp b/src/core/hw/tegra_x1/gpu/engines/compute.hpp index c708932f..c3323b08 100644 --- a/src/core/hw/tegra_x1/gpu/engines/compute.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/compute.hpp @@ -12,9 +12,13 @@ struct RegsCompute { class Compute : public EngineWithRegsBase, public InlineBase { public: + Compute(Gpu& gpu_) : gpu{gpu_} {} + void Method(u32 method, u32 arg) override; private: + Gpu& gpu; + // Methods DEFINE_INLINE_ENGINE_METHODS; }; diff --git a/src/core/hw/tegra_x1/gpu/engines/copy.cpp b/src/core/hw/tegra_x1/gpu/engines/copy.cpp index c60137ee..ffe42dc9 100644 --- a/src/core/hw/tegra_x1/gpu/engines/copy.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/copy.cpp @@ -46,7 +46,7 @@ void Copy::LaunchDMA(const u32 index, const LaunchDMAData data) { regs.stride_in); // Invalidate - RENDERER_INSTANCE.GetBufferCache().InvalidateMemory( + gpu.GetRenderer().GetBufferCache().InvalidateMemory( Range::FromSize(dst_ptr, regs.line_count * regs.stride_out)); } else { @@ -71,7 +71,7 @@ void Copy::LaunchDMA(const u32 index, const LaunchDMAData data) { } // Invalidate - RENDERER_INSTANCE.GetTextureCache().InvalidateMemory( + gpu.GetRenderer().GetTextureCache().InvalidateMemory( Range(dst_ptr, regs.stride_in * regs.line_count)); } diff --git a/src/core/hw/tegra_x1/gpu/engines/copy.hpp b/src/core/hw/tegra_x1/gpu/engines/copy.hpp index 306350cc..171786bb 100644 --- a/src/core/hw/tegra_x1/gpu/engines/copy.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/copy.hpp @@ -2,6 +2,10 @@ #include "core/hw/tegra_x1/gpu/engines/engine_base.hpp" +namespace hydra::hw::tegra_x1::gpu { +class Gpu; +} // namespace hydra::hw::tegra_x1::gpu + namespace hydra::hw::tegra_x1::gpu::renderer { class BufferBase; } // namespace hydra::hw::tegra_x1::gpu::renderer @@ -117,9 +121,13 @@ struct RegsCopy { class Copy : public EngineWithRegsBase { public: + Copy(Gpu& gpu_) : gpu{gpu_} {} + void Method(u32 method, u32 arg) override; private: + Gpu& gpu; + // Commands struct LaunchDMAData { TransferType type : 2; diff --git a/src/core/hw/tegra_x1/gpu/engines/inline.hpp b/src/core/hw/tegra_x1/gpu/engines/inline.hpp index 7d5471af..1edf4623 100644 --- a/src/core/hw/tegra_x1/gpu/engines/inline.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/inline.hpp @@ -10,9 +10,13 @@ struct RegsInline_ { class Inline : public EngineWithRegsBase, public InlineBase { public: + Inline(Gpu& gpu_) : gpu{gpu_} {} + void Method(u32 method, u32 arg) override; private: + Gpu& gpu; + // Methods DEFINE_INLINE_ENGINE_METHODS; }; diff --git a/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp b/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp index 5c1b935c..32bc9bd2 100644 --- a/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp +++ b/src/core/hw/tegra_x1/gpu/engines/inline_base.cpp @@ -8,12 +8,12 @@ namespace hydra::hw::tegra_x1::gpu::engines { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" -void InlineBase::LaunchDMAImpl(RegsInline& regs, const u32 index, +void InlineBase::LaunchDMAImpl(Gpu& gpu, RegsInline& regs, const u32 index, const u32 data) { LOG_FUNC_WITH_ARGS_STUBBED(Engines, "index: {}, data: {:#x}", index, data); } -void InlineBase::LoadInlineDataImpl(RegsInline& regs, const u32 index, +void InlineBase::LoadInlineDataImpl(Gpu& gpu, RegsInline& regs, const u32 index, const u32 data) { inline_data.push_back(data); // TODO: correct? @@ -36,7 +36,7 @@ void InlineBase::LoadInlineDataImpl(RegsInline& regs, const u32 index, inline_data.clear(); // Invalidate - RENDERER_INSTANCE.InvalidateMemory( + gpu.GetRenderer().InvalidateMemory( Range::FromSize(dst_ptr, inline_data.size() * sizeof(u32))); } } diff --git a/src/core/hw/tegra_x1/gpu/engines/inline_base.hpp b/src/core/hw/tegra_x1/gpu/engines/inline_base.hpp index 6fda725f..b3abbf94 100644 --- a/src/core/hw/tegra_x1/gpu/engines/inline_base.hpp +++ b/src/core/hw/tegra_x1/gpu/engines/inline_base.hpp @@ -6,12 +6,16 @@ 0x6c, 1, LaunchDMA, u32, 0x6d, 1, LoadInlineData, u32 #define DEFINE_INLINE_ENGINE_METHODS \ void LaunchDMA(const u32 index, const u32 data) { \ - LaunchDMAImpl(regs.regs_inline, index, data); \ + LaunchDMAImpl(gpu, regs.regs_inline, index, data); \ } \ void LoadInlineData(const u32 index, const u32 data) { \ - LoadInlineDataImpl(regs.regs_inline, index, data); \ + LoadInlineDataImpl(gpu, regs.regs_inline, index, data); \ } +namespace hydra::hw::tegra_x1::gpu { +class Gpu; +} + namespace hydra::hw::tegra_x1::gpu::engines { struct RegsInline { @@ -36,8 +40,10 @@ struct RegsInline { class InlineBase { protected: // Commands - void LaunchDMAImpl(RegsInline& regs, const u32 index, const u32 data); - void LoadInlineDataImpl(RegsInline& regs, const u32 index, const u32 data); + void LaunchDMAImpl(Gpu& gpu, RegsInline& regs, const u32 index, + const u32 data); + void LoadInlineDataImpl(Gpu& gpu, RegsInline& regs, const u32 index, + const u32 data); private: std::vector inline_data; diff --git a/src/core/hw/tegra_x1/gpu/gpu.cpp b/src/core/hw/tegra_x1/gpu/gpu.cpp index 216f0337..17cdb048 100644 --- a/src/core/hw/tegra_x1/gpu/gpu.cpp +++ b/src/core/hw/tegra_x1/gpu/gpu.cpp @@ -8,34 +8,27 @@ namespace hydra::hw::tegra_x1::gpu { namespace { -struct SetObjectArg { - u32 class_id : 16; - u32 engine_id : 5; -}; - -} // namespace - -SINGLETON_DEFINE_GET_INSTANCE(Gpu, Gpu) - -Gpu::Gpu() { - SINGLETON_SET_INSTANCE(Gpu, Gpu); - +renderer::IRenderer* CreateRenderer() { const auto renderer_type = CONFIG_INSTANCE.GetGpuRenderer(); switch (renderer_type) { case GpuRenderer::Metal: - renderer = new renderer::metal::Renderer(); - break; + return new renderer::metal::Renderer(); default: LOG_FATAL(Gpu, "Unknown Gpu renderer {}", renderer_type); - break; } } -Gpu::~Gpu() { - delete renderer; +struct SetObjectArg { + u32 class_id : 16; + u32 engine_id : 5; +}; + +} // namespace - SINGLETON_UNSET_INSTANCE(); -} +Gpu::Gpu() + : pfifo(*this), three_d_engine(*this), compute_engine(*this), + inline_engine(*this), two_d_engine(*this), + copy_engine(*this), renderer{CreateRenderer()} {} void Gpu::SubchannelMethod(u32 subchannel, u32 method, u32 arg) { if (method == 0x0) { // SetEngine diff --git a/src/core/hw/tegra_x1/gpu/gpu.hpp b/src/core/hw/tegra_x1/gpu/gpu.hpp index be690c61..1b162faf 100644 --- a/src/core/hw/tegra_x1/gpu/gpu.hpp +++ b/src/core/hw/tegra_x1/gpu/gpu.hpp @@ -7,10 +7,7 @@ #include "core/hw/tegra_x1/gpu/engines/copy.hpp" #include "core/hw/tegra_x1/gpu/engines/inline.hpp" #include "core/hw/tegra_x1/gpu/pfifo.hpp" -#include "core/hw/tegra_x1/gpu/renderer/renderer_base.hpp" - -#define GPU_INSTANCE hw::tegra_x1::gpu::Gpu::GetInstance() -#define RENDERER_INSTANCE GPU_INSTANCE.GetRenderer() +#include "core/hw/tegra_x1/gpu/renderer/renderer.hpp" namespace hydra::hw::tegra_x1::cpu { class IMmu; @@ -37,10 +34,7 @@ inline thread_local renderer::ICommandBuffer* tls_crnt_command_buffer = nullptr; class Gpu { public: - static Gpu& GetInstance(); - Gpu(); - ~Gpu(); // Memory map u32 CreateMap(usize size) { @@ -100,7 +94,7 @@ class Gpu { // Getters Pfifo& GetPfifo() { return pfifo; } - renderer::RendererBase& GetRenderer() const { return *renderer; } + renderer::IRenderer& GetRenderer() const { return *renderer.get(); } private: // Pfifo @@ -115,7 +109,7 @@ class Gpu { engines::EngineBase* subchannels[SUBCHANNEL_COUNT] = {nullptr}; // Renderer - renderer::RendererBase* renderer; + std::unique_ptr renderer; // Memory DynamicPool memory_maps; diff --git a/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp b/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp index ba2eb2c3..ded23df8 100644 --- a/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp +++ b/src/core/hw/tegra_x1/gpu/macro/driver_base.cpp @@ -121,7 +121,7 @@ bool DriverBase::ParseInstruction(u32 pc) { return pc == exit_after; } -u32 DriverBase::Get3DReg(u32 reg_3d) { return engine_3d->GetReg(reg_3d); } +u32 DriverBase::Get3DReg(u32 reg_3d) { return engine_3d.GetReg(reg_3d); } void DriverBase::SetMethod(u32 value) { method = value & 0xfff; @@ -129,7 +129,7 @@ void DriverBase::SetMethod(u32 value) { } void DriverBase::Send(u32 arg) { - engine_3d->Method(method, arg); + engine_3d.Method(method, arg); method += increment; } diff --git a/src/core/hw/tegra_x1/gpu/macro/driver_base.hpp b/src/core/hw/tegra_x1/gpu/macro/driver_base.hpp index 00e1babc..dbcb531e 100644 --- a/src/core/hw/tegra_x1/gpu/macro/driver_base.hpp +++ b/src/core/hw/tegra_x1/gpu/macro/driver_base.hpp @@ -19,7 +19,7 @@ struct result_t { class DriverBase { public: - DriverBase(engines::ThreeD* engine_3d_) : engine_3d{engine_3d_} {} + DriverBase(engines::ThreeD& engine_3d_) : engine_3d{engine_3d_} {} virtual ~DriverBase() = default; void Execute(); @@ -62,7 +62,7 @@ class DriverBase { void Send(u32 arg); private: - engines::ThreeD* engine_3d; + engines::ThreeD& engine_3d; // Memory u32 instruction_ram[0x1000] = {0}; // TODO: what should be the size? diff --git a/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.hpp b/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.hpp index 89da8b02..5cb82c8f 100644 --- a/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.hpp +++ b/src/core/hw/tegra_x1/gpu/macro/interpreter/driver.hpp @@ -6,7 +6,7 @@ namespace hydra::hw::tegra_x1::gpu::macro::interpreter { class Driver : public DriverBase { public: - Driver(engines::ThreeD* engine_3d) : DriverBase(engine_3d) {} + Driver(engines::ThreeD& engine_3d) : DriverBase(engine_3d) {} protected: void ExecuteImpl(u32 pc_, u32 param1) override; diff --git a/src/core/hw/tegra_x1/gpu/pfifo.cpp b/src/core/hw/tegra_x1/gpu/pfifo.cpp index 9c773e5a..aa46ec24 100644 --- a/src/core/hw/tegra_x1/gpu/pfifo.cpp +++ b/src/core/hw/tegra_x1/gpu/pfifo.cpp @@ -69,7 +69,7 @@ T Read(uptr& gpu_addr) { } // namespace -Pfifo::Pfifo() : thread(&Pfifo::ThreadFunc, this) {} +Pfifo::Pfifo(Gpu& gpu_) : gpu{gpu_}, thread(&Pfifo::ThreadFunc, this) {} Pfifo::~Pfifo() { stop = true; @@ -111,7 +111,7 @@ void Pfifo::ThreadFunc() { // Entries // TODO: flags tls_crnt_gmmu = &entry_list.gmmu; - tls_crnt_command_buffer = RENDERER_INSTANCE.CreateCommandBuffer(); + tls_crnt_command_buffer = gpu.GetRenderer().CreateCommandBuffer(); for (const auto& entry : entry_list.entries) SubmitEntry(entry); delete tls_crnt_command_buffer; @@ -192,8 +192,7 @@ bool Pfifo::SubmitCommand(uptr& gpu_addr) { ProcessMethodArg(header.subchannel, gpu_addr, offset, false); break; case SecondaryOpcode::ImmDataMethod: - Gpu::GetInstance().SubchannelMethod(header.subchannel, offset, - header.arg); + gpu.SubchannelMethod(header.subchannel, offset, header.arg); break; case SecondaryOpcode::OneInc: for (u32 i = 0; i < header.arg; i++) @@ -208,7 +207,7 @@ bool Pfifo::SubmitCommand(uptr& gpu_addr) { // TODO: is it okay to prefetch the parameters and then execute the // macro? if (header.method >= MACRO_METHODS_REGION) - Gpu::GetInstance().SubchannelFlushMacro(header.subchannel); + gpu.SubchannelFlushMacro(header.subchannel); return true; } @@ -216,7 +215,7 @@ bool Pfifo::SubmitCommand(uptr& gpu_addr) { void Pfifo::ProcessMethodArg(u32 subchannel, uptr& gpu_addr, u32& method, bool increment) { u32 arg = Read(gpu_addr); - Gpu::GetInstance().SubchannelMethod(subchannel, method, arg); + gpu.SubchannelMethod(subchannel, method, arg); if (increment) method++; } diff --git a/src/core/hw/tegra_x1/gpu/pfifo.hpp b/src/core/hw/tegra_x1/gpu/pfifo.hpp index eb81f439..10d2167b 100644 --- a/src/core/hw/tegra_x1/gpu/pfifo.hpp +++ b/src/core/hw/tegra_x1/gpu/pfifo.hpp @@ -9,7 +9,7 @@ class IMmu; namespace hydra::hw::tegra_x1::gpu { -class GMmu; +class Gpu; struct GpfifoEntryList { GMmu& gmmu; @@ -19,13 +19,15 @@ struct GpfifoEntryList { class Pfifo { public: - Pfifo(); + Pfifo(Gpu& gpu_); ~Pfifo(); void SubmitEntries(GMmu& gmmu, std::span entries, GpfifoFlags flags); private: + Gpu& gpu; + std::mutex mutex; std::condition_variable cond_var; diff --git a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp index 8f7e2e47..d1a93fc7 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.cpp @@ -25,7 +25,7 @@ BufferView BufferCache::Get(ICommandBuffer* command_buffer, Range range) { } } else { // Create new buffer - entry.buffer = RENDERER_INSTANCE.CreateBuffer(entry.range.GetSize()); + entry.buffer = renderer.CreateBuffer(entry.range.GetSize()); UpdateRange(command_buffer, entry, entry.range); } @@ -66,13 +66,12 @@ void BufferCache::UpdateRange(ICommandBuffer* command_buffer, entry.inline_copy = false; } else { // Copy from a temporary buffer - auto tmp_buffer = - RENDERER_INSTANCE.AllocateTemporaryBuffer(range.GetSize()); + auto tmp_buffer = renderer.AllocateTemporaryBuffer(range.GetSize()); tmp_buffer->CopyFrom(range.GetBegin()); entry.buffer->CopyFrom(command_buffer, tmp_buffer, range.GetBegin() - entry.range.GetBegin(), 0, range.GetSize()); - RENDERER_INSTANCE.FreeTemporaryBuffer(tmp_buffer); + renderer.FreeTemporaryBuffer(tmp_buffer); } } diff --git a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp index de7d95b7..88c7ef47 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/buffer_cache.hpp @@ -8,6 +8,8 @@ class IMmu; namespace hydra::hw::tegra_x1::gpu::renderer { +class IRenderer; + // TODO: also release the buffer struct BufferEntry { BufferBase* buffer{nullptr}; @@ -19,6 +21,7 @@ struct BufferEntry { // TODO: optional data hashing class BufferCache { public: + BufferCache(IRenderer& renderer_) : renderer{renderer_} {} ~BufferCache(); BufferView Get(ICommandBuffer* command_buffer, Range range); @@ -26,11 +29,13 @@ class BufferCache { void InvalidateMemory(Range range); private: + IRenderer& renderer; + std::map entries; // Helpers - static void UpdateRange(ICommandBuffer* command_buffer, BufferEntry& entry, - Range range); + void UpdateRange(ICommandBuffer* command_buffer, BufferEntry& entry, + Range range); BufferEntry& Find(Range range); }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp index 9d3eccfa..e7dce840 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/index_cache.cpp @@ -93,7 +93,7 @@ get_primitive_type_triangle_fan_to_triangle_strip() { IndexCache::~IndexCache() { for (auto& [key, index_buffer] : cache) - RENDERER_INSTANCE.FreeTemporaryBuffer(index_buffer); + renderer.FreeTemporaryBuffer(index_buffer); } BufferView IndexCache::Decode(ICommandBuffer* command_buffer, @@ -118,8 +118,8 @@ BufferView IndexCache::Decode(ICommandBuffer* command_buffer, break; \ } else { \ if (descriptor.mem_range) \ - return RENDERER_INSTANCE.GetBufferCache().Get( \ - command_buffer, *descriptor.mem_range); \ + return renderer.GetBufferCache().Get(command_buffer, \ + *descriptor.mem_range); \ else \ return BufferView(); \ } \ @@ -157,8 +157,7 @@ BufferView IndexCache::Decode(ICommandBuffer* command_buffer, return index_buffer; const auto index_size = get_index_type_size(out_type); - index_buffer = - RENDERER_INSTANCE.AllocateTemporaryBuffer(out_count * index_size); + index_buffer = renderer.AllocateTemporaryBuffer(out_count * index_size); uptr in_ptr = 0x0; if (descriptor.mem_range) in_ptr = descriptor.mem_range->GetBegin(); diff --git a/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp index d3a211b2..6984c5c5 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/index_cache.hpp @@ -5,6 +5,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer { class BufferBase; +class IRenderer; struct IndexDescriptor { engines::IndexType type; @@ -16,6 +17,7 @@ struct IndexDescriptor { // TODO: memory invalidation class IndexCache { public: + IndexCache(IRenderer& renderer_) : renderer{renderer_} {} ~IndexCache(); BufferView Decode(ICommandBuffer* command_buffer, @@ -26,6 +28,8 @@ class IndexCache { u32 Hash(const IndexDescriptor& descriptor); private: + IRenderer& renderer; + std::map cache; }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp index 01f1c28d..3279df1a 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.cpp @@ -4,7 +4,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -BlitPipelineCache::BlitPipelineCache() { +BlitPipelineCache::BlitPipelineCache(MTL::Device* device_) : device{device_} { // Source auto shader_source = R"( #include @@ -34,8 +34,8 @@ BlitPipelineCache::BlitPipelineCache() { )"; // Function - auto vertex_blit = CreateFunctionFromSource( - METAL_RENDERER_INSTANCE.GetDevice(), shader_source, "vertex_blit"); + auto vertex_blit = + CreateFunctionFromSource(device, shader_source, "vertex_blit"); // Pipeline descriptor pipeline_descriptor = MTL::RenderPipelineDescriptor::alloc()->init(); @@ -75,8 +75,8 @@ BlitPipelineCache::Create(const BlitPipelineDescriptor& descriptor) { )"; // Function - auto fragment_blit = CreateFunctionFromSource( - METAL_RENDERER_INSTANCE.GetDevice(), shader_source, "fragment_blit"); + auto fragment_blit = + CreateFunctionFromSource(device, shader_source, "fragment_blit"); // Pipeline pipeline_descriptor->setFragmentFunction(fragment_blit); @@ -98,8 +98,7 @@ BlitPipelineCache::Create(const BlitPipelineDescriptor& descriptor) { fragment_blit->release(); NS::Error* error; - auto pipeline = METAL_RENDERER_INSTANCE.GetDevice()->newRenderPipelineState( - pipeline_descriptor, &error); + auto pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); if (error) { LOG_ERROR(MetalRenderer, "Failed to create blit pipeline: {}", error->localizedDescription()->utf8String()); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.hpp index c0b5e363..6ebb1231 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/blit_pipeline_cache.hpp @@ -19,7 +19,7 @@ class BlitPipelineCache : public CacheBase { public: - BlitPipelineCache(); + BlitPipelineCache(MTL::Device* device_); void Destroy(); @@ -30,6 +30,8 @@ class BlitPipelineCache void DestroyElement(MTL::RenderPipelineState* pipeline); private: + MTL::Device* device; + MTL::RenderPipelineDescriptor* pipeline_descriptor; }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp index fab04485..e2aeb13a 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.cpp @@ -6,9 +6,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -Buffer::Buffer(u64 size) : BufferBase(size) { - buffer = METAL_RENDERER_INSTANCE.GetDevice()->newBuffer( - size, MTL::ResourceStorageModePrivate); +Buffer::Buffer(MTL::Device* device, u64 size) : BufferBase(size) { + buffer = device->newBuffer(size, MTL::ResourceStorageModePrivate); } Buffer::Buffer(MTL::Buffer* buffer_) diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.hpp index 81804c0f..d9aa1983 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/buffer.hpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { class Buffer final : public BufferBase { public: - Buffer(u64 size); + Buffer(MTL::Device* device, u64 size); Buffer(MTL::Buffer* buffer_); ~Buffer() override; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp index 7a919aef..96ed6998 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.cpp @@ -4,7 +4,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -ClearColorPipelineCache::ClearColorPipelineCache() { +ClearColorPipelineCache::ClearColorPipelineCache(MTL::Device* device_) + : device{device_} { // Source auto shader_source = R"( #include @@ -32,8 +33,7 @@ ClearColorPipelineCache::ClearColorPipelineCache() { // Function auto vertex_clear_color = - CreateFunctionFromSource(METAL_RENDERER_INSTANCE.GetDevice(), - shader_source, "vertex_clear_color"); + CreateFunctionFromSource(device, shader_source, "vertex_clear_color"); // Pipeline descriptor pipeline_descriptor = MTL::RenderPipelineDescriptor::alloc()->init(); @@ -64,8 +64,7 @@ MTL::RenderPipelineState* ClearColorPipelineCache::Create( // Function auto fragment_clear_color = - CreateFunctionFromSource(METAL_RENDERER_INSTANCE.GetDevice(), - shader_source, "fragment_clear_color"); + CreateFunctionFromSource(device, shader_source, "fragment_clear_color"); // Pipeline pipeline_descriptor->setFragmentFunction(fragment_clear_color); @@ -87,8 +86,7 @@ MTL::RenderPipelineState* ClearColorPipelineCache::Create( fragment_clear_color->release(); NS::Error* error; - auto pipeline = METAL_RENDERER_INSTANCE.GetDevice()->newRenderPipelineState( - pipeline_descriptor, &error); + auto pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); if (error) { LOG_ERROR(MetalRenderer, "Failed to create clear color pipeline: {}", error->localizedDescription()->utf8String()); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp index 25acbb8d..7c2c1a53 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_color_pipeline_cache.hpp @@ -14,7 +14,7 @@ class ClearColorPipelineCache : public CacheBase { public: - ClearColorPipelineCache(); + ClearColorPipelineCache(MTL::Device* device_); void Destroy(); @@ -26,6 +26,8 @@ class ClearColorPipelineCache void DestroyElement(MTL::RenderPipelineState* pipeline); private: + MTL::Device* device; + MTL::RenderPipelineDescriptor* pipeline_descriptor; }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp index e4ad9f61..548162b8 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.cpp @@ -4,7 +4,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -ClearDepthPipelineCache::ClearDepthPipelineCache() { +ClearDepthPipelineCache::ClearDepthPipelineCache(MTL::Device* device_) + : device{device_} { // Source auto shader_source = R"( #include @@ -37,8 +38,7 @@ ClearDepthPipelineCache::ClearDepthPipelineCache() { // Function auto vertex_clear_depth = - CreateFunctionFromSource(METAL_RENDERER_INSTANCE.GetDevice(), - shader_source, "vertex_clear_depth"); + CreateFunctionFromSource(device, shader_source, "vertex_clear_depth"); // Pipeline descriptor pipeline_descriptor = MTL::RenderPipelineDescriptor::alloc()->init(); @@ -55,8 +55,7 @@ ClearDepthPipelineCache::Create(MTL::PixelFormat pixel_format) { pipeline_descriptor->setDepthAttachmentPixelFormat(pixel_format); NS::Error* error; - auto pipeline = METAL_RENDERER_INSTANCE.GetDevice()->newRenderPipelineState( - pipeline_descriptor, &error); + auto pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); if (error) { LOG_ERROR(MetalRenderer, "Failed to create clear depth pipeline: {}", error->localizedDescription()->utf8String()); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp index a9b45efd..b4c3b236 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp @@ -8,7 +8,7 @@ class ClearDepthPipelineCache : public CacheBase { public: - ClearDepthPipelineCache(); + ClearDepthPipelineCache(MTL::Device* device_); void Destroy(); @@ -19,6 +19,8 @@ class ClearDepthPipelineCache void DestroyElement(MTL::RenderPipelineState* pipeline); private: + MTL::Device* device; + MTL::RenderPipelineDescriptor* pipeline_descriptor; }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.cpp index 6f081df7..78a05af2 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.cpp @@ -18,7 +18,7 @@ DepthStencilStateCache::Create(const DepthStencilStateDescriptor& descriptor) { descriptor.depth_compare_op != engines::CompareOp::Always) desc->setDepthWriteEnabled(true); - return METAL_RENDERER_INSTANCE.GetDevice()->newDepthStencilState(desc); + return device->newDepthStencilState(desc); } u32 DepthStencilStateCache::Hash( diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp index db708e52..7b2304c5 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp @@ -15,6 +15,8 @@ class DepthStencilStateCache : public CacheBase { public: + DepthStencilStateCache(MTL::Device* device_) : device{device_} {} + void Destroy() {} MTL::DepthStencilState* @@ -25,6 +27,7 @@ class DepthStencilStateCache void DestroyElement(MTL::DepthStencilState* depth_stencil_state); private: + MTL::Device* device; }; } // namespace hydra::hw::tegra_x1::gpu::renderer::metal diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp index 9957568b..d75bac07 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.cpp @@ -6,7 +6,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -Pipeline::Pipeline(const PipelineDescriptor& descriptor) +Pipeline::Pipeline(MTL::Device* device, const PipelineDescriptor& descriptor) : PipelineBase(descriptor) { MTL::RenderPipelineDescriptor* pipeline_descriptor = MTL::RenderPipelineDescriptor::alloc()->init(); @@ -137,8 +137,7 @@ Pipeline::Pipeline(const PipelineDescriptor& descriptor) // Pipeline NS::Error* error; - pipeline = METAL_RENDERER_INSTANCE.GetDevice()->newRenderPipelineState( - pipeline_descriptor, &error); + pipeline = device->newRenderPipelineState(pipeline_descriptor, &error); pipeline_descriptor->release(); if (error) { LOG_ERROR(MetalRenderer, "Failed to create pipeline: {}", diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.hpp index 0c7044b9..81ed665c 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/pipeline.hpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { class Pipeline final : public PipelineBase { public: - Pipeline(const PipelineDescriptor& descriptor); + Pipeline(MTL::Device* device, const PipelineDescriptor& descriptor); ~Pipeline() override; // Getters diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp index b8d049e3..41d00df7 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.cpp @@ -24,23 +24,11 @@ using namespace metal; namespace hydra::hw::tegra_x1::gpu::renderer::metal { -SINGLETON_DEFINE_GET_INSTANCE(Renderer, MetalRenderer) - -Renderer::Renderer() { - SINGLETON_SET_INSTANCE(Renderer, MetalRenderer); - - // Device - device = MTL::CreateSystemDefaultDevice(); - command_queue = device->newCommandQueue(); - - /* - // Library - MTL::Library* library = - CreateLibraryFromSource(device, utility_shader_source); - - // Functions - */ - +Renderer::Renderer() + : device{MTL::CreateSystemDefaultDevice()}, + command_queue{device->newCommandQueue()}, + depth_stencil_state_cache(device), blit_pipeline_cache(device), + clear_color_pipeline_cache(device), clear_depth_pipeline_cache(device) { // Resources // Depth stencil states @@ -65,12 +53,6 @@ Renderer::Renderer() { linear_sampler = device->newSamplerState(sampler_state_descriptor); sampler_state_descriptor->release(); - // Caches - depth_stencil_state_cache = new DepthStencilStateCache(); - blit_pipeline_cache = new BlitPipelineCache(); - clear_color_pipeline_cache = new ClearColorPipelineCache(); - clear_depth_pipeline_cache = new ClearDepthPipelineCache(); - // Info info = { .supports_quads_primitive = false, @@ -78,20 +60,15 @@ Renderer::Renderer() { } Renderer::~Renderer() { - delete depth_stencil_state_cache; - delete blit_pipeline_cache; - delete clear_color_pipeline_cache; - delete clear_depth_pipeline_cache; - linear_sampler->release(); nearest_sampler->release(); depth_stencil_state_always_and_write->release(); + // TODO: destroy caches here? + command_queue->release(); device->release(); - - SINGLETON_UNSET_INSTANCE(); } void Renderer::SetSurface(void* surface) { @@ -109,10 +86,12 @@ ISurfaceCompositor* Renderer::AcquireNextSurface() { if (!ca_drawable) return nullptr; - return new SurfaceCompositor(ca_drawable); + return new SurfaceCompositor(*this, ca_drawable); } -BufferBase* Renderer::CreateBuffer(u64 size) { return new Buffer(size); } +BufferBase* Renderer::CreateBuffer(u64 size) { + return new Buffer(device, size); +} BufferBase* Renderer::AllocateTemporaryBuffer(const u64 size) { // TODO: use a buffer allocator instead @@ -128,11 +107,68 @@ void Renderer::FreeTemporaryBuffer(BufferBase* buffer) { } ITexture* Renderer::CreateTexture(const TextureDescriptor& descriptor) { - return new Texture(descriptor); + return new Texture(device, descriptor); +} + +void Renderer::BlitTexture(ICommandBuffer* command_buffer, ITextureView* src, + float3 src_origin, usize3 src_size, u32 src_level, + u32 src_layer, ITextureView* dst, float3 dst_origin, + usize3 dst_size, u32 dst_level, u32 dst_layer, + u32 level_count, u32 layer_count) { + // TODO: what about 3D textures? + (void)src_level; + (void)src_layer; + (void)dst_level; + (void)level_count; + (void)layer_count; + + const auto command_buffer_impl = + static_cast(command_buffer); + const auto src_impl = static_cast(src); + const auto dst_impl = static_cast(dst); + + // Render pass + NS_STACK_SCOPED auto render_pass_descriptor = + MTL::RenderPassDescriptor::alloc()->init(); + auto color_attachment = + render_pass_descriptor->colorAttachments()->object(0); + color_attachment->setTexture(dst_impl->GetTexture()); + color_attachment->setLoadAction( + MTL::LoadActionLoad); // TODO: use don't care if blitting to the whole + // texture + color_attachment->setStoreAction(MTL::StoreActionStore); + + auto encoder = + command_buffer_impl->CreateRenderCommandEncoder(render_pass_descriptor); + + // Draw + encoder->setRenderPipelineState(blit_pipeline_cache.Find( + {src_impl->GetTexture()->pixelFormat(), false})); + encoder->setViewport(MTL::Viewport(f64(dst_origin.x()), f64(dst_origin.y()), + f64(dst_size.x()), f64(dst_size.y()), + 0.0, 1.0)); + encoder->setVertexBytes(&dst_layer, sizeof(dst_layer), 0); + BlitParams params = { + .src_offset = {static_cast(src_origin.x()) / + static_cast(src_size.x()), + static_cast(src_origin.y()) / + static_cast(src_size.y())}, + .src_scale = + float2(src_size) / + float2({static_cast(src_impl->GetTexture()->width()), + static_cast(src_impl->GetTexture()->height())}), + }; + encoder->setFragmentBytes(¶ms, sizeof(params), 0); + encoder->setFragmentTexture(src_impl->GetTexture(), NS::UInteger(0)); + encoder->setFragmentSamplerState( + linear_sampler, NS::UInteger(0)); // TODO: use the correct sampler + + encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), + NS::UInteger(3)); } SamplerBase* Renderer::CreateSampler(const SamplerDescriptor& descriptor) { - return new Sampler(descriptor); + return new Sampler(device, descriptor); } ICommandBuffer* Renderer::CreateCommandBuffer() { @@ -170,10 +206,9 @@ void Renderer::ClearColor(ICommandBuffer* command_buffer, u32 render_target_id, auto encoder = GetRenderCommandEncoder(command_buffer_impl); - command_buffer_impl->SetRenderPipelineState( - clear_color_pipeline_cache->Find( - {to_mtl_pixel_format(texture->GetDescriptor().format), - render_target_id, mask})); + command_buffer_impl->SetRenderPipelineState(clear_color_pipeline_cache.Find( + {to_mtl_pixel_format(texture->GetDescriptor().format), render_target_id, + mask})); // TODO: set viewport and scissor encoder->setVertexBytes(&render_target_id, sizeof(render_target_id), 0); encoder->setFragmentBytes(&color, sizeof(color), 0); @@ -204,9 +239,8 @@ void Renderer::ClearDepth(ICommandBuffer* command_buffer, u32 layer, auto encoder = GetRenderCommandEncoder(command_buffer_impl); - command_buffer_impl->SetRenderPipelineState( - clear_depth_pipeline_cache->Find( - to_mtl_pixel_format(texture->GetDescriptor().format))); + command_buffer_impl->SetRenderPipelineState(clear_depth_pipeline_cache.Find( + to_mtl_pixel_format(texture->GetDescriptor().format))); command_buffer_impl->SetDepthStencilState( depth_stencil_state_always_and_write); // TODO: set viewport and scissor @@ -226,26 +260,38 @@ void Renderer::ClearStencil(ICommandBuffer* command_buffer, u32 layer, MetalRenderer, "layer: {}, value: {:#x}", layer, value)); } -void Renderer::SetViewport(u32 index, const Viewport& viewport) { - state.viewports[index] = viewport; -} - -void Renderer::SetScissor(u32 index, const Scissor& scissor) { - state.scissors[index] = scissor; -} - ShaderBase* Renderer::CreateShader(const ShaderDescriptor& descriptor) { - return new Shader(descriptor); + return new Shader(device, descriptor); } PipelineBase* Renderer::CreatePipeline(const PipelineDescriptor& descriptor) { - return new Pipeline(descriptor); + return new Pipeline(device, descriptor); } void Renderer::BindPipeline(const PipelineBase* pipeline) { state.pipeline = static_cast(pipeline); } +void Renderer::SetDepthTestEnabled(bool enabled) { + state.depth_test_enabled = enabled; +} + +void Renderer::SetDepthWriteEnabled(bool enabled) { + state.depth_write_enabled = enabled; +} + +void Renderer::SetDepthCompareOp(engines::CompareOp op) { + state.depth_compare_op = op; +} + +void Renderer::SetViewport(u32 index, const Viewport& viewport) { + state.viewports[index] = viewport; +} + +void Renderer::SetScissor(u32 index, const Scissor& scissor) { + state.scissors[index] = scissor; +} + void Renderer::BindVertexBuffer(const BufferView& buffer, u32 index) { state.vertex_buffers[index] = buffer; } @@ -353,13 +399,13 @@ void Renderer::SetRenderPipelineState(CommandBuffer* command_buffer) { void Renderer::SetDepthStencilState(CommandBuffer* command_buffer) { DepthStencilStateDescriptor descriptor{ - .depth_test_enabled = static_cast(REGS_3D.depth_test_enabled), - .depth_write_enabled = static_cast(REGS_3D.depth_write_enabled), - .depth_compare_op = REGS_3D.depth_compare_op, + .depth_test_enabled = state.depth_test_enabled, + .depth_write_enabled = state.depth_write_enabled, + .depth_compare_op = state.depth_compare_op, }; command_buffer->SetDepthStencilState( - depth_stencil_state_cache->Find(descriptor)); + depth_stencil_state_cache.Find(descriptor)); } void Renderer::SetVertexBuffer(CommandBuffer* command_buffer, u32 index) { @@ -403,50 +449,6 @@ void Renderer::SetTexture(CommandBuffer* command_buffer, ShaderType shader_type, index); } -// TODO: what about 3D textures? -void Renderer::BlitTexture(CommandBuffer* command_buffer, MTL::Texture* src, - const float3 src_origin, const usize3 src_size, - MTL::Texture* dst, const u32 dst_layer, - const float3 dst_origin, const usize3 dst_size) { - // Render pass - auto render_pass_descriptor = MTL::RenderPassDescriptor::alloc()->init(); - auto color_attachment = - render_pass_descriptor->colorAttachments()->object(0); - color_attachment->setTexture(dst); - color_attachment->setLoadAction( - MTL::LoadActionLoad); // TODO: use don't care if blitting to the whole - // texture - color_attachment->setStoreAction(MTL::StoreActionStore); - - auto encoder = - command_buffer->CreateRenderCommandEncoder(render_pass_descriptor); - render_pass_descriptor->release(); - - // Draw - encoder->setRenderPipelineState( - blit_pipeline_cache->Find({src->pixelFormat(), false})); - encoder->setViewport(MTL::Viewport(f64(dst_origin.x()), f64(dst_origin.y()), - f64(dst_size.x()), f64(dst_size.y()), - 0.0, 1.0)); - encoder->setVertexBytes(&dst_layer, sizeof(dst_layer), 0); - // TODO: correct? - float2 scale = - (float2(src_size) / float2({static_cast(src->width()), - static_cast(src->height())})); - BlitParams params = { - .src_offset = {f32(src_origin.x()) / f32(src_size.x()), - f32(src_origin.y()) / f32(src_size.y())}, - .src_scale = scale, - }; - encoder->setFragmentBytes(¶ms, sizeof(params), 0); - encoder->setFragmentTexture(src, NS::UInteger(0)); - encoder->setFragmentSamplerState( - linear_sampler, NS::UInteger(0)); // TODO: use the correct sampler - - encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), - NS::UInteger(3)); -} - void Renderer::BeginCapture() { auto capture_manager = MTL::CaptureManager::sharedCaptureManager(); auto desc = MTL::CaptureDescriptor::alloc()->init(); @@ -517,6 +519,7 @@ void Renderer::BindDrawState(CommandBuffer* command_buffer) { SetRenderPipelineState(command_buffer); SetDepthStencilState(command_buffer); + // TODO /* if (REGS_3D.cull_face_enabled) { SetCullMode(ToMtlCullMode(REGS_3D.cull_face_mode)); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp index d4cdbb77..bd712e24 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/renderer.hpp @@ -5,10 +5,7 @@ #include "core/hw/tegra_x1/gpu/renderer/metal/clear_depth_pipeline_cache.hpp" #include "core/hw/tegra_x1/gpu/renderer/metal/const.hpp" #include "core/hw/tegra_x1/gpu/renderer/metal/depth_stencil_state_cache.hpp" -#include "core/hw/tegra_x1/gpu/renderer/renderer_base.hpp" - -#define METAL_RENDERER_INSTANCE \ - hw::tegra_x1::gpu::renderer::metal::Renderer::GetInstance() +#include "core/hw/tegra_x1/gpu/renderer/renderer.hpp" namespace hydra::hw::tegra_x1::gpu::renderer::metal { @@ -26,9 +23,12 @@ struct CombinedTextureSampler { struct State { const RenderPass* render_pass{nullptr}; + const Pipeline* pipeline{nullptr}; + bool depth_test_enabled; + bool depth_write_enabled; + engines::CompareOp depth_compare_op; Viewport viewports[VIEWPORT_COUNT]; Scissor scissors[VIEWPORT_COUNT]; - const Pipeline* pipeline{nullptr}; BufferView index_buffer{}; engines::IndexType index_type{engines::IndexType::None}; std::array vertex_buffers{}; @@ -41,10 +41,8 @@ struct State { // TODO: images }; -class Renderer : public RendererBase { +class Renderer : public IRenderer { public: - static Renderer& GetInstance(); - Renderer(); ~Renderer() override; @@ -59,6 +57,11 @@ class Renderer : public RendererBase { // Texture ITexture* CreateTexture(const TextureDescriptor& descriptor) override; + void BlitTexture(ICommandBuffer* command_buffer, ITextureView* src, + float3 src_origin, usize3 src_size, u32 src_level, + u32 src_layer, ITextureView* dst, float3 dst_origin, + usize3 dst_size, u32 dst_level, u32 dst_layer, + u32 level_count, u32 layer_count) override; // Sampler SamplerBase* CreateSampler(const SamplerDescriptor& descriptor) override; @@ -79,10 +82,6 @@ class Renderer : public RendererBase { void ClearStencil(ICommandBuffer* command_buffer, u32 layer, const u32 value) override; - // Viewport and scissor - void SetViewport(u32 index, const Viewport& viewport) override; - void SetScissor(u32 index, const Scissor& scissor) override; - // Shader ShaderBase* CreateShader(const ShaderDescriptor& descriptor) override; @@ -90,6 +89,15 @@ class Renderer : public RendererBase { PipelineBase* CreatePipeline(const PipelineDescriptor& descriptor) override; void BindPipeline(const PipelineBase* pipeline) override; + // Depth stencil + void SetDepthTestEnabled(bool enabled) override; + void SetDepthWriteEnabled(bool enabled) override; + void SetDepthCompareOp(engines::CompareOp op) override; + + // Viewport and scissor + void SetViewport(u32 index, const Viewport& viewport) override; + void SetScissor(u32 index, const Scissor& scissor) override; + // Resource binding void BindVertexBuffer(const BufferView& buffer, u32 index) override; void BindIndexBuffer(const BufferView& index_buffer, @@ -127,11 +135,6 @@ class Renderer : public RendererBase { void SetTexture(CommandBuffer* command_buffer, ShaderType shader_type, u32 index); - void BlitTexture(CommandBuffer* command_buffer, MTL::Texture* src, - const float3 src_origin, const usize3 src_size, - MTL::Texture* dst, const u32 dst_layer, - const float3 dst_origin, const usize3 dst_size); - protected: // Capture void BeginCapture() override; @@ -141,6 +144,13 @@ class Renderer : public RendererBase { MTL::Device* device; MTL::CommandQueue* command_queue; + // Caches + DepthStencilStateCache depth_stencil_state_cache; + BlitPipelineCache blit_pipeline_cache; + ClearColorPipelineCache clear_color_pipeline_cache; + ClearDepthPipelineCache clear_depth_pipeline_cache; + + // CA CA::MetalLayer* ca_layer{nullptr}; CA::MetalDrawable* ca_drawable{nullptr}; @@ -153,12 +163,6 @@ class Renderer : public RendererBase { MTL::SamplerState* nearest_sampler; MTL::SamplerState* linear_sampler; - // Caches - DepthStencilStateCache* depth_stencil_state_cache; - BlitPipelineCache* blit_pipeline_cache; - ClearColorPipelineCache* clear_color_pipeline_cache; - ClearDepthPipelineCache* clear_depth_pipeline_cache; - // State State state; [[maybe_unused]] u32 @@ -171,7 +175,7 @@ class Renderer : public RendererBase { public: GETTER(device, GetDevice); - GETTER(blit_pipeline_cache, GetBlitPipelineCache); + REF_GETTER(blit_pipeline_cache, GetBlitPipelineCache); GETTER(linear_sampler, GetLinearSampler); }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.cpp index c121bca2..63798a93 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.cpp @@ -5,7 +5,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -Sampler::Sampler(const SamplerDescriptor& descriptor) +Sampler::Sampler(MTL::Device* device, const SamplerDescriptor& descriptor) : SamplerBase(descriptor) { MTL::SamplerDescriptor* desc = MTL::SamplerDescriptor::alloc()->init(); desc->setMinFilter(to_mtl_sampler_min_mag_filter(descriptor.min_filter)); @@ -51,7 +51,7 @@ Sampler::Sampler(const SamplerDescriptor& descriptor) } desc->setBorderColor(mtl_border_color); - mtl_sampler = METAL_RENDERER_INSTANCE.GetDevice()->newSamplerState(desc); + mtl_sampler = device->newSamplerState(desc); } Sampler::~Sampler() { mtl_sampler->release(); } diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.hpp index 3fcd9b27..547f5d76 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/sampler.hpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { class Sampler final : public SamplerBase { public: - Sampler(const SamplerDescriptor& descriptor); + Sampler(MTL::Device* device, const SamplerDescriptor& descriptor); ~Sampler() override; // Getters diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp index 9ca756d2..f8486e02 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/shader.cpp @@ -4,7 +4,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -Shader::Shader(const ShaderDescriptor& descriptor) : ShaderBase(descriptor) { +Shader::Shader(MTL::Device* device, const ShaderDescriptor& descriptor) + : ShaderBase(descriptor) { // Options NS_STACK_SCOPED MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init(); @@ -22,8 +23,7 @@ Shader::Shader(const ShaderDescriptor& descriptor) : ShaderBase(descriptor) { source.assign(descriptor.code.begin(), descriptor.code.end()); NS::Error* error; - library = METAL_RENDERER_INSTANCE.GetDevice()->newLibrary( - ToNSString(source), options, &error); + library = device->newLibrary(ToNSString(source), options, &error); if (error) { LOG_ERROR(MetalRenderer, "Failed to create Metal library: {}", error->localizedDescription()->utf8String()); @@ -41,8 +41,7 @@ Shader::Shader(const ShaderDescriptor& descriptor) : ShaderBase(descriptor) { NS::Error* error; // TODO: options - library = METAL_RENDERER_INSTANCE.GetDevice()->newLibrary(dispatch_data, - &error); + library = device->newLibrary(dispatch_data, &error); if (error) { LOG_ERROR(MetalRenderer, "Failed to create Metal library: {}", error->localizedDescription()->utf8String()); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/shader.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/shader.hpp index 3eee9d41..a95263aa 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/shader.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/shader.hpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { class Shader final : public ShaderBase { public: - Shader(const ShaderDescriptor& descriptor); + Shader(MTL::Device* device, const ShaderDescriptor& descriptor); ~Shader() override; private: diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp index bdf03156..82436512 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp @@ -8,8 +8,9 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -SurfaceCompositor::SurfaceCompositor(CA::MetalDrawable* drawable_) - : drawable{drawable_} { +SurfaceCompositor::SurfaceCompositor(Renderer& renderer_, + CA::MetalDrawable* drawable_) + : renderer{renderer_}, drawable{drawable_} { // Render pass render_pass_descriptor = MTL::RenderPassDescriptor::alloc()->init(); auto color_attachment = @@ -34,9 +35,8 @@ void SurfaceCompositor::DrawTexture(ICommandBuffer* command_buffer, command_buffer_impl->GetRenderCommandEncoder(render_pass_descriptor); // Draw - encoder->setRenderPipelineState( - METAL_RENDERER_INSTANCE.GetBlitPipelineCache()->Find( - {drawable->texture()->pixelFormat(), transparent})); + encoder->setRenderPipelineState(renderer.GetBlitPipelineCache().Find( + {drawable->texture()->pixelFormat(), transparent})); encoder->setViewport(MTL::Viewport{static_cast(dst_rect.origin.x()), static_cast(dst_rect.origin.y()), static_cast(dst_rect.size.x()), @@ -60,7 +60,7 @@ void SurfaceCompositor::DrawTexture(ICommandBuffer* command_buffer, encoder->setFragmentBytes(¶ms, sizeof(params), 0); encoder->setFragmentTexture(texture_impl->GetTexture(), NS::UInteger(0)); - encoder->setFragmentSamplerState(METAL_RENDERER_INSTANCE.GetLinearSampler(), + encoder->setFragmentSamplerState(renderer.GetLinearSampler(), NS::UInteger(0)); encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3)); diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.hpp index 5ec0e493..9abe6899 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/surface_compositor.hpp @@ -6,10 +6,11 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { class CommandBuffer; +class Renderer; class SurfaceCompositor final : public ISurfaceCompositor { public: - SurfaceCompositor(CA::MetalDrawable* drawable_); + SurfaceCompositor(Renderer& renderer_, CA::MetalDrawable* drawable_); ~SurfaceCompositor() override; void DrawTexture(ICommandBuffer* command_buffer, @@ -19,6 +20,7 @@ class SurfaceCompositor final : public ISurfaceCompositor { void Present(ICommandBuffer* command_buffer) override; private: + Renderer& renderer; CA::MetalDrawable* drawable; MTL::RenderPassDescriptor* render_pass_descriptor; }; diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/texture.cpp b/src/core/hw/tegra_x1/gpu/renderer/metal/texture.cpp index a6785862..788ee131 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/texture.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/texture.cpp @@ -8,7 +8,8 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { -Texture::Texture(const TextureDescriptor& descriptor) : ITexture(descriptor) { +Texture::Texture(MTL::Device* device, const TextureDescriptor& descriptor) + : ITexture(descriptor) { const auto type = ToMtlTextureType(descriptor.type); MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init(); @@ -45,7 +46,7 @@ Texture::Texture(const TextureDescriptor& descriptor) : ITexture(descriptor) { const auto& pixel_format_info = to_mtl_pixel_format_info(descriptor.format); desc->setPixelFormat(pixel_format_info.pixel_format); - texture = METAL_RENDERER_INSTANCE.GetDevice()->newTexture(desc); + texture = device->newTexture(desc); } Texture::~Texture() { texture->release(); } @@ -111,31 +112,4 @@ void Texture::CopyFrom(ICommandBuffer* command_buffer, const ITexture* src, } } -void Texture::BlitFrom(ICommandBuffer* command_buffer, const ITexture* src, - const float3 src_origin, const usize3 src_size, - const u32 src_level, const u32 src_layer, - const float3 dst_origin, const usize3 dst_size, - const u32 dst_level, const u32 dst_layer, - const u32 level_count, const u32 layer_count) { - // TODO: support a wider range of parameters - ASSERT_DEBUG(src_level == 0, MetalRenderer, "Unsupported source level {}", - src_level); - ASSERT_DEBUG(src_layer == 0, MetalRenderer, "Unsupported source layer {}", - src_layer); - ASSERT_DEBUG(dst_level == 0, MetalRenderer, - "Unsupported destination level {}", dst_level); - ASSERT_DEBUG(dst_layer == 0, MetalRenderer, - "Unsupported destination layer {}", dst_layer); - ASSERT_DEBUG(level_count == 1, MetalRenderer, "Unsupported level_count {}", - level_count); - ASSERT_DEBUG(layer_count == 1, MetalRenderer, "Unsupported layer_count {}", - layer_count); - - const auto command_buffer_impl = - static_cast(command_buffer); - METAL_RENDERER_INSTANCE.BlitTexture( - command_buffer_impl, static_cast(src)->GetTexture(), - src_origin, src_size, texture, 0, dst_origin, dst_size); -} - } // namespace hydra::hw::tegra_x1::gpu::renderer::metal diff --git a/src/core/hw/tegra_x1/gpu/renderer/metal/texture.hpp b/src/core/hw/tegra_x1/gpu/renderer/metal/texture.hpp index c9800823..80144413 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/metal/texture.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/metal/texture.hpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer::metal { class Texture final : public ITexture { public: - Texture(const TextureDescriptor& descriptor); + Texture(MTL::Device* device, const TextureDescriptor& descriptor); ~Texture() override; ITextureView* @@ -24,14 +24,6 @@ class Texture final : public ITexture { const u32 dst_level, const u32 dst_layer, const usize3 size, const u32 level_count, const u32 layer_count) override; - // Blitting - void BlitFrom(ICommandBuffer* command_buffer, const ITexture* src, - const float3 src_origin, const usize3 src_size, - const u32 src_level, const u32 src_layer, - const float3 dst_origin, const usize3 dst_size, - const u32 dst_level, const u32 dst_layer, - const u32 level_count, const u32 layer_count) override; - private: MTL::Texture* texture; diff --git a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp index c9dbc25a..f7ec8ddc 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.cpp @@ -6,7 +6,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer { PipelineBase* PipelineCache::Create(const PipelineDescriptor& descriptor) { - return RENDERER_INSTANCE.CreatePipeline(descriptor); + return renderer.CreatePipeline(descriptor); } u32 PipelineCache::Hash(const PipelineDescriptor& descriptor) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp index 46cf3e5b..a9edf3c6 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/pipeline_cache.hpp @@ -5,10 +5,13 @@ namespace hydra::hw::tegra_x1::gpu::renderer { class PipelineBase; +class IRenderer; class PipelineCache : public CacheBase { public: + PipelineCache(IRenderer& renderer_) : renderer{renderer_} {} + void Destroy() {} PipelineBase* Create(const PipelineDescriptor& descriptor); @@ -16,6 +19,9 @@ class PipelineCache u32 Hash(const PipelineDescriptor& descriptor); void DestroyElement(PipelineBase* pipeline); + + private: + IRenderer& renderer; }; } // namespace hydra::hw::tegra_x1::gpu::renderer diff --git a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp index ee0355da..4dc9060b 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.cpp @@ -7,7 +7,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer { RenderPassBase* RenderPassCache::Create(const RenderPassDescriptor& descriptor) { - return RENDERER_INSTANCE.CreateRenderPass(descriptor); + return renderer.CreateRenderPass(descriptor); } u32 RenderPassCache::Hash(const RenderPassDescriptor& descriptor) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp index 452aa3e0..40ac3d23 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/render_pass_cache.hpp @@ -5,10 +5,13 @@ namespace hydra::hw::tegra_x1::gpu::renderer { class RenderPassBase; +class IRenderer; class RenderPassCache : public CacheBase { public: + RenderPassCache(IRenderer& renderer_) : renderer{renderer_} {} + void Destroy() {} RenderPassBase* Create(const RenderPassDescriptor& descriptor); @@ -16,6 +19,9 @@ class RenderPassCache u32 Hash(const RenderPassDescriptor& descriptor); void DestroyElement(RenderPassBase* render_pass); + + private: + IRenderer& renderer; }; } // namespace hydra::hw::tegra_x1::gpu::renderer diff --git a/src/core/hw/tegra_x1/gpu/renderer/renderer_base.hpp b/src/core/hw/tegra_x1/gpu/renderer/renderer.hpp similarity index 86% rename from src/core/hw/tegra_x1/gpu/renderer/renderer_base.hpp rename to src/core/hw/tegra_x1/gpu/renderer/renderer.hpp index dff9d123..2bf46834 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/renderer_base.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/renderer.hpp @@ -32,9 +32,13 @@ struct Info { } }; -class RendererBase { +class IRenderer { public: - virtual ~RendererBase() {} + IRenderer() + : buffer_cache(*this), texture_cache(*this), sampler_cache(*this), + render_pass_cache(*this), shader_cache(*this), pipeline_cache(*this), + index_cache(*this) {} + virtual ~IRenderer() {} // TODO: make this thread safe void InvalidateMemory(Range range) { @@ -54,6 +58,12 @@ class RendererBase { // Texture virtual ITexture* CreateTexture(const TextureDescriptor& descriptor) = 0; + virtual void BlitTexture(ICommandBuffer* command_buffer, ITextureView* src, + float3 src_origin, usize3 src_size, u32 src_level, + u32 src_layer, ITextureView* dst, + float3 dst_origin, usize3 dst_size, u32 dst_level, + u32 dst_layer, u32 level_count, + u32 layer_count) = 0; // Sampler virtual SamplerBase* CreateSampler(const SamplerDescriptor& descriptor) = 0; @@ -75,10 +85,6 @@ class RendererBase { virtual void ClearStencil(ICommandBuffer* command_buffer, u32 layer, const u32 value) = 0; - // Viewport and scissor - virtual void SetViewport(u32 index, const Viewport& viewport) = 0; - virtual void SetScissor(u32 index, const Scissor& scissor) = 0; - // Shader virtual ShaderBase* CreateShader(const ShaderDescriptor& descriptor) = 0; @@ -87,6 +93,15 @@ class RendererBase { CreatePipeline(const PipelineDescriptor& descriptor) = 0; virtual void BindPipeline(const PipelineBase* pipeline) = 0; + // Depth stencil + virtual void SetDepthTestEnabled(bool enabled) = 0; + virtual void SetDepthWriteEnabled(bool enabled) = 0; + virtual void SetDepthCompareOp(engines::CompareOp op) = 0; + + // Viewport and scissor + virtual void SetViewport(u32 index, const Viewport& viewport) = 0; + virtual void SetScissor(u32 index, const Scissor& scissor) = 0; + // Resource binding virtual void BindVertexBuffer(const BufferView& buffer, u32 index) = 0; virtual void BindIndexBuffer(const BufferView& index_buffer, diff --git a/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.cpp index 95c20243..ec6ea3ca 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.cpp @@ -6,7 +6,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer { SamplerBase* SamplerCache::Create(const SamplerDescriptor& descriptor) { - auto sampler = RENDERER_INSTANCE.CreateSampler(descriptor); + auto sampler = renderer.CreateSampler(descriptor); return sampler; } diff --git a/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp index a9a11b3c..c46780af 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/sampler_cache.hpp @@ -9,10 +9,13 @@ class IMmu; namespace hydra::hw::tegra_x1::gpu::renderer { class SamplerBase; +class IRenderer; class SamplerCache : public CacheBase { public: + SamplerCache(IRenderer& renderer_) : renderer{renderer_} {} + void Destroy() {} SamplerBase* Create(const SamplerDescriptor& descriptor); @@ -22,6 +25,7 @@ class SamplerCache void DestroyElement(SamplerBase* sampler); private: + IRenderer& renderer; }; } // namespace hydra::hw::tegra_x1::gpu::renderer diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp index 2a38be47..3f4edd82 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.cpp @@ -20,7 +20,7 @@ ShaderBase* ShaderCache::Create(const GuestShaderDescriptor& descriptor) { host_descriptor.backend, host_descriptor.code, host_descriptor.resource_mapping); - return RENDERER_INSTANCE.CreateShader(host_descriptor); + return renderer.CreateShader(host_descriptor); } u32 ShaderCache::Hash(const GuestShaderDescriptor& descriptor) { diff --git a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp index 43ee41cf..1b3b48b2 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/shader_cache.hpp @@ -6,6 +6,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer { class ShaderBase; +class IRenderer; struct GuestShaderState { engines::VertexAttribState vertex_attrib_states[VERTEX_ATTRIB_COUNT]; @@ -22,6 +23,8 @@ struct GuestShaderDescriptor { class ShaderCache : public CacheBase { public: + ShaderCache(IRenderer& renderer_) : renderer{renderer_} {} + void Destroy() {} ShaderBase* Create(const GuestShaderDescriptor& descriptor); @@ -29,6 +32,9 @@ class ShaderCache u32 Hash(const GuestShaderDescriptor& descriptor); void DestroyElement(ShaderBase* shader); + + private: + IRenderer& renderer; }; } // namespace hydra::hw::tegra_x1::gpu::renderer diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture.hpp b/src/core/hw/tegra_x1/gpu/renderer/texture.hpp index c8023ce8..7792e995 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture.hpp @@ -35,14 +35,6 @@ class ITexture { const usize3 size, const u32 level_count, const u32 layer_count) = 0; - // Blitting - virtual void BlitFrom(ICommandBuffer* command_buffer, const ITexture* src, - const float3 src_origin, const usize3 src_size, - const u32 src_level, const u32 src_layer, - const float3 dst_origin, const usize3 dst_size, - const u32 dst_level, const u32 dst_layer, - const u32 level_count, const u32 layer_count) = 0; - protected: const TextureDescriptor descriptor; diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp index 6c16231b..71c18eff 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.cpp @@ -246,7 +246,7 @@ ITextureView* TextureCache::GetTexture( const TextureDescriptor& descriptor, const TextureViewDescriptor& view_descriptor, TextureUsage usage) { if (!storage.base) { - storage.base = RENDERER_INSTANCE.CreateTexture(descriptor); + storage.base = renderer.CreateTexture(descriptor); DecodeTexture(command_buffer, storage); } @@ -422,8 +422,7 @@ void TextureCache::DecodeTexture(ICommandBuffer* command_buffer, const auto& descriptor = storage.base->GetDescriptor(); // Align the height to 16 bytes (TODO: why 16?) - auto tmp_buffer = - RENDERER_INSTANCE.AllocateTemporaryBuffer(descriptor.GetSize()); + auto tmp_buffer = renderer.AllocateTemporaryBuffer(descriptor.GetSize()); u8* in_data = reinterpret_cast(descriptor.ptr); u8* out_data = reinterpret_cast(tmp_buffer->GetPtr()); @@ -440,7 +439,7 @@ void TextureCache::DecodeTexture(ICommandBuffer* command_buffer, } storage.base->CopyFrom(command_buffer, tmp_buffer); - RENDERER_INSTANCE.FreeTemporaryBuffer(tmp_buffer); + renderer.FreeTemporaryBuffer(tmp_buffer); } } // namespace hydra::hw::tegra_x1::gpu::renderer diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp index 7706782c..07292ab9 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture_cache.hpp @@ -11,6 +11,7 @@ namespace hydra::hw::tegra_x1::gpu::renderer { class ICommandBuffer; class ITexture; class ITextureView; +class IRenderer; typedef std::chrono::steady_clock TextureCacheClock; typedef TextureCacheClock::time_point TextureCacheTimePoint; @@ -67,6 +68,7 @@ struct TextureMem { // TODO: texture readback class TextureCache { public: + TextureCache(IRenderer& renderer_) : renderer{renderer_} {} ~TextureCache(); ITextureView* Find(ICommandBuffer* command_buffer, @@ -88,6 +90,8 @@ class TextureCache { } private: + IRenderer& renderer; + std::mutex mutex; std::map entries; diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture_view.cpp b/src/core/hw/tegra_x1/gpu/renderer/texture_view.cpp index 1c1d0b85..faa7a965 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture_view.cpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture_view.cpp @@ -40,19 +40,4 @@ void ITextureView::CopyFrom(ICommandBuffer* command_buffer, layer_count); } -void ITextureView::BlitFrom(ICommandBuffer* command_buffer, - const ITextureView* src, const float3 src_origin, - const usize3 src_size, const u32 src_level, - const u32 src_layer, const float3 dst_origin, - const usize3 dst_size, const u32 dst_level, - const u32 dst_layer, const u32 level_count, - const u32 layer_count) { - base->BlitFrom( - command_buffer, src->GetBase(), src_origin, src_size, - src->GetDescriptor().levels.GetBegin() + src_level, - src->GetDescriptor().layers.GetBegin() + src_layer, dst_origin, - dst_size, descriptor.levels.GetBegin() + dst_level, - descriptor.layers.GetBegin() + dst_layer, level_count, layer_count); -} - } // namespace hydra::hw::tegra_x1::gpu::renderer diff --git a/src/core/hw/tegra_x1/gpu/renderer/texture_view.hpp b/src/core/hw/tegra_x1/gpu/renderer/texture_view.hpp index 88c62906..5ef25949 100644 --- a/src/core/hw/tegra_x1/gpu/renderer/texture_view.hpp +++ b/src/core/hw/tegra_x1/gpu/renderer/texture_view.hpp @@ -25,14 +25,6 @@ class ITextureView { const u32 dst_level, const u32 dst_layer, const usize3 size, const u32 level_count, const u32 layer_count); - // Blitting - void BlitFrom(ICommandBuffer* command_buffer, const ITextureView* src, - const float3 src_origin, const usize3 src_size, - const u32 src_level, const u32 src_layer, - const float3 dst_origin, const usize3 dst_size, - const u32 dst_level, const u32 dst_layer, - const u32 level_count, const u32 layer_count); - protected: ITexture* base; const TextureViewDescriptor descriptor; diff --git a/src/core/hw/wall_clock.cpp b/src/core/hw/wall_clock.cpp index 4ed67120..b3242c12 100644 --- a/src/core/hw/wall_clock.cpp +++ b/src/core/hw/wall_clock.cpp @@ -12,18 +12,12 @@ u64 MultiplyByFactor(u64 num, u128 factor) { return (num * factor) >> 64; } } // namespace -SINGLETON_DEFINE_GET_INSTANCE(WallClock, Other) - WallClock::WallClock() { - SINGLETON_SET_INSTANCE(WallClock, Other); - const auto host_freq = GetSystemFrequency(); guest_factor = GetFactor(GUEST_CNTFRQ, host_freq); gpu_tick_factor = GetFactor(GPU_TICK_FREQ, host_freq); } -WallClock::~WallClock() { SINGLETON_UNSET_INSTANCE(); } - u64 WallClock::GetCntpct() const { return MultiplyByFactor(GetSystemTick(), guest_factor); } diff --git a/src/core/hw/wall_clock.hpp b/src/core/hw/wall_clock.hpp index b0444bb4..c72effbe 100644 --- a/src/core/hw/wall_clock.hpp +++ b/src/core/hw/wall_clock.hpp @@ -7,10 +7,7 @@ constexpr u64 GPU_TICK_FREQ = 614'400'000; class WallClock { public: - static WallClock& GetInstance(); - WallClock(); - ~WallClock(); u64 GetCntpct() const; u64 GetGpuTick() const; diff --git a/src/core/input/apple_gc/device_list.mm b/src/core/input/apple_gc/device_list.mm index 4a391892..73b9a665 100644 --- a/src/core/input/apple_gc/device_list.mm +++ b/src/core/input/apple_gc/device_list.mm @@ -19,6 +19,7 @@ - (id)initWithParent:(DeviceList*)parent { if (self = [super init]) { self.parent = parent; + // Notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerConnected:) @@ -39,6 +40,19 @@ - (id)initWithParent:(DeviceList*)parent { selector:@selector(keyboardDisconnected:) name:GCKeyboardDidDisconnectNotification object:nil]; + + // Connected keyboards + if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) { + GCKeyboard* keyboard = [GCKeyboard coalescedKeyboard]; + if (keyboard) { + self.parent->_AddKeyboard(keyboard); + } + } + + // Connected controllers + for (GCController* controller in [GCController controllers]) { + self.parent->_AddController(controller); + } } return self; diff --git a/src/core/input/device_manager.hpp b/src/core/input/device_manager.hpp index 64f37927..e8790c1c 100644 --- a/src/core/input/device_manager.hpp +++ b/src/core/input/device_manager.hpp @@ -4,19 +4,12 @@ #include "core/input/profile.hpp" #include "core/input/state.hpp" -#define INPUT_DEVICE_MANAGER_INSTANCE input::DeviceManager::GetInstance() - namespace hydra::input { constexpr usize MAX_FINGER_COUNT = 16; class DeviceManager { public: - static DeviceManager& GetInstance() { - static DeviceManager s_instance; - return s_instance; - } - DeviceManager(); ~DeviceManager(); diff --git a/src/core/emulation_context.cpp b/src/core/system.cpp similarity index 82% rename from src/core/emulation_context.cpp rename to src/core/system.cpp index 073c4055..fa8f1e87 100644 --- a/src/core/emulation_context.cpp +++ b/src/core/system.cpp @@ -1,4 +1,4 @@ -#include "core/emulation_context.hpp" +#include "core/system.hpp" #include #include @@ -21,7 +21,7 @@ #include "core/horizon/loader/nca_loader.hpp" #include "core/horizon/loader/nro_loader.hpp" #include "core/horizon/loader/nso_loader.hpp" -#include "core/horizon/services/am/library_applet_controller.hpp" +#include "core/horizon/services/am/internal/library_applet_controller.hpp" #include "core/hw/tegra_x1/cpu/dynarmic/cpu.hpp" #include "core/hw/tegra_x1/cpu/mmu.hpp" #include "core/hw/tegra_x1/cpu/thread.hpp" @@ -47,99 +47,76 @@ namespace { constexpr auto STARTUP_MOVIE_FADE_IN_DURATION = 100ms; constexpr auto STARTUP_MOVIE_BREAK_AFTER_FADE_IN_DURATION = 200ms; -} // namespace - -CombinedTextureView::~CombinedTextureView() { - // TODO: uncomment - // delete view; - // delete base; -} - -EmulationContext::EmulationContext(horizon::ui::IHandler& ui_handler) { - LOGGER_INSTANCE.SetOutput(CONFIG_INSTANCE.GetLogOutput()); - - // Random - srand(static_cast(time(0))); - - // Initialize +hw::tegra_x1::cpu::ICpu* CreateCpu() { switch (CONFIG_INSTANCE.GetCpuBackend()) { case CpuBackend::AppleHypervisor: #if HYDRA_HYPERVISOR_ENABLED - cpu = new hw::tegra_x1::cpu::hypervisor::Cpu(); + return new hw::tegra_x1::cpu::hypervisor::Cpu(); #else LOG_FATAL(Other, "Apple Hypervisor not supported"); #endif - break; case CpuBackend::Dynarmic: - cpu = new hw::tegra_x1::cpu::dynarmic::Cpu(); - break; + return new hw::tegra_x1::cpu::dynarmic::Cpu(); default: // TODO: return an error instead LOG_FATAL(Other, "Unknown CPU backend {}", CONFIG_INSTANCE.GetCpuBackend()); - break; } +} - gpu = new hw::tegra_x1::gpu::Gpu(); - +audio::ICore* CreateAudioCore() { switch (CONFIG_INSTANCE.GetAudioBackend()) { case AudioBackend::Null: - audio_core = new audio::null::Core(); - break; + return new audio::null::Core(); case AudioBackend::Cubeb: #if HYDRA_CUBEB_ENABLED - audio_core = new audio::cubeb::Core(); + return new audio::cubeb::Core(); #else LOG_FATAL(Other, "cubeb not supported"); #endif - break; default: // TODO: return an error instead LOG_FATAL(Other, "Unknown audio backend {}", CONFIG_INSTANCE.GetAudioBackend()); - break; } +} - os = new horizon::OS(*audio_core, ui_handler); - - // Filesystem - /* - for (const auto& root_path : CONFIG_INSTANCE.GetRootPaths()) { - const auto res = - horizon::Filesystem::Filesystem::GetInstance().AddEntry( - root_path.guest_path, root_path.host_path, true); - ASSERT(res == horizon::Filesystem::FsResult::Success, Services, - "Failed to get root path: {}", res); - LOG_INFO(Other, "Mapped {} to {}", root_path.guest_path, - root_path.host_path); - } - */ +} // namespace + +CombinedTextureView::~CombinedTextureView() { + // TODO: uncomment + // delete view; + // delete base; } -EmulationContext::~EmulationContext() { - delete os; - delete audio_core; - delete gpu; - delete cpu; +System::System(horizon::ui::IHandler& ui_handler_) + : ui_handler{ui_handler_}, cpu{CreateCpu()}, audio_core{CreateAudioCore()}, + os(*this) { + // TODO: set this elsewhere + LOGGER_INSTANCE.SetOutput(CONFIG_INSTANCE.GetLogOutput()); +} +System::~System() { + // TODO: set this elsewhere LOGGER_INSTANCE.SetOutput(LogOutput::StdOut); } -void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { +void System::LoadAndStart(horizon::loader::LoaderBase* loader) { // Process ASSERT_THROWING(main_process == nullptr, Other, LoadAndStartError::ProcessAlreadyExists, "Process already exists"); main_process = - os->GetKernel().GetProcessManager().CreateProcess("Guest process"); - loader->LoadProcess(main_process); + os.GetKernel().GetProcessManager().CreateProcess("Guest process"); + loader->LoadProcess(*this, main_process); // Check for firmware applets - auto controller = new horizon::services::am::LibraryAppletController( - horizon::LibraryAppletMode::AllForeground); + auto controller = + new horizon::services::am::internal::LibraryAppletController( + horizon::LibraryAppletMode::AllForeground); // TODO: correct? u64 system_tick; - os->GetKernel().GetSystemTick(system_tick); + os.GetKernel().GetSystemTick(system_tick); switch (loader->GetTitleID()) { case 0x0100000000001003: { // controller // Common args @@ -279,7 +256,7 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { break; } - os->SetLibraryAppletSelfController(controller); + os.SetLibraryAppletSelfController(controller); // Loading screen assets hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer = nullptr; @@ -295,7 +272,7 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { 0x0, hw::tegra_x1::gpu::renderer::TextureType::_2D, hw::tegra_x1::gpu::renderer::TextureFormat::RGBA8Unorm, true, stride, width, height, 1, 1, 1, 0x0, 0x0, 0x0); - const auto texture = gpu->GetRenderer().CreateTexture(descriptor); + const auto texture = gpu.GetRenderer().CreateTexture(descriptor); const auto view_descriptor = hw::tegra_x1::gpu::renderer::TextureViewDescriptor( @@ -305,15 +282,15 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { nintendo_logo = {texture, texture_view}; // Command buffer - command_buffer = gpu->GetRenderer().CreateCommandBuffer(); + command_buffer = gpu.GetRenderer().CreateCommandBuffer(); // Copy data - auto tmp_buffer = gpu->GetRenderer().AllocateTemporaryBuffer(size); + auto tmp_buffer = gpu.GetRenderer().AllocateTemporaryBuffer(size); std::memcpy(reinterpret_cast(tmp_buffer->GetPtr()), data, size); free(data); texture->CopyFrom(command_buffer, tmp_buffer); - gpu->GetRenderer().FreeTemporaryBuffer(tmp_buffer); + gpu.GetRenderer().FreeTemporaryBuffer(tmp_buffer); } } { @@ -336,21 +313,21 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { // Command buffer if (!command_buffer) - command_buffer = gpu->GetRenderer().CreateCommandBuffer(); + command_buffer = gpu.GetRenderer().CreateCommandBuffer(); for (u32 i = 0; i < frame_count; i++) { // Create texture const auto texture = - gpu->GetRenderer().CreateTexture(descriptor); + gpu.GetRenderer().CreateTexture(descriptor); const auto texture_view = texture->CreateView(view_descriptor); // Copy data auto tmp_buffer = - gpu->GetRenderer().AllocateTemporaryBuffer(size); + gpu.GetRenderer().AllocateTemporaryBuffer(size); std::memcpy(reinterpret_cast(tmp_buffer->GetPtr()), data + i * height * width, size); texture->CopyFrom(command_buffer, tmp_buffer); - gpu->GetRenderer().FreeTemporaryBuffer(tmp_buffer); + gpu.GetRenderer().FreeTemporaryBuffer(tmp_buffer); startup_movie.push_back({texture, texture_view}); } free(data); @@ -406,8 +383,8 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { auto user_id = CONFIG_INSTANCE.GetUserId(); if (user_id == horizon::services::account::internal::INVALID_USER_ID) { // If there is just a single user, use that - if (USER_MANAGER_INSTANCE.GetUserCount() == 1) { - user_id = USER_MANAGER_INSTANCE.GetUserIDs()[0]; + if (os.GetUserManager().GetUserCount() == 1) { + user_id = os.GetUserManager().GetUserIDs()[0]; } else { // TODO: launch a select user applet in case the game requires it LOG_FATAL(Other, "Multiple user accounts"); @@ -430,7 +407,8 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { while (!main_process->IsRunning()) std::this_thread::yield(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - DEBUGGER_MANAGER_INSTANCE.GetDebugger(main_process).ActivateGdbServer(); + DEBUGGER_MANAGER_INSTANCE.GetDebugger(main_process) + .ActivateGdbServer(*this); } // Loading screen @@ -442,19 +420,19 @@ void EmulationContext::LoadAndStart(horizon::loader::LoaderBase* loader) { startup_movie_fade_in_time = crnt_time + STARTUP_MOVIE_FADE_IN_DURATION; } -void EmulationContext::RequestStop() { +void System::RequestStop() { // We don't request the processes to stop yet, instead we send a message to // all of them and give them some time to react - for (auto it = os->GetKernel().GetProcessManager().Begin(); - it != os->GetKernel().GetProcessManager().End(); ++it) + for (auto it = os.GetKernel().GetProcessManager().Begin(); + it != os.GetKernel().GetProcessManager().End(); ++it) (*it)->GetAppletState().SendMessage( horizon::kernel::AppletMessage::Exit); } -void EmulationContext::ForceStop() { +void System::ForceStop() { // Request all processes to stop immediately - for (auto it = os->GetKernel().GetProcessManager().Begin(); - it != os->GetKernel().GetProcessManager().End(); ++it) + for (auto it = os.GetKernel().GetProcessManager().Begin(); + it != os.GetKernel().GetProcessManager().End(); ++it) (*it)->Stop(); // Wait a small amount of time for all threads to catch up @@ -467,50 +445,50 @@ void EmulationContext::ForceStop() { } } -void EmulationContext::Pause() { - for (auto it = os->GetKernel().GetProcessManager().Begin(); - it != os->GetKernel().GetProcessManager().End(); ++it) +void System::Pause() { + for (auto it = os.GetKernel().GetProcessManager().Begin(); + it != os.GetKernel().GetProcessManager().End(); ++it) (*it)->SupervisorPause(); } -void EmulationContext::Resume() { - for (auto it = os->GetKernel().GetProcessManager().Begin(); - it != os->GetKernel().GetProcessManager().End(); ++it) +void System::Resume() { + for (auto it = os.GetKernel().GetProcessManager().Begin(); + it != os.GetKernel().GetProcessManager().End(); ++it) (*it)->SupervisorResume(); } -void EmulationContext::ProgressFrame(u32 width, u32 height, - bool& out_dt_average_updated) { +void System::ProgressFrame(u32 width, u32 height, + bool& out_dt_average_updated) { // Set the resolution for OS - os->SetSurfaceResolution({width, height}); + os.SetSurfaceResolution({width, height}); // Input - os->GetHidResourceManager().Update(); + os.GetHidResourceManager().Update(); // Present // Acquire surface - auto compositor = gpu->GetRenderer().AcquireNextSurface(); + auto compositor = gpu.GetRenderer().AcquireNextSurface(); if (!compositor) return; // Delta time { auto layer = - os->GetDisplayDriver().GetFirstLayerForProcess(main_process); + os.GetDisplayDriver().GetFirstLayerForProcess(main_process); if (layer) accumulated_dt += layer->GetAccumulatedDT(); } // Command buffer - auto command_buffer = gpu->GetRenderer().CreateCommandBuffer(); + auto command_buffer = gpu.GetRenderer().CreateCommandBuffer(); // Acquire present textures bool acquired = - os->GetDisplayDriver().AcquirePresentTextures(command_buffer); + os.GetDisplayDriver().AcquirePresentTextures(command_buffer); // Render pass - os->GetDisplayDriver().Present(command_buffer, compositor, width, height); + os.GetDisplayDriver().Present(command_buffer, compositor, width, height); if (loading) { if (acquired) { @@ -599,10 +577,10 @@ void EmulationContext::ProgressFrame(u32 width, u32 height, delete compositor; // Signal V-Sync - os->GetDisplayDriver().SignalVSync(); + os.GetDisplayDriver().SignalVSync(); } -bool EmulationContext::IsRunning() const { +bool System::IsRunning() const { if (!main_process) return false; @@ -615,8 +593,8 @@ bool EmulationContext::IsRunning() const { }; } -void EmulationContext::TakeScreenshot() { - auto layer = os->GetDisplayDriver().GetFirstLayerForProcess(main_process); +void System::TakeScreenshot() { + auto layer = os.GetDisplayDriver().GetFirstLayerForProcess(main_process); if (!layer) return; @@ -624,7 +602,7 @@ void EmulationContext::TakeScreenshot() { if (!texture) return; - std::thread thread([=]() { + std::thread thread([=, this]() { // Get the image data auto rect = layer->GetSrcRect(); @@ -638,8 +616,8 @@ void EmulationContext::TakeScreenshot() { } // Copy to a buffer - auto command_buffer = RENDERER_INSTANCE.CreateCommandBuffer(); - auto buffer = RENDERER_INSTANCE.AllocateTemporaryBuffer( + auto command_buffer = gpu.GetRenderer().CreateCommandBuffer(); + auto buffer = gpu.GetRenderer().AllocateTemporaryBuffer( static_cast(rect.size.y() * rect.size.x() * 4)); buffer->CopyFrom(command_buffer, texture, rect.origin, rect.size, Range(0, 1), Range(0, 1)); @@ -661,19 +639,19 @@ void EmulationContext::TakeScreenshot() { stbi_flip_vertically_on_write(false); // Free the buffer - RENDERER_INSTANCE.FreeTemporaryBuffer(buffer); + gpu.GetRenderer().FreeTemporaryBuffer(buffer); }); thread.detach(); } -void EmulationContext::CaptureGpuFrame() { +void System::CaptureGpuFrame() { // TODO: allow multiple frames - gpu->GetRenderer().CaptureFrames(1); + gpu.GetRenderer().CaptureFrames(1); } -void EmulationContext::TryApplyPatch(horizon::kernel::Process* process, - const std::string_view target_filename, - const std::filesystem::path path) { +void System::TryApplyPatch(horizon::kernel::Process* process, + const std::string_view target_filename, + const std::filesystem::path path) { if (to_lower(path.filename().string()) != target_filename) return; diff --git a/src/core/emulation_context.hpp b/src/core/system.hpp similarity index 66% rename from src/core/emulation_context.hpp rename to src/core/system.hpp index 05348490..cdbbedc2 100644 --- a/src/core/emulation_context.hpp +++ b/src/core/system.hpp @@ -1,17 +1,16 @@ #pragma once -#include "core/horizon/kernel/process.hpp" #include "core/horizon/os.hpp" -#include "core/hw/tegra_x1/cpu/cpu.hpp" #include "core/hw/tegra_x1/gpu/gpu.hpp" #include "core/hw/wall_clock.hpp" +#include "core/input/device_manager.hpp" -namespace hydra { - -namespace horizon::loader { +namespace hydra::horizon::loader { class LoaderBase; } +namespace hydra { + struct CombinedTextureView { hw::tegra_x1::gpu::renderer::ITexture* base; hw::tegra_x1::gpu::renderer::ITextureView* view; @@ -19,14 +18,14 @@ struct CombinedTextureView { ~CombinedTextureView(); }; -class EmulationContext { +class System { using clock_t = std::chrono::steady_clock; public: - EmulationContext(horizon::ui::IHandler& ui_handler); - ~EmulationContext(); + System(horizon::ui::IHandler& ui_handler_); + ~System(); - void SetSurface(void* surface) { gpu->GetRenderer().SetSurface(surface); } + void SetSurface(void* surface) { gpu.GetRenderer().SetSurface(surface); } enum class LoadAndStartError { ProcessAlreadyExists, @@ -39,7 +38,7 @@ class EmulationContext { void Pause(); void Resume(); - void NotifyOperationModeChanged() { os->NotifyOperationModeChanged(); } + void NotifyOperationModeChanged() { os.NotifyOperationModeChanged(); } // TODO: rename? void ProgressFrame(u32 width, u32 height, bool& out_dt_average_updated); @@ -51,12 +50,14 @@ class EmulationContext { void CaptureGpuFrame(); private: - // Objects + horizon::ui::IHandler& ui_handler; + hw::WallClock wall_clock; - hw::tegra_x1::cpu::ICpu* cpu; - hw::tegra_x1::gpu::Gpu* gpu; - audio::ICore* audio_core; - horizon::OS* os; + std::unique_ptr cpu; + hw::tegra_x1::gpu::Gpu gpu; + input::DeviceManager input_device_manager; + std::unique_ptr audio_core; + horizon::OS os; // Loading screen assets std::optional nintendo_logo{}; @@ -80,6 +81,15 @@ class EmulationContext { void TryApplyPatch(horizon::kernel::Process* process, const std::string_view target_filename, const std::filesystem::path path); + + public: + GETTER(ui_handler, GetUIHandler); + REF_GETTER(wall_clock, GetWallClock); + hw::tegra_x1::cpu::ICpu& GetCpu() { return *cpu.get(); } + REF_GETTER(gpu, GetGpu); + REF_GETTER(input_device_manager, GetInputDeviceManager); + audio::ICore& GetAudioCore() { return *audio_core.get(); } + REF_GETTER(os, GetOS); }; } // namespace hydra diff --git a/src/frontend/sdl3/window.cpp b/src/frontend/sdl3/window.cpp index 9e6136d9..f491fa62 100644 --- a/src/frontend/sdl3/window.cpp +++ b/src/frontend/sdl3/window.cpp @@ -5,7 +5,7 @@ namespace hydra::frontend::sdl3 { -Window::Window(int argc, const char* argv[]) : emulation_context(*this) { +Window::Window(int argc, const char* argv[]) : system(*this) { // SLD3 initialization if (!SDL_Init(SDL_INIT_VIDEO)) { LOG_FATAL(SDL3Window, "Failed to initialize SDL3: {}", SDL_GetError()); @@ -32,7 +32,7 @@ Window::Window(int argc, const char* argv[]) : emulation_context(*this) { } Window::~Window() { - INPUT_DEVICE_MANAGER_INSTANCE.DisconnectTouchScreenDevice("cursor"); + system.GetInputDeviceManager().DisconnectTouchScreenDevice("cursor"); SDL_DestroyWindow(window); SDL_Quit(); @@ -58,13 +58,13 @@ void Window::Run() { if (modifiers & SDL_KMOD_CTRL) { #endif if (e.key.key == SDLK_T) { - emulation_context.TakeScreenshot(); + system.TakeScreenshot(); } else if (e.key.key == SDLK_O) { auto& handheld_mode = CONFIG_INSTANCE.GetHandheldMode(); handheld_mode = !handheld_mode; - emulation_context.NotifyOperationModeChanged(); + system.NotifyOperationModeChanged(); } else if (e.key.key == SDLK_P) { - emulation_context.CaptureGpuFrame(); + system.CaptureGpuFrame(); } } break; @@ -75,14 +75,13 @@ void Window::Run() { } } - if (emulation_context.IsRunning()) { + if (system.IsRunning()) { // Present i32 width, height; SDL_GetWindowSize(window, &width, &height); bool dt_average_updated; - emulation_context.ProgressFrame(static_cast(width), - static_cast(height), - dt_average_updated); + system.ProgressFrame(static_cast(width), + static_cast(height), dt_average_updated); // Update window title if (dt_average_updated) @@ -125,18 +124,18 @@ Window::ShowSoftwareKeyboard(const std::string& header_text, void Window::BeginEmulation(const std::string& path) { // Connect cursor as a touch screen device - INPUT_DEVICE_MANAGER_INSTANCE.ConnectTouchScreenDevice("cursor", &cursor); + system.GetInputDeviceManager().ConnectTouchScreenDevice("cursor", &cursor); - emulation_context.SetSurface(SDL_GetRenderMetalLayer(renderer)); + system.SetSurface(SDL_GetRenderMetalLayer(renderer)); // TODO: support loading applets from firmware auto loader = horizon::loader::LoaderBase::CreateFromPath(path); - emulation_context.LoadAndStart(loader); + system.LoadAndStart(loader); title_id = loader->GetTitleID(); delete loader; } void Window::UpdateWindowTitle() { - const auto dt = emulation_context.GetLastDeltaTimeAverage(); + const auto dt = system.GetLastDeltaTimeAverage(); std::string fps_str; if (dt == 0.0f) fps_str = "0"; @@ -146,7 +145,7 @@ void Window::UpdateWindowTitle() { // TODO: title name const auto title = fmt::format("Hydra | TODO(TITLE_NAME) - 0x{:016x} | {} | {} FPS", - title_id, Config::GetInstance().GetGpuRenderer(), fps_str); + title_id, CONFIG_INSTANCE.GetGpuRenderer(), fps_str); SetWindowTitle(title); } diff --git a/src/frontend/sdl3/window.hpp b/src/frontend/sdl3/window.hpp index b22fd3a1..a7226862 100644 --- a/src/frontend/sdl3/window.hpp +++ b/src/frontend/sdl3/window.hpp @@ -1,7 +1,7 @@ #pragma once -#include "core/emulation_context.hpp" #include "core/horizon/ui/handler_base.hpp" +#include "core/system.hpp" #include "frontend/sdl3/cursor.hpp" // TODO: if macOS @@ -34,7 +34,7 @@ class Window : public horizon::ui::IHandler { Native native; Cursor cursor; - EmulationContext emulation_context; + System system; u64 title_id; void BeginEmulation(const std::string& path); diff --git a/src/frontend/swiftui/Api.swift b/src/frontend/swiftui/Api.swift index fcc679ff..52086db4 100644 --- a/src/frontend/swiftui/Api.swift +++ b/src/frontend/swiftui/Api.swift @@ -490,102 +490,6 @@ func hydraConfigGetGdbWaitForClient() -> UnsafeMutablePointer { hydra_config_get_gdb_wait_for_client() } -// Loader plugins -func hydraLoaderPluginManagerRefresh() { - hydra_loader_plugin_manager_refresh() -} - -enum HydraPluginError: Error { - case unknown -} - -class HydraLoaderPlugin { - internal let handle: UnsafeMutableRawPointer - - init(path: String) throws { - guard - let handle = - (path.withHydraString { hydraPath in - hydra_create_loader_plugin(hydraPath) - }) - else { - throw HydraPluginError.unknown - } - self.handle = handle - } - - deinit { - hydra_loader_plugin_destroy(self.handle) - } - - var name: String { - String(withHydraString: hydra_loader_plugin_get_name(self.handle)) - } - - var displayVersion: String { - String(withHydraString: hydra_loader_plugin_get_display_version(self.handle)) - } - - func getSupportedFormatCount() -> Int { - Int(hydra_loader_plugin_get_supported_format_count(self.handle)) - } - - func getSupportedFormat(at index: Int) -> String { - String( - withHydraString: hydra_loader_plugin_get_supported_format(self.handle, UInt32(index))) - } - - func getOptionConfigCount() -> Int { - Int(hydra_loader_plugin_get_option_config_count(self.handle)) - } - - // HACK: cast immutable to mutable - func getOptionConfig(at index: Int) -> HydraLoaderPluginOptionConfig { - HydraLoaderPluginOptionConfig( - handle: UnsafeMutableRawPointer( - mutating: hydra_loader_plugin_get_option_config(self.handle, UInt32(index)))) - } -} - -class HydraLoaderPluginOptionConfig: MutableHandleClass { - fileprivate override init(handle: UnsafeMutableRawPointer) { - super.init(handle: hydra_loader_plugin_option_config_copy(handle)) - } - - deinit { - hydra_loader_plugin_option_config_destroy(self.handle) - } - - var name: String { - String(withHydraString: hydra_loader_plugin_option_config_get_name(self.handle)) - } - - var description: String { - String(withHydraString: hydra_loader_plugin_option_config_get_description(self.handle)) - } - - var type: HydraLoaderPluginOptionType { - hydra_loader_plugin_option_config_get_type(self.handle) - } - - var isRequired: Bool { - hydra_loader_plugin_option_config_get_is_required(self.handle) - } - - // HACK: cast immutable to mutable - var enumValueNames: HydraStringViewList { - HydraStringViewList( - handle: UnsafeMutableRawPointer( - mutating: hydra_loader_plugin_option_config_get_enum_value_names(self.handle))) - } - - var pathContentTypes: HydraStringViewList { - HydraStringViewList( - handle: UnsafeMutableRawPointer( - mutating: hydra_loader_plugin_option_config_get_path_content_types(self.handle))) - } -} - // Filesystem class HydraFilesystem: MutableHandleClass { init() { @@ -642,10 +546,10 @@ enum HydraLoaderContent { } class HydraLoader: MutableHandleClass { - convenience init(path: String) throws { + convenience init(path: String, pluginManager: HydraLoaderPluginManager?) throws { guard let handle = path.withHydraString({ hydraPath in - hydra_create_loader_from_path(hydraPath) + hydra_create_loader_from_path(hydraPath, pluginManager?.handle) }) else { throw HydraLoaderError.unsupported @@ -738,6 +642,110 @@ class HydraNcaLoader: HydraLoader { } } +// Plugins +class HydraLoaderPluginManager: MutableHandleClass { + init() { + super.init(handle: hydra_create_loader_plugin_manager()) + } + + deinit { + hydra_loader_plugin_manager_destroy(self.handle) + } + + func refresh() { + hydra_loader_plugin_manager_refresh(self.handle) + } +} + +enum HydraPluginError: Error { + case unknown +} + +class HydraLoaderPlugin: MutableHandleClass { + init(path: String) throws { + guard + let handle = + (path.withHydraString { hydraPath in + hydra_create_loader_plugin(hydraPath) + }) + else { + throw HydraPluginError.unknown + } + super.init(handle: handle) + } + + deinit { + hydra_loader_plugin_destroy(self.handle) + } + + var name: String { + String(withHydraString: hydra_loader_plugin_get_name(self.handle)) + } + + var displayVersion: String { + String(withHydraString: hydra_loader_plugin_get_display_version(self.handle)) + } + + func getSupportedFormatCount() -> Int { + Int(hydra_loader_plugin_get_supported_format_count(self.handle)) + } + + func getSupportedFormat(at index: Int) -> String { + String( + withHydraString: hydra_loader_plugin_get_supported_format(self.handle, UInt32(index))) + } + + func getOptionConfigCount() -> Int { + Int(hydra_loader_plugin_get_option_config_count(self.handle)) + } + + // HACK: cast immutable to mutable + func getOptionConfig(at index: Int) -> HydraLoaderPluginOptionConfig { + HydraLoaderPluginOptionConfig( + handle: UnsafeMutableRawPointer( + mutating: hydra_loader_plugin_get_option_config(self.handle, UInt32(index)))) + } +} + +class HydraLoaderPluginOptionConfig: MutableHandleClass { + fileprivate override init(handle: UnsafeMutableRawPointer) { + super.init(handle: hydra_loader_plugin_option_config_copy(handle)) + } + + deinit { + hydra_loader_plugin_option_config_destroy(self.handle) + } + + var name: String { + String(withHydraString: hydra_loader_plugin_option_config_get_name(self.handle)) + } + + var description: String { + String(withHydraString: hydra_loader_plugin_option_config_get_description(self.handle)) + } + + var type: HydraLoaderPluginOptionType { + hydra_loader_plugin_option_config_get_type(self.handle) + } + + var isRequired: Bool { + hydra_loader_plugin_option_config_get_is_required(self.handle) + } + + // HACK: cast immutable to mutable + var enumValueNames: HydraStringViewList { + HydraStringViewList( + handle: UnsafeMutableRawPointer( + mutating: hydra_loader_plugin_option_config_get_enum_value_names(self.handle))) + } + + var pathContentTypes: HydraStringViewList { + HydraStringViewList( + handle: UnsafeMutableRawPointer( + mutating: hydra_loader_plugin_option_config_get_path_content_types(self.handle))) + } +} + struct HydraNacp: MutableHandleStruct { internal let handle: UnsafeMutableRawPointer @@ -860,13 +868,13 @@ struct HydraUser: MutableHandleStruct { } // Emulation context -class HydraEmulationContext: MutableHandleClass { +class HydraSystem: MutableHandleClass { init() { - super.init(handle: hydra_create_emulation_context()) + super.init(handle: hydra_create_system()) } deinit { - hydra_emulation_context_destroy(self.handle) + hydra_system_destroy(self.handle) } var surface: UnsafeMutableRawPointer { @@ -875,52 +883,68 @@ class HydraEmulationContext: MutableHandleClass { UnsafeMutableRawPointer(bitPattern: 0)! } set { - hydra_emulation_context_set_surface(self.handle, newValue) + hydra_system_set_surface(self.handle, newValue) } } func loadAndStart(loader: HydraLoader) { - hydra_emulation_context_load_and_start(self.handle, loader.handle) + hydra_system_load_and_start(self.handle, loader.handle) } func requestStop() { - hydra_emulation_context_request_stop(self.handle) + hydra_system_request_stop(self.handle) } func forceStop() { - hydra_emulation_context_force_stop(self.handle) + hydra_system_force_stop(self.handle) } func pause() { - hydra_emulation_context_pause(self.handle) + hydra_system_pause(self.handle) } func resume() { - hydra_emulation_context_resume(self.handle) + hydra_system_resume(self.handle) } func notifyOperationModeChanged() { - hydra_emulation_context_notify_operation_mode_changed(self.handle) + hydra_system_notify_operation_mode_changed(self.handle) } func progressFrame(width: UInt32, height: UInt32, dtAverageUpdated: inout Bool) { - hydra_emulation_context_progress_frame(self.handle, width, height, &dtAverageUpdated) + hydra_system_progress_frame(self.handle, width, height, &dtAverageUpdated) } func isRunning() -> Bool { - hydra_emulation_context_is_running(self.handle) + hydra_system_is_running(self.handle) } func getLastDeltaTimeAverage() -> Float { - hydra_emulation_context_get_last_delta_time_average(self.handle) + hydra_system_get_last_delta_time_average(self.handle) } func takeScreenshot() { - hydra_emulation_context_take_screenshot(self.handle) + hydra_system_take_screenshot(self.handle) } func captureGpuFrame() { - hydra_emulation_context_capture_gpu_frame(self.handle) + hydra_system_capture_gpu_frame(self.handle) + } + + func textureCacheLock() { + hydra_system_texture_cache_lock(self.handle) + } + + func textureCacheUnlock() { + hydra_system_texture_cache_unlock(self.handle) + } + + func textureCacheGetTextureMemoryCount() -> Int { + Int(hydra_system_texture_cache_get_texture_memory_count(self.handle)) + } + + func textureCacheGetTextureMemory(at index: Int) -> HydraTextureMemory { + HydraTextureMemory(handle: hydra_system_texture_cache_get_texture_memory(self.handle, UInt32(index))) } } @@ -1097,23 +1121,6 @@ class HydraDebuggerResolvedStackFrame: MutableHandleClass { // Texture cache -// Texture cache -func hydraTextureCacheLock() { - hydra_texture_cache_lock() -} - -func hydraTextureCacheUnlock() { - hydra_texture_cache_unlock() -} - -func hydraTextureCacheGetTextureMemoryCount() -> Int { - Int(hydra_texture_cache_get_texture_memory_count()) -} - -func hydraTextureCacheGetTextureMemory(at index: Int) -> HydraTextureMemory { - HydraTextureMemory(handle: hydra_texture_cache_get_texture_memory(UInt32(index))) -} - // Texture memory struct HydraTextureMemory: HandleStruct { internal let handle: UnsafeRawPointer diff --git a/src/frontend/swiftui/ContentView.swift b/src/frontend/swiftui/ContentView.swift index 8dccb93d..133b2c06 100644 --- a/src/frontend/swiftui/ContentView.swift +++ b/src/frontend/swiftui/ContentView.swift @@ -29,7 +29,7 @@ struct ContentView: View { var gitInsert = "" if gitVersion != "" { gitInsert = " (\(gitVersion))" } var fpsInsert = "" - if globalState.emulationContext != nil { fpsInsert = " | \(fps) FPS" } + if globalState.system != nil { fpsInsert = " | \(fps) FPS" } return "Hydra v\(appVersion)\(gitInsert)\(titleInsert)\(fpsInsert)" } diff --git a/src/frontend/swiftui/EmulationToolbarItems.swift b/src/frontend/swiftui/EmulationToolbarItems.swift index 8887b161..2fb00a97 100644 --- a/src/frontend/swiftui/EmulationToolbarItems.swift +++ b/src/frontend/swiftui/EmulationToolbarItems.swift @@ -11,14 +11,14 @@ struct EmulationToolbarItems: ToolbarContent { ToolbarItemGroup(placement: .principal) { if isRunning { Button("Pause", systemImage: "pause") { - guard let emulationContext = globalState.emulationContext else { return } - emulationContext.pause() + guard let system = globalState.system else { return } + system.pause() isRunning = false } } else { Button("Resume", systemImage: "play") { - guard let emulationContext = globalState.emulationContext else { return } - emulationContext.resume() + guard let system = globalState.system else { return } + system.resume() isRunning = true } } @@ -26,10 +26,10 @@ struct EmulationToolbarItems: ToolbarContent { globalState.isStopping = true } .onAppear { - isRunning = globalState.emulationContext!.isRunning() + isRunning = globalState.system!.isRunning() } } - + ToolbarItemGroup(placement: .confirmationAction) { if isFramerateUnlocked { Button{ @@ -59,14 +59,14 @@ struct EmulationToolbarItems: ToolbarContent { .help("Unlock Framerate") } } - + // This compiler check is only needed when compiling on a macOS version earlier than 26 #if compiler(>=6.2.3) if #available(macOS 26.0, *) { ToolbarSpacer(.fixed) } #endif - + if #available(macOS 26.0, *) { ToolbarItemGroup(placement: .confirmationAction) { Button("Console Mode", systemImage: "inset.filled.tv") { @@ -74,7 +74,7 @@ struct EmulationToolbarItems: ToolbarContent { } .disabled(!globalState.isHandheldMode) .help("Change to Console mode") - + Button("Handheld Mode", systemImage: "formfitting.gamecontroller.fill") { globalState.isHandheldMode.toggle() } diff --git a/src/frontend/swiftui/EmulationView.swift b/src/frontend/swiftui/EmulationView.swift index 959104ba..215e0f33 100644 --- a/src/frontend/swiftui/EmulationView.swift +++ b/src/frontend/swiftui/EmulationView.swift @@ -9,8 +9,8 @@ struct EmulationView: View { ZStack { MetalView(fps: $fps) .onAppear { - globalState.emulationContext = HydraEmulationContext() - globalState.emulationContext!.loadAndStart( + globalState.system = HydraSystem() + globalState.system!.loadAndStart( loader: globalState.activeGame!.loader) } .onDisappear { diff --git a/src/frontend/swiftui/Game.swift b/src/frontend/swiftui/Game.swift index ba1c8cd3..5dc34487 100644 --- a/src/frontend/swiftui/Game.swift +++ b/src/frontend/swiftui/Game.swift @@ -15,8 +15,8 @@ struct Game: Hashable { self.version = version } - init(url: URL) throws { - let loader = try HydraLoader(path: url.path(percentEncoded: false)) + init(url: URL, loaderPluginManager: HydraLoaderPluginManager?) throws { + let loader = try HydraLoader(path: url.path(percentEncoded: false), pluginManager: loaderPluginManager) // Get name and author var name = "" diff --git a/src/frontend/swiftui/GameListView.swift b/src/frontend/swiftui/GameListView.swift index 6041f77b..2a943c49 100644 --- a/src/frontend/swiftui/GameListView.swift +++ b/src/frontend/swiftui/GameListView.swift @@ -42,24 +42,24 @@ struct GameListView: View { } } .onAppear { - games = GameListView.createGameList(gamePaths: globalState.gamePaths) + games = GameListView.createGameList(gamePaths: globalState.gamePaths, loaderPluginManager: self.globalState.loaderPluginManager) } .onChange(of: globalState.gamePaths) { _, newValue in - games = GameListView.createGameList(gamePaths: newValue) + games = GameListView.createGameList(gamePaths: newValue, loaderPluginManager: self.globalState.loaderPluginManager) } - .onChange(of: globalState.loaderPluginChangeID) { _, _ in - games = GameListView.createGameList(gamePaths: globalState.gamePaths) + .onChange(of: globalState.loaderPluginRefreshID) { _, _ in + games = GameListView.createGameList(gamePaths: globalState.gamePaths, loaderPluginManager: self.globalState.loaderPluginManager) } } - static func createGameList(gamePaths: [String]) -> [Game] { + static func createGameList(gamePaths: [String], loaderPluginManager: HydraLoaderPluginManager?) -> [Game] { // Get all games var games: [Game] = [] for gamePath in gamePaths { do { let url = try resolveUrl(URL(fileURLWithPath: gamePath)) - try processUrl(games: &games, url: url) + try processUrl(games: &games, url: url, loaderPluginManager: loaderPluginManager) } catch { // TODO: error popup print("Failed to load game path \(gamePath): \(error)") @@ -72,10 +72,10 @@ struct GameListView: View { return games } - static func processUrl(games: inout [Game], url: URL) throws { + static func processUrl(games: inout [Game], url: URL, loaderPluginManager: HydraLoaderPluginManager?) throws { // Check if the URL is a game if url.pathExtension != "" { - tryAddGame(games: &games, url: url) + tryAddGame(games: &games, url: url, loaderPluginManager: loaderPluginManager) return } @@ -97,13 +97,13 @@ struct GameListView: View { let urls = try FileManager.default.contentsOfDirectory( at: url, includingPropertiesForKeys: nil) for url in urls { - try processUrl(games: &games, url: url) + try processUrl(games: &games, url: url, loaderPluginManager: loaderPluginManager) } } - static func tryAddGame(games: inout [Game], url: URL) { + static func tryAddGame(games: inout [Game], url: URL, loaderPluginManager: HydraLoaderPluginManager?) { do { - let game = try Game(url: url) + let game = try Game(url: url, loaderPluginManager: loaderPluginManager) games.append(game) } catch { // TODO: error popup diff --git a/src/frontend/swiftui/GameStopView.swift b/src/frontend/swiftui/GameStopView.swift index aad3a7ac..3b508d95 100644 --- a/src/frontend/swiftui/GameStopView.swift +++ b/src/frontend/swiftui/GameStopView.swift @@ -26,8 +26,8 @@ struct GameStopView: View { Button("Force Quit", role: .destructive) { timer!.invalidate() - globalState.emulationContext!.forceStop() - globalState.emulationContext = nil + globalState.system!.forceStop() + globalState.system = nil globalState.activeGame = nil globalState.isStopping = false @@ -39,14 +39,14 @@ struct GameStopView: View { .onAppear { let startTime = Date() - guard let emulationContext = globalState.emulationContext else { return } - emulationContext.requestStop() + guard let system = globalState.system else { return } + system.requestStop() timer = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { _ in - if !emulationContext.isRunning() { + if !system.isRunning() { timer!.invalidate() - globalState.emulationContext = nil + globalState.system = nil globalState.activeGame = nil globalState.isStopping = false } else if Date().timeIntervalSince(startTime) > 3 { diff --git a/src/frontend/swiftui/HydraApp.swift b/src/frontend/swiftui/HydraApp.swift index 634416f8..5eef65e7 100644 --- a/src/frontend/swiftui/HydraApp.swift +++ b/src/frontend/swiftui/HydraApp.swift @@ -3,23 +3,23 @@ import SwiftUI class GlobalState: ObservableObject { // Game library @Published var gamePaths: [String] = [] - @Published var loaderPluginChangeID = 0 // HACK + let loaderPluginManager = HydraLoaderPluginManager() + @Published var loaderPluginRefreshID = 0 // Emulation @Published var activeGame: Game? = nil - @Published var emulationContext: HydraEmulationContext? = nil + @Published var system: HydraSystem? = nil @Published var isStopping = false @Published var isHandheldMode: Bool { didSet { hydraConfigGetHandheldMode().pointee = isHandheldMode hydraConfigSerialize() - guard let emulationContext = emulationContext else { return } - emulationContext.notifyOperationModeChanged() + guard let system = system else { return } + system.notifyOperationModeChanged() } } init() { - hydraLoaderPluginManagerRefresh() isHandheldMode = hydraConfigGetHandheldMode().pointee let gamePathsOption = hydraConfigGetGamePaths() @@ -30,8 +30,8 @@ class GlobalState: ObservableObject { } func refreshLoaderPluginManager() { - hydraLoaderPluginManagerRefresh() - loaderPluginChangeID += 1 + loaderPluginManager.refresh() + loaderPluginRefreshID += 1 } } @@ -62,6 +62,7 @@ struct HydraApp: App { Window("Texture Viewer", id: "texture-viewer") { TextureViewer() + .environmentObject(globalState) } .defaultLaunchBehavior(.suppressed) diff --git a/src/frontend/swiftui/MenuCommands.swift b/src/frontend/swiftui/MenuCommands.swift index fe0952f1..2692b6cb 100644 --- a/src/frontend/swiftui/MenuCommands.swift +++ b/src/frontend/swiftui/MenuCommands.swift @@ -43,8 +43,8 @@ struct MenuCommands: Commands { CommandGroup(after: .sidebar) { Button("Take Screenshot", systemImage: "camera") { - guard let emulationContext = globalState.emulationContext else { return } - emulationContext.takeScreenshot() + guard let system = globalState.system else { return } + system.takeScreenshot() } .keyboardShortcut(KeyEquivalent("t"), modifiers: .command) } @@ -61,8 +61,8 @@ struct MenuCommands: Commands { CommandMenu("Debug") { Button("Capture GPU Frame") { - guard let emulationContext = globalState.emulationContext else { return } - emulationContext.captureGpuFrame() + guard let system = globalState.system else { return } + system.captureGpuFrame() } .keyboardShortcut(KeyEquivalent("p"), modifiers: .command) } diff --git a/src/frontend/swiftui/MetalView.swift b/src/frontend/swiftui/MetalView.swift index 1d93ce5a..cba44ca0 100644 --- a/src/frontend/swiftui/MetalView.swift +++ b/src/frontend/swiftui/MetalView.swift @@ -2,15 +2,15 @@ import MetalKit import SwiftUI class MetalLayerCoordinator: NSObject { - @Binding var emulationContext: HydraEmulationContext? + @Binding var system: HydraSystem? @Binding var fps: Int private var layer: CAMetalLayer? = nil private var displayLink: CADisplayLink? = nil private var surfaceSet = false - init(emulationContext: Binding, fps: Binding) { - self._emulationContext = emulationContext + init(system: Binding, fps: Binding) { + self._system = system self._fps = fps super.init() } @@ -43,26 +43,26 @@ class MetalLayerCoordinator: NSObject { #endif @objc func handleDisplayLink() { - if let emulationContext = emulationContext { + if let system = system { // Set the surface if its not already set if !self.surfaceSet { guard let layer = self.layer else { return } - emulationContext.surface = Unmanaged.passUnretained(layer).toOpaque() + system.surface = Unmanaged.passUnretained(layer).toOpaque() self.surfaceSet = true } // Present var dtAverageUpdated = false - emulationContext.progressFrame( + system.progressFrame( width: UInt32(self.layer!.drawableSize.width), height: UInt32(self.layer!.drawableSize.height), dtAverageUpdated: &dtAverageUpdated) // Update if dtAverageUpdated { - let dt = emulationContext.getLastDeltaTimeAverage() + let dt = system.getLastDeltaTimeAverage() if dt != 0.0 { fps = Int((1.0 / dt).rounded()) } else { @@ -100,7 +100,7 @@ class MetalLayerCoordinator: NSObject { func makeCoordinator() -> MetalLayerCoordinator { return MetalLayerCoordinator( - emulationContext: $globalState.emulationContext, fps: self.$fps) + system: $globalState.system, fps: self.$fps) } } #else @@ -137,7 +137,7 @@ class MetalLayerCoordinator: NSObject { } func makeCoordinator() -> MetalLayerCoordinator { - return MetalLayerCoordinator(emulationContext: $globalState.emulationContext, fps: $fps) + return MetalLayerCoordinator(system: $globalState.system, fps: $fps) } } #endif diff --git a/src/frontend/swiftui/texture_viewer/TextureListView.swift b/src/frontend/swiftui/texture_viewer/TextureListView.swift index 68fd4979..7118f414 100644 --- a/src/frontend/swiftui/texture_viewer/TextureListView.swift +++ b/src/frontend/swiftui/texture_viewer/TextureListView.swift @@ -42,6 +42,8 @@ struct TextureSizeView: View { } struct TextureListView: View { + @EnvironmentObject var globalState: GlobalState + @State private var refreshID = 0 @AppStorage("sizeFormat") private var sizeFormat: SizeFormat = .decimal @@ -106,11 +108,11 @@ struct TextureListView: View { } func load() { - hydraTextureCacheLock() + globalState.system!.textureCacheLock() self.textures.removeAll() - for i in 0..