protonscr

Decouple OpenVR and OpenXR from Steam

protonopen
ValveSoftware/Proton#8256 · opened 2024-11-19 by Tuupertunut · updated 2026-02-24 · 11 comments · github
1 matching comments, n / p to jump
TTuupertunut 2024-11-19 github

Currently both Proton's wineopenxr and vrclient modules depend on a Windows registry key HKEY_CURRENT_USER\Software\Wine\VR. This key seems to be used to store VR-related Vulkan extensions for use in those modules. The key must be present for wineopenxr or vrclient to work, otherwise they will crash when opening an OpenXR or OpenVR application.
https://github.com/ValveSoftware/Proton/blob/efbcf967a1d3354a0a92bcf978a981b3a56b61b4/wineopenxr/openxr.c#L333-L337
https://github.com/ValveSoftware/Proton/blob/3c3d468971353a5302f401a1e017730970ab8921/vrclient_x64/vrclient_main.c#L134-L138

The only code where this registry key is initialized is steam.cpp in steam_helper module, which means that Steam must always be run before any VR application is opened. Therefore Proton's VR support has a de-facto dependency on Steam.
https://github.com/ValveSoftware/Proton/blob/3c3d468971353a5302f401a1e017730970ab8921/steam_helper/steam.cpp#L702-L1024

From an architecture standpoint it would make more sense to decouple the VR initialization code from steam_helper, so that the wineopenxr and vrclient modules could be used independently and not require Steam. Currently they are already independent modules in every other way. This would allow using them in regular Wine as well as not having to ensure Steam runs before any VR app. I see two different approaches:

  1. Move the VR registry initialization code to the wineopenxr and vrclient modules so they could initialize themselves. I have an example patch for Proton 8.26 where I copy pasted the init code from steam_helper to vrclient and now I'm able to run non-Steam VR games with Wine-GE without having Steam.
    proton-vrfix.patch.txt

  2. As suggested in #6038, don't use the registry key at all and instead query Vulkan extensions directly from wineopenxr and vrclient modules when needed.

Another note:

The registry key also seems to have a state value that different modules like wineopenxr and vrclient, as well as dxvk and vkd3d use to check if steam_helper has finished initializing VR. As far as I've understood, this would not be needed if the wineopenxr and vrclient modules were in charge of initializing themselves.
https://github.com/doitsujin/dxvk/blob/dd15328ccf87f709235fc320edb04172d15fdea2/src/dxvk/dxvk_openvr.cpp#L62-L63
https://github.com/HansKristian-Work/vkd3d-proton/blob/657f81b0f6da25f6f991faa6a92fac2a09fcce08/libs/d3d12core/main.c#L129

Ccrabdancing 2025-05-08 github

Are there any workarounds for this in the short term? I'm trying to get Monado Proton VR stuff to work without Steam for my personal setup, and just ran into this. :/

TTuupertunut 2025-05-10 github

I don't know of any other workaround than editing the Proton code and compiling it yourself. I made that patch for the approach 1 by copy pasting the VR registry init code from steam_helper to vrclient and that worked for Proton 8.26, the VR modules could now be used in Wine-GE 8.26. For newer Proton versions the patch should probably be updated. Or if you happen to use Wine-GE 8.26 I can send you the precompiled files

Ccrabdancing 2025-05-10 github

@Tuupertunut

