CoreTiming: Limit throttling after Immediate XFB for better input latency.

This commit is contained in:
Jordan Woyak 2025-03-23 16:46:21 -05:00
parent e4525ca7ee
commit 8e581ea6bb
2 changed files with 28 additions and 2 deletions

View File

@ -28,6 +28,7 @@
#include "VideoCommon/PerformanceMetrics.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/VideoEvents.h"
namespace CoreTiming
{
@ -104,6 +105,13 @@ void CoreTimingManager::Init()
m_last_oc_factor = m_config_oc_factor;
m_globals.last_OC_factor_inverted = m_config_oc_inv_factor;
m_throttled_since_presentation = false;
m_frame_hook = AfterPresentEvent::Register(
[this](const PresentInfo&) {
m_throttled_since_presentation.store(false, std::memory_order_relaxed);
},
"CoreTiming AfterPresentEvent");
}
void CoreTimingManager::Shutdown()
@ -113,6 +121,7 @@ void CoreTimingManager::Shutdown()
ClearPendingEvents();
UnregisterAllEvents();
CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id);
m_frame_hook.reset();
}
void CoreTimingManager::RefreshConfig()
@ -403,6 +412,21 @@ void CoreTimingManager::SleepUntil(TimePoint time_point)
void CoreTimingManager::Throttle(const s64 target_cycle)
{
const TimePoint time = Clock::now();
const bool already_throttled =
m_throttled_since_presentation.exchange(true, std::memory_order_relaxed);
// When Immediate XFB is enabled, try to Throttle just once since each presentation.
// This lowers latency by speeding through to the next presentation after grabbing input.
// Make sure we don't get too far ahead of proper timing though,
// otherwise the emulator unreasonably speeds through loading screens that don't have XFB copies.
const bool skip_throttle = already_throttled && g_ActiveConfig.bImmediateXFB &&
((GetTargetHostTime(target_cycle) - time) < (m_max_fallback / 2));
if (skip_throttle)
return;
if (IsSpeedUnlimited())
{
ResetThrottle(target_cycle);
@ -422,8 +446,6 @@ void CoreTimingManager::Throttle(const s64 target_cycle)
TimePoint target_time = CalculateTargetHostTimeInternal(target_cycle);
const TimePoint time = Clock::now();
const TimePoint min_target = time - m_max_fallback;
if (target_time < min_target)
{

View File

@ -23,6 +23,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/HookableEvent.h"
#include "Common/SPSCQueue.h"
#include "Common/Timer.h"
#include "Core/CPUThreadConfigCallback.h"
@ -223,6 +224,9 @@ private:
std::atomic_bool m_use_precision_timer = false;
Common::PrecisionTimer m_precision_cpu_timer;
Common::PrecisionTimer m_precision_gpu_timer;
Common::EventHook m_frame_hook;
std::atomic<bool> m_throttled_since_presentation = false;
};
} // namespace CoreTiming