Skip to content

system: report HMD tracking system, model, and manufacturer strings (Serious Sam 3, seemingly fixes #232 too) - #394

Open
skryvel wants to merge 1 commit into
Supreeeme:mainfrom
skryvel:hmd-identity-strings
Open

skryvel wants to merge 1 commit into
Supreeeme:mainfrom
skryvel:hmd-identity-strings

Conversation

@skryvel

@skryvel skryvel commented Aug 2, 2026

Copy link
Copy Markdown

Game in question: Serious Sam 3 VR: BFE via Steam and Proton CachyOS from July
Hardware: Quest 3 on KDE Wayland via WiVRN and opensource AMD drivers
Prior status: shows some Vive looking controllers, asks to press right trigger, nothing happens with any button
Current status: fully playable, both controllers, shows Oculus models
Maybe odd: some in-gameplay interface objects have a strong glow - maybe that's just how it is
Note: game complains about display driver, but allows it to be ignored and works fine
Code by: Fable 5


Some games read the HMD's TrackingSystemName/ModelNumber/ManufacturerName strings to decide which motion controller scheme to enable. When these come back empty, such games conclude no supported controllers are present and ignore all controller input (menus still work via mouse) while rendering their fallback wand models.

Report Oculus-style identity strings for the HMD, consistent with the tracking system name already reported for the Touch controller profiles.

@skryvel

skryvel commented Aug 8, 2026

Copy link
Copy Markdown
Author

Questioned in another PR, the hardcoding of oculus etc.

OpenComposite reference. Also apparently these games read the HMD identity strings once at startup and never re-query. In my traces the game asked for TrackingSystemName ~14 seconds before the runtime bound any controller interaction profile, so at answer time there's no profile to pull from. OpenComposite probably had this too and hardcodes "oculus"/"Oculus". Games that identify controllers still get the profile-accurate strings from the controller devices, this fixed string only feeds the HMD-sniffing path.

@skryvel skryvel changed the title system: report HMD tracking system, model, and manufacturer strings (Serious Sam 3) system: report HMD tracking system, model, and manufacturer strings (Serious Sam 3, seemingly fixes #232 too) Aug 8, 2026
@ImSapphire

Copy link
Copy Markdown
Contributor

I don't think it's a good idea to hard-code the Quest 3 properties here. One idea I had is to spin up a headless session in IVRClientCore::Init and create a dummy action set with a single binding, suggest bindings for all interaction profiles, call xrSyncActions, then cache the bound interaction profiles and destroy the headless session before continuing initialisation. Then we'd have the information available early when games request such properties immediately.

Some games sniff these to decide which motion controller scheme to
enable, and they typically do it once at startup - before any controller
has connected - so the HMD is the only device that can answer. Empty
strings land such games in their fallback scheme: SUPERHOT VR picks its
Vive scheme, where dropping items needs a trackpad, and Serious Sam 3
ignores controller input entirely.

Games match against the handful of device families SteamVR shipped, so
derive the family from the OpenXR system name instead of hardcoding one
headset, and report the real system name as the model. An unrecognized
system name falls back to Oculus-style strings, since touch-style
controllers are the modern common case.

Implements xrGetSystemProperties in fakexr so the property tests can
exercise it.
mkopec added a commit to mkopec/xrizer that referenced this pull request Sep 17, 2026
Fallout 4 VR (and Skyrim VR, Serious Sam 3 VR) pick their control scheme
from the HMD's Prop_TrackingSystemName_String, which they read exactly
once right after init. We reported nothing useful for the HMD, so they
fell back to a reduced scheme where A/X and stick clicks don't work
(Supreeeme#365, Supreeeme#394).

Two changes are needed to fix this:

1. Give the HMD an identity. Each interaction profile now carries
   HmdProperties for the headset it normally ships with; the HMD answers
   ModelNumber/SerialNumber/ControllerType from that and shares
   TrackingSystemName/ManufacturerName with the controllers. Values are
   taken from Valve's Steam Link driver config (Quest 2/3 report
   "Oculus"/"Oculus Quest2|3", HMD controller type "rift"; Index
   "indexhmd"; Vive "vive"). The last seen profile is remembered so the
   identity survives session restarts and controllers going to sleep.

2. Know the profile in time. Runtimes only resolve interaction profiles
   on xrSyncActions in a focused session, and a session isn't focused
   until frames are submitted - normally by the game, long after it
   asked. So during IVRClientCore::Init, before the regular session is
   created, spin up a throwaway session with a dummy action set bound to
   the grip pose of every supported profile, submit empty frames until
   it is focused, sync once, cache the bound profiles and tear the
   session down again. The HMD identity is seeded from that cache.

fakexr now transitions to VISIBLE/FOCUSED after SYNCHRONIZED and can
preset the profile new sessions will bind, so this path is exercised;
hmd_identity_available_before_first_frame reproduces the game's access
pattern.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015X5yWegHAqamZYhDVW3WXv
mkopec added a commit to mkopec/xrizer that referenced this pull request Sep 17, 2026
Fallout 4 VR (and Skyrim VR, Serious Sam 3 VR) pick their control scheme
from the HMD's Prop_TrackingSystemName_String, which they read exactly
once right after init. We reported nothing useful for the HMD, so they
fell back to a reduced scheme where A/X and stick clicks don't work
(Supreeeme#365, Supreeeme#394).

Two changes are needed to fix this:

1. Give the HMD an identity. Each interaction profile now carries
   HmdProperties for the headset it normally ships with; the HMD answers
   ModelNumber/SerialNumber/ControllerType from that and shares
   TrackingSystemName/ManufacturerName with the controllers. Values are
   taken from Valve's Steam Link driver config (Quest 2/3 report
   "Oculus"/"Oculus Quest2|3", HMD controller type "rift"; Index
   "indexhmd"; Vive "vive"). The last seen profile is remembered so the
   identity survives session restarts and controllers going to sleep.

2. Know the profile in time. Runtimes only resolve interaction profiles
   on xrSyncActions in a focused session, and a session isn't focused
   until frames are submitted - normally by the game, long after it
   asked. So during IVRClientCore::Init, before the regular session is
   created, spin up a throwaway session with a dummy action set bound to
   the grip pose of every supported profile, submit empty frames until
   it is focused, sync once, cache the bound profiles and tear the
   session down again. The HMD identity is seeded from that cache.

fakexr now transitions to VISIBLE/FOCUSED after SYNCHRONIZED and can
preset the profile new sessions will bind, so this path is exercised;
hmd_identity_available_before_first_frame reproduces the game's access
pattern.
mkopec added a commit to mkopec/xrizer that referenced this pull request Sep 17, 2026
Fallout 4 VR (and Skyrim VR, Serious Sam 3 VR) pick their control scheme
from the HMD's Prop_TrackingSystemName_String, which they read exactly
once right after init. We reported nothing useful for the HMD, so they
fell back to a reduced scheme where A/X and stick clicks don't work
(Supreeeme#365, Supreeeme#394).

Two changes are needed to fix this:

1. Give the HMD an identity. Each interaction profile now carries
   HmdProperties for the headset it normally ships with; the HMD answers
   ModelNumber/SerialNumber/ControllerType from that and shares
   TrackingSystemName/ManufacturerName with the controllers. Values are
   taken from Valve's Steam Link driver config (Quest 2/3 report
   "Oculus"/"Oculus Quest2|3", HMD controller type "rift"; Index
   "indexhmd"; Vive "vive"). The last seen profile is remembered so the
   identity survives session restarts and controllers going to sleep.

2. Know the profile in time. Runtimes only resolve interaction profiles
   on xrSyncActions in a focused session, and a session isn't focused
   until frames are submitted - normally by the game, long after it
   asked. So during IVRClientCore::Init, before the regular session is
   created, spin up a throwaway session with a dummy action set bound to
   the grip pose of every supported profile, submit empty frames until
   it is focused, sync once, cache the bound profiles and tear the
   session down again. The HMD identity is seeded from that cache.

fakexr now transitions to VISIBLE/FOCUSED after SYNCHRONIZED and can
preset the profile new sessions will bind, so this path is exercised;
hmd_identity_available_before_first_frame reproduces the game's access
pattern.

Vibe coded using Claude Opus 5.
@skryvel
skryvel force-pushed the hmd-identity-strings branch from c12ddea to 87d15d2 Compare September 20, 2026 18:16
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