[client] main: improve frame rate sync lock with the guest

If the guest is not sending frames at a constant rate, the minimum FPS
timeout may expire drawing an additional frame. This change calculates
the average ups frame time over the past 100ms and adds this to the
timeout value allowing this value to be dynamic.
This commit is contained in:
Geoffrey McRae 2021-07-20 15:37:51 +10:00
parent b877bab48f
commit 3c0ebd54ec
2 changed files with 16 additions and 9 deletions

View File

@ -100,7 +100,7 @@ static bool fpsTimerFn(void * unused)
static uint64_t last; static uint64_t last;
if (!last) if (!last)
{ {
last = microtime(); last = nanotime();
return true; return true;
} }
@ -109,15 +109,19 @@ static bool fpsTimerFn(void * unused)
const uint64_t frameCount = atomic_exchange_explicit(&g_state.frameCount, 0, const uint64_t frameCount = atomic_exchange_explicit(&g_state.frameCount, 0,
memory_order_acquire); memory_order_acquire);
const uint64_t time = microtime(); const uint64_t time = nanotime();
const float elapsed = (float)(time - last) / 1e3; const float elapsedNs = time - last;
last = time; last = time;
const float fps = 1e3f / (elapsed / (float)renderCount); const float elapsedMs = (float)elapsedNs / 1e6;
const float ups = 1e3f / (elapsed / (float)frameCount);
atomic_store_explicit(&g_state.fps, fps, memory_order_relaxed); const float fps = 1e3f / (elapsedMs / (float)renderCount);
atomic_store_explicit(&g_state.ups, ups, memory_order_relaxed); const float ups = 1e3f / (elapsedMs / (float)frameCount);
const uint64_t upsTime = elapsedNs / frameCount;
atomic_store_explicit(&g_state.fps , fps , memory_order_relaxed);
atomic_store_explicit(&g_state.ups , ups , memory_order_relaxed);
atomic_store_explicit(&g_state.upsTime, upsTime, memory_order_relaxed);
return true; return true;
} }
@ -153,9 +157,12 @@ static int renderThread(void * unused)
{ {
if (g_params.fpsMin != 0) if (g_params.fpsMin != 0)
{ {
const uint64_t upsTime = atomic_load_explicit(&g_state.upsTime,
memory_order_relaxed);
lgWaitEventAbs(e_frame, &time); lgWaitEventAbs(e_frame, &time);
clock_gettime(CLOCK_MONOTONIC, &time); clock_gettime(CLOCK_MONOTONIC, &time);
tsAdd(&time, g_state.frameTime); tsAdd(&time, g_state.frameTime + upsTime);
} }
int resize = atomic_load(&g_state.lgrResize); int resize = atomic_load(&g_state.lgrResize);

View File

@ -104,7 +104,7 @@ struct AppState
RingBuffer renderTimings; RingBuffer renderTimings;
RingBuffer frameTimings; RingBuffer frameTimings;
atomic_uint_least64_t renderCount, frameCount; atomic_uint_least64_t renderCount, frameCount, upsTime;
_Atomic(float) fps, ups; _Atomic(float) fps, ups;
uint64_t resizeTimeout; uint64_t resizeTimeout;