[client] metrics: expose cadence pipeline stages

This commit is contained in:
Geoffrey McRae
2026-08-06 17:14:42 +10:00
parent 0b744d2286
commit bdfb1c3ce0
3 changed files with 41 additions and 6 deletions

View File

@@ -221,11 +221,14 @@ struct FrameTimingRecord
unsigned readyMask; unsigned readyMask;
bool producerValid; bool producerValid;
bool phaseValid; bool phaseValid;
bool transportValid;
uint64_t captureTime; uint64_t captureTime;
uint64_t postProcessTime; uint64_t postProcessTime;
uint64_t copyTime; uint64_t copyTime;
uint64_t readyTime; uint64_t readyTime;
uint64_t holdTime;
uint64_t readyLeadTime;
uint64_t importTime; uint64_t importTime;
uint64_t importWaitTime; uint64_t importWaitTime;
uint64_t dispatchTime; uint64_t dispatchTime;
@@ -385,6 +388,8 @@ static void frameTimingFinishFrame(LG_RendererFrameToken token,
record->postProcessTime = timing->postProcessTime; record->postProcessTime = timing->postProcessTime;
record->copyTime = timing->copyTime; record->copyTime = timing->copyTime;
record->readyTime = timing->readyTime; record->readyTime = timing->readyTime;
record->holdTime = timing->holdTime;
record->readyLeadTime = timing->readyLeadTime;
if (record->timestamp < timestamp) if (record->timestamp < timestamp)
record->timestamp = timestamp; record->timestamp = timestamp;
record->readyMask |= FRAME_TIMING_FRAME_READY; record->readyMask |= FRAME_TIMING_FRAME_READY;
@@ -422,12 +427,14 @@ static void frameTimingFinishRender(const LG_RendererFrameTiming * timing,
record->swapTime = timing->swapTime; record->swapTime = timing->swapTime;
record->readyMask |= FRAME_TIMING_RENDER_READY; record->readyMask |= FRAME_TIMING_RENDER_READY;
record->transportValid = record->phaseValid &&
timing->frameToken == cadenceToken;
feedbackFrameSerial = record->frameSerial; feedbackFrameSerial = record->frameSerial;
feedbackGeneration = record->scheduleGeneration; feedbackGeneration = record->scheduleGeneration;
feedbackEpoch = record->scheduleEpoch; feedbackEpoch = record->scheduleEpoch;
feedbackDeadline = record->scheduleDeadlineSerial; feedbackDeadline = record->scheduleDeadlineSerial;
feedbackValid = record->phaseValid && feedbackValid = record->transportValid;
timing->frameToken == cadenceToken;
feedbackQueueStart = record->queueStart; feedbackQueueStart = record->queueStart;
if (unlikely( if (unlikely(
@@ -500,10 +507,19 @@ static void frameTimingPublishReady(void)
const uint64_t queueTime = const uint64_t queueTime =
record->prepareStart > record->queueStart ? record->prepareStart > record->queueStart ?
record->prepareStart - record->queueStart : 0; 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 & OVERLAY_FRAME_TIMING_VALID_ALL &
(record->producerValid ? UINT32_MAX : ~OVERLAY_FRAME_TIMING_VALID_PRESENT;
~OVERLAY_FRAME_TIMING_VALID_PRODUCER); if (!record->producerValid)
validMask &= ~OVERLAY_FRAME_TIMING_VALID_PRODUCER;
if (!record->producerValid || !record->transportValid)
validMask &= ~OVERLAY_FRAME_TIMING_VALID_TRANSPORT;
const OverlayFrameTiming timing = { const OverlayFrameTiming timing = {
.timestamp = record->timestamp, .timestamp = record->timestamp,
.validMask = validMask, .validMask = validMask,
@@ -511,6 +527,8 @@ static void frameTimingPublishReady(void)
.postProcess = record->postProcessTime * 1e-6f, .postProcess = record->postProcessTime * 1e-6f,
.copy = record->copyTime * 1e-6f, .copy = record->copyTime * 1e-6f,
.ready = record->readyTime * 1e-6f, .ready = record->readyTime * 1e-6f,
.hold = record->holdTime * 1e-6f,
.transport = transportTime * 1e-6f,
.import = (record->importTime + .import = (record->importTime +
(record->producerValid ? 0 : record->importWaitTime)) * 1e-6f, (record->producerValid ? 0 : record->importWaitTime)) * 1e-6f,
.dispatch = record->dispatchTime * 1e-6f, .dispatch = record->dispatchTime * 1e-6f,
@@ -521,6 +539,7 @@ static void frameTimingPublishReady(void)
.desktop = record->desktopTime * 1e-6f, .desktop = record->desktopTime * 1e-6f,
.compose = record->composeTime * 1e-6f, .compose = record->composeTime * 1e-6f,
.swap = record->swapTime * 1e-6f, .swap = record->swapTime * 1e-6f,
.present = 0.0f,
}; };
ringbuffer_push(g_state.frameLatency, &timing); ringbuffer_push(g_state.frameLatency, &timing);
} }

View File

@@ -226,6 +226,8 @@ static const char * const frameTimingLabels[FRAME_TIMING_STAGE_COUNT] = {
"Post", "Post",
"Copy", "Copy",
"Ready", "Ready",
"Hold",
"Transport",
"Import", "Import",
"Dispatch", "Dispatch",
"Queue", "Queue",
@@ -235,6 +237,7 @@ static const char * const frameTimingLabels[FRAME_TIMING_STAGE_COUNT] = {
"Desktop", "Desktop",
"Compose", "Compose",
"Swap", "Swap",
"Present",
}; };
struct TimingPlotData struct TimingPlotData
@@ -296,6 +299,8 @@ static bool accumulateFrameTimingSample(int index, void * value_, void * udata_)
timing->postProcess, timing->postProcess,
timing->copy, timing->copy,
timing->ready, timing->ready,
timing->hold,
timing->transport,
timing->import, timing->import,
timing->dispatch, timing->dispatch,
timing->queue, timing->queue,
@@ -305,6 +310,7 @@ static bool accumulateFrameTimingSample(int index, void * value_, void * udata_)
timing->desktop, timing->desktop,
timing->compose, timing->compose,
timing->swap, timing->swap,
timing->present,
}; };
const uint64_t offset = timing->timestamp - data->windowStart; const uint64_t offset = timing->timestamp - data->windowStart;

View File

@@ -52,6 +52,8 @@ typedef struct OverlayFrameTiming
float postProcess; float postProcess;
float copy; float copy;
float ready; float ready;
float hold;
float transport;
float import; float import;
float dispatch; float dispatch;
float queue; float queue;
@@ -61,6 +63,7 @@ typedef struct OverlayFrameTiming
float desktop; float desktop;
float compose; float compose;
float swap; float swap;
float present;
} }
OverlayFrameTiming; OverlayFrameTiming;
@@ -70,6 +73,8 @@ enum OverlayFrameTimingStage
OVERLAY_FRAME_TIMING_POST_PROCESS, OVERLAY_FRAME_TIMING_POST_PROCESS,
OVERLAY_FRAME_TIMING_COPY, OVERLAY_FRAME_TIMING_COPY,
OVERLAY_FRAME_TIMING_READY, OVERLAY_FRAME_TIMING_READY,
OVERLAY_FRAME_TIMING_HOLD,
OVERLAY_FRAME_TIMING_TRANSPORT,
OVERLAY_FRAME_TIMING_IMPORT, OVERLAY_FRAME_TIMING_IMPORT,
OVERLAY_FRAME_TIMING_DISPATCH, OVERLAY_FRAME_TIMING_DISPATCH,
OVERLAY_FRAME_TIMING_QUEUE, OVERLAY_FRAME_TIMING_QUEUE,
@@ -79,13 +84,18 @@ enum OverlayFrameTimingStage
OVERLAY_FRAME_TIMING_DESKTOP, OVERLAY_FRAME_TIMING_DESKTOP,
OVERLAY_FRAME_TIMING_COMPOSE, OVERLAY_FRAME_TIMING_COMPOSE,
OVERLAY_FRAME_TIMING_SWAP, OVERLAY_FRAME_TIMING_SWAP,
OVERLAY_FRAME_TIMING_PRESENT,
OVERLAY_FRAME_TIMING_COUNT, OVERLAY_FRAME_TIMING_COUNT,
}; };
#define OVERLAY_FRAME_TIMING_VALID_ALL \ #define OVERLAY_FRAME_TIMING_VALID_ALL \
((1U << OVERLAY_FRAME_TIMING_COUNT) - 1U) ((1U << OVERLAY_FRAME_TIMING_COUNT) - 1U)
#define OVERLAY_FRAME_TIMING_VALID_PRODUCER \ #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, GraphHandle overlayGraph_register(const char * name, RingBuffer buffer,
float min, float max, GraphFormatFn formatFn); float min, float max, GraphFormatFn formatFn);