diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 8d9a305c29..bfea949301 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -55,10 +55,24 @@ struct ConfigCache unsigned int framelimit, frameSkip; TEXIDevices m_EXIDevice[MAX_EXI_CHANNELS]; std::string strBackend, sBackend; + std::string m_strGPUDeterminismMode; bool bSetFramelimit, bSetEXIDevice[MAX_EXI_CHANNELS], bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES], bSetFrameSkip; }; static ConfigCache config_cache; +static GPUDeterminismMode ParseGPUDeterminismMode(const std::string& mode) +{ + if (mode == "auto") + return GPU_DETERMINISM_AUTO; + if (mode == "none") + return GPU_DETERMINISM_NONE; + if (mode == "fake-completion") + return GPU_DETERMINISM_FAKE_COMPLETION; + + NOTICE_LOG(BOOT, "Unknown GPU determinism mode %s", mode.c_str()); + return GPU_DETERMINISM_AUTO; +} + // Boot the ISO or file bool BootCore(const std::string& _rFilename) { @@ -109,6 +123,7 @@ bool BootCore(const std::string& _rFilename) config_cache.bMergeBlocks = StartUp.bMergeBlocks; config_cache.bDSPHLE = StartUp.bDSPHLE; config_cache.strBackend = StartUp.m_strVideoBackend; + config_cache.m_strGPUDeterminismMode = StartUp.m_strGPUDeterminismMode; config_cache.m_EnableJIT = SConfig::GetInstance().m_DSPEnableJIT; config_cache.bDSPThread = StartUp.bDSPThread; config_cache.Volume = SConfig::GetInstance().m_Volume; @@ -168,6 +183,8 @@ bool BootCore(const std::string& _rFilename) dsp_section->Get("EnableJIT", &SConfig::GetInstance().m_DSPEnableJIT, SConfig::GetInstance().m_DSPEnableJIT); dsp_section->Get("Backend", &SConfig::GetInstance().sBackend, SConfig::GetInstance().sBackend); VideoBackend::ActivateBackend(StartUp.m_strVideoBackend); + core_section->Get("GPUDeterminismMode", &StartUp.m_strGPUDeterminismMode, StartUp.m_strGPUDeterminismMode); + StartUp.m_GPUDeterminismMode = ParseGPUDeterminismMode(StartUp.m_strGPUDeterminismMode); for (unsigned int i = 0; i < MAX_SI_CHANNELS; ++i) { @@ -277,6 +294,7 @@ void Stop() StartUp.bDSPHLE = config_cache.bDSPHLE; StartUp.bDSPThread = config_cache.bDSPThread; StartUp.m_strVideoBackend = config_cache.strBackend; + StartUp.m_strGPUDeterminismMode = config_cache.m_strGPUDeterminismMode; VideoBackend::ActivateBackend(StartUp.m_strVideoBackend); StartUp.bHLE_BS2 = config_cache.bHLE_BS2; SConfig::GetInstance().sBackend = config_cache.sBackend; diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 5b672305ed..3942fd87c9 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -317,6 +317,7 @@ void SConfig::SaveCoreSettings(IniFile& ini) core->Set("FrameLimit", m_Framelimit); core->Set("FrameSkip", m_FrameSkip); core->Set("GFXBackend", m_LocalCoreStartupParameter.m_strVideoBackend); + core->Set("GPUDeterminismMode", m_LocalCoreStartupParameter.m_strGPUDeterminismMode); } void SConfig::SaveMovieSettings(IniFile& ini) @@ -542,6 +543,7 @@ void SConfig::LoadCoreSettings(IniFile& ini) core->Get("FrameLimit", &m_Framelimit, 1); // auto frame limit by default core->Get("FrameSkip", &m_FrameSkip, 0); core->Get("GFXBackend", &m_LocalCoreStartupParameter.m_strVideoBackend, ""); + core->Get("GPUDeterminismMode", &m_LocalCoreStartupParameter.m_strGPUDeterminismMode, "auto"); } void SConfig::LoadMovieSettings(IniFile& ini) diff --git a/Source/Core/Core/CoreParameter.h b/Source/Core/Core/CoreParameter.h index b6008b3145..898c949714 100644 --- a/Source/Core/Core/CoreParameter.h +++ b/Source/Core/Core/CoreParameter.h @@ -97,6 +97,15 @@ enum Hotkey NUM_HOTKEYS, }; +enum GPUDeterminismMode +{ + GPU_DETERMINISM_AUTO, + GPU_DETERMINISM_NONE, + // This is currently the only mode. There will probably be at least + // one more at some point. + GPU_DETERMINISM_FAKE_COMPLETION, +}; + struct SCoreStartupParameter { // Settings @@ -200,6 +209,10 @@ struct SCoreStartupParameter EBootType m_BootType; std::string m_strVideoBackend; + std::string m_strGPUDeterminismMode; + + // set based on the string version + GPUDeterminismMode m_GPUDeterminismMode; // files std::string m_strFilename; diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index a47438c41e..44322d4d3b 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -421,21 +421,40 @@ void Fifo_UpdateWantDeterminism(bool want) { // We are paused (or not running at all yet) and have m_csHWVidOccupied, so // it should be safe to change this. - g_use_deterministic_gpu_thread = want && SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; - - // Hack: For now movies are an exception to this being on (but not - // to wanting determinism in general). Once vertex arrays are - // fixed, there should be no reason to want this off for movies by - // default, so this can be removed. - if (NetPlay::IsNetPlayRunning()) - g_use_deterministic_gpu_thread = false; - - if (g_use_deterministic_gpu_thread) + const SCoreStartupParameter& param = SConfig::GetInstance().m_LocalCoreStartupParameter; + bool gpu_thread; + switch (param.m_GPUDeterminismMode) { - // These haven't been updated in non-deterministic mode. - s_video_buffer_seen_ptr = g_video_buffer_pp_read_ptr = g_video_buffer_read_ptr; - CopyPreprocessCPStateFromMain(); - VertexLoaderManager::MarkAllDirty(); + case GPU_DETERMINISM_AUTO: + gpu_thread = want; + + // Hack: For now movies are an exception to this being on (but not + // to wanting determinism in general). Once vertex arrays are + // fixed, there should be no reason to want this off for movies by + // default, so this can be removed. + if (!NetPlay::IsNetPlayRunning()) + gpu_thread = false; + + break; + case GPU_DETERMINISM_NONE: + gpu_thread = false; + break; + case GPU_DETERMINISM_FAKE_COMPLETION: + gpu_thread = true; + break; } + gpu_thread = gpu_thread && SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; + + if (g_use_deterministic_gpu_thread != gpu_thread) + { + g_use_deterministic_gpu_thread = gpu_thread; + if (gpu_thread) + { + // These haven't been updated in non-deterministic mode. + s_video_buffer_seen_ptr = g_video_buffer_pp_read_ptr = g_video_buffer_read_ptr; + CopyPreprocessCPStateFromMain(); + VertexLoaderManager::MarkAllDirty(); + } + } }