Observation (David, hardware, 2026-08-28)
Across a week of weave-cadence experiments on the win box (runtime #1257 gate + slot-partition builds, native 3DLuma avatar, Leia panel), perceived 3D quality tracks cadence steadiness, not update rate:
| weave cadence |
panel updates/s |
David's verdict |
| steady (stock) |
60 |
fine |
| steady (partition D=3: app 20 + repaints 40) |
60 |
"tracking is great, no stutter, very good experience" |
| varying (gate hz30 adaptive: oscillating) |
28–50 |
"pretty stuttery" |
| varying (partition v2 on VK tier) |
45–50 unsteady |
"stuttery" |
A 45–50/s varying cadence looks worse than a steady 60 — and by more than temporal sampling explains. David's hypothesis: the head-position prediction is wrong per frame when the cadence varies. The SR runtime predicts from tracking history + a prediction horizon we provide via setLatency; if the horizon is a smoothed average while the actual weave-to-photon time varies frame-to-frame, every weave is derived for a head position at the wrong time → parallax error oscillating at the cadence-variation frequency → spatial judder that reads as stutter.
The code supports the hypothesis
src/drv_leia/leia_sr.cpp (ConfigureAdaptiveLatency, v2.6.4): the adaptive path smooths the weave interval with an EMA, default alpha 0.15 (LEIA_VK_LATENCY_EMA_ALPHA), plus a constant display term. An EMA with alpha 0.15 has a time constant of ~6 weaves — under a cadence oscillating between 28 and 50/s the estimate is always lagging and always averaged across two regimes, so the per-weave horizon error is on the order of half the interval spread (~±8 ms), which at a fast head motion (~0.3 m/s) is ~±2.4 mm of predicted-position error alternating frame to frame.
The comment also says paced paths get their horizon from the runtime's measured set_frame_timing feed — same question applies there: is that feed per-frame-accurate under a varying cadence, or also smoothed?
Repro recipe (all on one box, same app, same rate ladder)
Runtime branch builds from #1257 (or any means of producing the cadence regimes):
- Steady control: stock run — steady 60, smooth.
- Steady at reduced app rate:
DXR_APP_FRAME_DIVISOR=3 on the default hybrid path (slot partition, v2.14.10-20+) — steady 60 (20 app + 40 repaint), verdict "very good".
- Varying cadence: gate build hz30 adaptive (v2.14.10-16,
DXR_AVATAR_PRESENT_HZ=30) — panel oscillates 28–50/s, verdict "stuttery"; or partition v2 on the VK-pinned tier (45–50/s unsteady), same verdict.
- Move your head laterally at a constant moderate speed while comparing 2 vs 3. Witness lines (
DXR_FRAME_WITNESS=5) document the cadence of each run.
The discriminating experiment for the hypothesis: run regime 3 with LEIA_VK_LATENCY_FIXED_US set to the true mean horizon — if stutter persists identically, the error is the per-frame variance (not the estimator's lag), and no scalar setLatency value can be correct; per-weave horizons are needed.
Asks
- Verify what horizon actually reaches the SR predictor per weave under a varying cadence (adaptive EMA path and the
set_frame_timing measured path).
- If it is smoothed/lagged: provide the actual per-weave horizon — call
setLatency (or the timestamped equivalent) before each weave with that weave's real present-to-photon time, which the compositor knows (it owns the schedule; a repaint knows it presents at the next vblank).
- Vendor question for Leia SR (if per-call setLatency can't keep up or is internally smoothed): does the SR predictor support a per-call prediction timestamp rather than a scalar latency, and is
srWeaverSetLatencyInFrames(weaver, 1) (the non-adaptive default) interacting with the adaptive path?
Cross-refs: cadence data and verdicts in DisplayXR/displayxr-runtime#1257 (gate + partition investigation); the steadiness-vs-rate finding is what motivated the slot partition, but why variance is so visible was unexplained until this hypothesis — fixing it would also make variable-cadence modes viable.
Observation (David, hardware, 2026-08-28)
Across a week of weave-cadence experiments on the win box (runtime #1257 gate + slot-partition builds, native 3DLuma avatar, Leia panel), perceived 3D quality tracks cadence steadiness, not update rate:
A 45–50/s varying cadence looks worse than a steady 60 — and by more than temporal sampling explains. David's hypothesis: the head-position prediction is wrong per frame when the cadence varies. The SR runtime predicts from tracking history + a prediction horizon we provide via
setLatency; if the horizon is a smoothed average while the actual weave-to-photon time varies frame-to-frame, every weave is derived for a head position at the wrong time → parallax error oscillating at the cadence-variation frequency → spatial judder that reads as stutter.The code supports the hypothesis
src/drv_leia/leia_sr.cpp(ConfigureAdaptiveLatency, v2.6.4): the adaptive path smooths the weave interval with an EMA, default alpha 0.15 (LEIA_VK_LATENCY_EMA_ALPHA), plus a constant display term. An EMA with alpha 0.15 has a time constant of ~6 weaves — under a cadence oscillating between 28 and 50/s the estimate is always lagging and always averaged across two regimes, so the per-weave horizon error is on the order of half the interval spread (~±8 ms), which at a fast head motion (~0.3 m/s) is ~±2.4 mm of predicted-position error alternating frame to frame.The comment also says paced paths get their horizon from the runtime's measured
set_frame_timingfeed — same question applies there: is that feed per-frame-accurate under a varying cadence, or also smoothed?Repro recipe (all on one box, same app, same rate ladder)
Runtime branch builds from #1257 (or any means of producing the cadence regimes):
DXR_APP_FRAME_DIVISOR=3on the default hybrid path (slot partition, v2.14.10-20+) — steady 60 (20 app + 40 repaint), verdict "very good".DXR_AVATAR_PRESENT_HZ=30) — panel oscillates 28–50/s, verdict "stuttery"; or partition v2 on the VK-pinned tier (45–50/s unsteady), same verdict.DXR_FRAME_WITNESS=5) document the cadence of each run.The discriminating experiment for the hypothesis: run regime 3 with
LEIA_VK_LATENCY_FIXED_USset to the true mean horizon — if stutter persists identically, the error is the per-frame variance (not the estimator's lag), and no scalar setLatency value can be correct; per-weave horizons are needed.Asks
set_frame_timingmeasured path).setLatency(or the timestamped equivalent) before each weave with that weave's real present-to-photon time, which the compositor knows (it owns the schedule; a repaint knows it presents at the next vblank).srWeaverSetLatencyInFrames(weaver, 1)(the non-adaptive default) interacting with the adaptive path?Cross-refs: cadence data and verdicts in DisplayXR/displayxr-runtime#1257 (gate + partition investigation); the steadiness-vs-rate finding is what motivated the slot partition, but why variance is so visible was unexplained until this hypothesis — fixing it would also make variable-cadence modes viable.