Skip to content

libretro: follow the headset through the unified VR view API - #23

Merged
LibretroAdmin merged 2 commits into
libretro:masterfrom
Davey-Hughes:unified-vr
Oct 12, 2026
Merged

LibretroAdmin merged 2 commits into
libretro:masterfrom
Davey-Hughes:unified-vr

Conversation

@Davey-Hughes

Copy link
Copy Markdown

Moves the VR mode from #22 onto the unified VR view API in libretro/RetroArch#19811 (one OpenXR core for the desktop and Quest headsets, with head tracking).

It needs that pull request's libretro.h, so it should merge after it.

Against that RetroArch the current VR mode never starts. It negotiates once in retro_load_game() and waits for a recommended eye size, which the frontend only fills in while a headset session is running. Its map also lacks RETRO_VIDEO_VIEWS_FLAG_TRACKED, so it would show as a flat stereo screen.

What changes:

  • The core asks GET_VIDEO_VIEWS_STATUS every frame, enters VR on the first frame with RETRO_VIDEO_VIEWS_STATUS_HMD, sends a TRACKED map at the recommended eye size, and goes flat with an empty map.
  • Entering sets the engine's screen to one eye and reports the 2x-wide frame with SET_SYSTEM_AV_INFO. Leaving restores the flat size. A new eye size, flagged by TARGET_RESIZED or written back by the map, is followed, and the eye targets are rebuilt.
  • VR needs Color Format 24-bit (Standard). SET_PIXEL_FORMAT is only legal at load, so VR no longer switches HDR off at run time. On another format the core says so once when a headset is present.
  • A video reinit restarts the headset session, so a headset that goes missing is waited for about five seconds, repeating the last frame, before the core goes flat.
  • Supersampling is ignored while VR is active instead of being turned off, so doom_hdr_ssaa keeps the user's choice.

Commits:

  1. libretro-common: update libretro.h for the unified VR view API: the header from OpenXR: one core for the desktop and Quest headsets, with head tracking, controllers, settings and desktop OpenGL RetroArch#19811, taken whole.
  2. libretro: follow the headset through GET_VIDEO_VIEWS_STATUS: the change itself.

To try it:

  1. Build with HAVE_VR=1.
  2. RetroArch built from OpenXR: one core for the desktop and Quest headsets, with head tracking, controllers, settings and desktop OpenGL RetroArch#19811 (./configure --enable-openxr on Linux, or the Quest build), with an OpenGL video driver. glcore is the one tested here.
  3. Settings > Video > Stereo 3D & Screens > Headset Output (OpenXR) on, and boom3_vr_enable = enabled.

Tested on Linux, against a build of that pull request:

  • Monado's simulated headset, glcore driver, with the Doom 3 demo: the core enters VR at the runtime's eye size, and both eyes reach the headset as a tracked projection.
  • make -C neo HAVE_VR=1 builds at each commit. libretro.cpp also compiles without HAVE_VR.

@cscd98 tested this branch on a Quest, and it works there.

Known, and not addressed here:

  • Two defects in the core's existing VR drawing, seen on the Frame and reproduced under Monado: a GUI monitor scene in the Mars City intro draws grey in VR, and the dropship's exhaust effect shows in one eye only.
  • The two known bugs listed in Libretro VR support #22.
  • Full-size eyes are heavy: 13 to 36 ms a frame on the Frame.

Davey-Hughes and others added 2 commits October 12, 2026 05:11
Taken whole from RetroArch's unified OpenXR pull request
(libretro/RetroArch#19811). REQUEST_FLAT and ipd_hint_m are gone from
retro_video_views; a map with RETRO_VIDEO_VIEWS_FLAG_TRACKED is the
head-tracked view, and RETRO_VIDEO_VIEWS_STATUS_HMD is how a core
learns of a headset.

Co-authored-by: Craig <1188869+cscd98@users.noreply.github.com>
A core learns about a headset only from the HMD status bit, and the
recommended eye size is only filled in while that bit is set, so the
load-time negotiation never entered VR.  The core now asks for the
status every frame, enters VR on the first frame with HMD, sends a
TRACKED map at the frontend's recommended eye size, and goes flat with
an empty map.

Entering sets the engine's screen to one eye and reports the 2x-wide
frame with SET_SYSTEM_AV_INFO, which reinits video and runs
context_reset; leaving restores the flat size the same way.  A new eye
size, flagged by TARGET_RESIZED or written back by the map, does the
same, and the eye targets are rebuilt at the next bind.

SET_PIXEL_FORMAT is only legal at load, so VR no longer switches HDR
off.  It needs Color Format 24-bit (Standard), and says so once when a
headset is present on any other format.

A video reinit restarts the headset session.  A lost headset is waited
for five seconds, repeating the last frame, before the core goes flat.

Supersampling is ignored while VR is active instead of being turned
off, so entering VR no longer rewrites the doom_hdr_ssaa option, and
leaving it restores the choice.

Co-authored-by: Craig <1188869+cscd98@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants