Skip to content

Commit 2967d37

Browse files
committed
Throttle after IXFB for improved input latency
Technical explanation: dolphin-emu#13449
1 parent c5ef578 commit 2967d37

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

Source/Core/Core/CoreTiming.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "VideoCommon/PerformanceMetrics.h"
3030
#include "VideoCommon/VideoBackendBase.h"
3131
#include "VideoCommon/VideoConfig.h"
32+
#include "VideoCommon/VideoEvents.h"
3233

3334
namespace CoreTiming
3435
{
@@ -105,6 +106,14 @@ void CoreTimingManager::Init()
105106

106107
m_last_oc_factor = m_config_oc_factor;
107108
m_globals.last_OC_factor_inverted = m_config_oc_inv_factor;
109+
110+
m_throttled_since_presentation = false;
111+
m_frame_hook = AfterPresentEvent::Register(
112+
[this](const PresentInfo&) {
113+
m_throttled_since_presentation.store(false, std::memory_order_relaxed);
114+
},
115+
"CoreTiming AfterPresentEvent"
116+
);
108117
}
109118

110119
void CoreTimingManager::Shutdown()
@@ -406,6 +415,22 @@ void CoreTimingManager::SleepUntil(TimePoint time_point)
406415

407416
void CoreTimingManager::Throttle(const s64 target_cycle)
408417
{
418+
const TimePoint time = Clock::now();
419+
420+
const bool already_throttled =
421+
m_throttled_since_presentation.exchange(true, std::memory_order_relaxed);
422+
423+
// When Immediate XFB is enabled, try to Throttle just once since each presentation.
424+
// This lowers latency by speeding through to the next presentation after grabbing input.
425+
// Make sure we don't get too far ahead of proper timing though,
426+
// otherwise the emulator unreasonably speeds through loading screens that don't have XFB copies.
427+
428+
const bool skip_throttle = already_throttled && g_ActiveConfig.bImmediateXFB &&
429+
((GetTargetHostTime(target_cycle) - time) < (m_max_fallback / 2));
430+
431+
if (skip_throttle)
432+
return;
433+
409434
if (IsSpeedUnlimited())
410435
{
411436
ResetThrottle(target_cycle);
@@ -425,8 +450,6 @@ void CoreTimingManager::Throttle(const s64 target_cycle)
425450

426451
TimePoint target_time = CalculateTargetHostTimeInternal(target_cycle);
427452

428-
const TimePoint time = Clock::now();
429-
430453
const TimePoint min_target = time - m_max_fallback;
431454
if (target_time < min_target)
432455
{

Source/Core/Core/CoreTiming.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <vector>
2424

2525
#include "Common/CommonTypes.h"
26+
#include "Common/HookableEvent.h"
2627
#include "Common/SPSCQueue.h"
2728
#include "Common/Timer.h"
2829
#include "Core/CPUThreadConfigCallback.h"
@@ -225,6 +226,8 @@ class CoreTimingManager
225226
std::atomic_bool m_use_precision_timer = false;
226227
Common::PrecisionTimer m_precision_cpu_timer;
227228
Common::PrecisionTimer m_precision_gpu_timer;
229+
Common::EventHook m_frame_hook;
230+
std::atomic<bool> m_throttled_since_presentation = false;
228231
};
229232

230233
} // namespace CoreTiming

0 commit comments

Comments
 (0)