Engineering record of the risk-retirement gates behind the demo in the
README: Beat Saber 1.29.4 → CrossOver/DXMT → wineopenxr →
oxrsys → embedded ALVR → Quest 3 at 72 fps and ~79 ms motion-to-photon (the
pre-1.3.0 baseline; see README for the current WiFi baseline
with the native arm64 HEVC helper — 102.9 ms p50 on-head, USB 93.5 as the
gate-era transport-isolation figure) —
what each gate proved and which fixes were load-bearing. Condensed; the full
transcript is in the git history of FINDINGS-oxrsys.md (repo root). The
dead SteamVR-under-Wine path:
steamvr-blocked.
| Component | Value |
|---|---|
| Host | Apple M3 Max, macOS 26.5.1 |
| CrossOver | 26.2.0 — bottle MoltenVK 1.2.10 (x86_64, Vulkan api 1.2.290) |
| Native arm64 Vulkan | Homebrew MoltenVK 1.4.1 + vulkan-loader 1.4.350 |
| Toolchain | clang 21, mingw-w64 16.1, cmake/ninja/meson + Metal toolchain |
Question: can a cross-process GPU surface — the blocking primitive for Mac
VR — be shared via VK_EXT_metal_objects/IOSurface, across the
Rosetta-x86_64 ↔ native-arm64 boundary between the Wine bottle and oxrsys?
Method: src/gate0_iosurf.mm — Metal fills an IOSurface-backed texture
and signals an MTLSharedEvent; Vulkan imports both (VkImage + timeline
VkSemaphore), waits, copies out, byte-compares. Cross-process mode shares
by global IOSurfaceID. Built for arm64 (MoltenVK 1.4.1) and for x86_64
against CrossOver's own MoltenVK 1.2.10, run under Rosetta.
Results — all byte-exact, 0/16384 mismatched (evidence/gate0-*.txt,
local artifacts, not in the repo):
| Test | MoltenVK | Result |
|---|---|---|
| 0a single-process import + MTLSharedEvent→VkSemaphore sync | 1.4.1 arm64 | PASS |
| 0a single-process import + sync | 1.2.10 x86_64 (Rosetta) | PASS |
| 0b cross-process IOSurface share | arm64 → arm64 | PASS |
| 0b cross-process + cross-arch: arm64 creator → x86_64/Rosetta importer | mixed | PASS |
| 0b cross-process + cross-arch: x86_64/Rosetta creator → arm64 importer | mixed | PASS |
Determination: the zero-copy mechanism works — through the bottle's own MoltenVK under Rosetta and across the x86↔arm64 boundary in both directions; no MoltenVK upgrade needed. MTLSharedEvent sync was proven single-process on both arches; cross-process event transport is covered by the OpenXR swapchain-release protocol. Residual risk: low.
A minimal native Metal OpenXR client (src/oxrsys_cubes.mm, full
xrWaitFrame/Begin/EndFrame loop) drove oxrsys to a Quest 3 over USB ADB
reverse TCP: 2272×1264 H.265 @ 72 Hz, every frame decoded, render-pose match
100%, client latency ≈11–12 ms (evidence/gate1-*.txt, local artifacts, not
in the repo). The headset pose streams back and the app re-renders from it —
6DoF world-locked rendering confirmed visually in-headset, hand tracking
active. Launcher: scripts/dev/run_quest_gate1.sh. Fast-motion artifacting
is an oxrsys quality limitation, not a gate blocker.
Verdict: the existential dependency — a native macOS OpenXR runtime that streams to the Quest with tracking — holds on this machine.
Mid-project we found monofunc/wineopenxr: a working D3D11
OpenXR→native-runtime bridge for CrossOver, sharing D3D11 swapchain textures
zero-copy as MTLTextures via a DXMT interop fork (IMTLD3D11InteropDevice)
— no winevulkan patch, no Wine-from-source build, real D3D11 PCVR games. It
retired the original Gate 2 (Wine source) and Gate 4 (winevulkan) outright.
| Component | How | Result |
|---|---|---|
| monofunc/dxmt (feature/openxr, interop) | fork + GitHub CI artifact | d3d11.dll, dxgi.dll, d3d10core.dll, winemetal.dll + winemetal.so (x86_64) |
| wineopenxr | local cmake + mingw (Wine headers only) | wineopenxr.dll (PE) + wineopenxr.so (Mach-O x86_64) |
| oxrsys-x64 backend | rebuilt x86_64 with H.264 ported for Rosetta | liboxrsys-runtime.dylib, all tests pass under Rosetta |
| D3D11 test app | src/d3d11_clear.cpp (shader-free clear-color OpenXR client) + cross-built loader |
d3d11_clear.exe + libopenxr_loader.dll |
Chain: d3d11_clear.exe → libopenxr_loader.dll → wineopenxr.dll →
wineopenxr.so → oxrsys-x64, D3D11↔Metal via DXMT interop, in a dedicated
bottle with the DXMT fork overlaid. Headless: wine exit 0, 150 frames,
ImportMTLTexture2D succeeded for both eyes (evidence/bridge-SUCCESS-*.txt,
local artifact, not in the repo). Compositor pixel readback then proved the
rendered content arrives byte-exact and live — the app's pulsing red,
snapshot src[0,0] BGRA=25,25,213,255 (evidence/blackscreen-ROOTCAUSE.txt,
local artifact, not in the repo).
Seven integration fixes were the actual work:
- App OpenXR
apiVersion→ 1.1.0 (oxrsys ≤1.1.57 rejects the PE headers' 1.1.60 withXR_ERROR_API_VERSION_UNSUPPORTED). active_runtime.x86_64.jsonmust live at/usr/local/share/openxr/1/— the macOS loader ignoresXR_RUNTIME_JSONunder wine's secure-exec.- H.264 under Rosetta (HEVC hardware encode unavailable translated);
PreferredVideoCodec()auto-selects. - Request a non-sRGB swapchain format: an sRGB host texture trips
ImportMTLTexture2D'sORIGINAL_FORMATcheck (DXMT expects typeless-parent → linear). - oxrsys swapchain MTLTextures need
MTLTextureUsagePixelFormatView(DXMT requires it). - Fence sync at
xrReleaseSwapchainImage: oxrsys snapshots without waiting for the producer, and DXMT renders on its own queue → black frames; wineopenxr now waits on the DXMT/Metal fence before releasing. - Discovery loopback: broadcasts to
255.255.255.255don't loop back on macOS; a127.0.0.1beacon was added for the local simulator.
Fixes 4–5 are oxrsys↔DXMT interop findings (reported upstream). Remaining
simulator black screens were a codec mismatch, not the bridge: the simulator
only decoded H.265 while the Rosetta path sends H.264 — an H264Decoder +
codec router were added. (The legacy streamer's pacing and watchdog fixes are
in the git history; the ALVR backend below replaced it.)
Hardware H.264 encode works under Rosetta
(UsingHardwareAcceleratedVideoEncoder=true); only HEVC hardware encode is
unavailable translated (still true on macOS 27.0 beta — see the
2026-08-01 re-verification
below). The rest is subtler.
Low-latency rate control: zero-chroma bug, root-caused and fixed.
EnableLowLatencyRateControl halves encode latency (~14.8 → 7.8 ms p50) but
under Rosetta produced correct luma with all-zero chroma — a green image.
Decoded-plane scans (Y[max≈59], Cb/Cr=[0..0]) ruled out color
interpretation; the flag was first gated off. tools/vt-llrc-probe
(four-config matrix, {LL-RC on/off} × {BGRA/NV12 input}) then isolated the
failing stage: LL+BGRA = dead chroma, LL+NV12 = healthy. The bug is VT's
internal RGB→YCbCr conversion inside the low-latency (rtvc) encoder under
Rosetta — undocumented: production VT users all feed 4:2:0. Report:
apple-feedback-1-lowlatency-bgra-zero-chroma.
Fix (oxrsys 47dc2a2): 420v biplanar encoder pool + rgb_to_nv12 Metal
kernel (BT.709 video-range) on every compose path; LL-RC re-enabled with a
retry-without fallback. Encode p50 33 → 10.3 ms, live motion-to-photon
311 → 79 ms. (Apple fixed the underlying VT bug on macOS 27.0 beta — LL+BGRA now decodes
healthy chroma — and the NV12 conversion was subsequently removed on the
oxrsys bgra-direct branch; see the
re-verification and the
decision note that follows it.)
ConstantBitRate — banned, but the stall claim was retracted (2026-07-04).
kVTCompressionPropertyKey_ConstantBitRate is still never used, but the
original "accepted then stalls the pipeline" claim was retracted: an
instrumented probe (--cbr, including an exact production-config mirror)
shows classic RC accepts-and-ignores CBR while LL-RC rejects it
(-12900); the "stall" evidence was RealTime frame drops miscounted as
missing callbacks, and the live freeze matched the same-day use-after-free
below. The header also documents CBR as incompatible with
AverageBitRate/DataRateLimits, which we set. Retraction record:
apple-feedback-2-constantbitrate-pipeline-stall.
Bitrate is not enforced. VT does not reliably hold
AverageBitRate/DataRateLimits on hard content in any mode under Rosetta
(probe: 77–122 Mbps at a 42 Mbps target on noise). Mitigated with ALVR's
Adaptive bitrate feedback loop, not VT-side caps.
Rejected properties. MaxFrameDelayCount and
PrioritizeEncodingSpeedOverQuality are rejected (-12900) by the LL encoder.
Use-after-free postmortem. Frame-context fields were written after
VTCompressionSessionEncodeFrame hands the refcon to VT; LL-RC makes
callbacks near-synchronous, so the callback (which frees the context) can run
before EncodeFrame returns. Rule: all refcon writes precede submission.
Re-ran tools/vt-llrc-probe (rebuilt fresh, x86_64/Rosetta) plus one-off HEVC
and per-frame-latency probes on the newer macOS beta. Three findings:
-
The LL-RC zero-chroma "green" bug no longer reproduces. LL+BGRA now decodes healthy chroma (
Cb[42..236] Cr[60..245], deterministic across 4 runs) where it was previouslyCHROMA DEAD. Apple appears to have fixed VT's internal RGB→YCbCr path under Rosetta. We are not removing the NV12 conversion — it's beta-only, could regress, is still needed on stable macOS, and also fixes color-matrix correctness, not just the bug. -
Hardware HEVC is still unavailable under Rosetta — unchanged. Creating a session with
RequireHardwareAcceleratedVideoEncoder=YESfails (H.264 succeeds; HEVC returns -12908 classic / -12902 LL-RC).VTCopyVideoEncoderListunder x86_64 shows onlyHEVC … hardware=no(software); native arm64 on the same machine showsApple HEVC (HW) … hardware=YES, proving the silicon has the encoder — VT just won't hand it to a translated process. The software HEVC fallback is ~600 ms/frame p50 (40× over the 14 ms 72fps budget) and can't use LL-RC at all, so it's not viable. This is why the native-arm64 out-of-process encoder (noted under the ALVR WiFi backend section) is the real path to HEVC. -
"LL-RC has a worse latency tail" is an artifact, not a regression. Steady-state per-frame latency is identical to classic RC (~10 ms p50; both flat ~9–11 ms from frame 6 on). The apparent gap is three separable things: (1) a 5–6-frame warmup ramp (large IDR + HW spin-up) that dominates p95/max in a 48-frame sample — LL-RC's ramp peaks lower but stays elevated longer, inflating its p95; (2) the probe's classic-only
DataRateLimitscap made the original bitrate comparison unfair (fixed: same cap → same conclusion); and (3) LL-RC drops frames by design to hold its latency ceiling — on the probe's incompressible per-pixel-noise content it sheds every other frame from ~frame 20 (14/48), while classic RC absorbs the load and drops none. Real temporally-coherent game frames (~21 KB inter-frames here) don't trigger this, which is why LL-RC+NV12 is the live production path.
The "we are not removing the NV12 conversion" position above was reversed the
same day, with the color-matrix concern resolved by measurement rather than
assumption. A new tools/vt-llrc-probe --matrix mode encodes flat color bands
and compares decoded Y/Cb/Cr against the same BT.709 limited-range reference
the rgb_to_nv12 kernel implemented: on 26A5388g, VT's internal conversion of
BGRA matches within ±1 across all bands (NV12 controls exact at 0.0;
deterministic across runs, both classic and LL-RC). With correctness proven,
the oxrsys bgra-direct branch deletes the kernel, the NV12 pool/plane views,
and the convert pass; the BGRA composite target is now the encoder's
CVPixelBuffer itself. Consequences: the pipeline requires macOS 27+ under
Rosetta (doctor checks this; older hosts must pin oxrsys ≤ cf5f926), and
the fork carries the risk that the beta fix regresses before GA — re-run
--matrix on each macOS beta bump.
Live-verified 2026-08-02 (Quest 3, stock client, 3008x1664@72): colors
correct, 72 fps, zero packet loss. A same-day live A/B against the NV12-era
build (only the encoder reverted) measured a real latency cost that the
CPU-written offline probe cannot see: VT's internal RGB→YCbCr of
GPU-written IOSurfaces under Rosetta takes ~25 ms inside VT (vs ~2 ms for
the old Metal kernel), so encode is ~35-40 ms vs ~13-22 ms and client-measured
motion-to-photon ~114 ms vs ~82-96 ms. Accepted (decision 2026-08-02) in
favor of the simpler path — the NV12 kernel was retroactively also a Rosetta
performance optimization, and the planned native-arm64 out-of-process encoder
is the roadmap item that recovers the latency (plus HW HEVC). Merged to fork
main as ab070b8.
The original Vulkan+winevulkan plan is unnecessary: the D3D11 path works end-to-end and is the real-PCVR-game path. Remaining work is polish, not architecture.
A real Unity-OpenXR title runs through the bridge in-headset with no real Steam:
- Version: Beat Saber 1.29.4 — the first native-OpenXR build;
predates the Meta account gate that hard-crashes newer builds
(
GetXPlatformAccessTokenAsynctimeout →NullReferenceExceptioninAppInit). Pinned depot download: see the README. - DRM: Goldberg Steam emulator satisfies
steam_api64.dlloffline (no SteamStub on the exe) — also sidesteps CrossOver's Steam/CEF instability. - Launch:
./demo.sh run(run_beatsaber_1294.shremains inscripts/dev/as a superseded reference). - Confirmed in-headset: menu navigation (laser + trigger) and gameplay.
Four runtime fixes were needed beyond the clear-app bridge (all in
ext/oxrsys, one paired with ext/wineopenxr):
XR_KHR_convert_timespec_timeadvertised and implemented — Unity hard-requires the Win32 perf-counter time extension wineopenxr synthesizes from it; without itxrCreateInstancefails.XrEventDataInteractionProfileChangedemitted when the controller profile resolves — the key input fix: without it Unity's Input System stayed on the KHR Simple-Controller fallback and the menu trigger never fired.- Profile + float→bool: report
oculus/touch_controller, and threshold float sources (trigger/value,squeeze/value,select/value) to boolean inGetButtonClick. - Aim pose streamed distinctly from grip so menu lasers point where you aim.
Audio and haptics landed later with the ALVR backend, verified live. In-song pause resolved as a game/Unity limitation on every OpenXR runtime — pause works via X/A or the Quest system button; see menu-button.
oxrsys's built-in streamer was replaced by embedding alvr_server_core
v20.14.1 (its C API) into the runtime, with the stock ALVR client (v20.14.1, version-matched sideload)
on the headset. ext/ALVR is a submodule pinned to the fork branch
oxrsys-v20.14.1, which carries the reliability patches;
patches/alvr-v20.14.1-oxrsys.patch mirrors that branch as a reviewable diff
(patches/README).
The first WiFi session ran end-to-end — video, tracking, buttons, haptics and audio — but with ~2.5 stutter bursts/sec, blur from ALVR's 30 Mbps default overriding the configured bitrate, and a stream that died on headset sleep. After three fix rounds: 72 fps, total latency 78–82 ms (motion-to-photon p50 ≈79 ms), encode p50 10.3 ms, Quest decode 23 ms (226 ms at first connect), ~60 Mbps Adaptive bitrate, zero encoder drops.
Reconnect took three distinct fixes:
- A macOS-only ABBA deadlock: the CoreAudio capture callback blocked on the
session lock while
connection_pipelineheld it across cpal device enumeration, which needs the HAL mutex the callback's thread holds — every reconnect wedged as a client "error 11" timeout. Fix: a non-blockingis_streamingfor the audio callback. - Stale
StreamSenderclones pinned the UDP port after disconnect → every re-bind failed EADDRINUSE. Fix: a closeable stream writer (close_writer()on every disconnect flavor + an RAII guard) and a lock-free disconnecting flag. - Headset sleep killed tracking: the tracking/statistics receive loops exited permanently on socket error; they now retry.
Smaller patches: socket buffers actually sized (macOS rejects u32::MAX with
EINVAL, silently leaving 9216 bytes; now 8 MiB with a halving retry), audio
teardown polling 500 → 50 ms, a leftover client.wired entry no longer
starves WiFi discovery, and video-send / manual-IP failures are logged. Full
inventory: patches/README.
Top remaining quality lever is stream resolution (currently 0.75-scale of client-native), then a native-arm64 out-of-process encoder: running VideoToolbox natively removes the Rosetta fragility (hardware HEVC, LL-RC without the NV12 workaround) and reuses Gate 0's cross-arch IOSurface hand-off.
First gate of the out-of-process encoder effort (plan: gpt-5.6-sol design +
Codex adversarial review). vt-llrc-probe gained a --gpu mode: a Metal
compute kernel writes each frame into one of 3 rotating IOSurface-backed BGRA
pixel buffers and VTCompressionSessionEncodeFrame runs from the command
buffer's completed handler — the production oxrsys shape, on both arches
(--size 3008x1664 = live stream dims; vt-llrc-probe-arm64 is the native
build). Results:
- HW HEVC Main LL-RC works natively with GPU-written surfaces: session
creates with hardware required (
com.apple.videotoolbox.videoencoder.hevc.rtvc), sustains 72 Hz at 3008x1664, and under deliberately incompressible noise content degrades better than H.264 (p95 20.5 ms vs 49.6 ms; the heavy frame-shedding on this content is LL-RC's documented load behavior, same as the 2026-08-01 CPU-probe note). Under Rosetta the same config still fails -12902 (re-verified with this exact code path). - LL-RC keyframe contract holds: a mid-run
ForceKeyFrameproduces a sync sample at exactly the requested PTS on both codecs, and parameter sets extract cleanly — HEVC VPS/SPS/PPS (NAL types 32/33/34, 26/53/7 bytes),NALUnitHeaderLengthOut= 4 on both codecs. - BT.709 color contract holds natively:
--gpu --matrixworst band delta 1.1/255 (H.264) and 1.0/255 (HEVC) vs the probe's own limited-range reference. - The probe still cannot reproduce the live Rosetta conversion penalty. GPU-written x86_64 H.264 shows p50 13.6 ms — nowhere near the live ~35-40 ms. GPU-written buffers alone are not sufficient; the live cost evidently needs the game's concurrent GPU load contending with VT's conversion. Consequence: offline probe latency numbers bound the pipeline optimistically in BOTH environments; the BGRA-vs-NV12 helper input decision and all latency acceptance move to the live A/B gates (D/E).
- Curiosity, same code/content/config: the Rosetta H.264 encoder held the 42 Mbps target with 0 drops; the native one ran at ~79 Mbps and shed 136/300 frames. The two rtvc builds have different quality/rate floors — expect live HEVC bitrate behavior to need Gate E tuning, not config parity alone.
- Client HEVC capability resolved (was a plan unknown): ALVR v20.14.1
never capability-checks H.264/HEVC —
VideoStreamingCapabilitieshas flags only for AV1/10-bit/high-profile (connection.rs:787-800; 10-bit gate at:751). H.264 and HEVC are assumed universal in the protocol, so HEVC is safe to select for the stock Quest client, and the negotiated codec is echoed intosession.jsonopenvr_config/codec— the same fileRefreshNegotiatedConfigalready reads for dims.
Gate A verdict: PASS — existence proof complete (native HW HEVC LL-RC + IDR contract + color), with the latency criterion explicitly deferred to the live gates per the both-ways probe/live divergence above.
tools/xarch-ipc-probe (one source, two builds): an x86_64 parent
(simulating the Rosetta/Wine runtime) spawns the arm64 build as the future
encoder helper, hands it 3 IOSurface-backed 32BGRA 3008x1664 CVPixelBuffers
by Mach send right, and drives the production frame loop across the arch
boundary — parent GPU-writes, socketpair notify after the command buffer's
completed handler, child verifies/encodes. Logs:
evidence/xarch-ipc-probe-gateB-100k.log, -gateB2-noise.log,
-gateB2-matrix.log.
- The preferred rendezvous route is dead — by XPC poisoning, not by
rendezvous. Installing the parent's receive right as the child's
bootstrap port (
posix_spawnattr_setspecialport_np(TASK_BOOTSTRAP_PORT)) delivers the check-in message fine, but libxpc latches the bootstrap port during libSystem init, beforemain(); restoring the real port afterwards (sent by the parent in the first Mach message, thentask_set_special_port+bootstrap_port) does not heal it. The child's first XPC-touching call hangs forever — concretelyIOSurfaceLookupFromMachPort → os_log_create → _os_trace_get_logd_port → bootstrap_look_up2against a port nobody launchd-serves (sampled stack in the probe header). Metal's shader compiler and VideoToolbox sit behind the same door, so this route cannot host an encoder helper unless the parent proxies the launchd protocol. The probe detects the hang with a 10 s watchdog (_exit(3)) and falls back automatically. - The fallback is the design: bootstrap namespace left intact. Child
bootstrap_registers a per-spawn name (xarch-ipc-probe.<pid>.<seq>), parentbootstrap_look_ups it — worked first try, every spawn (11 spawns/run).bootstrap_registeris deprecated; the production helper should invert it (parentbootstrap_check_ina well-known per-pid name before spawning, child looks it up), same namespace-intact principle. - IOSurface transfer + rotation: 100,000/100,000 rotations, zero stale. Each surface validated in the child (3008x1664 'BGRA', rowBytes 12032, alloc 20 021 312) and re-verified per rotation by a child-side Metal compute pass over all 5M pixels (frame index encoded in a pixel block and hashed into every pixel). Notify+verify round-trip p50 0.76 ms / p95 4.2 ms / p99 5.4 ms / max 7.9 ms — the IPC hop itself is noise against a 13.9 ms frame budget (early Gate C signal).
- Kill/respawn leaks nothing. 5 cycles of SIGKILL mid-stream (frames in flight) → respawn → re-register the same surfaces → 200/200 clean rotations. Parent Mach port count flat at 69 across all 5 cycles; parent-held IOSurfaces unaffected by child death.
- Clock-domain trap for the helper protocol:
mach_absolute_timeticks are not comparable across the Rosetta boundary — the x86_64 side sees a 1/1 ns timebase, native arm64 125/3. First B2 run produced 7.7e14 ms "latencies". Wire timestamps must be normalized (we use nanoseconds); same underlying counter, so deltas are then valid cross-process. - Gate B2 — hardware HEVC accepts foreign surfaces. The child wraps each
received IOSurface once with
CVPixelBufferCreateWithIOSurface(+ BT.709 ShouldPropagate attachments) and feeds the wrapped buffers to a hardware-required HEVC Main LL-RC session (com.apple.videotoolbox.videoencoder.hevc.rtvc, Gate A property set): 300/300 frames accounted, decode-back chroma healthy, and the flat-band pass decodes to BT.709 limited-range with worst band delta 1.0/255 (tolerance 8), 0 drops at 0.2 Mbps (static content). GPU-done → child-VT-callback p50 15.7 ms / p95 19.7 ms / p99 67 ms on band content; noise content reproduces Gate A's native-HEVC floor exactly (ran ~80 Mbps against the 42 Mbps target, shed 143/300) — Gate E bitrate tuning, not a seam problem. Two arm64 LL-RC quirks:PrioritizeEncodingSpeedOverQualityis rejected (-12900), and theUsingHardwareAcceleratedVideoEncoderquery itself fails (-12900) — hardware is proven by the RequireHardware create succeeding plus the rtvc encoder ID.
Gate B verdict: PASS — via the bootstrap-namespace route; the special-port route is a documented FAIL (rendezvous works, XPC dies) and the helper design moves to bootstrap-based rendezvous. Gate B2 verdict: PASS — the foreign-surface wrap-once seam is production-viable; hardware HEVC LL-RC encodes parent-written surfaces cross-arch with correct color.
USB-wired session (adb forward tcp:9943/9944 + client.wired pinned to
127.0.0.1 — the ALVR wired shape; the "searching for streamer" WiFi symptom
earlier that night was these same leftover adb forwards squatting the Mac's
ports). Helper spawned by the runtime from INSIDE the Wine process via
posix_spawn (arm64 native, capsH264=0x3 capsH265=0x3).
- Gate D (helper H.264, isolates IPC) PASS: enc totalMs p50 24-35ms / p95 28-40ms — same band as the in-process baseline (~35-40ms), 0-2 drops/s. Live IPC cost is invisible, as Gates B/C predicted. Corollary: the "~25ms Rosetta conversion penalty" is mostly VT's conversion contending with the game's GPU load — native VT pays it too under load; the remaining encoder lever is the NV12 Metal kernel in the parent (untested trade), not the arch.
- Gate E (helper HEVC) PASS — the codec thesis confirmed: 30s dashboard sample (n=1997): total M2P 93.5ms p50 (vs ~114ms H.264/WiFi baseline); Quest decoder 16.6ms p50 (was ~28-32); decoder_queue 1.1ms p50 (was ~30 — collapsed exactly as predicted: HEVC decodes faster than realtime so the queue can't build). decode+queue: ~55-60ms → ~18ms. Note vsync_queue 22.9ms p50 — frames now arrive EARLY and wait for display; frame-pacer tuning could reclaim another ~10-15ms. Encoder unchanged (37.6ms p50); native encoder sheds ~6 frames/s pushing against the 80Mbps cap (its quality floor is higher than Rosetta's — bitrate/preset tuning open).
- Gate F (SIGKILL helper mid-HEVC-stream) PASS: EOF detected → in-flight frames reclaimed → new helper up and HEVC re-ready 383ms after the kill → codec config re-sent → stream continued; EndFrame never blocked, tracking uninterrupted, "failure 1 this session" budget accounting correct. Same-codec respawn, no codec flip needed. (Cosmetic: "VideoEncoder: Shut down" logs twice during the swap.) Parent-kill and generation-chaos legs deferred to the soak gate at the time — both completed 2026-08-04, see the batch A / soak section below.
Deployed config now ships encoder_process = "auto" + video_codec = "auto".
Player verdict: "feels rly good" — and Gate D over USB already felt better
tracking-wise (wired network 2.7ms p50 vs WiFi ~6ms spiky, independent of
codec).
Full record: evidence/batchA-soak-20260804-results.md +
evidence/soak-20260804-samples.csv (local artifacts). Stock ALVR Quest
client v20.14.1, WiFi discovery, 3008x1664@72, 80 Mbps, oxrsys 1ca5ef6.
- WiFi baseline (desk-idle, 231,484 frames): total 106.9 ms p50 / 130.7 p95 — encoder 38.2, network 7.4, decoder 16.7, decoder_queue 1.9, vsync_queue 24.4 (pacing headroom). On-head (1 min head-motion): 102.9 / 130.5 — motion state doesn't move the number. Never compared against the USB 93.5 (different transport).
- V4 codec/fallback matrix 5/5:
h264-forced on the helper; silent auto fallback with the helper absent; spawn-fail ×2 → pin (13 ms failover) with the hands-free 30 s budget retry landing to the second; reconnect no-inherit; codec-churn identity rebuilds. - V5 kill legs: SIGKILL→HEVC-ready 398 ms (matches the 383 ms USB
gate figure; 515 ms on a mid-soak repeat); parent kill-9 → helper EOF-exit
0.32 s, no orphan, no
alvr_shutdown; EndFrame enqueue ≤0.03 ms p95 throughout. - V7 soak (60 min): 0 uninduced helper deaths; RSS/fd flat (helper ~48 MB / 20-21 fds per generation); 6 IDR storms limiter-capped at ~1/s; one labeled generation rebuild (515 ms).
- Found and since fixed (oxrsys
a0d37b8+ the wine-vr preflight commits): the configure-time sweep deleting the staged helper, the warn-onlyautopreflight, the toml trailing-comment parser bug, and the silent auto→in-process downgrade log gap. Still open: the Quest display-standby freeze (client-side experiments next) and the upstream dashboard egui wedge (restart recovers).