diff --git a/src/core/core.cpp b/src/core/core.cpp index 2293669e5..75c259068 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -27,71 +27,9 @@ namespace Core { /*static*/ System System::s_instance; -System::System() = default; - -System::~System() = default; - -/// Runs a CPU core while the system is powered on -static void RunCpuCore(std::shared_ptr cpu_state) { - while (Core::System::GetInstance().IsPoweredOn()) { - cpu_state->RunLoop(true); - } -} - -Cpu& System::CurrentCpuCore() { - // If multicore is enabled, use host thread to figure out the current CPU core - if (Settings::values.use_multi_core) { - const auto& search = thread_to_cpu.find(std::this_thread::get_id()); - ASSERT(search != thread_to_cpu.end()); - ASSERT(search->second); - return *search->second; - } - - // Otherwise, use single-threaded mode active_core variable - return *cpu_cores[active_core]; -} - -System::ResultStatus System::RunLoop(bool tight_loop) { - status = ResultStatus::Success; - - // Update thread_to_cpu in case Core 0 is run from a different host thread - thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; - - if (GDBStub::IsServerEnabled()) { - GDBStub::HandlePacket(); - - // If the loop is halted and we want to step, use a tiny (1) number of instructions to - // execute. Otherwise, get out of the loop function. - if (GDBStub::GetCpuHaltFlag()) { - if (GDBStub::GetCpuStepFlag()) { - tight_loop = false; - } else { - return ResultStatus::Success; - } - } - } - - for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { - cpu_cores[active_core]->RunLoop(tight_loop); - if (Settings::values.use_multi_core) { - // Cores 1-3 are run on other threads in this mode - break; - } - } - - if (GDBStub::IsServerEnabled()) { - GDBStub::SetCpuStepFlag(false); - } - - return status; -} - -System::ResultStatus System::SingleStep() { - return RunLoop(false); -} - -static FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, - const std::string& path) { +namespace { +FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, + const std::string& path) { // To account for split 00+01+etc files. std::string dir_name; std::string filename; @@ -121,41 +59,267 @@ static FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem return vfs->OpenFile(path, FileSys::Mode::Read); } +/// Runs a CPU core while the system is powered on +void RunCpuCore(std::shared_ptr cpu_state) { + while (Core::System::GetInstance().IsPoweredOn()) { + cpu_state->RunLoop(true); + } +} +} // Anonymous namespace + +struct System::Impl { + Cpu& CurrentCpuCore() { + if (Settings::values.use_multi_core) { + const auto& search = thread_to_cpu.find(std::this_thread::get_id()); + ASSERT(search != thread_to_cpu.end()); + ASSERT(search->second); + return *search->second; + } + + // Otherwise, use single-threaded mode active_core variable + return *cpu_cores[active_core]; + } + + ResultStatus RunLoop(bool tight_loop) { + status = ResultStatus::Success; + + // Update thread_to_cpu in case Core 0 is run from a different host thread + thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; + + if (GDBStub::IsServerEnabled()) { + GDBStub::HandlePacket(); + + // If the loop is halted and we want to step, use a tiny (1) number of instructions to + // execute. Otherwise, get out of the loop function. + if (GDBStub::GetCpuHaltFlag()) { + if (GDBStub::GetCpuStepFlag()) { + tight_loop = false; + } else { + return ResultStatus::Success; + } + } + } + + for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { + cpu_cores[active_core]->RunLoop(tight_loop); + if (Settings::values.use_multi_core) { + // Cores 1-3 are run on other threads in this mode + break; + } + } + + if (GDBStub::IsServerEnabled()) { + GDBStub::SetCpuStepFlag(false); + } + + return status; + } + + ResultStatus Init(Frontend::EmuWindow& emu_window) { + LOG_DEBUG(HW_Memory, "initialized OK"); + + CoreTiming::Init(); + kernel.Initialize(); + + // Create a default fs if one doesn't already exist. + if (virtual_filesystem == nullptr) + virtual_filesystem = std::make_shared(); + + current_process = Kernel::Process::Create(kernel, "main"); + + cpu_barrier = std::make_shared(); + cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size()); + for (size_t index = 0; index < cpu_cores.size(); ++index) { + cpu_cores[index] = std::make_shared(cpu_exclusive_monitor, cpu_barrier, index); + } + + telemetry_session = std::make_unique(); + service_manager = std::make_shared(); + + Service::Init(service_manager, virtual_filesystem); + GDBStub::Init(); + + renderer = VideoCore::CreateRenderer(emu_window); + if (!renderer->Init()) { + return ResultStatus::ErrorVideoCore; + } + + gpu_core = std::make_unique(renderer->Rasterizer()); + + // Create threads for CPU cores 1-3, and build thread_to_cpu map + // CPU core 0 is run on the main thread + thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; + if (Settings::values.use_multi_core) { + for (size_t index = 0; index < cpu_core_threads.size(); ++index) { + cpu_core_threads[index] = + std::make_unique(RunCpuCore, cpu_cores[index + 1]); + thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; + } + } + + LOG_DEBUG(Core, "Initialized OK"); + + // Reset counters and set time origin to current frame + GetAndResetPerfStats(); + perf_stats.BeginSystemFrame(); + + return ResultStatus::Success; + } + + ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { + app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); + + if (!app_loader) { + LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); + return ResultStatus::ErrorGetLoader; + } + std::pair, Loader::ResultStatus> system_mode = + app_loader->LoadKernelSystemMode(); + + if (system_mode.second != Loader::ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", + static_cast(system_mode.second)); + + return ResultStatus::ErrorSystemMode; + } + + ResultStatus init_result{Init(emu_window)}; + if (init_result != ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", + static_cast(init_result)); + Shutdown(); + return init_result; + } + + const Loader::ResultStatus load_result{app_loader->Load(current_process)}; + if (load_result != Loader::ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast(load_result)); + Shutdown(); + + return static_cast(static_cast(ResultStatus::ErrorLoader) + + static_cast(load_result)); + } + status = ResultStatus::Success; + return status; + } + + void Shutdown() { + // Log last frame performance stats + auto perf_results = GetAndResetPerfStats(); + Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", + perf_results.emulation_speed * 100.0); + Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", + perf_results.game_fps); + Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", + perf_results.frametime * 1000.0); + + // Shutdown emulation session + renderer.reset(); + GDBStub::Shutdown(); + Service::Shutdown(); + service_manager.reset(); + telemetry_session.reset(); + gpu_core.reset(); + + // Close all CPU/threading state + cpu_barrier->NotifyEnd(); + if (Settings::values.use_multi_core) { + for (auto& thread : cpu_core_threads) { + thread->join(); + thread.reset(); + } + } + thread_to_cpu.clear(); + for (auto& cpu_core : cpu_cores) { + cpu_core.reset(); + } + cpu_barrier.reset(); + + // Shutdown kernel and core timing + kernel.Shutdown(); + CoreTiming::Shutdown(); + + // Close app loader + app_loader.reset(); + + LOG_DEBUG(Core, "Shutdown OK"); + } + + Loader::ResultStatus GetGameName(std::string& out) const { + if (app_loader == nullptr) + return Loader::ResultStatus::ErrorNotInitialized; + return app_loader->ReadTitle(out); + } + + void SetStatus(ResultStatus new_status, const char* details = nullptr) { + status = new_status; + if (details) { + status_details = details; + } + } + + PerfStats::Results GetAndResetPerfStats() { + return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); + } + + Kernel::KernelCore kernel; + /// RealVfsFilesystem instance + FileSys::VirtualFilesystem virtual_filesystem; + /// AppLoader used to load the current executing application + std::unique_ptr app_loader; + std::unique_ptr renderer; + std::unique_ptr gpu_core; + std::shared_ptr debug_context; + Kernel::SharedPtr current_process; + std::shared_ptr cpu_exclusive_monitor; + std::shared_ptr cpu_barrier; + std::array, NUM_CPU_CORES> cpu_cores; + std::array, NUM_CPU_CORES - 1> cpu_core_threads; + size_t active_core{}; ///< Active core, only used in single thread mode + + /// Service manager + std::shared_ptr service_manager; + + /// Telemetry session for this emulation session + std::unique_ptr telemetry_session; + + ResultStatus status = ResultStatus::Success; + std::string status_details = ""; + + /// Map of guest threads to CPU cores + std::map> thread_to_cpu; + + Core::PerfStats perf_stats; + Core::FrameLimiter frame_limiter; +}; + +System::System() : impl{std::make_unique()} {} +System::~System() = default; + +Cpu& System::CurrentCpuCore() { + return impl->CurrentCpuCore(); +} + +System::ResultStatus System::RunLoop(bool tight_loop) { + return impl->RunLoop(tight_loop); +} + +System::ResultStatus System::SingleStep() { + return RunLoop(false); +} + +void System::InvalidateCpuInstructionCaches() { + for (auto& cpu : impl->cpu_cores) { + cpu->ArmInterface().ClearInstructionCache(); + } +} + System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { - app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); + return impl->Load(emu_window, filepath); +} - if (!app_loader) { - LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); - return ResultStatus::ErrorGetLoader; - } - std::pair, Loader::ResultStatus> system_mode = - app_loader->LoadKernelSystemMode(); - - if (system_mode.second != Loader::ResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", - static_cast(system_mode.second)); - - return ResultStatus::ErrorSystemMode; - } - - ResultStatus init_result{Init(emu_window)}; - if (init_result != ResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", - static_cast(init_result)); - System::Shutdown(); - return init_result; - } - - const Loader::ResultStatus load_result{app_loader->Load(current_process)}; - if (load_result != Loader::ResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast(load_result)); - System::Shutdown(); - - return static_cast(static_cast(ResultStatus::ErrorLoader) + - static_cast(load_result)); - } - status = ResultStatus::Success; - return status; +bool System::IsPoweredOn() const { + return impl->cpu_barrier && impl->cpu_barrier->IsAlive(); } void System::PrepareReschedule() { @@ -163,131 +327,134 @@ void System::PrepareReschedule() { } PerfStats::Results System::GetAndResetPerfStats() { - return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); + return impl->GetAndResetPerfStats(); +} + +Core::TelemetrySession& System::TelemetrySession() const { + return *impl->telemetry_session; +} + +ARM_Interface& System::CurrentArmInterface() { + return CurrentCpuCore().ArmInterface(); +} + +size_t System::CurrentCoreIndex() { + return CurrentCpuCore().CoreIndex(); +} + +Kernel::Scheduler& System::CurrentScheduler() { + return *CurrentCpuCore().Scheduler(); } const std::shared_ptr& System::Scheduler(size_t core_index) { ASSERT(core_index < NUM_CPU_CORES); - return cpu_cores[core_index]->Scheduler(); + return impl->cpu_cores[core_index]->Scheduler(); } -Kernel::KernelCore& System::Kernel() { - return kernel; -} - -const Kernel::KernelCore& System::Kernel() const { - return kernel; +Kernel::SharedPtr& System::CurrentProcess() { + return impl->current_process; } ARM_Interface& System::ArmInterface(size_t core_index) { ASSERT(core_index < NUM_CPU_CORES); - return cpu_cores[core_index]->ArmInterface(); + return impl->cpu_cores[core_index]->ArmInterface(); } Cpu& System::CpuCore(size_t core_index) { ASSERT(core_index < NUM_CPU_CORES); - return *cpu_cores[core_index]; + return *impl->cpu_cores[core_index]; +} + +ExclusiveMonitor& System::Monitor() { + return *impl->cpu_exclusive_monitor; +} + +Tegra::GPU& System::GPU() { + return *impl->gpu_core; +} + +const Tegra::GPU& System::GPU() const { + return *impl->gpu_core; +} + +VideoCore::RendererBase& System::Renderer() { + return *impl->renderer; +} + +const VideoCore::RendererBase& System::Renderer() const { + return *impl->renderer; +} + +Kernel::KernelCore& System::Kernel() { + return impl->kernel; +} + +const Kernel::KernelCore& System::Kernel() const { + return impl->kernel; +} + +Core::PerfStats& System::GetPerfStats() { + return impl->perf_stats; +} + +const Core::PerfStats& System::GetPerfStats() const { + return impl->perf_stats; +} + +Core::FrameLimiter& System::FrameLimiter() { + return impl->frame_limiter; +} + +const Core::FrameLimiter& System::FrameLimiter() const { + return impl->frame_limiter; +} + +Loader::ResultStatus System::GetGameName(std::string& out) const { + return impl->GetGameName(out); +} + +void System::SetStatus(ResultStatus new_status, const char* details) { + impl->SetStatus(new_status, details); +} + +const std::string& System::GetStatusDetails() const { + return impl->status_details; +} + +Loader::AppLoader& System::GetAppLoader() const { + return *impl->app_loader; +} + +void System::SetGPUDebugContext(std::shared_ptr context) { + impl->debug_context = std::move(context); +} + +std::shared_ptr System::GetGPUDebugContext() const { + return impl->debug_context; +} + +void System::SetFilesystem(FileSys::VirtualFilesystem vfs) { + impl->virtual_filesystem = std::move(vfs); +} + +FileSys::VirtualFilesystem System::GetFilesystem() const { + return impl->virtual_filesystem; } System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { - LOG_DEBUG(HW_Memory, "initialized OK"); - - CoreTiming::Init(); - kernel.Initialize(); - - // Create a default fs if one doesn't already exist. - if (virtual_filesystem == nullptr) - virtual_filesystem = std::make_shared(); - - current_process = Kernel::Process::Create(kernel, "main"); - - cpu_barrier = std::make_shared(); - cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size()); - for (size_t index = 0; index < cpu_cores.size(); ++index) { - cpu_cores[index] = std::make_shared(cpu_exclusive_monitor, cpu_barrier, index); - } - - telemetry_session = std::make_unique(); - service_manager = std::make_shared(); - - Service::Init(service_manager, virtual_filesystem); - GDBStub::Init(); - - renderer = VideoCore::CreateRenderer(emu_window); - if (!renderer->Init()) { - return ResultStatus::ErrorVideoCore; - } - - gpu_core = std::make_unique(renderer->Rasterizer()); - - // Create threads for CPU cores 1-3, and build thread_to_cpu map - // CPU core 0 is run on the main thread - thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; - if (Settings::values.use_multi_core) { - for (size_t index = 0; index < cpu_core_threads.size(); ++index) { - cpu_core_threads[index] = - std::make_unique(RunCpuCore, cpu_cores[index + 1]); - thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; - } - } - - LOG_DEBUG(Core, "Initialized OK"); - - // Reset counters and set time origin to current frame - GetAndResetPerfStats(); - perf_stats.BeginSystemFrame(); - - return ResultStatus::Success; + return impl->Init(emu_window); } void System::Shutdown() { - // Log last frame performance stats - auto perf_results = GetAndResetPerfStats(); - Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", - perf_results.emulation_speed * 100.0); - Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Framerate", - perf_results.game_fps); - Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", - perf_results.frametime * 1000.0); - - // Shutdown emulation session - renderer.reset(); - GDBStub::Shutdown(); - Service::Shutdown(); - service_manager.reset(); - telemetry_session.reset(); - gpu_core.reset(); - - // Close all CPU/threading state - cpu_barrier->NotifyEnd(); - if (Settings::values.use_multi_core) { - for (auto& thread : cpu_core_threads) { - thread->join(); - thread.reset(); - } - } - thread_to_cpu.clear(); - for (auto& cpu_core : cpu_cores) { - cpu_core.reset(); - } - cpu_barrier.reset(); - - // Shutdown kernel and core timing - kernel.Shutdown(); - CoreTiming::Shutdown(); - - // Close app loader - app_loader.reset(); - - LOG_DEBUG(Core, "Shutdown OK"); + impl->Shutdown(); } Service::SM::ServiceManager& System::ServiceManager() { - return *service_manager; + return *impl->service_manager; } const Service::SM::ServiceManager& System::ServiceManager() const { - return *service_manager; + return *impl->service_manager; } } // namespace Core diff --git a/src/core/core.h b/src/core/core.h index 2c18f7193..984e8f94c 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -94,11 +94,7 @@ public: * This function should only be used by GDB Stub to support breakpoints, memory updates and * step/continue commands. */ - void InvalidateCpuInstructionCaches() { - for (auto& cpu : cpu_cores) { - cpu->ArmInterface().ClearInstructionCache(); - } - } + void InvalidateCpuInstructionCaches(); /// Shutdown the emulated system. void Shutdown(); @@ -117,17 +113,13 @@ public: * application). * @returns True if the emulated system is powered on, otherwise false. */ - bool IsPoweredOn() const { - return cpu_barrier && cpu_barrier->IsAlive(); - } + bool IsPoweredOn() const; /** * Returns a reference to the telemetry session for this emulation session. * @returns Reference to the telemetry session. */ - Core::TelemetrySession& TelemetrySession() const { - return *telemetry_session; - } + Core::TelemetrySession& TelemetrySession() const; /// Prepare the core emulation for a reschedule void PrepareReschedule(); @@ -136,14 +128,13 @@ public: PerfStats::Results GetAndResetPerfStats(); /// Gets an ARM interface to the CPU core that is currently running - ARM_Interface& CurrentArmInterface() { - return CurrentCpuCore().ArmInterface(); - } + ARM_Interface& CurrentArmInterface(); /// Gets the index of the currently running CPU core - size_t CurrentCoreIndex() { - return CurrentCpuCore().CoreIndex(); - } + size_t CurrentCoreIndex(); + + /// Gets the scheduler for the CPU core that is currently running + Kernel::Scheduler& CurrentScheduler(); /// Gets an ARM interface to the CPU core with the specified index ARM_Interface& ArmInterface(size_t core_index); @@ -151,43 +142,26 @@ public: /// Gets a CPU interface to the CPU core with the specified index Cpu& CpuCore(size_t core_index); + /// Gets the exclusive monitor + ExclusiveMonitor& Monitor(); + /// Gets a mutable reference to the GPU interface - Tegra::GPU& GPU() { - return *gpu_core; - } + Tegra::GPU& GPU(); /// Gets an immutable reference to the GPU interface. - const Tegra::GPU& GPU() const { - return *gpu_core; - } + const Tegra::GPU& GPU() const; /// Gets a mutable reference to the renderer. - VideoCore::RendererBase& Renderer() { - return *renderer; - } + VideoCore::RendererBase& Renderer(); /// Gets an immutable reference to the renderer. - const VideoCore::RendererBase& Renderer() const { - return *renderer; - } - - /// Gets the scheduler for the CPU core that is currently running - Kernel::Scheduler& CurrentScheduler() { - return *CurrentCpuCore().Scheduler(); - } - - /// Gets the exclusive monitor - ExclusiveMonitor& Monitor() { - return *cpu_exclusive_monitor; - } + const VideoCore::RendererBase& Renderer() const; /// Gets the scheduler for the CPU core with the specified index const std::shared_ptr& Scheduler(size_t core_index); /// Gets the current process - Kernel::SharedPtr& CurrentProcess() { - return current_process; - } + Kernel::SharedPtr& CurrentProcess(); /// Provides a reference to the kernel instance. Kernel::KernelCore& Kernel(); @@ -195,49 +169,37 @@ public: /// Provides a constant reference to the kernel instance. const Kernel::KernelCore& Kernel() const; + /// Provides a reference to the internal PerfStats instance. + Core::PerfStats& GetPerfStats(); + + /// Provides a constant reference to the internal PerfStats instance. + const Core::PerfStats& GetPerfStats() const; + + /// Provides a reference to the frame limiter; + Core::FrameLimiter& FrameLimiter(); + + /// Provides a constant referent to the frame limiter + const Core::FrameLimiter& FrameLimiter() const; + /// Gets the name of the current game - Loader::ResultStatus GetGameName(std::string& out) const { - if (app_loader == nullptr) - return Loader::ResultStatus::ErrorNotInitialized; - return app_loader->ReadTitle(out); - } + Loader::ResultStatus GetGameName(std::string& out) const; - PerfStats perf_stats; - FrameLimiter frame_limiter; + void SetStatus(ResultStatus new_status, const char* details); - void SetStatus(ResultStatus new_status, const char* details = nullptr) { - status = new_status; - if (details) { - status_details = details; - } - } + const std::string& GetStatusDetails() const; - const std::string& GetStatusDetails() const { - return status_details; - } - - Loader::AppLoader& GetAppLoader() const { - return *app_loader; - } + Loader::AppLoader& GetAppLoader() const; Service::SM::ServiceManager& ServiceManager(); const Service::SM::ServiceManager& ServiceManager() const; - void SetGPUDebugContext(std::shared_ptr context) { - debug_context = std::move(context); - } + void SetGPUDebugContext(std::shared_ptr context); - std::shared_ptr GetGPUDebugContext() const { - return debug_context; - } + std::shared_ptr GetGPUDebugContext() const; - void SetFilesystem(FileSys::VirtualFilesystem vfs) { - virtual_filesystem = std::move(vfs); - } + void SetFilesystem(FileSys::VirtualFilesystem vfs); - FileSys::VirtualFilesystem GetFilesystem() const { - return virtual_filesystem; - } + FileSys::VirtualFilesystem GetFilesystem() const; private: System(); @@ -253,34 +215,10 @@ private: */ ResultStatus Init(Frontend::EmuWindow& emu_window); - Kernel::KernelCore kernel; - /// RealVfsFilesystem instance - FileSys::VirtualFilesystem virtual_filesystem; - /// AppLoader used to load the current executing application - std::unique_ptr app_loader; - std::unique_ptr renderer; - std::unique_ptr gpu_core; - std::shared_ptr debug_context; - Kernel::SharedPtr current_process; - std::shared_ptr cpu_exclusive_monitor; - std::shared_ptr cpu_barrier; - std::array, NUM_CPU_CORES> cpu_cores; - std::array, NUM_CPU_CORES - 1> cpu_core_threads; - size_t active_core{}; ///< Active core, only used in single thread mode - - /// Service manager - std::shared_ptr service_manager; - - /// Telemetry session for this emulation session - std::unique_ptr telemetry_session; + struct Impl; + std::unique_ptr impl; static System s_instance; - - ResultStatus status = ResultStatus::Success; - std::string status_details = ""; - - /// Map of guest threads to CPU cores - std::map> thread_to_cpu; }; inline ARM_Interface& CurrentArmInterface() { diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 8bc49935a..0b37098e1 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -7,6 +7,7 @@ #include "core/core.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" #include "core/hle/service/nvdrv/devices/nvmap.h" +#include "core/perf_stats.h" #include "video_core/gpu.h" #include "video_core/renderer_base.h" @@ -31,7 +32,7 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 transform, crop_rect}; auto& instance = Core::System::GetInstance(); - instance.perf_stats.EndGameFrame(); + instance.GetPerfStats().EndGameFrame(); instance.Renderer().SwapBuffers(framebuffer); } diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 3996c24fe..06040da6f 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -17,6 +17,7 @@ #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "core/hle/service/nvflinger/nvflinger.h" +#include "core/perf_stats.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" @@ -137,7 +138,7 @@ void NVFlinger::Compose() { auto& system_instance = Core::System::GetInstance(); // There was no queued buffer to draw, render previous frame - system_instance.perf_stats.EndGameFrame(); + system_instance.GetPerfStats().EndGameFrame(); system_instance.Renderer().SwapBuffers({}); continue; } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 73d6419b4..3c4a9f17c 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -14,6 +14,7 @@ #include "core/core_timing.h" #include "core/frontend/emu_window.h" #include "core/memory.h" +#include "core/perf_stats.h" #include "core/settings.h" #include "core/tracer/recorder.h" #include "video_core/renderer_opengl/gl_rasterizer.h" @@ -115,7 +116,7 @@ RendererOpenGL::~RendererOpenGL() = default; void RendererOpenGL::SwapBuffers(boost::optional framebuffer) { ScopeAcquireGLContext acquire_context{render_window}; - Core::System::GetInstance().perf_stats.EndSystemFrame(); + Core::System::GetInstance().GetPerfStats().EndSystemFrame(); // Maintain the rasterizer's state as a priority OpenGLState prev_state = OpenGLState::GetCurState(); @@ -140,8 +141,8 @@ void RendererOpenGL::SwapBuffers(boost::optional