mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #1204 from lioncash/pimpl
core: Make the main System class use the PImpl idiom
This commit is contained in:
		
						commit
						f08d24e9c0
					
				| @ -27,19 +27,48 @@ 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
 | ||||
| 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()); | ||||
| @ -51,7 +80,7 @@ Cpu& System::CurrentCpuCore() { | ||||
|         return *cpu_cores[active_core]; | ||||
|     } | ||||
| 
 | ||||
| System::ResultStatus System::RunLoop(bool tight_loop) { | ||||
|     ResultStatus RunLoop(bool tight_loop) { | ||||
|         status = ResultStatus::Success; | ||||
| 
 | ||||
|         // Update thread_to_cpu in case Core 0 is run from a different host thread
 | ||||
| @ -86,110 +115,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) { | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
| System::ResultStatus System::SingleStep() { | ||||
|     return RunLoop(false); | ||||
| } | ||||
| 
 | ||||
| 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 (concat.empty()) | ||||
|             return nullptr; | ||||
| 
 | ||||
|         return FileSys::ConcatenateFiles(concat, dir->GetName()); | ||||
|     } | ||||
| 
 | ||||
|     return vfs->OpenFile(path, FileSys::Mode::Read); | ||||
| } | ||||
| 
 | ||||
| System::ResultStatus System::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<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)); | ||||
| 
 | ||||
|         return ResultStatus::ErrorSystemMode; | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
|     } | ||||
| 
 | ||||
|     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(); | ||||
| 
 | ||||
|         return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + | ||||
|                                          static_cast<u32>(load_result)); | ||||
|     } | ||||
|     status = ResultStatus::Success; | ||||
|     return status; | ||||
| } | ||||
| 
 | ||||
| void System::PrepareReschedule() { | ||||
|     CurrentCpuCore().PrepareReschedule(); | ||||
| } | ||||
| 
 | ||||
| PerfStats::Results System::GetAndResetPerfStats() { | ||||
|     return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); | ||||
| } | ||||
| 
 | ||||
| const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) { | ||||
|     ASSERT(core_index < NUM_CPU_CORES); | ||||
|     return cpu_cores[core_index]->Scheduler(); | ||||
| } | ||||
| 
 | ||||
| Kernel::KernelCore& System::Kernel() { | ||||
|     return kernel; | ||||
| } | ||||
| 
 | ||||
| const Kernel::KernelCore& System::Kernel() const { | ||||
|     return kernel; | ||||
| } | ||||
| 
 | ||||
| ARM_Interface& System::ArmInterface(size_t core_index) { | ||||
|     ASSERT(core_index < NUM_CPU_CORES); | ||||
|     return cpu_cores[core_index]->ArmInterface(); | ||||
| } | ||||
| 
 | ||||
| Cpu& System::CpuCore(size_t core_index) { | ||||
|     ASSERT(core_index < NUM_CPU_CORES); | ||||
|     return *cpu_cores[core_index]; | ||||
| } | ||||
| 
 | ||||
| System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | ||||
|     ResultStatus Init(Frontend::EmuWindow& emu_window) { | ||||
|         LOG_DEBUG(HW_Memory, "initialized OK"); | ||||
| 
 | ||||
|         CoreTiming::Init(); | ||||
| @ -240,7 +166,44 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { | ||||
|         return ResultStatus::Success; | ||||
|     } | ||||
| 
 | ||||
| void System::Shutdown() { | ||||
|     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<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)); | ||||
| 
 | ||||
|             return ResultStatus::ErrorSystemMode; | ||||
|         } | ||||
| 
 | ||||
|         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; | ||||
|         } | ||||
| 
 | ||||
|         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; | ||||
|     } | ||||
| 
 | ||||
|     void Shutdown() { | ||||
|         // Log last frame performance stats
 | ||||
|         auto perf_results = GetAndResetPerfStats(); | ||||
|         Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", | ||||
| @ -282,12 +245,216 @@ void System::Shutdown() { | ||||
|         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<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); | ||||
| } | ||||
| 
 | ||||
| void System::InvalidateCpuInstructionCaches() { | ||||
|     for (auto& cpu : impl->cpu_cores) { | ||||
|         cpu->ArmInterface().ClearInstructionCache(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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() { | ||||
|     CurrentCpuCore().PrepareReschedule(); | ||||
| } | ||||
| 
 | ||||
| PerfStats::Results System::GetAndResetPerfStats() { | ||||
|     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<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 impl->cpu_cores[core_index]->ArmInterface(); | ||||
| } | ||||
| 
 | ||||
| Cpu& System::CpuCore(size_t core_index) { | ||||
|     ASSERT(core_index < NUM_CPU_CORES); | ||||
|     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<Tegra::DebugContext> context) { | ||||
|     impl->debug_context = std::move(context); | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|  | ||||
							
								
								
									
										138
									
								
								src/core/core.h
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								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; | ||||
| 
 | ||||
|     /// 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<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() { | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|         } | ||||
|  | ||||
| @ -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(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei