diff options
| author | 2020-03-19 13:09:32 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:52 -0400 | |
| commit | f2ade343e2492c213ac93680a55e9bed712dac9a (patch) | |
| tree | 30bce0eb24a0b2b38310f07fa37c7ba881fc8535 /src | |
| parent | GUI: Make multicore only work with Async and add GUI for multicore. (diff) | |
| download | yuzu-f2ade343e2492c213ac93680a55e9bed712dac9a.tar.gz yuzu-f2ade343e2492c213ac93680a55e9bed712dac9a.tar.xz yuzu-f2ade343e2492c213ac93680a55e9bed712dac9a.zip | |
SingleCore: Move Host Timing from a sepparate thread to main cpu thread.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/core.cpp | 2 | ||||
| -rw-r--r-- | src/core/core_timing.cpp | 20 | ||||
| -rw-r--r-- | src/core/core_timing.h | 7 | ||||
| -rw-r--r-- | src/core/cpu_manager.cpp | 17 | ||||
| -rw-r--r-- | src/core/cpu_manager.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 9 |
7 files changed, 48 insertions, 10 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 0f0eb885a..2ca9c0be5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -158,6 +158,8 @@ struct System::Impl { | |||
| 158 | kernel.SetMulticore(is_multicore); | 158 | kernel.SetMulticore(is_multicore); |
| 159 | cpu_manager.SetMulticore(is_multicore); | 159 | cpu_manager.SetMulticore(is_multicore); |
| 160 | cpu_manager.SetAsyncGpu(is_async_gpu); | 160 | cpu_manager.SetAsyncGpu(is_async_gpu); |
| 161 | core_timing.SetMulticore(is_multicore); | ||
| 162 | cpu_manager.SetRenderWindow(emu_window); | ||
| 161 | 163 | ||
| 162 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); | 164 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); |
| 163 | kernel.Initialize(); | 165 | kernel.Initialize(); |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 3438f79ce..189d4aa34 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -55,7 +55,9 @@ void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) { | |||
| 55 | event_fifo_id = 0; | 55 | event_fifo_id = 0; |
| 56 | const auto empty_timed_callback = [](u64, s64) {}; | 56 | const auto empty_timed_callback = [](u64, s64) {}; |
| 57 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); | 57 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); |
| 58 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); | 58 | if (is_multicore) { |
| 59 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); | ||
| 60 | } | ||
| 59 | } | 61 | } |
| 60 | 62 | ||
| 61 | void CoreTiming::Shutdown() { | 63 | void CoreTiming::Shutdown() { |
| @@ -63,7 +65,9 @@ void CoreTiming::Shutdown() { | |||
| 63 | shutting_down = true; | 65 | shutting_down = true; |
| 64 | pause_event.Set(); | 66 | pause_event.Set(); |
| 65 | event.Set(); | 67 | event.Set(); |
| 66 | timer_thread->join(); | 68 | if (timer_thread) { |
| 69 | timer_thread->join(); | ||
| 70 | } | ||
| 67 | ClearPendingEvents(); | 71 | ClearPendingEvents(); |
| 68 | timer_thread.reset(); | 72 | timer_thread.reset(); |
| 69 | has_started = false; | 73 | has_started = false; |
| @@ -78,12 +82,14 @@ void CoreTiming::SyncPause(bool is_paused) { | |||
| 78 | return; | 82 | return; |
| 79 | } | 83 | } |
| 80 | Pause(is_paused); | 84 | Pause(is_paused); |
| 81 | if (!is_paused) { | 85 | if (timer_thread) { |
| 82 | pause_event.Set(); | 86 | if (!is_paused) { |
| 87 | pause_event.Set(); | ||
| 88 | } | ||
| 89 | event.Set(); | ||
| 90 | while (paused_set != is_paused) | ||
| 91 | ; | ||
| 83 | } | 92 | } |
| 84 | event.Set(); | ||
| 85 | while (paused_set != is_paused) | ||
| 86 | ; | ||
| 87 | } | 93 | } |
| 88 | 94 | ||
| 89 | bool CoreTiming::IsRunning() const { | 95 | bool CoreTiming::IsRunning() const { |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 032eb08aa..03f9a5c76 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -67,6 +67,11 @@ public: | |||
| 67 | /// Tears down all timing related functionality. | 67 | /// Tears down all timing related functionality. |
| 68 | void Shutdown(); | 68 | void Shutdown(); |
| 69 | 69 | ||
| 70 | /// Sets if emulation is multicore or single core, must be set before Initialize | ||
| 71 | void SetMulticore(bool is_multicore) { | ||
| 72 | this->is_multicore = is_multicore; | ||
| 73 | } | ||
| 74 | |||
| 70 | /// Pauses/Unpauses the execution of the timer thread. | 75 | /// Pauses/Unpauses the execution of the timer thread. |
| 71 | void Pause(bool is_paused); | 76 | void Pause(bool is_paused); |
| 72 | 77 | ||
| @@ -147,6 +152,8 @@ private: | |||
| 147 | std::atomic<bool> has_started{}; | 152 | std::atomic<bool> has_started{}; |
| 148 | std::function<void(void)> on_thread_init{}; | 153 | std::function<void(void)> on_thread_init{}; |
| 149 | 154 | ||
| 155 | bool is_multicore{}; | ||
| 156 | |||
| 150 | std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{}; | 157 | std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{}; |
| 151 | }; | 158 | }; |
| 152 | 159 | ||
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index d7bd162bc..2aea95a25 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -242,8 +242,11 @@ void CpuManager::SingleCoreRunGuestLoop() { | |||
| 242 | break; | 242 | break; |
| 243 | } | 243 | } |
| 244 | } | 244 | } |
| 245 | physical_core.ClearExclusive(); | ||
| 246 | system.ExitDynarmicProfile(); | 245 | system.ExitDynarmicProfile(); |
| 246 | thread->SetPhantomMode(true); | ||
| 247 | system.CoreTiming().Advance(); | ||
| 248 | thread->SetPhantomMode(false); | ||
| 249 | physical_core.ClearExclusive(); | ||
| 247 | PreemptSingleCore(); | 250 | PreemptSingleCore(); |
| 248 | auto& scheduler = kernel.Scheduler(current_core); | 251 | auto& scheduler = kernel.Scheduler(current_core); |
| 249 | scheduler.TryDoContextSwitch(); | 252 | scheduler.TryDoContextSwitch(); |
| @@ -255,6 +258,7 @@ void CpuManager::SingleCoreRunIdleThread() { | |||
| 255 | while (true) { | 258 | while (true) { |
| 256 | auto& physical_core = kernel.CurrentPhysicalCore(); | 259 | auto& physical_core = kernel.CurrentPhysicalCore(); |
| 257 | PreemptSingleCore(); | 260 | PreemptSingleCore(); |
| 261 | idle_count++; | ||
| 258 | auto& scheduler = physical_core.Scheduler(); | 262 | auto& scheduler = physical_core.Scheduler(); |
| 259 | scheduler.TryDoContextSwitch(); | 263 | scheduler.TryDoContextSwitch(); |
| 260 | } | 264 | } |
| @@ -280,15 +284,24 @@ void CpuManager::SingleCoreRunSuspendThread() { | |||
| 280 | void CpuManager::PreemptSingleCore() { | 284 | void CpuManager::PreemptSingleCore() { |
| 281 | preemption_count = 0; | 285 | preemption_count = 0; |
| 282 | std::size_t old_core = current_core; | 286 | std::size_t old_core = current_core; |
| 283 | current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); | ||
| 284 | auto& scheduler = system.Kernel().Scheduler(old_core); | 287 | auto& scheduler = system.Kernel().Scheduler(old_core); |
| 285 | Kernel::Thread* current_thread = scheduler.GetCurrentThread(); | 288 | Kernel::Thread* current_thread = scheduler.GetCurrentThread(); |
| 289 | if (idle_count >= 4) { | ||
| 290 | current_thread->SetPhantomMode(true); | ||
| 291 | system.CoreTiming().Advance(); | ||
| 292 | current_thread->SetPhantomMode(false); | ||
| 293 | } | ||
| 294 | current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); | ||
| 286 | scheduler.Unload(); | 295 | scheduler.Unload(); |
| 287 | auto& next_scheduler = system.Kernel().Scheduler(current_core); | 296 | auto& next_scheduler = system.Kernel().Scheduler(current_core); |
| 288 | Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); | 297 | Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); |
| 289 | /// May have changed scheduler | 298 | /// May have changed scheduler |
| 290 | auto& current_scheduler = system.Kernel().Scheduler(current_core); | 299 | auto& current_scheduler = system.Kernel().Scheduler(current_core); |
| 291 | current_scheduler.Reload(); | 300 | current_scheduler.Reload(); |
| 301 | auto* currrent_thread2 = current_scheduler.GetCurrentThread(); | ||
| 302 | if (!currrent_thread2->IsIdleThread()) { | ||
| 303 | idle_count = 0; | ||
| 304 | } | ||
| 292 | } | 305 | } |
| 293 | 306 | ||
| 294 | void CpuManager::SingleCorePause(bool paused) { | 307 | void CpuManager::SingleCorePause(bool paused) { |
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 37cef2b12..e6b8612f0 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -104,6 +104,7 @@ private: | |||
| 104 | bool is_multicore{}; | 104 | bool is_multicore{}; |
| 105 | std::atomic<std::size_t> current_core{}; | 105 | std::atomic<std::size_t> current_core{}; |
| 106 | std::size_t preemption_count{}; | 106 | std::size_t preemption_count{}; |
| 107 | std::size_t idle_count{}; | ||
| 107 | static constexpr std::size_t max_cycle_runs = 5; | 108 | static constexpr std::size_t max_cycle_runs = 5; |
| 108 | Core::Frontend::EmuWindow* render_window; | 109 | Core::Frontend::EmuWindow* render_window; |
| 109 | 110 | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d2f5f9bf2..a19cd7a1f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -303,7 +303,7 @@ struct KernelCore::Impl { | |||
| 303 | } | 303 | } |
| 304 | const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); | 304 | const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); |
| 305 | const Kernel::Thread* current = sched.GetCurrentThread(); | 305 | const Kernel::Thread* current = sched.GetCurrentThread(); |
| 306 | if (current != nullptr) { | 306 | if (current != nullptr && !current->IsPhantomMode()) { |
| 307 | result.guest_handle = current->GetGlobalHandle(); | 307 | result.guest_handle = current->GetGlobalHandle(); |
| 308 | } else { | 308 | } else { |
| 309 | result.guest_handle = InvalidHandle; | 309 | result.guest_handle = InvalidHandle; |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index f42d7bd13..f998890c4 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -597,6 +597,14 @@ public: | |||
| 597 | is_continuous_on_svc = is_continuous; | 597 | is_continuous_on_svc = is_continuous; |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | bool IsPhantomMode() const { | ||
| 601 | return is_phantom_mode; | ||
| 602 | } | ||
| 603 | |||
| 604 | void SetPhantomMode(bool phantom) { | ||
| 605 | is_phantom_mode = phantom; | ||
| 606 | } | ||
| 607 | |||
| 600 | private: | 608 | private: |
| 601 | friend class GlobalScheduler; | 609 | friend class GlobalScheduler; |
| 602 | friend class Scheduler; | 610 | friend class Scheduler; |
| @@ -699,6 +707,7 @@ private: | |||
| 699 | bool is_continuous_on_svc = false; | 707 | bool is_continuous_on_svc = false; |
| 700 | 708 | ||
| 701 | bool will_be_terminated = false; | 709 | bool will_be_terminated = false; |
| 710 | bool is_phantom_mode = false; | ||
| 702 | 711 | ||
| 703 | bool was_running = false; | 712 | bool was_running = false; |
| 704 | 713 | ||