xrGetSystem fails for Quest 3 with SteamLink


I’m using this example as a simple playground: OpenXRSamples/SingleFileExample/main.cpp at master · maluoi/OpenXRSamples · GitHub

I upgraded the dependency to OpenXR Loader 1.0.32. Everything works fine with Oculus OpenXR Runtime when connected to Quest 3 through AirLink. I even managed to implement XR_EXT_hand_tracking (had to enable Developer Runtime Features in the Oculus app) with fingers rendered in the SingleFileExample app.

Then I wanted to use SteamLink instead of Oculus app. It loads SteamVR home successfully on Quest. Then I launch the SingleFileExample. However, it fails on xrGetSystem call with the error XR_ERROR_FORM_FACTOR_UNAVAILABLE. I learned that in some cases you have to retry, so I created a loop:

		res = xrGetSystem(xr_instance, &systemInfo, &xr_system_id);

but it never exits with a successful result.

Does SteamLink+Oculus OpenXR need some other kind of system setup?

I also tried another experiment. I switch OpenXR runtime to SteamVR and again wait for SteamVR home to load on Quest and launch the SingleFileExample. This time it successfully goes past the xrGetSystem but then it crashes on the first xrEnumerateSwapchainImages call in the loop (view_count is 2) with

Exception thrown at 0x00007FFCE33D81A4 (vrclient_x64.dll) in SingleFileExample.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

Am I stuck with using Oculus AirLink or is there any trick to make it work with SteamLink?

The Oculus OpenXR runtime only supports connections through Link and AirLink, as well as Metas PC based headsets. It has no support for other drivers like SteamLink. SteamLink equally only works though SteamVR, which requires using the SteamVR OpenXR runtime. Neither application will automatically set the active OpenXR runtime automatically if it has already been set by the other, so if the user installs both, they will have to manually change it.

For the xrEnumerateSwapchainImages error, I remember it crashing with SteamVR unless every element of the output image array (swapchain.surface_images) has the structure type (XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) set before calling the function. SteamVR used to be more lenient with it before, which might break older examples.

1 Like

Hmm, it does look like that’s being set, but something like that is likely the issue, yes.

1 Like

Thanks for the explanation. So, if I understand correctly, SteamLink uses Oculus runtime on the Quest device itself through the Android app, and so the PC has to use SteamVR OpenXR runtime for it. Makes sense.

The example is missing a few XrResult res to make debugging easier.

Now I added

		XrResult res = xrCreateSwapchain(xr_session, &swapchain_info, &handle);

and noticed that it returns XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED. So the handle stays initialized invalid and, of course, the next calls crash.

Now if only we could figure out what exactly doesn’t it like.

swapchain_format is

 int64_t              d3d_swapchain_fmt = DXGI_FORMAT_R8G8B8A8_UNORM;

Digging further. I added a call of xrEnumerateSwapchainFormats and got the following:


So indeed, no DXGI_FORMAT_R8G8B8A8_UNORM, and I guess the closest is DXGI_FORMAT_R8G8B8A8_UNORM_SRGB. And it worked!

Even hand tracking “kinda works”. But not really - it seems, SteamVR is exposing a fake hand-tracking model based on the controller and not on Oculus hand-tracking. So, I’ll have to switch back to Oculus OpenXR and AirLink if I want to use real hand tracking, until Steam sorts things out with Meta and exposes the real hand tracking.


The SRGB encoded texture is the better format to use for 8-bit textures either way, like the spec notes here: The OpenXR™ Specification