GPU: OpenXR integration
Description
Implements functions to create/manage an OpenXR instance/system/session/swapchain, without exposing raw GPU handles to the end user. This branch still needs a lot of work, but the foundation is layed at the least, and I'm opening this PR to hopefully make it easier to get some help with some of the problems I'm currently encountering (namely the validation error and the resource management oopsies I'm likely committing).
Existing Issue(s)
#10925
TODO
- [x] VSCode seems to have decided to reformat bits of
SDL_gpu.h, so I'll need to fix that (is there a clang-format config I should be using? or is the formatting all manual) - [ ] Code styling is all over the place (C is not my main language, so my code style is a bit of a mess)
- [x] Vulkan validation error on app exit, not sure how to resolve
VUID-vkDestroyImageView-imageView-01026(ERROR / SPEC): msgNum: 1672225264 - Validation Error: [ VUID-vkDestroyImageView-imageView-01026 ] | MessageID = 0x63ac21f0 | vkDestroyImageView(): can't be called on VkImageView 0x9f9b41000000003c[] that is currently in use by VkFramebuffer 0x45d6d1000000004c[]. The Vulkan spec states: All submitted commands that refer to imageView must have completed execution (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkDestroyImageView-imageView-01026)
- [ ] Vulkan resource management needs a look from an experienced vulkan dev (I'm not too familiar with writing Vulkan code, but I tried my best to follow the OpenXR specifications for how to manage the Vulkan resource states)
- [x] My CMake patches are a mess and I likely need to rewrite them, right now they just assume OpenXR is available, so for now i've set OpenXR to disabled by default, you can enable it with
-DSDL_GPU_OPENXR=ONwhen configuring the project - [x] I need to check which OpenXR graphics binding extensions are available before picking the backend and creating the GPU device, right now I assume XR_KHR_vulkan_enable2 is always available (this is true on all PC OpenXR runtimes except the Microsoft WMR OpenXR runtime, which is D3D11 and D3D12 only)
- [x] De-duplicate most of the device picking logic and such inside
SDL_gpu_vulkan.c - [ ] Lots of erroneous XR_ERROR_RUNTIME_FAILURE error returns (should we even be returning XrResult in the SDL API surface?)
- [x] Decouple OpenXR from
SDL_gpu.h(SDL_gpu_xr.hmaybe?) - [x] Support non
XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAYform factors - [x] Expose openxr-loader getprocaddress
- [ ] Move GPU stuff from
SDL_openxr.h->SDL_gpu.h - [ ] Figure out what OpenXR swapchain usage flags are allowed inside
SDL_CreateGPUXRSwapchain - [ ] Figure out OpenXR loading on Android (specifically with the official Khronos OpenXR Loader)
- [ ] Finish D3D12 backend support
- [ ] Allow requesting specific texture format for the swapchain, to allow using depth swapchains
- [ ] Fix validation errors when blitting to framebuffer on Vulkan
Ported the branch to windows, and its now tested working with latest SteamVR on Windows 10

so now it is tested working with the dominant OpenXR runtimes on Windows (SteamVR) and Linux (Monado)
also tested working on the Windows Oculus runtime
still a long way to go before being ready to merge though
Aside from the validation errors on exit, this branch is in a fully usable state (I've been building a game with it for the past couple weeks, and that's mostly what has driven this work).
While it's definitely not ready to be merged, I think it's in a state where it's ready to get preliminary review and pointers to where to take the public API surface, since right now its a bit cobbled together.
I also need help with the Vulkan validation error on app exit
VUID-vkDestroyImageView-imageView-01026(ERROR / SPEC): msgNum: 1672225264 - Validation Error: [ VUID-vkDestroyImageView-imageView-01026 ] | MessageID = 0x63ac21f0 | vkDestroyImageView(): can't be called on VkImageView 0x9f9b41000000003c[] that is currently in use by VkFramebuffer 0x45d6d1000000004c[].
The Vulkan spec states: All submitted commands that refer to imageView must have completed execution (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkDestroyImageView-imageView-01026)
Just run this fork of SDL_gpu_examples on the openxr branch, using the latest version of this PR, then close the app as normal.
You are required to have an OpenXR runtime setup, so either build Monado with the simulated driver, use an actual device with SteamVR, or some other simulator like the Meta XR Simulator
I also need help with the Vulkan validation error on app exit
VUID-vkDestroyImageView-imageView-01026(ERROR / SPEC): msgNum: 1672225264 - Validation Error: [ VUID-vkDestroyImageView-imageView-01026 ] | MessageID = 0x63ac21f0 | vkDestroyImageView(): can't be called on VkImageView 0x9f9b41000000003c[] that is currently in use by VkFramebuffer 0x45d6d1000000004c[]. The Vulkan spec states: All submitted commands that refer to imageView must have completed execution (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkDestroyImageView-imageView-01026)
This sounds like the device isn't asked to wait for idle before destroying the swapchain. You need to make sure the device is idle before teardown.
I think SDL_openxr.h can just be folded into SDL_gpu.h, it depends on gpu.h anyway and all of the API surface relies on GPU API handles.
I was thinking the same aswell, but when doing so, I needed to define a bunch of extra types to not depend on the upstream OpenXR headers, which is why I originally created the SDL_openxr.h header. I later also was thinking of exposing the internal openxr-loader handle (or at least the getprocaddress function), the same way SDL_vulkan.h does, to aid integration, and those wouldnt fit inside SDL_gpu.h. Perhaps the GPU specific functions should go inside SDL_gpu.h, and the OpenXR types and the getprocaddress function should go inside SDL_openxr.h.
The Vulkan device setup functions are basically fully duplicated. I think it would be possible to just stick the XR setup inside the rest of the setup functions. I might even go as far as saying that there shouldn't be a separate CreateXRDevice and we could just include XR setup details as device properties.
This can be done, perhaps bool SDL.gpu.device.create.openxr, XrInstance* SDL.gpu.device.create.xr.out_instance, XrSystemId* SDL.gpu.device.create.xr.out_system_id. This would allow the two functions to be folded into eachother, and when creating an OpenXR GPU instance, you set create.openxr, and then the two out ptr properties.
I think the same probably goes for swapchain creation, but I'll have to look at it more closely.
Normal GPU swapchain creation is quite different from OpenXR swapchains. OpenXR swapchains are really just an array of VkImage handles gotten from the OpenXR runtime. The functions are unique code except for the end step, which is mostly derivative from the texture creation code, so parts can probably be merged with that.
What's the OpenXR story for D3D12/Metal? In general I've been reluctant to merge features that are only implemented on one backend because I don't want to give the impression that features might be missing or different on specific backends. If you're not able to develop for these platforms that's fine but we should try to find someone who can. Unfortunately I don't have a VR device so I can't be much help there personally.
With regards to D3D12, I don't own a Windows device capable of running an OpenXR runtime. The only device I own is the Volterra ARM64 dev kit, which is missing vital Vulkan extensions to run Monado (the Monado compositor is written in Vulkan, and uses interop extensions for implementing other APIs), and SteamVR does not have an ARM64 Windows port. Someone could very easily contribute D3D12 support though, and I'd be happy to help anyone who wants to try (perhaps the Vulkan side should be cleaned up first though, so there's a good reference of "where to start").
With regards to Metal, I dont believe this should be too strongly of a concern. SteamVR for MacOS was abandoned before OpenXR became a thing, and the WIP MacOS port of Monado does not support the KHR_metal_enable OpenXR extension. ~~Off the top of my head, I don't know any runtime which supports it.~~
~~The Khronos extension support report doesn't list a single runtime with the Metal extension, so I don't think we could implement/test this, even if we wanted to.~~
Turns out the Meta XR Simulator does support it! Seems in the past month this has become feasable. For reference, here's the qtquick3d and godot usages of the extension. I still don't own a capable enough Mac for this, but someone is free to implement it on their own mac using the Meta XR Simulator, and I'd be happy to guide them through it.
This sounds like the device isn't asked to wait for idle before destroying the swapchain. You need to make sure the device is idle before teardown.
Yeah this seems to be the case, I attempted to test this earlier by just sleeping the main thread by 5 seconds and it still happened, but then I realized SDL_WaitForGPUIdle exists, and calling that fixes the validation error. Would it make sense to call VULKAN_Wait internally inside VULKAN_DestroyXRSwapchain? Or should this be deferred to callers
Yeah go ahead and put a Wait in the destroy call. You can see we do something similar for UnclaimWindow and DestroyDevice.
The Vulkan device setup functions are basically fully duplicated. I think it would be possible to just stick the XR setup inside the rest of the setup functions. I might even go as far as saying that there shouldn't be a separate CreateXRDevice and we could just include XR setup details as device properties.
I've made these changes, now, creating an OpenXR capable GPU device looks like this
I think SDL_openxr.h can just be folded into SDL_gpu.h, it depends on gpu.h anyway and all of the API surface relies on GPU API handles.
I'm struggling with the build system trying to get this working. SDL_gpu.h needs to work even when the OpenXR header isn't imported/available, but SDL_gpu.h cannot define the OpenXR types (which I define myself inside here) due to it being pulled in by SDL_internal.h, and that being a precompiled header incldued before all internal code. Since SDL_internal.h is implicitly and pre-imported by all the internal code (such as SDL_gpu_vulkan.c) relying on openxr.h, I get duplicate definition errors when the internal code tries to import openxr.h.
I'm not entirely sure how to proceed here, I'm not great with C preprocessor spaghetti.
Options I can see are, but there's probably a proper one.
a) Keep the function definitions which rely directly on OpenXR types inside SDL_openxr.h
b) Undefine the conflicting types inside SDL_internal.h (this feels jank/prone to breakage)
c) Don't use the OpenXR types in the function definitions if they aren't available, and instead use generic types like const void * instead of const XrCreateInfo *, or Uint32 instead of XrResult
Minor thing: I got this bogus warning from gcc:
src/gpu/vulkan/SDL_gpu_vulkan.c: In function 'VULKAN_PrepareDriver':
src/gpu/vulkan/SDL_gpu_vulkan.c:11975: warning: 'instancePfns' may be used uninitialized in this function
Something like the following cures it for me.
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -11972,7 +11972,7 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
#ifdef HAVE_GPU_OPENXR
XrResult xrResult;
- XrInstancePfns *instancePfns;
+ XrInstancePfns *instancePfns = NULL;
XrInstance xrInstance = XR_NULL_HANDLE;
XrSystemId xrSystemId = XR_NULL_HANDLE;
bool xr = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE, false);
@@ -12062,7 +12062,7 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
renderer->vkDestroyInstance(renderer->instance, NULL);
}
#ifdef HAVE_GPU_OPENXR
- if (xr) {
+ if (instancePfns) {
instancePfns->xrDestroyInstance(xrInstance);
SDL_free(instancePfns);
SDL_OPENXR_UnloadLoaderSymbols();
Got a working Windows VM with a dedicated GPU passed through, so I'm going to start working on D3D12 support. Regarding Metal, I still don't have the hardware for working on that, so someone else will have to work on that.
Made a bunch of progress on the D3D12 backend, it's now rendering to the screen successfully (at least the BasicVr sample is, I havent tested my game on it), however there's a bunch of validation errors relating to resource states.
Need to take a deeper look tomorrow into how rendering to images is internally handled in SDL_gpu's D3D12 backend.
D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: Using ID3D12DebugCommandList1::AssertResourceState on Command List (0x000001BFB756D000:'Unnamed ID3D12GraphicsCommandList Object'): Resource state (0x4: D3D12_RESOURCE_STATE_RENDER_TARGET) of resource (0x000001BFB6E51010:'Unnamed ID3D12Resource Object') (subresource: 0) is invalid for use as a INITIAL|PRESENT. Expected State Bits (all): 0x0: D3D12_RESOURCE_STATE_[COMMON|PRESENT], Actual State: 0x4: D3D12_RESOURCE_STATE_RENDER_TARGET, Missing State: 0x0: D3D12_RESOURCE_STATE_[COMMON|PRESENT]. [ EXECUTION ERROR #538: INVALID_SUBRESOURCE_STATE]
D3D12 ERROR: ID3D12CommandQueue::ExecuteCommandLists: Using ResourceBarrier on Command List (0x000001BFB756D000:'Unnamed ID3D12GraphicsCommandList Object'): Before state (0x0: D3D12_RESOURCE_STATE_[COMMON|PRESENT]) of resource (0x000001BFB6E51010:'Unnamed ID3D12Resource Object') (subresource: 0) specified by transition barrier does not match with the state (0x4: D3D12_RESOURCE_STATE_RENDER_TARGET) specified in the previous call to ResourceBarrier [ RESOURCE_MANIPULATION ERROR #527: RESOURCE_BARRIER_BEFORE_AFTER_MISMATCH]
D3D12 WARNING: ID3D12CommandList::ClearRenderTargetView: The application did not pass any clear value to resource creation. The clear operation is typically slower as a result; but will still clear to the desired value. [ EXECUTION WARNING #820: CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE]
Feel free to ping me or come to the OpenXR forum if you have questions on the OpenXR side. https://community.khronos.org/c/openxr/25
Congrats on everyone on the SDL 3.0 release! Just rebased my work on latest main to bring it up to date. Still haven't resolved the issues with the D3D12 driver yet, but the VK one still works great after the rebase.
Something I noticed on Windows when working on the D3D12 driver is that OpenXR's loader when compiled in debug mode produces a DLL named openxr_loaderd.dll, which is different than the release name of openxr_loader.dll. How should I handle this in SDL's OpenXR DLL loading code? Should I try release -> debug (may not pick the one the developer wants if the actual loader is installed system wide), or should i try debug -> release (which may adversely pick up a local debug build of the loader when the user wants a release version stored system wide).
Something I noticed on Windows when working on the D3D12 driver is that OpenXR's loader when compiled in debug mode produces a DLL named
openxr_loaderd.dll, which is different than the release name ofopenxr_loader.dll. How should I handle this in SDL's OpenXR DLL loading code? Should I try release -> debug (may not pick the one the developer wants if the actual loader is installed system wide), or should i try debug -> release (which may adversely pick up a local debug build of the loader when the user wants a release version stored system wide).
This is done here in OpenXR-SDK. SDL2's CMake script also does this, which was undone immediately after the SDL3 fork creation.
I'd ask Khronos, but the sensible way is to always use openxr_loader.dll (without suffix) and require openxr-loader to be configured with -DOPENXR_DEBUG_POSTFIX=.
the sensible way is to always use
openxr_loader.dll(without suffix) and require openxr-loader to be configured with-DOPENXR_DEBUG_POSTFIX=.
Makes sense, although, when using the OpenXR SDK through vcpkg+cmake, it does not seem possible to tell it to give you the non-debug binaries always. When building your app for debug, ittl always provide you with openxr_loaderd.dll. I'd imagine this would be a common enough issue to cause confusion. Likely should document somewhere (maybe provide a hint to change the loaded lib path aswell?) that we require the non-suffix version, although not sure where exactly that would be best to do.
the sensible way is to always use
openxr_loader.dll(without suffix) and require openxr-loader to be configured with-DOPENXR_DEBUG_POSTFIX=.Makes sense, although, when using the OpenXR SDK through vcpkg+cmake, it does not seem possible to tell it to give you the non-debug binaries always. When building your app for debug, ittl always provide you with
openxr_loaderd.dll. I'd imagine this would be a common enough issue to cause confusion. Likely should document somewhere (maybe provide a hint to change the loaded lib path aswell?) that we require the non-suffix version, although not sure where exactly that would be best to do.
I asked the openxr developers here
Looks like the OpenXR devs are not confident on this topic. They'd require extra testing to make sure mixing MSVC CRT's works.
They suggested attempting to load both names. Perhaps we should turn the library name into a hint, use openxr_loader.dll by default? Perhaps the hint can accept a comma separated list of dlls?
Perhaps we should turn the library name into a hint, use
openxr_loader.dllby default? Perhaps the hint can accept a comma separated list of dlls?
This seems reasonable to me, I'll do that. I likely should document this somewhere aswell, but not sure where would be best.
Perhaps also add libopenxr-dev (for Ubuntu) and openxr-devel (for Fedora) to README-linux.md?
And add libopenxr-dev to .github/workflows/create-test-plan.py. (The first list is for Ubuntu 20.04+, the second list is 22.04+.
Perhaps also add libopenxr-dev (for Ubuntu) and openxr-devel (for Fedora) to
README-linux.md? And addlibopenxr-devto .github/workflows/create-test-plan.py. (The first list is for Ubuntu 20.04+, the second list is 22.04+.
I don't believe we need to, as I vendored the OpenXR headers same as was done for Vulkan. So we don't actually need the OpenXR dev packages on the host when compiling to get an OpenXR-enabled SDL.
I don't believe we need to, as I vendored the OpenXR headers same as was done for Vulkan. So we don't actually need the OpenXR dev packages on the host when compiling to get an OpenXR-enabled SDL.
Right, the page does not have a run-time depencies section.
If somebody feels like testing, ideally in a scripted fashion, to make sure that mixing the CRT is not a problem here, I would love to see that, I just don't have time available to do that testing myself, and I have been burned by this many years ago, and burned hard enough that I just instinctively avoid anything that even looks like mixing CRTs.
I'm marking this as draft, since it seems like there's still a lot to be done.
I'm marking this as draft, since it seems like there's still a lot to be done.
Agree, I had moved it out of draft initially to get some review to push me in the right direction for further work, the current branch is in a good enough state to the point where I've been able to develop multiple cross-platform OpenXR applications using it (that have been deployed successfully to users).
The big work points I need to complete right now are finishing the D3D12 backend support, and writing a much more rigorous suite of test/sample applications to try to uncover issues/show ideal usage.
My current bandwidth to work on it is limited (I'm in the middle of a move, and the branch has gotten "good enough" where I'm able to work on games/apps using it, rather than working on just this branch alone), however I do still intend to try to bring this code to completion. It just may be a slow process as I focus on the games/apps using this branch, along with my other projects.
I'll be sure to say explicitly when specific things are in need for review again/I need assistance, until then I'll churn on this branch in the background to bring it closer to completion.
I would like to help and see this integration completed for SDL3. I looked into the MacOS aspect, and while the Meta XR Simulator supports MacOS it only supports devices with Apple Silicon chips. And correct me if I'm wrong here but it isn't like you can actually do any real VR development with this simulator. It's for minor tweaks and such without the need for constantly putting on / taking off a headset. There isn't any OpenXR runtime for Mac. SteamVR still has some limited capability, but then it doesn't support Macs with Apple Silicon chips at all. The examples I saw from you @Beyley were integrations an engine has for the simulator. In my opinion, we could (should) ignore it. BUT.. I'm more than happy to help with this though if it absolutely necessary.
I would like to help and see this integration completed for SDL3.
I've been very busy with personal things and other projects, so haven't been able to really work on this as of late, so another pair of hands would be very helpful, and I'd be glad to give pointers to what work specifically needs to be done to bring this closer to the finish line.
I looked into the MacOS aspect, and while the Meta XR Simulator supports MacOS it only supports devices with Apple Silicon chips. And correct me if I'm wrong here but it isn't like you can actually do any real VR development with this simulator. It's for minor tweaks and such without the need for constantly putting on / taking off a headset.
This is correct, however I don't expect that to be the case forever. Especially since visionOS now has support for PSVR2 controllers, and those drivers have also made their way into macOS itself (probably for the "remote rendering" thing I've heard about?). I expect an OpenXR runtime for the Apple family of OSes (besides the Meta XR Simulator) to come to fruition as either a commercial product (la VDXR [is open source, but usage driven through the commertial streaming application]), or an open source project (la macOS port of Monado or WiVRn) at some point, so I feel it's an important thing to support in SDL early, and the Meta XR Simulator is the only runtime which it can be tested against (Godot and Unity both support running with the KHR_metal_enable extension awsell, with Godot's implementation being open source to reference).
I don't expect adding macOS support to be a particularly difficult task, the main concern is image handling.
The Vulkan and D3D12 sides both have unresolved image handling issues in this branch, more specifically, D3D12 rendering is spewing errors relating to resource states during presentation, and the Vulkan backend throws validation errors when you try to use the Blit function onto a swapchain which during creation should in theory support it, due to a missing image transition.
The best place to start would be to rebase this branch and my SDL_gpu_examples fork and get it running again. A rebase is tricky as of late, because a change I had made originally in this branch (adding a properties to GPU device creation) has also now been done upstream, so I would recommend squashing a fair amount of these commits to clean up the history, and removing those duplicate changes so it rebases cleanly on-top of main.
For some test apps, see here (app which does pretty much nothing) and here (contains a simple, but more complex than the previous, OpenXR sample).
For basic rendering workloads, the Vulkan backend is stable on both Windows and Linux (SteamVR and Monado tested to work with no problems). The D3D12 backend renders, but throws non-fatal errors. I think a simple goal would be to get the SDL_gpu_examples example rendering again with D3D12 and Vulkan on top of main, then adding macOS/Metal support so that example can run.
You would think Apple would have already implemented a runtime of some kind years ago ;) but makes sense.
But yes, I will do that. It's going to take a minute to wrap my head around OpenXR and how this all works.
You would think Apple would have already implemented a runtime of some kind years ago ;) but makes sense.
I've heard there's an unannounced legal dispute between Apple and Khronos, so I doubt that'd happen any time soon if ever, but let's not get into that here. Apple has their own VR APIs, and there's been some work in the past to bring OpenXR runtimes to those platforms (there's a port of Monado to iOS sitting around somewhere, created to be able to stream VR from a PC to iOS using the WiVRn client, but it doesnt support the KHR_metal_enable extension)
It's going to take a minute to wrap my head around OpenXR and how this all works.
If you've used Vulkan before, it's a very similar API in style to that. Luckily, a large amount of the OpenXR code is either abstracted away already in my code, or isn't your problem to deal with in the SDL side, and is done in the application side. The tricky part is handling the resources OpenXR gives SDL to properly wrap them into GPU textures and such.
Heya folks, just incase anyone needed to figure out Android stuff in the future, it's something I had working at one point in time when using Zig + SDL2 + OpenXR on both Windows desktop and my Oculus Quest 2 device.
Changes to make Android OpenXR work
Cliff notes based on my re-reading of my own code below the things I recall are...
- Retrieve the Android Java VM, this is used for
XrLoaderInitInfoAndroidKHRandXrInstanceCreateInfoAndroidKHR
jniEnv = sdl.SDL_GetAndroidJNIEnv(); // https://wiki.libsdl.org/SDL3/SDL_GetAndroidJNIEnv
void* javaVm;
jniEnv.GetJavaVM(jniEnv, &javaVm);
- Android requires you initialize BEFORE you enumerate layers and etc. This is pretty much at the top of
func main().
initializeLoader = xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", ...)
initializeLoader(&XrLoaderInitInfoAndroidKHR{
.type = openxr.XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR,
// applicationVM is a pointer to the JNI’s opaque JavaVM structure, cast to a void pointer
.applicationVM = javaVm,
// applicationContext is a JNI reference to an android.content.Context associated
// with the application, cast to a void pointer.
.applicationContext = SDL_GetAndroidActivity(),
})
- CreateInstance requires a
nextparameter ofXrInstanceCreateInfoAndroidKHRandenabledExtensionNamesshould also contain AndroidXR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME
xrPlatformCreateInfo = XrInstanceCreateInfoAndroidKHR{
.type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR,
.next = null,
.applicationVM = javaVm,
.applicationActivity = SDL_GetAndroidActivity(),
}
xrInstanceCreateInfo.next = &xrPlatformCreateInfo;
xrInstanceCreateInfo.enabledExtensionNames = []const u8{
XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME,
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME, // <- Likely will just use Vulkan/D3D/Metal instead for SDL3
};
xrInstanceCreateInfo.enabledExtensionCount = xrInstanceCreateInfo.enabledExtensionNames.length;
Search the file for cases of builtin.abi == .android to see Android specific code. Anything not listed above I assume is OpenGL vs OpenGLES related.
main-zig.txt
Finally something I was stuck on for a while as someone new to Android was ensuring the AndroidManifest.xml file was properly configured.
I didn't have the following in the correct place which caused the OpenXR application to work as expected with my Oculus Quest controllers but it didn't open up in full headset view. Here's the full file I used and got working: AndroidManifest.xml
<application android:label="@string/app_name">
<activity android:name="HelloVRSDLActivity" etc>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
</intent-filter>
</activity>
</application>