diff options
author | Lioncash <mathew1800@gmail.com> | 2018-08-30 10:50:54 -0400 |
---|---|---|
committer | Lioncash <mathew1800@gmail.com> | 2018-08-31 07:16:57 -0400 |
commit | e2457418dae19b889b2ad85255bb95d4cd0e4bff (patch) | |
tree | 76ad194f1cc1933f7907223dbb2542b3614576e5 | |
parent | 5094dfa081c7275e35496374a42996b11f0f6005 (diff) |
core: Make the main System class use the PImpl idiom
core.h is kind of a massive header in terms what it includes within
itself. It includes VFS utilities, kernel headers, file_sys header,
ARM-related headers, etc. This means that changing anything in the
headers included by core.h essentially requires you to rebuild almost
all of core.
Instead, we can modify the System class to use the PImpl idiom, which
allows us to move all of those headers to the cpp file and forward
declare the bulk of the types that would otherwise be included, reducing
compile times. This change specifically only performs the PImpl portion.
-rw-r--r-- | src/core/core.cpp | 515 | ||||
-rw-r--r-- | src/core/core.h | 138 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 3 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 7 |
5 files changed, 387 insertions, 279 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 2293669e5b..75c259068f 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -27,135 +27,299 @@ namespace Core { /*static*/ System System::s_instance; -System::System() = default; +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; + Common::SplitPath(path, &dir_name, &filename, nullptr); + if (filename == "00") { + const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read); + std::vector<FileSys::VirtualFile> concat; + for (u8 i = 0; i < 0x10; ++i) { + auto next = dir->GetFile(fmt::format("{:02X}", i)); + if (next != nullptr) + concat.push_back(std::move(next)); + else { + next = dir->GetFile(fmt::format("{:02x}", i)); + if (next != nullptr) + concat.push_back(std::move(next)); + else + break; + } + } -System::~System() = default; + if (concat.empty()) + return nullptr; + + return FileSys::ConcatenateFiles(concat, dir->GetName()); + } + + return vfs->OpenFile(path, FileSys::Mode::Read); +} /// Runs a CPU core while the system is powered on -static void RunCpuCore(std::shared_ptr<Cpu> cpu_state) { +void RunCpuCore(std::shared_ptr<Cpu> cpu_state) { while (Core::System::GetInstance().IsPoweredOn()) { cpu_state->RunLoop(true); } } +} // Anonymous namespace -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; +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]; } - // Otherwise, use single-threaded mode active_core variable - return *cpu_cores[active_core]; -} + ResultStatus RunLoop(bool tight_loop) { + status = ResultStatus::Success; -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]; - // 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 (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; + } + } + } - // 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; } - for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { - cpu_cores[active_core]->RunLoop(tight_loop); + 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<FileSys::RealVfsFilesystem>(); + + current_process = Kernel::Process::Create(kernel, "main"); + + cpu_barrier = std::make_shared<CpuBarrier>(); + 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>(cpu_exclusive_monitor, cpu_barrier, index); + } + + telemetry_session = std::make_unique<Core::TelemetrySession>(); + service_manager = std::make_shared<Service::SM::ServiceManager>(); + + Service::Init(service_manager, virtual_filesystem); + GDBStub::Init(); + + renderer = VideoCore::CreateRenderer(emu_window); + if (!renderer->Init()) { + return ResultStatus::ErrorVideoCore; + } + + gpu_core = std::make_unique<Tegra::GPU>(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) { - // Cores 1-3 are run on other threads in this mode - break; + for (size_t index = 0; index < cpu_core_threads.size(); ++index) { + cpu_core_threads[index] = + std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]); + thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; + } } - } - if (GDBStub::IsServerEnabled()) { - GDBStub::SetCpuStepFlag(false); + LOG_DEBUG(Core, "Initialized OK"); + + // Reset counters and set time origin to current frame + GetAndResetPerfStats(); + perf_stats.BeginSystemFrame(); + + return ResultStatus::Success; } - return status; -} + ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { + app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); -System::ResultStatus System::SingleStep() { - return RunLoop(false); -} + if (!app_loader) { + LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); + return ResultStatus::ErrorGetLoader; + } + std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode = + app_loader->LoadKernelSystemMode(); -static 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; - Common::SplitPath(path, &dir_name, &filename, nullptr); - if (filename == "00") { - const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read); - std::vector<FileSys::VirtualFile> concat; - for (u8 i = 0; i < 0x10; ++i) { - auto next = dir->GetFile(fmt::format("{:02X}", i)); - if (next != nullptr) - concat.push_back(std::move(next)); - else { - next = dir->GetFile(fmt::format("{:02x}", i)); - if (next != nullptr) - concat.push_back(std::move(next)); - else - break; - } + if (system_mode.second != Loader::ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", + static_cast<int>(system_mode.second)); + + return ResultStatus::ErrorSystemMode; } - if (concat.empty()) - return nullptr; + ResultStatus init_result{Init(emu_window)}; + if (init_result != ResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", + static_cast<int>(init_result)); + Shutdown(); + return init_result; + } - return FileSys::ConcatenateFiles(concat, dir->GetName()); + 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<int>(load_result)); + Shutdown(); + + return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + + static_cast<u32>(load_result)); + } + status = ResultStatus::Success; + return status; } - return vfs->OpenFile(path, FileSys::Mode::Read); -} + 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(); -System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { - app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); + // Shutdown kernel and core timing + kernel.Shutdown(); + CoreTiming::Shutdown(); + + // Close app loader + app_loader.reset(); - if (!app_loader) { - LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); - return ResultStatus::ErrorGetLoader; + LOG_DEBUG(Core, "Shutdown OK"); } - std::pair<boost::optional<u32>, 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<int>(system_mode.second)); + Loader::ResultStatus GetGameName(std::string& out) const { + if (app_loader == nullptr) + return Loader::ResultStatus::ErrorNotInitialized; + return app_loader->ReadTitle(out); + } - return ResultStatus::ErrorSystemMode; + void SetStatus(ResultStatus new_status, const char* details = nullptr) { + status = new_status; + if (details) { + status_details = details; + } } - ResultStatus init_result{Init(emu_window)}; - if (init_result != ResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", - static_cast<int>(init_result)); - System::Shutdown(); - return init_result; + PerfStats::Results GetAndResetPerfStats() { + return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); } - 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<int>(load_result)); - System::Shutdown(); + Kernel::KernelCore kernel; + /// RealVfsFilesystem instance + FileSys::VirtualFilesystem virtual_filesystem; + /// AppLoader used to load the current executing application + std::unique_ptr<Loader::AppLoader> app_loader; + std::unique_ptr<VideoCore::RendererBase> renderer; + std::unique_ptr<Tegra::GPU> gpu_core; + std::shared_ptr<Tegra::DebugContext> debug_context; + Kernel::SharedPtr<Kernel::Process> current_process; + std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor; + std::shared_ptr<CpuBarrier> cpu_barrier; + std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores; + std::array<std::unique_ptr<std::thread>, 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::SM::ServiceManager> service_manager; + + /// Telemetry session for this emulation session + std::unique_ptr<Core::TelemetrySession> telemetry_session; + + ResultStatus status = ResultStatus::Success; + std::string status_details = ""; + + /// Map of guest threads to CPU cores + std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu; + + Core::PerfStats perf_stats; + Core::FrameLimiter frame_limiter; +}; + +System::System() : impl{std::make_unique<Impl>()} {} +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); +} - return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + - static_cast<u32>(load_result)); +void System::InvalidateCpuInstructionCaches() { + for (auto& cpu : impl->cpu_cores) { + cpu->ArmInterface().ClearInstructionCache(); } - status = ResultStatus::Success; - return status; +} + +System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { + return impl->Load(emu_window, filepath); +} + +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(); } -const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) { - ASSERT(core_index < NUM_CPU_CORES); - return cpu_cores[core_index]->Scheduler(); +Core::TelemetrySession& System::TelemetrySession() const { + return *impl->telemetry_session; } -Kernel::KernelCore& System::Kernel() { - return kernel; +ARM_Interface& System::CurrentArmInterface() { + return CurrentCpuCore().ArmInterface(); } -const Kernel::KernelCore& System::Kernel() const { - return kernel; +size_t System::CurrentCoreIndex() { + return CurrentCpuCore().CoreIndex(); +} + +Kernel::Scheduler& System::CurrentScheduler() { + return *CurrentCpuCore().Scheduler(); +} + +const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) { + ASSERT(core_index < NUM_CPU_CORES); + return impl->cpu_cores[core_index]->Scheduler(); +} + +Kernel::SharedPtr<Kernel::Process>& 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]; } -System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { - LOG_DEBUG(HW_Memory, "initialized OK"); +ExclusiveMonitor& System::Monitor() { + return *impl->cpu_exclusive_monitor; +} - CoreTiming::Init(); - kernel.Initialize(); +Tegra::GPU& System::GPU() { + return *impl->gpu_core; +} - // Create a default fs if one doesn't already exist. - if (virtual_filesystem == nullptr) - virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>(); +const Tegra::GPU& System::GPU() const { + return *impl->gpu_core; +} - current_process = Kernel::Process::Create(kernel, "main"); +VideoCore::RendererBase& System::Renderer() { + return *impl->renderer; +} - cpu_barrier = std::make_shared<CpuBarrier>(); - 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>(cpu_exclusive_monitor, cpu_barrier, index); - } +const VideoCore::RendererBase& System::Renderer() const { + return *impl->renderer; +} - telemetry_session = std::make_unique<Core::TelemetrySession>(); - service_manager = std::make_shared<Service::SM::ServiceManager>(); +Kernel::KernelCore& System::Kernel() { + return impl->kernel; +} - Service::Init(service_manager, virtual_filesystem); - GDBStub::Init(); +const Kernel::KernelCore& System::Kernel() const { + return impl->kernel; +} - renderer = VideoCore::CreateRenderer(emu_window); - if (!renderer->Init()) { - return ResultStatus::ErrorVideoCore; - } +Core::PerfStats& System::GetPerfStats() { + return impl->perf_stats; +} - gpu_core = std::make_unique<Tegra::GPU>(renderer->Rasterizer()); +const Core::PerfStats& System::GetPerfStats() const { + return impl->perf_stats; +} - // 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<std::thread>(RunCpuCore, cpu_cores[index + 1]); - thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; - } - } +Core::FrameLimiter& System::FrameLimiter() { + return impl->frame_limiter; +} - LOG_DEBUG(Core, "Initialized OK"); +const Core::FrameLimiter& System::FrameLimiter() const { + return impl->frame_limiter; +} - // Reset counters and set time origin to current frame - GetAndResetPerfStats(); - perf_stats.BeginSystemFrame(); +Loader::ResultStatus System::GetGameName(std::string& out) const { + return impl->GetGameName(out); +} - return ResultStatus::Success; +void System::SetStatus(ResultStatus new_status, const char* details) { + impl->SetStatus(new_status, details); } -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(); +const std::string& System::GetStatusDetails() const { + return impl->status_details; +} - // Shutdown kernel and core timing - kernel.Shutdown(); - CoreTiming::Shutdown(); +Loader::AppLoader& System::GetAppLoader() const { + return *impl->app_loader; +} - // Close app loader - app_loader.reset(); +void System::SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) { + impl->debug_context = std::move(context); +} - LOG_DEBUG(Core, "Shutdown OK"); +std::shared_ptr<Tegra::DebugContext> 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) { + return impl->Init(emu_window); +} + +void System::Shutdown() { + 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 2c18f7193f..984e8f94c1 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<Kernel::Scheduler>& Scheduler(size_t core_index); /// Gets the current process - Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { - return current_process; - } + Kernel::SharedPtr<Kernel::Process>& 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; - /// 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); - } + /// Provides a reference to the internal PerfStats instance. + Core::PerfStats& GetPerfStats(); - PerfStats perf_stats; - FrameLimiter frame_limiter; + /// Provides a constant reference to the internal PerfStats instance. + const Core::PerfStats& GetPerfStats() const; - void SetStatus(ResultStatus new_status, const char* details = nullptr) { - status = new_status; - if (details) { - status_details = details; - } - } + /// Provides a reference to the frame limiter; + Core::FrameLimiter& FrameLimiter(); - const std::string& GetStatusDetails() const { - return status_details; - } + /// Provides a constant referent to the frame limiter + const Core::FrameLimiter& FrameLimiter() const; - Loader::AppLoader& GetAppLoader() const { - return *app_loader; - } + /// Gets the name of the current game + Loader::ResultStatus GetGameName(std::string& out) const; + + void SetStatus(ResultStatus new_status, const char* details); + + const std::string& GetStatusDetails() const; + + Loader::AppLoader& GetAppLoader() const; Service::SM::ServiceManager& ServiceManager(); const Service::SM::ServiceManager& ServiceManager() const; - void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) { - debug_context = std::move(context); - } + void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context); - std::shared_ptr<Tegra::DebugContext> GetGPUDebugContext() const { - return debug_context; - } + std::shared_ptr<Tegra::DebugContext> 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<Loader::AppLoader> app_loader; - std::unique_ptr<VideoCore::RendererBase> renderer; - std::unique_ptr<Tegra::GPU> gpu_core; - std::shared_ptr<Tegra::DebugContext> debug_context; - Kernel::SharedPtr<Kernel::Process> current_process; - std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor; - std::shared_ptr<CpuBarrier> cpu_barrier; - std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores; - std::array<std::unique_ptr<std::thread>, 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::SM::ServiceManager> service_manager; - - /// Telemetry session for this emulation session - std::unique_ptr<Core::TelemetrySession> telemetry_session; + struct Impl; + std::unique_ptr<Impl> impl; static System s_instance; - - ResultStatus status = ResultStatus::Success; - std::string status_details = ""; - - /// Map of guest threads to CPU cores - std::map<std::thread::id, std::shared_ptr<Cpu>> 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 8bc49935a8..0b37098e16 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 3996c24fea..06040da6f9 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 73d6419b40..3c4a9f17c5 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<const Tegra::FramebufferConfig&> 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<const Tegra::FramebufferConfig& render_window.PollEvents(); - Core::System::GetInstance().frame_limiter.DoFrameLimiting(CoreTiming::GetGlobalTimeUs()); - Core::System::GetInstance().perf_stats.BeginSystemFrame(); + Core::System::GetInstance().FrameLimiter().DoFrameLimiting(CoreTiming::GetGlobalTimeUs()); + Core::System::GetInstance().GetPerfStats().BeginSystemFrame(); // Restore the rasterizer state prev_state.Apply(); |