[host] measure ready time at framebuffer publication

Exclude command queue reset and cleanup from the ready stage, and keep
the wall-clock residual only as the legacy timing fallback.
This commit is contained in:
Geoffrey McRae
2026-08-03 16:22:07 +10:00
parent aa289fa022
commit 24be0a8869
16 changed files with 157 additions and 67 deletions

View File

@@ -97,6 +97,7 @@ typedef struct LG_TransportFrameTiming
uint64_t captureTime;
uint64_t postProcessTime;
uint64_t copyTime;
uint64_t readyTime;
}
LG_TransportFrameTiming;

View File

@@ -205,6 +205,7 @@ struct RenderTiming
uint64_t captureTime;
uint64_t postProcessTime;
uint64_t copyTime;
uint64_t readyTime;
uint64_t importTime;
};
@@ -225,6 +226,8 @@ static struct RenderTiming frameTimingLoad(void)
&g_state.producerPostProcessTime, memory_order_seq_cst);
timing.copyTime = atomic_load_explicit(
&g_state.producerCopyTime, memory_order_seq_cst);
timing.readyTime = atomic_load_explicit(
&g_state.producerReadyTime, memory_order_seq_cst);
timing.importTime = atomic_load_explicit(
&g_state.clientImportTime, memory_order_seq_cst);
@@ -245,6 +248,8 @@ static void frameTimingStore(const LG_TransportFrameTiming * timing,
timing->postProcessTime, memory_order_seq_cst);
atomic_store_explicit(&g_state.producerCopyTime,
timing->copyTime, memory_order_seq_cst);
atomic_store_explicit(&g_state.producerReadyTime,
timing->readyTime, memory_order_seq_cst);
atomic_store_explicit(&g_state.clientImportTime,
importTime, memory_order_seq_cst);
atomic_fetch_add_explicit(
@@ -257,13 +262,14 @@ static void preSwapCallback(void * udata)
const uint64_t timestamp = nanotime();
const uint64_t renderTime = timestamp - timing->renderStart;
if (timing->captureTime || timing->postProcessTime || timing->copyTime ||
timing->importTime)
timing->readyTime || timing->importTime)
{
const OverlayFrameTiming frameTiming = {
.timestamp = timestamp,
.capture = timing->captureTime * 1e-6f,
.postProcess = timing->postProcessTime * 1e-6f,
.copy = timing->copyTime * 1e-6f,
.ready = timing->readyTime * 1e-6f,
.import = timing->importTime * 1e-6f,
.render = renderTime * 1e-6f,
};

View File

@@ -154,6 +154,7 @@ struct AppState
atomic_uint_least64_t producerCaptureTime;
atomic_uint_least64_t producerPostProcessTime;
atomic_uint_least64_t producerCopyTime;
atomic_uint_least64_t producerReadyTime;
atomic_uint_least64_t clientImportTime;
atomic_uint_least64_t renderCount, frameCount;
_Atomic(float) fps, ups;

View File

@@ -179,7 +179,7 @@ static bool rbCalcMetrics(int index, void * value_, void * udata_)
#define TIMING_PLOT_WINDOW_NS 20000000000ULL
#define TIMING_PLOT_BUCKET_NS \
(TIMING_PLOT_WINDOW_NS / TIMING_PLOT_BUCKETS)
#define TIMING_STAGE_COUNT 5
#define TIMING_STAGE_COUNT 6
struct TimingPlotData
{
@@ -239,6 +239,7 @@ static bool accumulateTimingSample(int index, void * value_, void * udata_)
timing->capture,
timing->postProcess,
timing->copy,
timing->ready,
timing->import,
timing->render,
};
@@ -349,6 +350,7 @@ static void renderTimingStatistic(struct OverlayGraph * graph,
"Capture",
"Post",
"Copy",
"Ready",
"Import",
"Render",
};

View File

@@ -50,6 +50,7 @@ typedef struct OverlayFrameTiming
float capture;
float postProcess;
float copy;
float ready;
float import;
float render;
}

View File

@@ -136,6 +136,7 @@ int main(void)
wireFrame->captureTime = 100;
wireFrame->postProcessTime = 200;
wireFrame->copyTime = 300;
wireFrame->readyTime = 400;
wireFrame->timingSerial = wireFrame->frameSerial;
wireFrame->timingValid = 1;
FrameBuffer * framebuffer = (FrameBuffer *)((uint8_t *)wireFrame +
@@ -182,6 +183,7 @@ int main(void)
CHECK(timing.captureTime == wireFrame->captureTime);
CHECK(timing.postProcessTime == wireFrame->postProcessTime);
CHECK(timing.copyTime == wireFrame->copyTime);
CHECK(timing.readyTime == wireFrame->readyTime);
LGT_LGMP.releaseFrame(transport, &frame);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_OK);
LGT_LGMP.releasePointer(transport, &pointer);

View File

@@ -637,6 +637,7 @@ static void lgmp_getFrameTiming(LG_Transport * this,
timing->captureTime = this->pendingFrame->captureTime;
timing->postProcessTime = this->pendingFrame->postProcessTime;
timing->copyTime = this->pendingFrame->copyTime;
timing->readyTime = this->pendingFrame->readyTime;
}
static void lgmp_releaseFrame(LG_Transport * this, LG_TransportFrame * frame)