Files
daniel-lynch--ovrplugin-ope…/docs/handoffs/HANDOFF-2026-06-26-skipblack.md
T
Daniel LynchandClaude Opus 5.5 da7dd08640 docs: fix runtime claim, stale header notes and dangling doc references
- ovrplugin_shim.h: runtime on Steam Frame is SteamVR (HOST.md), not Monado;
  drop the "Status: scaffold" line and the note that SetupLayer /
  GetLayerTexture2 await a 128-byte desc (implemented against the 108-byte
  ovrpLayerDesc); point RE-NOTES/SHIM-SCOPE at docs/research/.
- lever2-detect-skip-black-handoff.md lives in docs/research/, not analysis/.
- References to unpublished RE notes now say so instead of naming files that
  are not in the repo.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 22:44:34 -04:00

82 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RE4 VR Shim — Handoff (2026-06-26, skipblack instrument session)
Continuation of `HANDOFF-2026-06-26.md` (morning). Branch `latency-perffix-copyring`.
This session built + ran **Lever 2 step 1 (instrument-only black-frame detector)** and
validated the signal is real but coarse. Detailed finding in auto-memory
`skipblack-posthitch-signal-validated`. Design: `docs/research/lever2-detect-skip-black-handoff.md`.
## TL;DR — the post-hitch black signal is REAL but needs a tighter gate + frame-accurate proof
Added `debug.re4vr.skipblack 1` (instrument-only): after a HITCH (dt>20ms), flag the next
`skipblackn` frames as LIKELY-TRUNCATED and log them. NO behavior change at level 1. Ran on
device (standing, walk off bridge into house). 47 HITCHes / 89 flagged frames. Result:
- **The truncated/black frame has a signature: a SHORT (<12ms) frame right after a big hitch**
— it finishes fast because UE rendered almost nothing into it (matches RenderDoc 28-vs-198
draws → pure black).
- **Big hitches (≥40ms): 25, of which 52% have that <12ms truncated recovery frame.**
- **Mild hitches (20–40ms): 22, only 5%** — these recover to a full ~14ms frame = a 1-frame
judder, NOT black. The current heuristic OVER-flags these.
- HITCH magnitudes span 20ms → 3.8s. The multi-hundred-ms / multi-second ones are
**load/streaming stalls** (level transitions) — a different event from per-frame gameplay
black drops. Must be separated from the gameplay black.
- Ground truth is still COARSE: user confirmed "black" happened, but not frame-accurate; the
short-dt=black link rests on the single RenderDoc capture, not per-frame verified.
Raw frame/flag sequence persisted: `analysis/skipblack-2026-06-26/frame-sequence.log`.
## NEXT TASK — do BOTH (user decision this session):
### (3) Tighten the detector, then re-instrument
- **Gate the arm on hitch ≥40ms** (drops the 22 harmless mild hitches; ~halves false flags).
- **Add short-dt confirmation:** only treat a post-hitch frame as truncated if its own
dt < ~12ms. Combines the two corroborating signals; cuts the ~48% of big hitches whose
recovery wasn't short (those may be a different failure mode — investigate separately).
- **Handle sustained-overload clusters** (e.g. f=3162–3173: ~10 consecutive hitches). The
fixed "next 2 frames" model is wrong there — the whole burst is bad. Consider: stay armed
while consecutive frames keep hitching, not a fixed count.
- Re-run instrument-only and re-inspect (reuse the awk recipes from this session's analysis).
- Code is all in `shim/src/xr_runtime.c`: `skipblack_level()`/`skipblack_count()` (~205) and
the flag block inside the FRAME/HITCH trace (~1186, look for `SKIPBLACK: LIKELY-TRUNCATED`).
### (2) Frame-accurate ground truth via Meta Cast (do alongside / before reproject)
- In-game recording is broken (empty mp4); display 0 is FLAG_SECURE so scrcpy/screenrecord
can't see VR. Use **Meta Cast → desktop screen-record** while walking off the bridge.
- Run with `skipblack=1 skipblackn=2 trace=1`, capture logcat with timestamps in parallel.
- Align the video's visible black flashes to the `SKIPBLACK: LIKELY-TRUNCATED` log
timestamps to PROVE (or refute) flag == perceived black, per frame. This is the
`verify-before-theory` discipline — don't build the reproject on the coarse signal alone.
### THEN — Lever 2 step 2 (reproject, `debug.re4vr.skipblack 2`)
Only after (2)+(3). Re-present the **last-good** eye image with the current pose so the
OpenXR compositor timewarps it instead of showing black.
- **Use the COPY-ring, NOT a cross-frame swapchain hold** — holding across frames is what
sank `pipeline=1` (see memory `deferred-flush-unstable-abandoned`). Copy last-good eye →
shim VkImage (`xrr_vk_alloc_images`/`shimImages[]`, copy path in end_frame ~922), blit it
into the acquired image on a flagged frame, submit the composition with the CURRENT pose.
- Low harm on false positives: reprojecting a stale frame ≈ what the compositor already does
during the hitch, so over-flagging mild hitches is tolerable but wasteful — the ≥40ms gate
keeps it clean.
- Success = black flashes replaced by (at worst) brief reprojection judder, not black.
## Build / deploy / test (unchanged)
```
./shim/build_android.sh && ./packaging/repack.sh # repack bundles LAST build — check
# shim/build/arm64/libOVRPlugin.so timestamp
adb -s <redacted-serial> install -r packaging/out/re4vr-shim.apk
adb -s <redacted-serial> logcat | grep -iE "xrr|SKIPBLACK"
```
Launch is BLOCKED by the controllers-asleep system dialog
(`app_launch_blocked_controller_required`) — wake controllers + headset on before
`am start -n com.Armature.VR4/com.epicgames.ue4.GameActivity`.
Logcat is dominated by PerfMetrics polling — filter to `FRAME f=|HITCH|SKIPBLACK` for pacing.
## Props
- `debug.re4vr.skipblack 0|1|2` — 0 off / 1 instrument-only (built) / 2 reproject (TODO).
- `debug.re4vr.skipblackn N` — post-hitch frames to flag (default 2). Will change with the
cluster-aware rewrite in (3).
- Reset to baseline now: skipblack=0, skipblackn=0, trace=0, ffr=2, resscale=100.
## State
- Code committed? **NO — `skipblack` detector is UNCOMMITTED** in the working tree
(`shim/src/xr_runtime.c`). Commit it (instrument-only, gated off, safe) before further work.
- Branch `latency-perffix-copyring`, clean except the skipblack edit + the new analysis dir.