8709 Commits
Author SHA1 Message Date
lbgos edaa507b59 Arch packages: release r29 r29 2026-10-16 22:22:55 +03:00
lbgos 41e1aabe06 Rift S: keep Quick Calibrate from putting the floor at head height
Quick Calibrate places the floor where the headset is, but off-head the
Rift S is in standby and holds its last head pose, so the floor ended up
at head height (#5). The Room Setup guard now keeps the calibration made
while the headset was in use. If the standing origin changes in the same
universe while the headset is in standby, the guard restores that
calibration and explains that Room Setup sets the floor. The unbounded
session universe cannot be committed through IVRChaperoneSetup, so this
restore reloads the saved file.

Each session also re-bases tracking, so offsets saved in universe 3 sent
the floor to the wrong height in later sessions. The session origin is
now reset to the plain origin at startup. The saved room (universe 2) is
unchanged.

Fixes #5
2026-10-16 21:23:22 +03:00
lbgos 68c8b14a36 roomsetup: give first-time setup a floor to adjust
Full Room Setup (step 7) resets the floor to pending detection and waits
for floor_detection_result. The guard only published the saved plane, and
on a first setup it does not trust that plane, so no result ever arrived:
the step showed no floor, and pulling the trigger off the panel just
hid the dashboard, which cancels setup (#4).

When the saved plane is untrusted, publish this session's nominal floor
(raw Y=0, the floor the unanchored universe already uses). The user then
adjusts it as usual. The old plane and the manual-floor reset are still
never sent from an untrusted session.

Refs #4
2026-10-16 21:23:22 +03:00
lbgos 0863f9eb27 rifts-setup: keep SteamVR on the host so the driver loads
Steam starts SteamVR 2.17 inside the Steam Linux Runtime (sniper)
container, which only sees the host's /usr under /run/host. vrserver then
skips /usr/share/steamvr-monado as "not a directory" and reports
HmdNotFound (#3).

The registration service now sets SteamVR's launch option to
vrmonitor.sh %command%, which starts SteamVR on the host. Steam rewrites
localconfig.vdf on exit, so the option is written only while Steam is
closed, and the service logs a restart hint until then. Custom launch
options are left alone. Uninstall removes only this option.

Fixes #3
2026-10-16 21:05:22 +03:00
Ryan FordandClaude Opus 5.5 b7826d277f steamvr_drv: set SteamVR's preferred refresh rate to the Rift S rate
SteamVR's default steamvr/preferredRefreshRate is 90. On start the
compositor logs "Trying to match desired rate of 90.000000Hz", only
finds the 1440x2560@80 mode, sets Prop_DisplayFrequency_Float to 90
and paces frames for 90 Hz. UpdateDisplayFrequency() then puts the
property back to 80, but the frames are still paced wrong. A light
app (SteamVR Home at ~5 ms CPU/GPU) still dropped ~9% of frames with
~1 timed-out frame per second; with no reprojection on Linux each
dropped frame is a visible hitch.

Write the device's display frequency to steamvr/preferredRefreshRate
when the Rift S activates, before the compositor starts. The compositor
then requests 80 Hz and the frequency override no longer fires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:54:32 +03:00
Ryan FordandClaude Opus 5.5 e9a098e313 rift_s: resync camera frame time after a clock discontinuity
IMU samples are ignored until the first SLAM frame is accepted, so the
first frame's epoch offset is computed against an IMU timestamp of 0.
When the extended IMU clock is a 2^32 us epoch ahead of the camera
clock, that frame maps to a negative monotonic time and is rejected as
"went backward". last_frame_time then stays 0, IMU stays ignored, the
epoch offset is never corrected, and every following frame is rejected
too: no head tracking, an empty grey Room View in Room Setup.

Seen on 8 of 8 starts on one headset, e.g.:
  frame_ts=1625067443000 imu_ts=0 hw2mono=-3395444712931
  -> mono=-1770377269931 (now=2524604154978)
with the IMU clock at 5920 s vs the camera at 1625 s once IMU ran.

Treat a backward step of more than a second as a discontinuity and
accept the frame. It is not fresh, so it is not submitted to SLAM, but
it ungates IMU; the next frame gets the correct epoch offset and maps
to ~now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:54:32 +03:00
lbgos ad1553f855 Arch packages: prebuilt release package and PKGBUILDs 2026-10-14 15:43:18 +03:00
lbgos d82b8cbdac Settings: apply the VR View KWin rule from packaged installs r28 2026-10-14 15:23:12 +03:00
lbgos 09680d2c3c README: replace internal status line with a features list 2026-10-14 01:59:27 +03:00
lbgos f09fac0c5a README: Rift S, liberated tagline and demo video 2026-10-14 01:54:21 +03:00
lbgos bef2332a52 Use native-style Desktop dashboard tab and hide KWin duplicate 2026-10-14 01:50:57 +03:00
lbgos 328cb4b1eb Update public README for r28 features and source installation 2026-10-14 01:48:56 +03:00
lbgos 7c9c704d24 Enable full-resolution preview through persisted SteamVR VR View 2026-10-14 01:18:57 +03:00
lbgos 5109b4f0ca Launch the desktop overlay through Rift S driver registration 2026-10-14 01:11:02 +03:00
lbgos 03f03bc7af Add native SteamVR desktop dashboard overlay 2026-10-14 01:11:02 +03:00
lbgos 188aaebfdb Settings: disconnect on VREvent_Quit instead of being killed
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.
2026-10-14 00:41:52 +03:00
lbgos 836ed95987 Hold Rift S room coordinates through tracking loss and SLAM recovery 2026-10-14 00:36:36 +03:00
lbgos 43c9507755 Settings preview: track requested swapchain size; test process lookup
Compare layout changes against the size the swapchain was requested
for, not the extent the surface caps may clamp it to, so a clamped
surface cannot recreate the swapchain every frame. Add a focused test
for the /proc process lookup that replaced pgrep.
2026-10-13 20:08:19 +03:00
lbgos 2183251966 Settings: remove dead preview and UI code
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.
2026-10-13 19:51:21 +03:00
lbgos 5526967a23 Settings preview: zero-copy GPU path at headset refresh rate
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.
2026-10-13 19:46:23 +03:00
lbgos 9669e23ef3 Settings preview: 30 fps JPEG stream and fullscreen
Poll the headset preview at 30 fps instead of 5 Hz, encode frames
as JPEG to keep the Tauri IPC round-trip small, cache the vrserver
PID and the overlay handle on the hot path, and retain a ready
Vulkan device across transient frame errors. Add a fullscreen
preview (button, double-click, F11, Esc) with aspect-preserving
fill, plus a small fps/size/latency readout.
2026-10-13 18:31:00 +03:00
lbgos b9ad1f17ad Package the missing 32-bit EGL GBM platform for Steam desktop capture 2026-10-13 17:03:07 +03:00
lbgos b7ee38860c Keep recognized SteamVR room stable and enable Wayland desktop capture 2026-10-13 16:51:47 +03:00
lbgos 4024175ac8 Bound confirmed display-crash cleanup without resurrecting quit sessions 2026-10-13 07:32:01 +03:00
lbgos 412ae0e13c tests: cover compositor respawn during display recovery
Fake vrcompositor/vrserver/vrmonitor daemons let DisplayRecovery pin,
lose and re-pin generations. A respawned compositor must not trigger a
session restart; a dead one with no replacement still must.
2026-10-13 07:27:18 +03:00
lbgos 3b561682a0 steamvr_drv: reuse the live pose thread on repeated Activate
Activate can run again on the same driver object without an intervening
Deactivate. Spawning a second pose thread orphaned the first (leaked,
never joined) and left two threads racing on m_pose via
TrackedDevicePoseUpdated. Keep the running thread instead.
2026-10-13 07:27:18 +03:00
lbgos c74d60eb6e steamvr_drv: stop the whole pinned session before waiting in recover_display
The helper SIGTERMed only the monitor and then waited 10s for a server
and compositor it never asked to exit. Signal all three pinned
generations up front; give up only if the server itself is already gone.
2026-10-13 07:27:18 +03:00
lbgos d18846dcbc steamvr_drv: adopt a respawned compositor instead of restarting the session
DisplayRecovery froze its compositor handle while the loss latch was set,
so a compositor SteamVR had already respawned still looked dead and the
guard SIGTERMed a self-healed session. Re-pin whenever the tracked
generation exits and a unique replacement exists; keep the dead handle
only while nothing replaced it.
2026-10-13 07:27:18 +03:00
lbgos 7965751cc9 Exercise production haptic reset and shutdown radio bypass 2026-10-13 07:21:07 +03:00
lbgos 96d91f162f Require a live guard world frame before Save confirms saved bounds
A SLAM restart between the last recorded keyframe and Save clears
world_valid; confirming then publishes saved bounds in a
session-derived frame until the 1 Hz verifier revokes them. Stay
unconfirmed and relocalize from fresh votes instead.
2026-10-13 07:19:47 +03:00
lbgos addb8495fe tests: cover haptic latched-stop across transport reset 2026-10-13 07:19:47 +03:00
lbgos e76388e9ea rift_s: destroy camera debug sinks, avoid destroy on uninited mutex 2026-10-13 07:19:47 +03:00
lbgos cffa075777 rift_s: let shutdown haptic stops bypass a wedged radio epoch 2026-10-13 07:19:47 +03:00
lbgos c9f0f6ff8e rift_s: keep latched haptic identity across transport loss so reconnect stops it 2026-10-13 07:19:47 +03:00
lbgos 73dbdf1401 Exercise controller snapshot queries through batched IMU reports 2026-10-13 06:55:05 +03:00
lbgos 59d3eddac1 Keep exact controller head queries outside the pose mutex 2026-10-13 06:51:36 +03:00
lbgos 5c23f4b9a2 Require advancing native vsync before ending display recovery 2026-10-13 05:31:02 +03:00
lbgos dce2075d43 Recover SteamVR display sessions after Rift S reattachment 2026-10-13 05:24:49 +03:00
lbgos 37ce53bbbc Reconfirm saved bounds after tracking loss and verify drift at one hertz 2026-10-13 04:45:39 +03:00
lbgos 90d695a566 Keep HID and camera handles out of SteamVR child processes 2026-10-13 04:41:42 +03:00
lbgos 10e56431ce Recognize the saved room from sparse samples and skip matching off-head
Hold world confirmations across invalid SLAM samples instead of
resetting on every miss; a candidate drops only when stale (>3 s) or
from an older SLAM session. The 3-vote bar, 4 cm / 3 deg agreement and
the chained 3 s window are unchanged, so transient wrong matches still
cannot accumulate votes.

Wait up to 250 ms for the exposure's SLAM sample and accept the same
250 ms gap the display pose path tolerates, so a loaded backend does
not make recognition samples unusable while published poses stay valid.

Skip feature matching while proximity reports off-head standby, and
verify at 0.2 Hz once the room is localized; match every queued pair
while searching or recording. Attempts and diagnostics freeze visibly
while skipping.

Count the first failing usability gate per unusable attempt
(paused/sample/gap/flags/generation/guard) in diagnostics, the
per-second world log, the pending-room warning and the status file, so
the next worn session shows which condition dominates.

Triangulate at most one landmark per second-view pixel, with separate
live and reference-image sets so temporal pairs keep their own domain.
Replay: same-room recognition still confirms in ~0.5 s with tighter
votes on fewer map points; sparse valid samples confirm where the old
window reset could not.
2026-10-13 04:23:11 +03:00
lbgos 3952df76d0 Return the Monado input update result for proximity 2026-10-13 02:37:46 +03:00
lbgos e54298ff75 Expose physical Rift S proximity to native runtime standby 2026-10-13 02:37:13 +03:00
lbgos 8bc9f0856b Publish Rift S transport loss through OpenVR connection poses 2026-10-13 02:32:16 +03:00
lbgos d68d598459 Keep the HMD alive while waiting for camera enumeration 2026-10-13 02:25:28 +03:00
lbgos e1ee4a8c2d Invalidate the retained tracker pose used by attached hand devices on loss 2026-10-13 02:22:59 +03:00
lbgos 66015ec751 Initialize online state in controller fixture constructors 2026-10-13 02:19:38 +03:00
lbgos ae84e8b785 Retry bounded EIO failures and model attached hardware in pose fixtures 2026-10-13 02:18:19 +03:00
lbgos 7ed84cfcdd Release SLAM buffers on USB loss and bound radio busy polling 2026-10-13 02:16:26 +03:00
lbgos fde10e6e9d d/v4l2: fix reconnect UAF, thread/mmap leaks on device loss
Refcount frameserver storage so destroy defers munmap/free/close
until outstanding ROI frames return; always join the stream thread
via a joinable flag instead of the running flag; wake blocked DQBUF
with poll timeout plus STREAMOFF; make running/used state atomic.
2026-10-13 02:15:42 +03:00