cmbruns / pyopenxr

Unofficial python bindings for OpenXR access to VR and AR devices
Apache License 2.0
103 stars 8 forks source link

Allow running headless, without xrGetOpenGLGraphicsRequirementsKHR #53

Open kwahoo2 opened 2 years ago

kwahoo2 commented 2 years ago

Hi,

I am trying to get a headless session (without the compositor) with the XR_MND_headless extension. I modified the example script a bit:

import time
import xr

available = xr.enumerate_instance_extension_properties()
required = [xr.MND_HEADLESS_EXTENSION_NAME]
for prop in required:
    assert prop in available

with xr.Instance(application_name="track_headless", requested_extensions = required) as instance:
    with xr.System(instance) as system:
        with xr.Session(system) as session:
            for _ in range(50):
                print ("entered loop")
                session.poll_xr_events()

But it fails at system creation:

Info: All enumerated devices attached.
Info: Loaded drivers: HTCVive
Info: Adding tracked object T20 from HTC
Info: Device T20 has watchman FW version 1562916277 and FPGA version 538/10/2; named '                       watchman'. Hardware id 0x110e0009
Info: Detected LH gen 2 system.
LOG in xrCreateInstance: Info: Adding lighthouse ch 1 (idx: 0, cnt: 1)
Instance created
    createInfo->applicationInfo.applicationName: track_headless
    createInfo->applicationInfo.applicationVersion: 0
    createInfo->applicationInfo.engineName: pyopenvr
    createInfo->applicationInfo.engineVersion: 1902
    appinfo.detected.engine.name: (null)
    appinfo.detected.engine.version: 0.0.0
    quirks.disable_vulkan_format_depth_stencil: false
Info: OOTX not set for LH in channel 1; attaching ootx decoder using device T20
Info: LightcapMode (T20) 1 -> 2
Info: MPFIT stats for T20:
Info:   seed runs         0 / 0
Info:   error failures    0
Traceback (most recent call last):
  File "/home/adi/xrwork/pyopenxr/examples/track_nohmd.py", line 10, in <module>
    with xr.System(instance) as system:
  File "/home/adi/.local/lib/python3.9/site-packages/xr/classes.py", line 115, in __init__
    get_instance_proc_addr(
  File "/home/adi/.local/lib/python3.9/site-packages/xr/functions.py", line 33, in get_instance_proc_addr
    raise result
xr.exception.FunctionUnsupportedError: The requested function was not found or is otherwise unsupported.

And this is the part of the System class being the culprit:

        self.pxrGetOpenGLGraphicsRequirementsKHR = ctypes.cast(
            get_instance_proc_addr(
                self.instance.handle,
                "xrGetOpenGLGraphicsRequirementsKHR",
            ),
            PFN_xrGetOpenGLGraphicsRequirementsKHR
        )
cmbruns commented 2 years ago

Thank you for reporting this! I am glad you are working on this. At the moment the System class is just a sketch, containing exactly what's needed to get the vanilla track_hmd example working.

I expect you could get this case working by using the lower level api like system_id = xr.get_system(...) etc. On the other hand, the case you are working on has the potential to be the very simplest useful example case. Especially if XR_whatever_headless extension catches on in something other than Monado.

Because this higher level System class is so new, we should probably think carefully about how the architecture for this sort of thing should work. Do you have any thoughts about this should work?

kwahoo2 commented 2 years ago

I have no good idea how this should work. Especially, since there are 2 extensions in the OpenXR registry: XR_MND_headless and XR_KHR_headless. The second one mentions XrGraphicsBindingHeadlessKHR structure, while Monado's one says that a session may be created without XrGraphicsBinding*, so both these extensions seem to be at least partially incompatible. And I haven't seen a runtime implementing XR_KHR_headless yet.

cmbruns commented 2 years ago

The System class should check whether its parent Instance here has the OpenGL extension before creating this function pointer. Or at least wrap this call in a try.

cmbruns commented 2 years ago

One reason I'm not fixing this right away is that I have not fully thought through how to expose extension-only methods. At the moment I'm thinking of defining all extension methods, but they can fail with a ExtensionNotLoaded error at call time. Because this would be more informative than a NoSuchMethodError or whatever the equivalent in python is. Also I haven't yet got Monado working so I cannot debug this particular example. But soon. I consider this a top priority problem. I've just got a bunch of other stuff also going on at the moment.

hendrikunger commented 1 year ago

Just humbly wanted to add a +1,as I would like to use the headless mode as well. Unfortunately I am not skilled enough to help you with the implementation.

kwahoo2 commented 12 months ago

Hi, I just would like to share a small discovery: It seems that SteamVR exposes XR_MND_headless extension since SteamVR 1.25 release.

Allow an OpenXR instance to be created even if there's no headset connected and the headless extension isn't enabled. This allows applications and tools to probe the SteamVR runtime for system information.

Funnily the extension name is mentioned only in the Swedish translation of the announcement... and it is wrong:

Tillåter att en OpenXR-instans skapas även om det inte finns något headset anslutet och XR_KHR_headless inte är aktiver