diff --git a/src/core/core.cpp b/src/core/core.cpp index 032da7aa5..0f0eb885a 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -152,8 +152,12 @@ struct System::Impl { device_memory = std::make_unique(system); - kernel.SetMulticore(Settings::values.use_multi_core); - cpu_manager.SetMulticore(Settings::values.use_multi_core); + is_multicore = Settings::values.use_multi_core; + is_async_gpu = is_multicore || Settings::values.use_asynchronous_gpu_emulation; + + kernel.SetMulticore(is_multicore); + cpu_manager.SetMulticore(is_multicore); + cpu_manager.SetAsyncGpu(is_async_gpu); core_timing.Initialize([&system]() { system.RegisterHostThread(); }); kernel.Initialize(); @@ -395,6 +399,9 @@ struct System::Impl { std::unique_ptr perf_stats; Core::FrameLimiter frame_limiter; + bool is_multicore{}; + bool is_async_gpu{}; + std::array dynarmic_ticks{}; }; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index e92b0fb37..d7bd162bc 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -9,6 +9,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/cpu_manager.h" +#include "core/frontend/emu_window.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" @@ -21,7 +22,17 @@ CpuManager::CpuManager(System& system) : system{system} {} CpuManager::~CpuManager() = default; void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { + if (!cpu_manager.is_async_gpu && !cpu_manager.is_multicore) { + cpu_manager.render_window->MakeCurrent(); + } cpu_manager.RunThread(core); + if (!cpu_manager.is_async_gpu && !cpu_manager.is_multicore) { + cpu_manager.render_window->DoneCurrent(); + } +} + +void CpuManager::SetRenderWindow(Core::Frontend::EmuWindow& render_window) { + this->render_window = &render_window; } void CpuManager::Initialize() { diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index c0e454a7d..37cef2b12 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -16,6 +16,10 @@ class Event; class Fiber; } // namespace Common +namespace Core::Frontend { +class EmuWindow; +} // namespace Core::Frontend + namespace Core { class System; @@ -35,6 +39,12 @@ public: void SetMulticore(bool is_multicore) { this->is_multicore = is_multicore; } + + /// Sets if emulation is using an asynchronous GPU. + void SetAsyncGpu(bool is_async_gpu) { + this->is_async_gpu = is_async_gpu; + } + void Initialize(); void Shutdown(); @@ -51,6 +61,8 @@ public: return current_core.load(); } + void SetRenderWindow(Core::Frontend::EmuWindow& render_window); + private: static void GuestThreadFunction(void* cpu_manager); static void GuestRewindFunction(void* cpu_manager); @@ -88,10 +100,12 @@ private: std::array core_data{}; + bool is_async_gpu{}; bool is_multicore{}; std::atomic current_core{}; std::size_t preemption_count{}; static constexpr std::size_t max_cycle_runs = 5; + Core::Frontend::EmuWindow* render_window; System& system; }; diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index f872bddec..2711116a2 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -54,7 +54,7 @@ - Emulate CPU in Multiple Cores + Multicore CPU Emulation diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index de0c7fe8c..f1d9ec326 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -534,14 +534,34 @@ void GMainWindow::InitializeWidgets() { if (emulation_running) { return; } - Settings::values.use_asynchronous_gpu_emulation = - !Settings::values.use_asynchronous_gpu_emulation; + bool is_async = !Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; + Settings::values.use_asynchronous_gpu_emulation = is_async; async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); Settings::Apply(); }); async_status_button->setText(tr("ASYNC")); async_status_button->setCheckable(true); async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); + + // Setup Multicore button + multicore_status_button = new QPushButton(); + multicore_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); + multicore_status_button->setFocusPolicy(Qt::NoFocus); + connect(multicore_status_button, &QPushButton::clicked, [&] { + if (emulation_running) { + return; + } + Settings::values.use_multi_core = !Settings::values.use_multi_core; + bool is_async = Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; + Settings::values.use_asynchronous_gpu_emulation = is_async; + async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); + multicore_status_button->setChecked(Settings::values.use_multi_core); + Settings::Apply(); + }); + multicore_status_button->setText(tr("MULTICORE")); + multicore_status_button->setCheckable(true); + multicore_status_button->setChecked(Settings::values.use_multi_core); + statusBar()->insertPermanentWidget(0, multicore_status_button); statusBar()->insertPermanentWidget(0, async_status_button); // Setup Renderer API button @@ -1043,6 +1063,7 @@ void GMainWindow::BootGame(const QString& filename) { } status_bar_update_timer.start(2000); async_status_button->setDisabled(true); + multicore_status_button->setDisabled(true); renderer_status_button->setDisabled(true); if (UISettings::values.hide_mouse) { @@ -1130,6 +1151,7 @@ void GMainWindow::ShutdownGame() { game_fps_label->setVisible(false); emu_frametime_label->setVisible(false); async_status_button->setEnabled(true); + multicore_status_button->setEnabled(true); #ifdef HAS_VULKAN renderer_status_button->setEnabled(true); #endif @@ -1935,7 +1957,10 @@ void GMainWindow::OnConfigure() { } dock_status_button->setChecked(Settings::values.use_docked_mode); + multicore_status_button->setChecked(Settings::values.use_multi_core); + Settings::values.use_asynchronous_gpu_emulation = Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); + #ifdef HAS_VULKAN renderer_status_button->setChecked(Settings::values.renderer_backend == Settings::RendererBackend::Vulkan); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index d55e55cc6..5581874ed 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -235,6 +235,7 @@ private: QLabel* game_fps_label = nullptr; QLabel* emu_frametime_label = nullptr; QPushButton* async_status_button = nullptr; + QPushButton* multicore_status_button = nullptr; QPushButton* renderer_status_button = nullptr; QPushButton* dock_status_button = nullptr; QTimer status_bar_update_timer;