From 35ab073ff891abc7f06d4af75f5306b46d0c2e89 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sat, 4 Jun 2022 11:23:58 +0200 Subject: [PATCH] early-access version 2757 --- README.md | 2 +- src/core/cpu_manager.cpp | 105 ++++++++++++++---- src/core/cpu_manager.h | 10 +- src/yuzu/configuration/configure_graphics.cpp | 1 - 4 files changed, 91 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 8b1994b25..3bc1febfa 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2756. +This is the source code for early-access 2757. ## Legal Notice diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index db42a5596..09d9c5163 100755 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -16,8 +16,7 @@ namespace Core { -CpuManager::CpuManager(System& system_) - : pause_barrier{std::make_unique(1)}, system{system_} {} +CpuManager::CpuManager(System& system_) : system{system_} {} CpuManager::~CpuManager() = default; void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, @@ -31,10 +30,8 @@ void CpuManager::Initialize() { for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); } - pause_barrier = std::make_unique(Core::Hardware::NUM_CPU_CORES + 1); } else { core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0); - pause_barrier = std::make_unique(2); } } @@ -148,6 +145,44 @@ void CpuManager::MultiCoreRunSuspendThread() { } } +void CpuManager::MultiCorePause(bool paused) { + if (!paused) { + bool all_not_barrier = false; + while (!all_not_barrier) { + all_not_barrier = true; + for (const auto& data : core_data) { + all_not_barrier &= !data.is_running.load() && data.initialized.load(); + } + } + for (auto& data : core_data) { + data.enter_barrier->Set(); + } + if (paused_state.load()) { + bool all_barrier = false; + while (!all_barrier) { + all_barrier = true; + for (const auto& data : core_data) { + all_barrier &= data.is_paused.load() && data.initialized.load(); + } + } + for (auto& data : core_data) { + data.exit_barrier->Set(); + } + } + } else { + /// Wait until all cores are paused. + bool all_barrier = false; + while (!all_barrier) { + all_barrier = true; + for (const auto& data : core_data) { + all_barrier &= data.is_paused.load() && data.initialized.load(); + } + } + /// Don't release the barrier + } + paused_state = paused; +} + /////////////////////////////////////////////////////////////////////////////// /// SingleCore /// /////////////////////////////////////////////////////////////////////////////// @@ -239,16 +274,37 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) { } } -void CpuManager::Pause(bool paused) { - if (pause_state == paused) { - return; +void CpuManager::SingleCorePause(bool paused) { + if (!paused) { + bool all_not_barrier = false; + while (!all_not_barrier) { + all_not_barrier = !core_data[0].is_running.load() && core_data[0].initialized.load(); + } + core_data[0].enter_barrier->Set(); + if (paused_state.load()) { + bool all_barrier = false; + while (!all_barrier) { + all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load(); + } + core_data[0].exit_barrier->Set(); + } + } else { + /// Wait until all cores are paused. + bool all_barrier = false; + while (!all_barrier) { + all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load(); + } + /// Don't release the barrier } + paused_state = paused; +} - pause_state.store(paused); - pause_state.notify_all(); - - // Wait for all threads to successfully pause/unpause before returning - pause_barrier->Sync(); +void CpuManager::Pause(bool paused) { + if (is_multicore) { + MultiCorePause(paused); + } else { + SingleCorePause(paused); + } } void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { @@ -264,29 +320,27 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { Common::SetCurrentThreadName(name.c_str()); Common::SetCurrentThreadPriority(Common::ThreadPriority::High); auto& data = core_data[core]; + data.enter_barrier = std::make_unique(); + data.exit_barrier = std::make_unique(); data.host_context = Common::Fiber::ThreadToFiber(); + data.is_running = false; + data.initialized = true; const bool sc_sync = !is_async_gpu && !is_multicore; bool sc_sync_first_use = sc_sync; // Cleanup SCOPE_EXIT({ data.host_context->Exit(); + data.enter_barrier.reset(); + data.exit_barrier.reset(); + data.initialized = false; MicroProfileOnThreadExit(); }); /// Running while (running_mode) { - if (pause_state.load(std::memory_order_relaxed)) { - // Wait for caller to acknowledge pausing - pause_barrier->Sync(); - - // Wait until unpaused - pause_state.wait(true, std::memory_order_relaxed); - - // Wait for caller to acknowledge unpausing - pause_barrier->Sync(); - } - + data.is_running = false; + data.enter_barrier->Wait(); if (sc_sync_first_use) { system.GPU().ObtainContext(); sc_sync_first_use = false; @@ -298,7 +352,12 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { } auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); + data.is_running = true; Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext()); + data.is_running = false; + data.is_paused = true; + data.exit_barrier->Wait(); + data.is_paused = false; } } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index c757cd506..aee352245 100755 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -69,11 +69,13 @@ private: void MultiCoreRunGuestLoop(); void MultiCoreRunIdleThread(); void MultiCoreRunSuspendThread(); + void MultiCorePause(bool paused); void SingleCoreRunGuestThread(); void SingleCoreRunGuestLoop(); void SingleCoreRunIdleThread(); void SingleCoreRunSuspendThread(); + void SingleCorePause(bool paused); static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core); @@ -81,12 +83,16 @@ private: struct CoreData { std::shared_ptr host_context; + std::unique_ptr enter_barrier; + std::unique_ptr exit_barrier; + std::atomic is_running; + std::atomic is_paused; + std::atomic initialized; std::jthread host_thread; }; std::atomic running_mode{}; - std::atomic pause_state{}; - std::unique_ptr pause_barrier; + std::atomic paused_state{}; std::array core_data{}; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 70015a373..85f34dc35 100755 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -5,7 +5,6 @@ // Include this early to include Vulkan headers how we want to #include "video_core/vulkan_common/vulkan_wrapper.h" -#include #include #include