protonscr

wineopenxr: xrEnumerateInstanceExtensionProperties returns XR_ERROR_RUNTIME_UNAVAILABLE with WiVRn/Monado runtime

protonclosed
ValveSoftware/Proton#9988 · opened 2026-07-19 by cat5edopeHA · updated 2026-07-19 · 1 comments · github
Ccat5edopeHA 2026-07-19 github

wineopenxr: xrEnumerateInstanceExtensionProperties returns XR_ERROR_RUNTIME_UNAVAILABLE with WiVRn/Monado runtime

Summary

Calling xrEnumerateInstanceExtensionProperties (standard two-call pattern: count query, then data query) through the Khronos OpenXR loader against wineopenxr under Proton + WiVRn/Monado returns XR_ERROR_RUNTIME_UNAVAILABLE (-1) on the data call. The loader's built-in validation rejects all returned XrExtensionProperties structs with:

Error [SPEC | xrEnumerateInstanceExtensionProperties | VUID-XrExtensionProperties-type-type] : unknown type in properties
Error [SPEC | xrEnumerateInstanceExtensionProperties | VUID-xrEnumerateInstanceExtensionProperties-properties-parameter] : invalid properties

This blocks any Windows OpenXR application from even enumerating extensions — the very first OpenXR call fails.

Expected Behavior

The two-call enumeration should succeed: the count call returns the number of extensions, and the data call fills the caller's XrExtensionProperties array with proper type=XR_TYPE_EXTENSION_PROPERTIES, next=NULL, and valid extension name strings.

Actual Behavior

63 consecutive "unknown type in properties" errors are emitted for every extension struct, followed by "invalid properties", and the function returns XR_ERROR_RUNTIME_UNAVAILABLE. The probe exits with failure code.

Environment

  • Proton: DW-Proton 11.0-3 (community fork; stock Valve Proton not yet tested)
  • OpenXR runtime: WiVRn 26.6.2 (Flatpak) / Monado, Quest 3 HMD connected
  • GPU: AMD Radeon RX 9070 XT (RADV GFX1201), Mesa radv 26.1.4, kernel driver amdgpu
  • DXVK: v2.7.1-625
  • Host: Linux, kernel 7.1.3

Loader Versions Tested (all fail identically)

  • openxr_loader.dll 1.0.17 (shipped with Kayak VR)
  • openxr_loader.dll 1.0.25 (shipped with VAIL)
  • openxr_loader.dll 1.1.45 (shipped with ChilloutVR, 2025)

What Works

  • Proton's own internal wineopenxr test instance succeeds in the same run — it creates an instance, enumerates 'WiVRn HMD' + controllers, and reaches session state SYNCHRONIZED.
  • Native Linux OpenXR (WiVRn/Monado via standard loader) works correctly.
  • The probe's XrExtensionProperties structs are spec-correct: type=XR_TYPE_EXTENSION_PROPERTIES, next=NULL, 128-byte extension name field — verified against OpenXR 1.x spec.

Probable Cause

The following Wine log line appears immediately before the validation errors in the Proton log:

fixme:openxr:wine_xrEnumerateInstanceExtensionProperties Force enabled extension XR_KHR_convert_timespec_time already supported by the runtime.

This suggests the defect is in wineopenxr's force-enable path in wine_xrEnumerateInstanceExtensionProperties. When wineopenxr force-adds an extension entry to the array, it writes the extension name via strcpy but does not set the type (XR_TYPE_EXTENSION_PROPERTIES) or next (NULL) fields on the newly added entries. Since these array slots lie beyond what the native Monado runtime filled, the type field contains uninitialized memory, and the Khronos loader's conformant validation rejects the entire array.

The relevant code path (Proton HEAD at 25880e8, wineopenxr/openxr.c):

for (j = 0; j < ARRAY_SIZE(substitute_extensions); ++j) {
    if (substitute_extensions[j].force_enable) {
        strcpy(properties[*propertyCountOutput].extensionName, substitute_extensions[j].win32_ext);
        ++*propertyCountOutput;
        // ^^^ type and next fields are never set on this entry
    }
}

Similarly, the non-force-enable substitution path that appends (dst = (*propertyCountOutput)++) also writes to uninitialized slots without setting type/next.

Minimal Reproduction

Any Windows OpenXR application that performs the standard two-call xrEnumerateInstanceExtensionProperties under Proton with a WiVRn/Monado runtime and a validating Khronos loader will hit this. A minimal self-contained Windows OpenXR caller (dynamic binding, no SDK dependency) was used to isolate the failure.

Not fixed by XR_ENABLE_API_LAYERS="" (validation is compiled into the loader) or WINEDEBUG=-all (it's a hard XrResult, not a debug print).

Additional Notes

  • The defect has been reproduced only on DW-Proton 11.0-3. Stock Valve Proton has not been tested — the issue may or may not reproduce there depending on whether the same code path is present.
  • Native Linux OpenXR works correctly on the same system — this is specifically a wineopenxr thunk issue, not a runtime or GPU problem.
Ccat5edopeHA 2026-07-19 github

Correction and retraction: this report was caused by errors in my minimal caller's hand-written OpenXR ABI constants, not by Proton/wineopenxr.

The caller incorrectly defined several XrStructureType values, including:

  • XR_TYPE_EXTENSION_PROPERTIES as 3 (Khronos defines 2)
  • XR_TYPE_INSTANCE_CREATE_INFO as 2 (Khronos defines 3)
  • XR_TYPE_SYSTEM_GET_INFO as 25 (Khronos defines 4)
  • XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR as 1000027003 (Khronos defines 1000027002)

This fully explains the loader validation messages (unknown type in properties and expected XR_TYPE_INSTANCE_CREATE_INFO). The issue body's source-level hypothesis about wineopenxr leaving type/next uninitialized was therefore invalid: the caller was passing incorrect structure-type values.

I am closing this as invalid. Apologies for the erroneous report and noise; I should have compared every hand-written ABI constant against the generated Khronos header before filing.

Proton versions

Launch options

DLLs