4 changes: 3 additions & 1 deletion Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
Expand Up @@ -10,6 +10,7 @@
#include "Core/HW/CPU.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

const u8* JitBase::Dispatch(JitBase& jit)
{
Expand Down Expand Up @@ -55,6 +56,7 @@ void JitBase::RefreshConfig()
m_fprf = Config::Get(Config::MAIN_FPRF);
m_accurate_nans = Config::Get(Config::MAIN_ACCURATE_NANS);
m_fastmem_enabled = Config::Get(Config::MAIN_FASTMEM);
m_mmu_enabled = Core::System::GetInstance().IsMMUMode();
analyzer.SetDebuggingEnabled(m_enable_debugging);
analyzer.SetBranchFollowingEnabled(Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH));
analyzer.SetFloatExceptionsEnabled(m_enable_float_exceptions);
Expand All @@ -80,7 +82,7 @@ void JitBase::UpdateMemoryAndExceptionOptions()
{
bool any_watchpoints = PowerPC::memchecks.HasAny();
jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (MSR.DR || !any_watchpoints);
jo.memcheck = SConfig::GetInstance().bMMU || any_watchpoints;
jo.memcheck = m_mmu_enabled || any_watchpoints;
jo.fp_exceptions = m_enable_float_exceptions;
jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions;
}
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/PowerPC/JitCommon/JitBase.h
Expand Up @@ -133,6 +133,7 @@ class JitBase : public CPUCoreBase
bool m_fprf = false;
bool m_accurate_nans = false;
bool m_fastmem_enabled = false;
bool m_mmu_enabled = false;

void RefreshConfig();

Expand Down
3 changes: 2 additions & 1 deletion Source/Core/Core/PowerPC/MMU.cpp
Expand Up @@ -21,6 +21,7 @@
#include "Core/PowerPC/GDBStub.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

#include "VideoCommon/VideoBackendBase.h"

Expand Down Expand Up @@ -1147,7 +1148,7 @@ TranslateResult JitCache_TranslateAddress(u32 address)
static void GenerateDSIException(u32 effective_address, bool write)
{
// DSI exceptions are only supported in MMU mode.
if (!SConfig::GetInstance().bMMU)
if (!Core::System::GetInstance().IsMMUMode())
{
PanicAlertFmt("Invalid {} {:#010x}, PC = {:#010x}", write ? "write to" : "read from",
effective_address, PC);
Expand Down
8 changes: 8 additions & 0 deletions Source/Core/Core/System.cpp
Expand Up @@ -3,6 +3,8 @@

#include "Core/System.h"

#include "Core/Config/MainSettings.h"

namespace Core
{
struct System::Impl
Expand All @@ -14,4 +16,10 @@ System::System() : m_impl{std::make_unique<Impl>()}
}

System::~System() = default;

void System::Initialize()
{
m_separate_cpu_and_gpu_threads = Config::Get(Config::MAIN_CPU_THREAD);
m_mmu_enabled = Config::Get(Config::MAIN_MMU);
}
} // namespace Core
8 changes: 8 additions & 0 deletions Source/Core/Core/System.h
Expand Up @@ -26,10 +26,18 @@ class System
return instance;
}

void Initialize();

bool IsDualCoreMode() const { return m_separate_cpu_and_gpu_threads; }
bool IsMMUMode() const { return m_mmu_enabled; }

private:
System();

struct Impl;
std::unique_ptr<Impl> m_impl;

bool m_separate_cpu_and_gpu_threads = false;
bool m_mmu_enabled = false;
};
} // namespace Core
4 changes: 2 additions & 2 deletions Source/Core/DolphinQt/Settings/AdvancedPane.cpp
Expand Up @@ -178,7 +178,7 @@ void AdvancedPane::ConnectLayout()
});

connect(m_enable_mmu_checkbox, &QCheckBox::toggled, this,
[](bool checked) { SConfig::GetInstance().bMMU = checked; });
[](bool checked) { Config::SetBaseOrCurrent(Config::MAIN_MMU, checked); });

m_cpu_clock_override_checkbox->setChecked(Config::Get(Config::MAIN_OVERCLOCK_ENABLE));
connect(m_cpu_clock_override_checkbox, &QCheckBox::toggled, [this](bool enable_clock_override) {
Expand Down Expand Up @@ -243,7 +243,7 @@ void AdvancedPane::Update()
}
m_cpu_emulation_engine_combobox->setEnabled(!running);

m_enable_mmu_checkbox->setChecked(SConfig::GetInstance().bMMU);
m_enable_mmu_checkbox->setChecked(Config::Get(Config::MAIN_MMU));
m_enable_mmu_checkbox->setEnabled(!running);

QFont bf = font();
Expand Down
5 changes: 2 additions & 3 deletions Source/Core/DolphinQt/Settings/GeneralPane.cpp
Expand Up @@ -252,7 +252,7 @@ void GeneralPane::LoadConfig()
#if defined(USE_ANALYTICS) && USE_ANALYTICS
m_checkbox_enable_analytics->setChecked(Settings::Instance().IsAnalyticsEnabled());
#endif
m_checkbox_dualcore->setChecked(SConfig::GetInstance().bCPUThread);
m_checkbox_dualcore->setChecked(Config::Get(Config::MAIN_CPU_THREAD));
m_checkbox_cheats->setChecked(Settings::Instance().GetCheatsEnabled());
m_checkbox_override_region_settings->setChecked(
Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS));
Expand All @@ -263,7 +263,7 @@ void GeneralPane::LoadConfig()
int selection = qRound(Config::Get(Config::MAIN_EMULATION_SPEED) * 10);
if (selection < m_combobox_speedlimit->count())
m_combobox_speedlimit->setCurrentIndex(selection);
m_checkbox_dualcore->setChecked(SConfig::GetInstance().bCPUThread);
m_checkbox_dualcore->setChecked(Config::Get(Config::MAIN_CPU_THREAD));

const auto fallback = Settings::Instance().GetFallbackRegion();

Expand Down Expand Up @@ -346,7 +346,6 @@ void GeneralPane::OnSaveConfig()
Settings::Instance().SetAnalyticsEnabled(m_checkbox_enable_analytics->isChecked());
DolphinAnalytics::Instance().ReloadConfig();
#endif
settings.bCPUThread = m_checkbox_dualcore->isChecked();
Config::SetBaseOrCurrent(Config::MAIN_CPU_THREAD, m_checkbox_dualcore->isChecked());
Settings::Instance().SetCheatsEnabled(m_checkbox_cheats->isChecked());
Config::SetBaseOrCurrent(Config::MAIN_OVERRIDE_REGION_SETTINGS,
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/VideoCommon/CommandProcessor.cpp
Expand Up @@ -17,6 +17,7 @@
#include "Core/HW/GPFifo.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/System.h"
#include "VideoCommon/Fifo.h"

namespace CommandProcessor
Expand All @@ -42,7 +43,7 @@ static Common::Flag s_interrupt_waiting;

static bool IsOnThread()
{
return SConfig::GetInstance().bCPUThread;
return Core::System::GetInstance().IsDualCoreMode();
}

static void UpdateInterrupts_Wrapper(u64 userdata, s64 cyclesLate)
Expand Down
81 changes: 48 additions & 33 deletions Source/Core/VideoCommon/Fifo.cpp
Expand Up @@ -19,6 +19,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/Host.h"
#include "Core/System.h"

#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/CPMemory.h"
Expand Down Expand Up @@ -71,6 +72,20 @@ static std::atomic<int> s_sync_ticks;
static bool s_syncing_suspended;
static Common::Event s_sync_wakeup_event;

static std::optional<size_t> s_config_callback_id = std::nullopt;
static bool s_config_sync_gpu = false;
static int s_config_sync_gpu_max_distance = 0;
static int s_config_sync_gpu_min_distance = 0;
static float s_config_sync_gpu_overclock = 0.0f;

static void RefreshConfig()
{
s_config_sync_gpu = Config::Get(Config::MAIN_SYNC_GPU);
s_config_sync_gpu_max_distance = Config::Get(Config::MAIN_SYNC_GPU_MAX_DISTANCE);
s_config_sync_gpu_min_distance = Config::Get(Config::MAIN_SYNC_GPU_MIN_DISTANCE);
s_config_sync_gpu_overclock = Config::Get(Config::MAIN_SYNC_GPU_OVERCLOCK);
}

void DoState(PointerWrap& p)
{
p.DoArray(s_video_buffer, FIFO_SIZE);
Expand All @@ -95,9 +110,7 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock)
SyncGPU(SyncGPUReason::Other);
EmulatorState(false);

const SConfig& param = SConfig::GetInstance();

if (!param.bCPUThread || s_use_deterministic_gpu_thread)
if (!Core::System::GetInstance().IsDualCoreMode() || s_use_deterministic_gpu_thread)
return;

s_gpu_mainloop.WaitYield(std::chrono::milliseconds(100), Host_YieldToUI);
Expand All @@ -111,10 +124,14 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock)