That's really kind of you to offer! I'm super comfortable compiling stuff myself, and I usually deploy my stuff with Nix. (Also, am currently on proton-experimental and proton-9, and sometimes proton-8, depending on the app I'm trying to run.) If you give me an old example of your patch's source code, I could write some code to apply it continuously to newer versions using the Nix build system! :D Might even be helpful to other people.

TTuupertunut 2025-05-13 github

The patch is there linked in the issue, proton-vrfix.patch.txt

Ccrabdancing 2025-05-20 github

@Tuupertunut Oh cool! I'll try it out.

GGloriousEggroll 2025-09-20 github

The patch is there linked in the issue, proton-vrfix.patch.txt

can we get a rebase of this patch? I attempted to rebase it but hit some snags with missing includes (../src/ivrclientcore.h and openvr.h)

TTuupertunut 2025-09-20 github

Back when I made that patch I also tried to rebase it for Proton 9 but something had changed in the way the wineopenxr module could call the vrclient_x64 module and I ran into errors. That's why the patch only works with Proton 8.26.

The logic of the patch goes something like this:

  • Copy-paste the VR registry initialization code from steam_helper/steam.cpp to a new file vrclient_x64/setup_vr.cpp. For some reason it didn't work if it was copy-pasted into wineopenxr so I copy-pasted it into vrclient_x64 instead.
  • When wineopenxr first time needs that registry key, load vrclient_x64.dll as a dynamic library and call the setup_vr code. This is enough to get it working with OpenXR games.
  • When vrclient_x64 first time needs that registry key, just call the setup_vr code directly as it's in the same module. This makes it work also with OpenVR games.

After rebasing it on Proton 9 if I remember correctly, wineopenxr was unable to load vrclient_x64 as a dynamic library anymore and crashed at runtime and I couldn't figure out why. I tried different calling conventions and none of them worked so maybe some Wine magic. I welcome anyone to make a similar patch for the latest Proton.

TTuupertunut 2025-11-22 github

I think an easy way to rebase it for newer Proton would be to forget about calling vrclient_x64 from wineopenxr and just copy-paste the same setup_vr code directly to both.

Mmactan-sc 2026-02-02 github

are there prospects for this request or one like it in 2026? Star Citizen a non-steam game added VR at the end of 2025 and it would be vastly preferable to have OpenXR from upstream wine

GGloriousEggroll 2026-02-22 github

I got this working finally. I took the in-wine implementation patches for wineopenxr: https://bugs.winehq.org/show_bug.cgi?id=56145, rebased them on proton, gutted proton's version, then implemented the same concept as the vrclient patch in this tracker. we re-create the registry entries for openvr, but in this case i just make wineopenxr do it upon xr detection so both xr and vr are always active if xr is found. we dont even bother touching vrclient.

I still need to clean up the code and implement disabling/removing the registry entries if XR/VR are not being used, but otherwise it seems to be working using umu-launcher + ge-proton + wivrn flatpak with meta quest 3.

test build:
https://devbuilds.nobaraproject.org/GE-Proton10-33.tar.gz

example usage with gog game and wivrn flatpak installed under user (should work for system too but need to adjust wivrn file paths for flatpak system install):

export PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/wivrn/comp_ipc:$HOME/.local/share/flatpak/app/io.github.wivrn.wivrn
export XR_RUNTIME_JSON="$HOME/.local/share/flatpak/app/io.github.wivrn.wivrn/current/active/files/share/openxr/1/openxr_wivrn.json"
WINEPREFIX=~/Games/projectwingman/ PROTONPATH=GE-Proton10-33 umu-run ProjectWingman.exe -vr -d3d11
GGloriousEggroll 2026-02-24 github

Just to clarify how my workaround works in a nutshell for better understanding:

If steam vrclient fails/not available/does not do the OpenVR setup that it's supposed to when steam triggers it, then:

  1. wineopenxr sets registry status stage 0 connected->waiting, (or if theres some error stage 4294967295 is error connecting)
  2. wineopenxr then probes for vulkan extensions and sets up the rest of the openxr registry entries for them on its own, and sets stage 1 is connected->proceed
  3. wineopenxr then verifies the new openxr registry entries exist and stage is 1, then it checks if openvr registry entries exist, and if not, generates them too based off the openxr entry values.

So steam's vrclient solution still remains fully functional, we just have a non-vrclient fallback now.

Proton versions

Launch options

Upstream links

DLLs