diff --git a/client/src/frame_scheduler.c b/client/src/frame_scheduler.c index 41fa8d2d..6c378371 100644 --- a/client/src/frame_scheduler.c +++ b/client/src/frame_scheduler.c @@ -47,7 +47,7 @@ static struct _Atomic(uint32_t) generation; _Atomic(uint64_t) period; uint64_t lastSend; - uint64_t lastCadence; + _Atomic(uint64_t) lastCadence; int64_t phaseError; uint32_t feedbackFrameSerial; @@ -181,19 +181,24 @@ void frameScheduler_stop(void) l_frameScheduler.immediatePending = false; } +void frameScheduler_observeCadence(void) +{ + atomic_store_explicit( + &l_frameScheduler.lastCadence, nanotime(), memory_order_release); +} + void frameScheduler_update(void) { if (!l_frameScheduler.supported) return; + const uint64_t lastCadence = atomic_load_explicit( + &l_frameScheduler.lastCadence, memory_order_acquire); const uint64_t now = nanotime(); - const uint64_t period = presentationPeriod(); - if (period < FRAME_SCHEDULER_MIN_PERIOD_NS || - period > FRAME_SCHEDULER_MAX_PERIOD_NS) + if (!lastCadence || + now - lastCadence > FRAME_SCHEDULER_CADENCE_GRACE_NS) { - if (l_frameScheduler.active && l_frameScheduler.lastCadence && - now - l_frameScheduler.lastCadence > - FRAME_SCHEDULER_CADENCE_GRACE_NS && + if (l_frameScheduler.active && sendSchedule(LG_TRANSPORT_FRAME_SCHEDULE_RELEASE, 0)) { l_frameScheduler.active = false; @@ -210,7 +215,11 @@ void frameScheduler_update(void) } return; } - l_frameScheduler.lastCadence = now; + + const uint64_t period = presentationPeriod(); + if (period < FRAME_SCHEDULER_MIN_PERIOD_NS || + period > FRAME_SCHEDULER_MAX_PERIOD_NS) + return; bool reset = !l_frameScheduler.period; if (!reset) diff --git a/client/src/frame_scheduler.h b/client/src/frame_scheduler.h index 0ed22dab..c21aff36 100644 --- a/client/src/frame_scheduler.h +++ b/client/src/frame_scheduler.h @@ -29,6 +29,7 @@ void frameScheduler_init(void); void frameScheduler_free(void); void frameScheduler_start(LG_TransportFeatureFlags features); void frameScheduler_stop(void); +void frameScheduler_observeCadence(void); void frameScheduler_update(void); void frameScheduler_feedback(uint64_t frameSerial, uint32_t generation, uint32_t scheduleEpoch, uint32_t deadlineSerial, diff --git a/client/src/main.c b/client/src/main.c index a6cd7126..138ba42d 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -647,6 +647,9 @@ static int renderThread(void * unused) if (g_state.jitRender) { const LG_DSWaitFrameResult waitResult = g_state.ds->waitFrame(); + if (waitResult & LG_DS_WAIT_FRAME_CADENCE) + frameScheduler_observeCadence(); + const LG_RendererFrameToken queuedAtWake = waitResult == LG_DS_WAIT_FRAME_CADENCE ? frameTimingQueuedToken() : LG_RENDERER_FRAME_TOKEN_NONE; @@ -756,6 +759,9 @@ static int renderThread(void * unused) const uint64_t renderEnd = nanotime(); LG_UNLOCK(g_state.lgrLock); + if (!g_state.jitRender) + frameScheduler_observeCadence(); + if (rendererTiming.frameToken != LG_RENDERER_FRAME_TOKEN_NONE) frameTimingFinishRender( &rendererTiming, prepareStart, prepareTime, renderEnd,