void Init()
{
if (!s_config_callback_id)
s_config_callback_id = Config::AddConfigChangedCallback(RefreshConfig);
RefreshConfig();

// Padded so that SIMD overreads in the vertex loader are safe
s_video_buffer = static_cast<u8*>(Common::AllocateMemoryPages(FIFO_SIZE + 4));
ResetVideoBuffer();
if (SConfig::GetInstance().bCPUThread)
if (Core::System::GetInstance().IsDualCoreMode())
s_gpu_mainloop.Prepare();
s_sync_ticks.store(0);
}
Expand All @@ -132,6 +149,12 @@ void Shutdown()
s_video_buffer_seen_ptr = nullptr;
s_fifo_aux_write_ptr = nullptr;
s_fifo_aux_read_ptr = nullptr;

if (s_config_callback_id)
{
Config::RemoveConfigChangedCallback(*s_config_callback_id);
s_config_callback_id = std::nullopt;
}
}

// May be executed from any thread, even the graphics thread.
Expand Down Expand Up @@ -297,10 +320,8 @@ void RunGpuLoop()
AsyncRequests::GetInstance()->SetEnable(true);
AsyncRequests::GetInstance()->SetPassthrough(false);

const SConfig& param = SConfig::GetInstance();

s_gpu_mainloop.Run(
[&param] {
[] {
// Run events from the CPU thread.
AsyncRequests::GetInstance()->PullEvents();

Expand Down Expand Up @@ -331,7 +352,7 @@ void RunGpuLoop()
fifo.bFF_GPReadEnable.load(std::memory_order_relaxed) &&
fifo.CPReadWriteDistance.load(std::memory_order_relaxed) && !AtBreakpoint())
{
if (param.bSyncGPU && s_sync_ticks.load() < param.iSyncGpuMinDistance)
if (s_config_sync_gpu && s_sync_ticks.load() < s_config_sync_gpu_min_distance)
break;

u32 cyclesExecuted = 0;
Expand Down Expand Up @@ -363,12 +384,12 @@ void RunGpuLoop()

CommandProcessor::SetCPStatusFromGPU();

if (param.bSyncGPU)
if (s_config_sync_gpu)
{
cyclesExecuted = (int)(cyclesExecuted / param.fSyncGpuOverclock);
cyclesExecuted = (int)(cyclesExecuted / s_config_sync_gpu_overclock);
int old = s_sync_ticks.fetch_sub(cyclesExecuted);
if (old >= param.iSyncGpuMaxDistance &&
old - (int)cyclesExecuted < param.iSyncGpuMaxDistance)
if (old >= s_config_sync_gpu_max_distance &&
old - (int)cyclesExecuted < s_config_sync_gpu_max_distance)
s_sync_wakeup_event.Set();
}

Expand All @@ -383,7 +404,7 @@ void RunGpuLoop()
if (s_sync_ticks.load() > 0)
{
int old = s_sync_ticks.exchange(0);
if (old >= param.iSyncGpuMaxDistance)
if (old >= s_config_sync_gpu_max_distance)
s_sync_wakeup_event.Set();
}

Expand All @@ -400,9 +421,7 @@ void RunGpuLoop()

void FlushGpu()
{
const SConfig& param = SConfig::GetInstance();

if (!param.bCPUThread || s_use_deterministic_gpu_thread)
if (!Core::System::GetInstance().IsDualCoreMode() || s_use_deterministic_gpu_thread)
return;

s_gpu_mainloop.Wait();
Expand All @@ -423,17 +442,16 @@ bool AtBreakpoint()

void RunGpu()
{
const SConfig& param = SConfig::GetInstance();
const bool is_dual_core = Core::System::GetInstance().IsDualCoreMode();

// wake up GPU thread
if (param.bCPUThread && !s_use_deterministic_gpu_thread)
if (is_dual_core && !s_use_deterministic_gpu_thread)
{
s_gpu_mainloop.Wakeup();
}

// if the sync GPU callback is suspended, wake it up.
if (!SConfig::GetInstance().bCPUThread || s_use_deterministic_gpu_thread ||
SConfig::GetInstance().bSyncGPU)
if (!is_dual_core || s_use_deterministic_gpu_thread || s_config_sync_gpu)
{
if (s_syncing_suspended)
{
Expand All @@ -447,7 +465,7 @@ static int RunGpuOnCpu(int ticks)
{
CommandProcessor::SCPFifoStruct& fifo = CommandProcessor::fifo;
bool reset_simd_state = false;
int available_ticks = int(ticks * SConfig::GetInstance().fSyncGpuOverclock) + s_sync_ticks.load();
int available_ticks = int(ticks * s_config_sync_gpu_overclock) + s_sync_ticks.load();
while (fifo.bFF_GPReadEnable.load(std::memory_order_relaxed) &&
fifo.CPReadWriteDistance.load(std::memory_order_relaxed) && !AtBreakpoint() &&
available_ticks >= 0)
Expand Down Expand Up @@ -508,7 +526,6 @@ void UpdateWantDeterminism(bool want)
{
// We are paused (or not running at all yet), so
// it should be safe to change this.
const SConfig& param = SConfig::GetInstance();
bool gpu_thread = false;
switch (Config::GetGPUDeterminismMode())
{
Expand All @@ -523,7 +540,7 @@ void UpdateWantDeterminism(bool want)
break;
}

gpu_thread = gpu_thread && param.bCPUThread;
gpu_thread = gpu_thread && Core::System::GetInstance().IsDualCoreMode();

if (s_use_deterministic_gpu_thread != gpu_thread)
{
Expand All @@ -550,8 +567,6 @@ bool UseDeterministicGPUThread()
*/
static int WaitForGpuThread(int ticks)
{
const SConfig& param = SConfig::GetInstance();

int old = s_sync_ticks.fetch_add(ticks);
int now = old + ticks;

Expand All @@ -560,15 +575,15 @@ static int WaitForGpuThread(int ticks)
return -1;

// Wakeup GPU
if (old < param.iSyncGpuMinDistance && now >= param.iSyncGpuMinDistance)
if (old < s_config_sync_gpu_min_distance && now >= s_config_sync_gpu_min_distance)
RunGpu();

// If the GPU is still sleeping, wait for a longer time
if (now < param.iSyncGpuMinDistance)
return GPU_TIME_SLOT_SIZE + param.iSyncGpuMinDistance - now;
if (now < s_config_sync_gpu_min_distance)
return GPU_TIME_SLOT_SIZE + s_config_sync_gpu_min_distance - now;

// Wait for GPU
if (now >= param.iSyncGpuMaxDistance)
if (now >= s_config_sync_gpu_max_distance)
s_sync_wakeup_event.Wait();

return GPU_TIME_SLOT_SIZE;
Expand All @@ -579,11 +594,11 @@ static void SyncGPUCallback(u64 ticks, s64 cyclesLate)
ticks += cyclesLate;
int next = -1;

if (!SConfig::GetInstance().bCPUThread || s_use_deterministic_gpu_thread)
if (!Core::System::GetInstance().IsDualCoreMode() || s_use_deterministic_gpu_thread)
{
next = RunGpuOnCpu((int)ticks);
}
else if (SConfig::GetInstance().bSyncGPU)
else if (s_config_sync_gpu)
{
next = WaitForGpuThread((int)ticks);
}
Expand All @@ -597,9 +612,9 @@ void SyncGPUForRegisterAccess()
{
SyncGPU(SyncGPUReason::Other);

if (!SConfig::GetInstance().bCPUThread || s_use_deterministic_gpu_thread)
if (!Core::System::GetInstance().IsDualCoreMode() || s_use_deterministic_gpu_thread)
RunGpuOnCpu(GPU_TIME_SLOT_SIZE);
else if (SConfig::GetInstance().bSyncGPU)
else if (s_config_sync_gpu)
WaitForGpuThread(GPU_TIME_SLOT_SIZE);
}

Expand Down
5 changes: 4 additions & 1 deletion Source/Core/VideoCommon/PixelEngine.cpp
Expand Up @@ -10,11 +10,14 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"

#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/System.h"

#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/PerfQueryBase.h"
Expand Down Expand Up @@ -286,7 +289,7 @@ static void RaiseEvent(int cycles_into_future)

CoreTiming::FromThread from = CoreTiming::FromThread::NON_CPU;
s64 cycles = 0; // we don't care about timings for dual core mode.
if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
if (!Core::System::GetInstance().IsDualCoreMode() || Fifo::UseDeterministicGPUThread())
{
from = CoreTiming::FromThread::CPU;

Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoCommon/VideoBackendBase.cpp
Expand Up @@ -13,14 +13,14 @@

#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/Event.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"

#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/System.h"

// TODO: ugly
#ifdef _WIN32
Expand Down Expand Up @@ -289,7 +289,7 @@ void VideoBackendBase::PopulateBackendInfoFromUI()

void VideoBackendBase::DoState(PointerWrap& p)
{
if (!SConfig::GetInstance().bCPUThread)
if (!Core::System::GetInstance().IsDualCoreMode())
{
VideoCommon_DoState(p);
return;
Expand Down