diff --git a/client/src/main.c b/client/src/main.c index 138ba42d..f4b8d54e 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -221,11 +221,14 @@ struct FrameTimingRecord unsigned readyMask; bool producerValid; bool phaseValid; + bool transportValid; uint64_t captureTime; uint64_t postProcessTime; uint64_t copyTime; uint64_t readyTime; + uint64_t holdTime; + uint64_t readyLeadTime; uint64_t importTime; uint64_t importWaitTime; uint64_t dispatchTime; @@ -385,6 +388,8 @@ static void frameTimingFinishFrame(LG_RendererFrameToken token, record->postProcessTime = timing->postProcessTime; record->copyTime = timing->copyTime; record->readyTime = timing->readyTime; + record->holdTime = timing->holdTime; + record->readyLeadTime = timing->readyLeadTime; if (record->timestamp < timestamp) record->timestamp = timestamp; record->readyMask |= FRAME_TIMING_FRAME_READY; @@ -422,12 +427,14 @@ static void frameTimingFinishRender(const LG_RendererFrameTiming * timing, record->swapTime = timing->swapTime; record->readyMask |= FRAME_TIMING_RENDER_READY; + record->transportValid = record->phaseValid && + timing->frameToken == cadenceToken; + feedbackFrameSerial = record->frameSerial; feedbackGeneration = record->scheduleGeneration; feedbackEpoch = record->scheduleEpoch; feedbackDeadline = record->scheduleDeadlineSerial; - feedbackValid = record->phaseValid && - timing->frameToken == cadenceToken; + feedbackValid = record->transportValid; feedbackQueueStart = record->queueStart; if (unlikely( @@ -500,10 +507,19 @@ static void frameTimingPublishReady(void) const uint64_t queueTime = record->prepareStart > record->queueStart ? record->prepareStart - record->queueStart : 0; - const uint32_t validMask = + const uint64_t transportAccounted = + record->importTime + record->dispatchTime + queueTime; + const uint64_t transportTime = + record->readyLeadTime > transportAccounted ? + record->readyLeadTime - transportAccounted : 0; + uint32_t validMask = OVERLAY_FRAME_TIMING_VALID_ALL & - (record->producerValid ? UINT32_MAX : - ~OVERLAY_FRAME_TIMING_VALID_PRODUCER); + ~OVERLAY_FRAME_TIMING_VALID_PRESENT; + if (!record->producerValid) + validMask &= ~OVERLAY_FRAME_TIMING_VALID_PRODUCER; + if (!record->producerValid || !record->transportValid) + validMask &= ~OVERLAY_FRAME_TIMING_VALID_TRANSPORT; + const OverlayFrameTiming timing = { .timestamp = record->timestamp, .validMask = validMask, @@ -511,6 +527,8 @@ static void frameTimingPublishReady(void) .postProcess = record->postProcessTime * 1e-6f, .copy = record->copyTime * 1e-6f, .ready = record->readyTime * 1e-6f, + .hold = record->holdTime * 1e-6f, + .transport = transportTime * 1e-6f, .import = (record->importTime + (record->producerValid ? 0 : record->importWaitTime)) * 1e-6f, .dispatch = record->dispatchTime * 1e-6f, @@ -521,6 +539,7 @@ static void frameTimingPublishReady(void) .desktop = record->desktopTime * 1e-6f, .compose = record->composeTime * 1e-6f, .swap = record->swapTime * 1e-6f, + .present = 0.0f, }; ringbuffer_push(g_state.frameLatency, &timing); } diff --git a/client/src/overlay/graphs.c b/client/src/overlay/graphs.c index 9a8e8d67..8ea2c9ec 100644 --- a/client/src/overlay/graphs.c +++ b/client/src/overlay/graphs.c @@ -226,6 +226,8 @@ static const char * const frameTimingLabels[FRAME_TIMING_STAGE_COUNT] = { "Post", "Copy", "Ready", + "Hold", + "Transport", "Import", "Dispatch", "Queue", @@ -235,6 +237,7 @@ static const char * const frameTimingLabels[FRAME_TIMING_STAGE_COUNT] = { "Desktop", "Compose", "Swap", + "Present", }; struct TimingPlotData @@ -296,6 +299,8 @@ static bool accumulateFrameTimingSample(int index, void * value_, void * udata_) timing->postProcess, timing->copy, timing->ready, + timing->hold, + timing->transport, timing->import, timing->dispatch, timing->queue, @@ -305,6 +310,7 @@ static bool accumulateFrameTimingSample(int index, void * value_, void * udata_) timing->desktop, timing->compose, timing->swap, + timing->present, }; const uint64_t offset = timing->timestamp - data->windowStart; diff --git a/client/src/overlays.h b/client/src/overlays.h index 17d8dab8..de4629a6 100644 --- a/client/src/overlays.h +++ b/client/src/overlays.h @@ -52,6 +52,8 @@ typedef struct OverlayFrameTiming float postProcess; float copy; float ready; + float hold; + float transport; float import; float dispatch; float queue; @@ -61,6 +63,7 @@ typedef struct OverlayFrameTiming float desktop; float compose; float swap; + float present; } OverlayFrameTiming; @@ -70,6 +73,8 @@ enum OverlayFrameTimingStage OVERLAY_FRAME_TIMING_POST_PROCESS, OVERLAY_FRAME_TIMING_COPY, OVERLAY_FRAME_TIMING_READY, + OVERLAY_FRAME_TIMING_HOLD, + OVERLAY_FRAME_TIMING_TRANSPORT, OVERLAY_FRAME_TIMING_IMPORT, OVERLAY_FRAME_TIMING_DISPATCH, OVERLAY_FRAME_TIMING_QUEUE, @@ -79,13 +84,18 @@ enum OverlayFrameTimingStage OVERLAY_FRAME_TIMING_DESKTOP, OVERLAY_FRAME_TIMING_COMPOSE, OVERLAY_FRAME_TIMING_SWAP, + OVERLAY_FRAME_TIMING_PRESENT, OVERLAY_FRAME_TIMING_COUNT, }; #define OVERLAY_FRAME_TIMING_VALID_ALL \ ((1U << OVERLAY_FRAME_TIMING_COUNT) - 1U) #define OVERLAY_FRAME_TIMING_VALID_PRODUCER \ - ((1U << OVERLAY_FRAME_TIMING_IMPORT) - 1U) + ((1U << OVERLAY_FRAME_TIMING_TRANSPORT) - 1U) +#define OVERLAY_FRAME_TIMING_VALID_TRANSPORT \ + (1U << OVERLAY_FRAME_TIMING_TRANSPORT) +#define OVERLAY_FRAME_TIMING_VALID_PRESENT \ + (1U << OVERLAY_FRAME_TIMING_PRESENT) GraphHandle overlayGraph_register(const char * name, RingBuffer buffer, float min, float max, GraphFormatFn formatFn);