Frame Timing¶
WIP
Precise frame timing is the central guarantee vstimd provides. This page explains what "frame-accurate" means, how the server achieves it, and how to verify it.
What is measured¶
The key metric is command-to-photon latency: the time from when a client sends a command to when the corresponding change appears on screen.
| Stage | Latency |
|---|---|
| ZMQ round-trip (client → server → client) | ~100–400 µs |
| Next vsync wait | 0–1 frame (0–16.7 ms at 60 Hz) |
| GPU render | 0.5–2 ms |
| Display panel response | 1–10 ms |
| Total (60 Hz) | ~2–30 ms |
The dominant term is the vsync wait. Use deferred mode to control exactly which frame a batch of changes becomes visible.
Vblank synchronisation¶
The server uses the following priority chain to lock to the display vblank. Each source is tried in order; on error the source is permanently disabled and the next is used. The active source is shown in the System panel of the overlay (F5). For the full init requirements and module-level details, see Rendering & DRM internals.
Priority chain¶
-
DRM vblank (
DRM_IOCTL_WAIT_VBLANK) — bare-metal DRM mode only. A blocking kernel ioctl that fires at the start of the vertical blanking interval. Most precise; zero offset from true vblank, minimal kernel overhead. -
VK_EXT_display_control(vkRegisterDisplayEventEXT) — bare-metal DRM mode fallback. Creates a one-shot Vulkan fence that signals onFIRST_PIXEL_OUT, which is the first active scanline after the blanking interval ends. On a 120 Hz display this is approximately 330 µs after true vblank — a fixed, predictable offset. Used on Jetson Orin (Tegra nvdisplay) whereDRM_IOCTL_WAIT_VBLANKis not available whenVK_KHR_displayholds DRM master (the driver does not enable vblank IRQs for non-master file descriptors). -
VK_KHR_present_wait— Vulkan extension that wakes after the previous frame is confirmed presented. Available on most drivers in desktop (winit) mode. -
GPU fence completion — last resort. Wakes when the GPU finishes rendering, not when the frame appears on screen. Adds up to one frame of unpredictable latency. The overlay labels this "Clock: GPU-completion (inaccurate)".
Why FIFO acquire is not used as a vblank source¶
vkAcquireNextImageKHR with FIFO present mode blocks at the display refresh rate,
but the block point is at image acquisition — before tessellation and upload.
This means scene inputs are processed after the sync point; they are stale by one
full frame relative to sources 1–3, which all fire after the previous frame is already
visible and before tessellation begins.
For input-latency-sensitive applications (neuroscience, psychophysics) the DRM /
VK_EXT_display_control approach is the correct choice.
Platform notes¶
| Platform | Source selected | Reason |
|---|---|---|
| Jetson Orin (nvdisplay) | VK_EXT_display_control | nvdisplay does not enable vblank IRQs for non-master fds |
| Generic Linux desktop | DrmVblank or PresentWait | Depends on driver and present mode |
| Any platform | GpuCompletion | Last resort if no vblank source is available |
The VK_EXT_display_control init prerequisites and the module-level implementation
are documented in Rendering & DRM internals.
Present mode¶
The server always uses VK_PRESENT_MODE_FIFO_KHR (vsync, no tearing) in production.
MAILBOX_KHR (triple-buffer) is available via --present-mode mailbox for benchmarking
only — it reduces vsync wait by up to one frame but makes it impossible to determine which
frame a deferred flip was first visible on.
On-device overlay¶
The overlay has panels on F1–F7 (Shift+F–key hides one). Two are timing-related:
- System (F5) — active vblank clock source, refresh rate, backend.
- Benchmarks (F7) — FPS and measured frame duration, per-frame sparkline (red bars = missed vblank), phase breakdown (tessellate / upload / fence / acquire / record / submit, in µs), drop count, and jitter.