Settings never polled OpenVR events. When vrmonitor crashed at 21:12:01,
vrserver sent VREvent_Quit to all clients; Steam and the web helpers
disconnected, Settings stayed connected and vrserver SIGKILLed it at
21:12:06 ("didn't quit in time"), holding up SteamVR shutdown 5 s.
The preview thread now drains the event queue every 250 ms (also while
the preview is hidden). On VREvent_Quit it shuts the OpenVR client down
and stays disconnected from that vrserver; the existing PID-change guard
reconnects to the next one. The window keeps running.
Everything below lost its last caller when the GPU preview replaced the
CPU path; each was grepped for references, then the app was rebuilt
(--locked, no Rust warnings) and cargo test passed.
- native/overlay_preview.{cpp,hpp,comp}, bridge rifts_preview() and
the Rust `preview` command: the CPU readback, compute downscale,
JPEG q80 encode and Tauri IPC frame path.
- jpeg-encoder dependency: only used by that command.
- build.rs compute-shader step and the overlay_preview sources.
- PID_CACHE/server_pid_fast(): a 1 s TTL cache that hid the ~9 ms
pgrep spawn from the old per-frame path; process lookup now reads
/proc and the preview no longer resolves the PID per frame.
- style.css body.mirror/#mirror-only (standalone mirror window, no
markup sets them) and .seg (segmented control, no markup uses it).
- main.tsx Snapshot.proximity/idle: never read by the frontend. The
backend still emits them for --snapshot evidence and the restart guard.
The headset view is drawn natively instead of streamed through the
webview. A preview thread re-acquires SteamVR's system.HeadsetView
overlay once per compositor vsync with the same VROverlayView_t (as
the OpenVR header advises), samples it on SteamVR's GPU and presents
into a Vulkan swapchain on a Wayland subsurface placed over the
preview box. No readback, encode, IPC or decode.
- Re-acquire without release: ~25 us, no vrclient log line per frame
(acquire+release cost ~1 ms and logged one line each time).
- Paced from IVRSystem::GetTimeSinceLastVsync, one present per
compositor frame, MAILBOX/IMMEDIATE so the thread never blocks.
- In HMD Standby with no new compositor frame, refresh once a second:
any display-rate GPU submit costs vrcompositor CPU on NVIDIA.
- The subsurface has an empty input region; double-click, F11, Esc and
the Fullscreen button keep working, aspect kept with black bars.
- Snapshot holds the OpenVR lock only for OpenVR calls, so its process
spawns cannot stall the preview; process lookup reads /proc instead
of spawning pgrep.