mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-12 23:03:37 +00:00
GPU: OpenXR integration (#14837)
Based on Beyley's initial draft in #11601. Co-authored-by: Beyley Cardellio <ep1cm1n10n123@gmail.com> Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>
This commit is contained in:
@@ -39,6 +39,7 @@ LOCAL_SRC_FILES := \
|
||||
$(wildcard $(LOCAL_PATH)/src/io/generic/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/gpu/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/gpu/vulkan/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/gpu/xr/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/haptic/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/haptic/android/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \
|
||||
|
||||
@@ -391,6 +391,7 @@ set_option(SDL_LIBUDEV "Enable libudev support" ON)
|
||||
set_option(SDL_ASAN "Use AddressSanitizer to detect memory errors" OFF)
|
||||
set_option(SDL_CCACHE "Use Ccache to speed up build" OFF)
|
||||
set_option(SDL_CLANG_TIDY "Run clang-tidy static analysis" OFF)
|
||||
dep_option(SDL_GPU_OPENXR "Build SDL_GPU with OpenXR support" ON "SDL_GPU;NOT RISCOS" OFF)
|
||||
|
||||
set(SDL_VENDOR_INFO "" CACHE STRING "Vendor name and/or version to add to SDL_REVISION")
|
||||
|
||||
@@ -1272,6 +1273,8 @@ sdl_glob_sources(
|
||||
"${SDL3_SOURCE_DIR}/src/filesystem/*.h"
|
||||
"${SDL3_SOURCE_DIR}/src/gpu/*.c"
|
||||
"${SDL3_SOURCE_DIR}/src/gpu/*.h"
|
||||
"${SDL3_SOURCE_DIR}/src/gpu/xr/*.c"
|
||||
"${SDL3_SOURCE_DIR}/src/gpu/xr/*.h"
|
||||
"${SDL3_SOURCE_DIR}/src/joystick/*.c"
|
||||
"${SDL3_SOURCE_DIR}/src/joystick/*.h"
|
||||
"${SDL3_SOURCE_DIR}/src/haptic/*.c"
|
||||
@@ -3550,6 +3553,9 @@ if(SDL_GPU)
|
||||
set(SDL_VIDEO_RENDER_GPU 1)
|
||||
set(HAVE_RENDER_GPU TRUE)
|
||||
endif()
|
||||
if(SDL_GPU_OPENXR)
|
||||
set(HAVE_GPU_OPENXR 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Dummies
|
||||
|
||||
@@ -927,6 +927,12 @@
|
||||
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.XboxOne.x64'">CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_gpu_openxr.c" />
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_openxrdyn.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_gpu_openxr_c.h" />
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_openxr_internal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\src\core\windows\version.rc" />
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
<ClCompile Include="..\..\src\gpu\SDL_gpu.c" />
|
||||
<ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c" />
|
||||
<ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_gpu_openxr.c" />
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_openxrdyn.c" />
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_openxr_internal.h" />
|
||||
<ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
|
||||
<ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
|
||||
<ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
|
||||
|
||||
@@ -475,6 +475,8 @@
|
||||
<ClInclude Include="..\..\src\gpu\d3d12\D3D12_Blit.h" />
|
||||
<ClInclude Include="..\..\src\gpu\SDL_sysgpu.h" />
|
||||
<ClInclude Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan_vkfuncs.h" />
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_gpu_openxr_c.h" />
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_openxr_internal.h" />
|
||||
<ClInclude Include="..\..\src\hidapi\SDL_hidapi_windows.h" />
|
||||
<ClInclude Include="..\..\src\hidapi\windows\hidapi_cfgmgr32.h" />
|
||||
<ClInclude Include="..\..\src\hidapi\windows\hidapi_descriptor_reconstruct.h" />
|
||||
@@ -629,6 +631,8 @@
|
||||
<ClCompile Include="..\..\src\gpu\SDL_gpu.c" />
|
||||
<ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c" />
|
||||
<ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_gpu_openxr.c" />
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_openxrdyn.c" />
|
||||
<ClCompile Include="..\..\src\io\generic\SDL_asyncio_generic.c" />
|
||||
<ClCompile Include="..\..\src\io\SDL_asyncio.c" />
|
||||
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c" />
|
||||
|
||||
@@ -981,6 +981,15 @@
|
||||
<ClInclude Include="..\..\src\gpu\SDL_sysgpu.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan_vkfuncs.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_gpu_openxr_c.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gpu\xr\SDL_openxr_internal.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_storage.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_time.h" />
|
||||
<ClInclude Include="..\..\src\core\SDL_core_unsupported.h" />
|
||||
@@ -1953,6 +1962,26 @@
|
||||
<ClCompile Include="..\..\src\gpu\SDL_gpu.c">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_gpu_openxr.c">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gpu\xr\SDL_openxrdyn.c">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\process\SDL_process.c" />
|
||||
<ClCompile Include="..\..\src\process\windows\SDL_windowsprocess.c" />
|
||||
<ClCompile Include="..\..\src\render\gpu\SDL_pipeline_gpu.c" />
|
||||
<ClCompile Include="..\..\src\render\gpu\SDL_render_gpu.c" />
|
||||
<ClCompile Include="..\..\src\render\gpu\SDL_shaders_gpu.c" />
|
||||
<ClCompile Include="..\..\src\storage\generic\SDL_genericstorage.c" />
|
||||
<ClCompile Include="..\..\src\storage\steam\SDL_steamstorage.c" />
|
||||
<ClCompile Include="..\..\src\storage\SDL_storage.c" />
|
||||
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_steam_triton.c">
|
||||
<Filter>joystick\hidapi</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -366,6 +366,10 @@
|
||||
E4F257952C81903800FCEAFC /* SDL_gpu_vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F257832C81903800FCEAFC /* SDL_gpu_vulkan.c */; };
|
||||
E4F257962C81903800FCEAFC /* SDL_gpu.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F257852C81903800FCEAFC /* SDL_gpu.c */; };
|
||||
E4F257972C81903800FCEAFC /* SDL_sysgpu.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F257862C81903800FCEAFC /* SDL_sysgpu.h */; };
|
||||
E4F257982C81903800FCEAFC /* SDL_gpu_openxr.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F257882C81903800FCEAFC /* SDL_gpu_openxr.c */; };
|
||||
E4F257992C81903800FCEAFC /* SDL_openxrdyn.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F257892C81903800FCEAFC /* SDL_openxrdyn.c */; };
|
||||
E4F2579A2C81903800FCEAFC /* SDL_gpu_openxr_c.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F2578A2C81903800FCEAFC /* SDL_gpu_openxr_c.h */; };
|
||||
E4F2579B2C81903800FCEAFC /* SDL_openxr_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F2578C2C81903800FCEAFC /* SDL_openxr_internal.h */; };
|
||||
E4F7981A2AD8D84800669F54 /* SDL_core_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */; };
|
||||
E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */; };
|
||||
E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */; };
|
||||
@@ -937,6 +941,10 @@
|
||||
E4F257832C81903800FCEAFC /* SDL_gpu_vulkan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gpu_vulkan.c; sourceTree = "<group>"; };
|
||||
E4F257852C81903800FCEAFC /* SDL_gpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gpu.c; sourceTree = "<group>"; };
|
||||
E4F257862C81903800FCEAFC /* SDL_sysgpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysgpu.h; sourceTree = "<group>"; };
|
||||
E4F257882C81903800FCEAFC /* SDL_gpu_openxr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gpu_openxr.c; sourceTree = "<group>"; };
|
||||
E4F257892C81903800FCEAFC /* SDL_openxrdyn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_openxrdyn.c; sourceTree = "<group>"; };
|
||||
E4F2578A2C81903800FCEAFC /* SDL_gpu_openxr_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gpu_openxr_c.h; sourceTree = "<group>"; };
|
||||
E4F2578C2C81903800FCEAFC /* SDL_openxr_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_openxr_internal.h; sourceTree = "<group>"; };
|
||||
E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_core_unsupported.c; sourceTree = "<group>"; };
|
||||
E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dynapi_unsupported.h; sourceTree = "<group>"; };
|
||||
E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_render_unsupported.c; sourceTree = "<group>"; };
|
||||
@@ -2354,11 +2362,23 @@
|
||||
path = vulkan;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E4F2578B2C81903800FCEAFC /* xr */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E4F257882C81903800FCEAFC /* SDL_gpu_openxr.c */,
|
||||
E4F257892C81903800FCEAFC /* SDL_openxrdyn.c */,
|
||||
E4F2578A2C81903800FCEAFC /* SDL_gpu_openxr_c.h */,
|
||||
E4F2578C2C81903800FCEAFC /* SDL_openxr_internal.h */,
|
||||
);
|
||||
path = xr;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E4F257872C81903800FCEAFC /* gpu */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E4F257812C81903800FCEAFC /* metal */,
|
||||
E4F257842C81903800FCEAFC /* vulkan */,
|
||||
E4F2578B2C81903800FCEAFC /* xr */,
|
||||
E4F257852C81903800FCEAFC /* SDL_gpu.c */,
|
||||
E4F257862C81903800FCEAFC /* SDL_sysgpu.h */,
|
||||
);
|
||||
@@ -2946,6 +2966,8 @@
|
||||
A7D8A95723E2514000DCD162 /* SDL_atomic.c in Sources */,
|
||||
A75FDBCE23EA380300529352 /* SDL_hidapi_rumble.c in Sources */,
|
||||
E4F257952C81903800FCEAFC /* SDL_gpu_vulkan.c in Sources */,
|
||||
E4F257982C81903800FCEAFC /* SDL_gpu_openxr.c in Sources */,
|
||||
E4F257992C81903800FCEAFC /* SDL_openxrdyn.c in Sources */,
|
||||
A7D8BB2723E2514500DCD162 /* SDL_displayevents.c in Sources */,
|
||||
A7D8AB2523E2514100DCD162 /* SDL_log.c in Sources */,
|
||||
A7D8AE8823E2514100DCD162 /* SDL_cocoaopengl.m in Sources */,
|
||||
|
||||
@@ -2364,6 +2364,20 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER "SDL.gpu.device.create.vulkan.options"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_METAL_ALLOW_MACFAMILY1_BOOLEAN "SDL.gpu.device.create.metal.allowmacfamily1"
|
||||
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE_BOOLEAN "SDL.gpu.device.create.xr.enable"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_INSTANCE_POINTER "SDL.gpu.device.create.xr.instance_out"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_SYSTEM_ID_POINTER "SDL.gpu.device.create.xr.system_id_out"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_VERSION_NUMBER "SDL.gpu.device.create.xr.version"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_FORM_FACTOR_NUMBER "SDL.gpu.device.create.xr.form_factor"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_COUNT_NUMBER "SDL.gpu.device.create.xr.extensions.count"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_NAMES_POINTER "SDL.gpu.device.create.xr.extensions.names"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_COUNT_NUMBER "SDL.gpu.device.create.xr.layers.count"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_NAMES_POINTER "SDL.gpu.device.create.xr.layers.names"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_NAME_STRING "SDL.gpu.device.create.xr.application.name"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_VERSION_NUMBER "SDL.gpu.device.create.xr.application.version"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_NAME_STRING "SDL.gpu.device.create.xr.engine.name"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_VERSION_NUMBER "SDL.gpu.device.create.xr.engine.version"
|
||||
|
||||
|
||||
/**
|
||||
* A structure specifying additional options when using Vulkan.
|
||||
|
||||
@@ -1145,6 +1145,18 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_GPU_DRIVER "SDL_GPU_DRIVER"
|
||||
|
||||
/**
|
||||
* A variable that specifies the library name to use when loading the OpenXR loader.
|
||||
*
|
||||
* By default, SDL will try the system default name, but on some platforms like Windows,
|
||||
* debug builds of the OpenXR loader have a different name, and are not always directly compatible with release applications.
|
||||
* Setting this hint allows you to compensate for this difference in your app when applicable.
|
||||
*
|
||||
* This hint should be set before the OpenXR loader is loaded.
|
||||
* For example, creating an OpenXR GPU device will load the OpenXR loader.
|
||||
*/
|
||||
#define SDL_HINT_OPENXR_LIBRARY "SDL_OPENXR_LIBRARY"
|
||||
|
||||
/**
|
||||
* A variable to control whether SDL_hid_enumerate() enumerates all HID
|
||||
* devices or only controllers.
|
||||
|
||||
207
include/SDL3/SDL_openxr.h
Normal file
207
include/SDL3/SDL_openxr.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/**
|
||||
* # CategoryOpenXR
|
||||
*
|
||||
* Functions for creating OpenXR handles for SDL_gpu contexts.
|
||||
*
|
||||
* For the most part, OpenXR operates independent of SDL, but
|
||||
* the graphics initialization depends on direct support from SDL_gpu.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SDL_openxr_h_
|
||||
#define SDL_openxr_h_
|
||||
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
#include <SDL3/SDL_begin_code.h>
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(OPENXR_H_)
|
||||
#define NO_SDL_OPENXR_TYPEDEFS 1
|
||||
#endif /* OPENXR_H_ */
|
||||
|
||||
#if !defined(NO_SDL_OPENXR_TYPEDEFS)
|
||||
#define XR_NULL_HANDLE 0
|
||||
|
||||
#if !defined(XR_DEFINE_HANDLE)
|
||||
#define XR_DEFINE_HANDLE(object) typedef Uint64 object;
|
||||
#endif /* XR_DEFINE_HANDLE */
|
||||
|
||||
typedef enum XrStructureType {
|
||||
XR_TYPE_SESSION_CREATE_INFO = 8,
|
||||
XR_TYPE_SWAPCHAIN_CREATE_INFO = 9,
|
||||
} XrStructureType;
|
||||
|
||||
XR_DEFINE_HANDLE(XrInstance)
|
||||
XR_DEFINE_HANDLE(XrSystemId)
|
||||
XR_DEFINE_HANDLE(XrSession)
|
||||
XR_DEFINE_HANDLE(XrSwapchain)
|
||||
|
||||
typedef struct {
|
||||
XrStructureType type;
|
||||
const void* next;
|
||||
} XrSessionCreateInfo;
|
||||
typedef struct {
|
||||
XrStructureType type;
|
||||
const void* next;
|
||||
} XrSwapchainCreateInfo;
|
||||
|
||||
typedef enum XrResult {
|
||||
XR_ERROR_FUNCTION_UNSUPPORTED = -7,
|
||||
XR_ERROR_HANDLE_INVALID = -12,
|
||||
} XrResult;
|
||||
|
||||
#define PFN_xrGetInstanceProcAddr SDL_FunctionPointer
|
||||
#endif /* NO_SDL_OPENXR_TYPEDEFS */
|
||||
|
||||
/**
|
||||
* Creates an OpenXR session. The OpenXR system ID is pulled from the passed GPU context.
|
||||
*
|
||||
* \param device a GPU context.
|
||||
* \param createinfo the create info for the OpenXR session, sans the system ID.
|
||||
* \param session a pointer filled in with an OpenXR session created for the given device.
|
||||
* \returns the result of the call.
|
||||
*
|
||||
* \sa SDL_CreateGPUDeviceWithProperties
|
||||
*/
|
||||
extern SDL_DECLSPEC XrResult SDLCALL SDL_CreateGPUXRSession(SDL_GPUDevice *device, const XrSessionCreateInfo *createinfo, XrSession *session);
|
||||
|
||||
/**
|
||||
* Queries the GPU device for supported XR swapchain image formats.
|
||||
*
|
||||
* The returned pointer should be allocated with SDL_malloc() and will be
|
||||
* passed to SDL_free().
|
||||
*
|
||||
* \param device a GPU context.
|
||||
* \param session an OpenXR session created for the given device.
|
||||
* \param num_formats a pointer filled with the number of supported XR swapchain formats.
|
||||
* \returns a 0 terminated array of supported formats or NULL on failure;
|
||||
* call SDL_GetError() for more information. This should be freed
|
||||
* with SDL_free() when it is no longer needed.
|
||||
*
|
||||
* \sa SDL_CreateGPUXRSwapchain
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_GPUTextureFormat * SDLCALL SDL_GetGPUXRSwapchainFormats(SDL_GPUDevice *device, XrSession session, int *num_formats);
|
||||
|
||||
/**
|
||||
* Creates an OpenXR swapchain.
|
||||
*
|
||||
* The array returned via `textures` is sized according to
|
||||
*`xrEnumerateSwapchainImages`, and thus should only be accessed via index
|
||||
* values returned from `xrAcquireSwapchainImage`.
|
||||
*
|
||||
* Applications are still allowed to call `xrEnumerateSwapchainImages` on the
|
||||
* returned XrSwapchain if they need to get the exact size of the array.
|
||||
*
|
||||
* \param device a GPU context.
|
||||
* \param session an OpenXR session created for the given device.
|
||||
* \param createinfo the create info for the OpenXR swapchain, sans the format.
|
||||
* \param format a supported format for the OpenXR swapchain.
|
||||
* \param swapchain a pointer filled in with the created OpenXR swapchain.
|
||||
* \param textures a pointer filled in with the array of created swapchain images.
|
||||
* \returns the result of the call.
|
||||
*
|
||||
* \sa SDL_CreateGPUDeviceWithProperties
|
||||
* \sa SDL_CreateGPUXRSession
|
||||
* \sa SDL_GetGPUXRSwapchainFormats
|
||||
* \sa SDL_DestroyGPUXRSwapchain
|
||||
*/
|
||||
extern SDL_DECLSPEC XrResult SDLCALL SDL_CreateGPUXRSwapchain(
|
||||
SDL_GPUDevice *device,
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo *createinfo,
|
||||
SDL_GPUTextureFormat format,
|
||||
XrSwapchain *swapchain,
|
||||
SDL_GPUTexture ***textures);
|
||||
|
||||
/**
|
||||
* Destroys and OpenXR swapchain previously returned by SDL_CreateGPUXRSwapchain.
|
||||
*
|
||||
* \param device a GPU context.
|
||||
* \param swapchain a swapchain previously returned by SDL_CreateGPUXRSwapchain.
|
||||
* \param swapchainImages an array of swapchain images returned by the same call to SDL_CreateGPUXRSwapchain.
|
||||
* \returns the result of the call.
|
||||
*
|
||||
* \sa SDL_CreateGPUDeviceWithProperties
|
||||
* \sa SDL_CreateGPUXRSession
|
||||
* \sa SDL_CreateGPUXRSwapchain
|
||||
*/
|
||||
extern SDL_DECLSPEC XrResult SDLCALL SDL_DestroyGPUXRSwapchain(SDL_GPUDevice *device, XrSwapchain swapchain, SDL_GPUTexture **swapchainImages);
|
||||
|
||||
/**
|
||||
* Dynamically load the OpenXR loader. This can be called at any time.
|
||||
*
|
||||
* SDL keeps a reference count of the OpenXR loader, calling this function multiple
|
||||
* times will increment that count, rather than loading the library multiple times.
|
||||
*
|
||||
* If not called, this will be implicitly called when creating a GPU device with OpenXR.
|
||||
*
|
||||
* This function will use the platform default OpenXR loader name,
|
||||
* unless the `SDL_HINT_OPENXR_LIBRARY` hint is set.
|
||||
*
|
||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||
* information.
|
||||
*
|
||||
* \threadsafety This function is not thread safe.
|
||||
*
|
||||
* \sa SDL_HINT_OPENXR_LIBRARY
|
||||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_OpenXR_LoadLibrary(void);
|
||||
|
||||
/**
|
||||
* Unload the OpenXR loader previously loaded by SDL_OpenXR_LoadLibrary.
|
||||
*
|
||||
* SDL keeps a reference count of the OpenXR loader, calling this function will decrement that count.
|
||||
* Once the reference count reaches zero, the library is unloaded.
|
||||
*
|
||||
* \threadsafety This function is not thread safe.
|
||||
*/
|
||||
extern SDL_DECLSPEC void SDLCALL SDL_OpenXR_UnloadLibrary(void);
|
||||
|
||||
/**
|
||||
* Get the address of the `xrGetInstanceProcAddr` function.
|
||||
*
|
||||
* This should be called after either calling SDL_OpenXR_LoadLibrary() or
|
||||
* creating an OpenXR SDL_GPUDevice.
|
||||
*
|
||||
* The actual type of the returned function pointer is PFN_xrGetInstanceProcAddr,
|
||||
* but that isn't always available. You should include the OpenXR headers before this header,
|
||||
* or cast the return value of this function to the correct type.
|
||||
*
|
||||
* \returns the function pointer for `xrGetInstanceProcAddr` or NULL on
|
||||
* failure; call SDL_GetError() for more information.
|
||||
*/
|
||||
extern SDL_DECLSPEC PFN_xrGetInstanceProcAddr SDLCALL SDL_OpenXR_GetXrGetInstanceProcAddr(void);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <SDL3/SDL_close_code.h>
|
||||
|
||||
#endif /* SDL_openxr_h_ */
|
||||
@@ -488,6 +488,7 @@
|
||||
#cmakedefine SDL_GPU_D3D12 1
|
||||
#cmakedefine SDL_GPU_VULKAN 1
|
||||
#cmakedefine SDL_GPU_METAL 1
|
||||
#cmakedefine HAVE_GPU_OPENXR 1
|
||||
|
||||
#cmakedefine SDL_GPU_PRIVATE 1
|
||||
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
#define SDL_VIDEO_VULKAN 1
|
||||
#define SDL_VIDEO_RENDER_VULKAN 1
|
||||
#define SDL_GPU_VULKAN 1
|
||||
#define HAVE_GPU_OPENXR 1
|
||||
#define SDL_VIDEO_RENDER_GPU 1
|
||||
#endif
|
||||
|
||||
|
||||
@@ -289,6 +289,7 @@ typedef unsigned int uintptr_t;
|
||||
#endif
|
||||
#define SDL_GPU_D3D12 1
|
||||
#define SDL_GPU_VULKAN 1
|
||||
#define HAVE_GPU_OPENXR 1
|
||||
#define SDL_VIDEO_RENDER_GPU 1
|
||||
|
||||
/* Enable system power support */
|
||||
|
||||
@@ -233,6 +233,7 @@
|
||||
#undef SDL_GPU_D3D12
|
||||
#undef SDL_GPU_METAL
|
||||
#undef SDL_GPU_VULKAN
|
||||
#undef HAVE_GPU_OPENXR
|
||||
#undef SDL_VIDEO_RENDER_GPU
|
||||
#endif // SDL_GPU_DISABLED
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#endif
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_openxr.h>
|
||||
#define SDL_MAIN_NOIMPL // don't drag in header-only implementation of SDL_main
|
||||
#include <SDL3/SDL_main.h>
|
||||
#include "../core/SDL_core_unsupported.h"
|
||||
@@ -597,6 +598,7 @@ static void SDL_InitDynamicAPI(void)
|
||||
#else // SDL_DYNAMIC_API
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_openxr.h>
|
||||
|
||||
Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize);
|
||||
Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize)
|
||||
|
||||
@@ -1272,6 +1272,13 @@ SDL3_0.0.0 {
|
||||
SDL_LoadSurface;
|
||||
SDL_SetWindowFillDocument;
|
||||
SDL_TryLockJoysticks;
|
||||
SDL_CreateGPUXRSession;
|
||||
SDL_GetGPUXRSwapchainFormats;
|
||||
SDL_CreateGPUXRSwapchain;
|
||||
SDL_DestroyGPUXRSwapchain;
|
||||
SDL_OpenXR_LoadLibrary;
|
||||
SDL_OpenXR_UnloadLibrary;
|
||||
SDL_OpenXR_GetXrGetInstanceProcAddr;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
||||
@@ -1298,3 +1298,10 @@
|
||||
#define SDL_LoadSurface SDL_LoadSurface_REAL
|
||||
#define SDL_SetWindowFillDocument SDL_SetWindowFillDocument_REAL
|
||||
#define SDL_TryLockJoysticks SDL_TryLockJoysticks_REAL
|
||||
#define SDL_CreateGPUXRSession SDL_CreateGPUXRSession_REAL
|
||||
#define SDL_GetGPUXRSwapchainFormats SDL_GetGPUXRSwapchainFormats_REAL
|
||||
#define SDL_CreateGPUXRSwapchain SDL_CreateGPUXRSwapchain_REAL
|
||||
#define SDL_DestroyGPUXRSwapchain SDL_DestroyGPUXRSwapchain_REAL
|
||||
#define SDL_OpenXR_LoadLibrary SDL_OpenXR_LoadLibrary_REAL
|
||||
#define SDL_OpenXR_UnloadLibrary SDL_OpenXR_UnloadLibrary_REAL
|
||||
#define SDL_OpenXR_GetXrGetInstanceProcAddr SDL_OpenXR_GetXrGetInstanceProcAddr_REAL
|
||||
|
||||
@@ -1306,3 +1306,10 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface_IO,(SDL_IOStream *a,bool b),(a,b),r
|
||||
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_SetWindowFillDocument,(SDL_Window *a,bool b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_TryLockJoysticks,(void),(),return)
|
||||
SDL_DYNAPI_PROC(XrResult,SDL_CreateGPUXRSession,(SDL_GPUDevice *a,const XrSessionCreateInfo *b,XrSession *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(SDL_GPUTextureFormat*,SDL_GetGPUXRSwapchainFormats,(SDL_GPUDevice *a,XrSession b,int *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(XrResult,SDL_CreateGPUXRSwapchain,(SDL_GPUDevice *a,XrSession b,const XrSwapchainCreateInfo *c,SDL_GPUTextureFormat d,XrSwapchain *e,SDL_GPUTexture ***f),(a,b,c,d,e,f),return)
|
||||
SDL_DYNAPI_PROC(XrResult,SDL_DestroyGPUXRSwapchain,(SDL_GPUDevice *a,XrSwapchain b,SDL_GPUTexture **c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_OpenXR_LoadLibrary,(void),(),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_OpenXR_UnloadLibrary,(void),(),)
|
||||
SDL_DYNAPI_PROC(PFN_xrGetInstanceProcAddr,SDL_OpenXR_GetXrGetInstanceProcAddr,(void),(),return)
|
||||
|
||||
@@ -607,6 +607,13 @@ static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_GPU_OPENXR
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE_BOOLEAN, false)) {
|
||||
SDL_SetError("OpenXR is not enabled in this build of SDL");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
gpudriver = SDL_GetHint(SDL_HINT_GPU_DRIVER);
|
||||
if (gpudriver == NULL) {
|
||||
gpudriver = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, NULL);
|
||||
@@ -752,6 +759,13 @@ void SDL_DestroyGPUDevice(SDL_GPUDevice *device)
|
||||
device->DestroyDevice(device);
|
||||
}
|
||||
|
||||
XrResult SDL_DestroyGPUXRSwapchain(SDL_GPUDevice *device, XrSwapchain swapchain, SDL_GPUTexture **swapchainImages)
|
||||
{
|
||||
CHECK_DEVICE_MAGIC(device, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return device->DestroyXRSwapchain(device->driverData, swapchain, swapchainImages);
|
||||
}
|
||||
|
||||
int SDL_GetNumGPUDrivers(void)
|
||||
{
|
||||
#ifndef SDL_GPU_DISABLED
|
||||
@@ -3567,3 +3581,36 @@ SDL_GPUTextureFormat SDL_GetGPUTextureFormatFromPixelFormat(SDL_PixelFormat form
|
||||
return SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
XrResult SDL_CreateGPUXRSession(
|
||||
SDL_GPUDevice *device,
|
||||
const XrSessionCreateInfo *createinfo,
|
||||
XrSession *session)
|
||||
{
|
||||
CHECK_DEVICE_MAGIC(device, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return device->CreateXRSession(device->driverData, createinfo, session);
|
||||
}
|
||||
|
||||
SDL_GPUTextureFormat* SDL_GetGPUXRSwapchainFormats(
|
||||
SDL_GPUDevice *device,
|
||||
XrSession session,
|
||||
int *num_formats)
|
||||
{
|
||||
CHECK_DEVICE_MAGIC(device, NULL);
|
||||
|
||||
return device->GetXRSwapchainFormats(device->driverData, session, num_formats);
|
||||
}
|
||||
|
||||
XrResult SDL_CreateGPUXRSwapchain(
|
||||
SDL_GPUDevice *device,
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo *createinfo,
|
||||
SDL_GPUTextureFormat format,
|
||||
XrSwapchain *swapchain,
|
||||
SDL_GPUTexture ***textures)
|
||||
{
|
||||
CHECK_DEVICE_MAGIC(device, XR_ERROR_HANDLE_INVALID);
|
||||
|
||||
return device->CreateXRSwapchain(device->driverData, session, createinfo, format, swapchain, textures);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#ifndef SDL_GPU_DRIVER_H
|
||||
#define SDL_GPU_DRIVER_H
|
||||
|
||||
#include <SDL3/SDL_openxr.h>
|
||||
|
||||
// GraphicsDevice Limits
|
||||
|
||||
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
|
||||
@@ -669,6 +671,11 @@ struct SDL_GPUDevice
|
||||
|
||||
void (*DestroyDevice)(SDL_GPUDevice *device);
|
||||
|
||||
XrResult (*DestroyXRSwapchain)(
|
||||
SDL_GPURenderer *device,
|
||||
XrSwapchain swapchain,
|
||||
SDL_GPUTexture **swapchainImages);
|
||||
|
||||
SDL_PropertiesID (*GetDeviceProperties)(SDL_GPUDevice *device);
|
||||
|
||||
// State Creation
|
||||
@@ -705,6 +712,24 @@ struct SDL_GPUDevice
|
||||
Uint32 size,
|
||||
const char *debugName);
|
||||
|
||||
XrResult (*CreateXRSession)(
|
||||
SDL_GPURenderer *driverData,
|
||||
const XrSessionCreateInfo *createinfo,
|
||||
XrSession *session);
|
||||
|
||||
SDL_GPUTextureFormat* (*GetXRSwapchainFormats)(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
int *num_formats);
|
||||
|
||||
XrResult (*CreateXRSwapchain)(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo *createinfo,
|
||||
SDL_GPUTextureFormat format,
|
||||
XrSwapchain *swapchain,
|
||||
SDL_GPUTexture ***textures);
|
||||
|
||||
// Debug Naming
|
||||
|
||||
void (*SetBufferName)(
|
||||
@@ -1105,6 +1130,7 @@ struct SDL_GPUDevice
|
||||
result->func = name##_##func;
|
||||
#define ASSIGN_DRIVER(name) \
|
||||
ASSIGN_DRIVER_FUNC(DestroyDevice, name) \
|
||||
ASSIGN_DRIVER_FUNC(DestroyXRSwapchain, name) \
|
||||
ASSIGN_DRIVER_FUNC(GetDeviceProperties, name) \
|
||||
ASSIGN_DRIVER_FUNC(CreateComputePipeline, name) \
|
||||
ASSIGN_DRIVER_FUNC(CreateGraphicsPipeline, name) \
|
||||
@@ -1113,6 +1139,9 @@ struct SDL_GPUDevice
|
||||
ASSIGN_DRIVER_FUNC(CreateTexture, name) \
|
||||
ASSIGN_DRIVER_FUNC(CreateBuffer, name) \
|
||||
ASSIGN_DRIVER_FUNC(CreateTransferBuffer, name) \
|
||||
ASSIGN_DRIVER_FUNC(CreateXRSession, name) \
|
||||
ASSIGN_DRIVER_FUNC(GetXRSwapchainFormats, name) \
|
||||
ASSIGN_DRIVER_FUNC(CreateXRSwapchain, name) \
|
||||
ASSIGN_DRIVER_FUNC(SetBufferName, name) \
|
||||
ASSIGN_DRIVER_FUNC(SetTextureName, name) \
|
||||
ASSIGN_DRIVER_FUNC(InsertDebugLabel, name) \
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../video/directx/SDL_d3d12.h"
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
#define XR_USE_GRAPHICS_API_D3D12 1
|
||||
#include "../xr/SDL_openxr_internal.h"
|
||||
#include "../xr/SDL_openxrdyn.h"
|
||||
#include "../xr/SDL_gpu_openxr.h"
|
||||
#endif
|
||||
|
||||
#include "../SDL_sysgpu.h"
|
||||
|
||||
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
|
||||
@@ -584,6 +592,30 @@ static DXGI_FORMAT SDLToD3D12_TypelessFormat[] = {
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TypelessFormat, SDL_arraysize(SDLToD3D12_TypelessFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
// For XR sRGB format selection - maps DXGI sRGB formats to SDL formats
|
||||
typedef struct TextureFormatPair
|
||||
{
|
||||
DXGI_FORMAT dxgi;
|
||||
SDL_GPUTextureFormat sdl;
|
||||
} TextureFormatPair;
|
||||
|
||||
static TextureFormatPair SDLToD3D12_TextureFormat_SrgbOnly[] = {
|
||||
{ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB },
|
||||
{ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB },
|
||||
{ DXGI_FORMAT_BC1_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB },
|
||||
{ DXGI_FORMAT_BC2_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB },
|
||||
{ DXGI_FORMAT_BC3_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB },
|
||||
{ DXGI_FORMAT_BC7_UNORM_SRGB, SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB },
|
||||
};
|
||||
|
||||
// Forward declarations for XR helper functions
|
||||
static bool D3D12_INTERNAL_SearchForOpenXrGpuExtension(XrExtensionProperties *found_extension);
|
||||
static XrResult D3D12_INTERNAL_GetXrGraphicsRequirements(XrInstance instance, XrSystemId systemId, D3D_FEATURE_LEVEL *minimumFeatureLevel, LUID *adapter);
|
||||
static bool D3D12_INTERNAL_GetAdapterByLuid(LUID luid, IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapter);
|
||||
static bool D3D12_INTERNAL_FindXRSrgbSwapchain(int64_t *supportedFormats, Uint32 supportedFormatsCount, SDL_GPUTextureFormat *sdlFormat, DXGI_FORMAT *dxgiFormat);
|
||||
#endif /* HAVE_GPU_OPENXR */
|
||||
|
||||
static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
|
||||
D3D12_COMPARISON_FUNC_NEVER, // INVALID
|
||||
D3D12_COMPARISON_FUNC_NEVER, // NEVER
|
||||
@@ -789,6 +821,9 @@ typedef struct D3D12TextureContainer
|
||||
bool canBeCycled;
|
||||
|
||||
char *debugName;
|
||||
|
||||
// XR swapchain images are managed by OpenXR runtime
|
||||
bool externallyManaged;
|
||||
} D3D12TextureContainer;
|
||||
|
||||
// Null views represent by heap = NULL
|
||||
@@ -819,6 +854,9 @@ struct D3D12Texture
|
||||
D3D12StagingDescriptor srvHandle;
|
||||
|
||||
SDL_AtomicInt referenceCount;
|
||||
|
||||
// XR swapchain images are managed by OpenXR runtime
|
||||
bool externallyManaged;
|
||||
};
|
||||
|
||||
typedef struct D3D12Sampler
|
||||
@@ -977,6 +1015,13 @@ struct D3D12Renderer
|
||||
SDL_Mutex *windowLock;
|
||||
SDL_Mutex *fenceLock;
|
||||
SDL_Mutex *disposeLock;
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
// OpenXR state
|
||||
XrInstance xrInstance;
|
||||
XrSystemId xrSystemId;
|
||||
XrInstancePfns *xr;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct D3D12CommandBuffer
|
||||
@@ -1409,7 +1454,8 @@ static void D3D12_INTERNAL_DestroyTexture(
|
||||
D3D12_INTERNAL_ReleaseStagingDescriptorHandle(
|
||||
&texture->srvHandle);
|
||||
|
||||
if (texture->resource) {
|
||||
// XR swapchain images are owned by the OpenXR runtime
|
||||
if (texture->resource && !texture->externallyManaged) {
|
||||
ID3D12Resource_Release(texture->resource);
|
||||
}
|
||||
|
||||
@@ -8623,6 +8669,25 @@ static bool D3D12_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
// Check for OpenXR support if requested
|
||||
bool xr = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE_BOOLEAN, false);
|
||||
if (xr) {
|
||||
if (!SDL_OpenXR_LoadLibrary()) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Failed to load OpenXR");
|
||||
return false;
|
||||
}
|
||||
|
||||
XrExtensionProperties gpuExtension;
|
||||
if (!D3D12_INTERNAL_SearchForOpenXrGpuExtension(&gpuExtension)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D12: Failed to find " XR_KHR_D3D12_ENABLE_EXTENSION_NAME " extension");
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@@ -8824,6 +8889,403 @@ static void D3D12_INTERNAL_TryInitializeD3D12DebugInfoLogger(D3D12Renderer *rend
|
||||
}
|
||||
#endif
|
||||
|
||||
// OpenXR D3D12 Support
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
static bool D3D12_INTERNAL_SearchForOpenXrGpuExtension(XrExtensionProperties *found_extension)
|
||||
{
|
||||
XrResult result;
|
||||
Uint32 extension_count;
|
||||
Uint32 i;
|
||||
|
||||
result = xrEnumerateInstanceExtensionProperties(NULL, 0, &extension_count, NULL);
|
||||
if (result != XR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XrExtensionProperties *extension_properties = (XrExtensionProperties *)SDL_calloc(extension_count, sizeof(XrExtensionProperties));
|
||||
for (i = 0; i < extension_count; i++) {
|
||||
extension_properties[i] = (XrExtensionProperties){ XR_TYPE_EXTENSION_PROPERTIES };
|
||||
}
|
||||
|
||||
result = xrEnumerateInstanceExtensionProperties(NULL, extension_count, &extension_count, extension_properties);
|
||||
if (result != XR_SUCCESS) {
|
||||
SDL_free(extension_properties);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < extension_count; i++) {
|
||||
XrExtensionProperties extension = extension_properties[i];
|
||||
|
||||
if (SDL_strcmp(extension.extensionName, XR_KHR_D3D12_ENABLE_EXTENSION_NAME) == 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Found " XR_KHR_D3D12_ENABLE_EXTENSION_NAME " extension");
|
||||
|
||||
*found_extension = extension;
|
||||
|
||||
SDL_free(extension_properties);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(extension_properties);
|
||||
return false;
|
||||
}
|
||||
|
||||
static XrResult D3D12_INTERNAL_GetXrGraphicsRequirements(XrInstance instance, XrSystemId systemId, D3D_FEATURE_LEVEL *minimumFeatureLevel, LUID *adapter)
|
||||
{
|
||||
XrResult xrResult;
|
||||
|
||||
PFN_xrGetD3D12GraphicsRequirementsKHR xrGetD3D12GraphicsRequirementsKHR;
|
||||
if ((xrResult = xrGetInstanceProcAddr(instance, "xrGetD3D12GraphicsRequirementsKHR", (PFN_xrVoidFunction *)&xrGetD3D12GraphicsRequirementsKHR)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get xrGetD3D12GraphicsRequirementsKHR");
|
||||
return xrResult;
|
||||
}
|
||||
|
||||
XrGraphicsRequirementsD3D12KHR graphicsRequirementsD3D12 = { XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR };
|
||||
if ((xrResult = xrGetD3D12GraphicsRequirementsKHR(instance, systemId, &graphicsRequirementsD3D12)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get D3D12 graphics requirements, got OpenXR error %d", xrResult);
|
||||
return xrResult;
|
||||
}
|
||||
|
||||
*adapter = graphicsRequirementsD3D12.adapterLuid;
|
||||
*minimumFeatureLevel = graphicsRequirementsD3D12.minFeatureLevel;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
static bool D3D12_INTERNAL_GetAdapterByLuid(LUID luid, IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapter)
|
||||
{
|
||||
HRESULT res;
|
||||
|
||||
// We need to iterate over all the adapters in the system to find the one with the matching LUID
|
||||
for (Uint32 adapterIndex = 0;; adapterIndex++) {
|
||||
// EnumAdapters1 will fail with DXGI_ERROR_NOT_FOUND when there are no more adapters to enumerate.
|
||||
IDXGIAdapter1 *adapter;
|
||||
res = IDXGIFactory1_EnumAdapters1(factory, adapterIndex, &adapter);
|
||||
if (FAILED(res)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to get an adapter when iterating, i: %d, res: %ld", adapterIndex, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||
res = IDXGIAdapter1_GetDesc1(adapter, &adapterDesc);
|
||||
if (FAILED(res)) {
|
||||
IDXGIAdapter1_Release(adapter);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to get description of adapter, i: %d, res %ld", adapterIndex, res);
|
||||
return false;
|
||||
}
|
||||
if (SDL_memcmp(&adapterDesc.AdapterLuid, &luid, sizeof(luid)) == 0) {
|
||||
*outAdapter = adapter;
|
||||
return true;
|
||||
}
|
||||
IDXGIAdapter1_Release(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool D3D12_INTERNAL_FindXRSrgbSwapchain(
|
||||
int64_t *supportedFormats,
|
||||
Uint32 supportedFormatsCount,
|
||||
SDL_GPUTextureFormat *sdlFormat,
|
||||
DXGI_FORMAT *dxgiFormat)
|
||||
{
|
||||
for (Uint32 i = 0; i < SDL_arraysize(SDLToD3D12_TextureFormat_SrgbOnly); i++) {
|
||||
for (Uint32 j = 0; j < supportedFormatsCount; j++) {
|
||||
if (SDLToD3D12_TextureFormat_SrgbOnly[i].dxgi == supportedFormats[j]) {
|
||||
*sdlFormat = SDLToD3D12_TextureFormat_SrgbOnly[i].sdl;
|
||||
*dxgiFormat = SDLToD3D12_TextureFormat_SrgbOnly[i].dxgi;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* HAVE_GPU_OPENXR */
|
||||
|
||||
static XrResult D3D12_DestroyXRSwapchain(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSwapchain swapchain,
|
||||
SDL_GPUTexture **swapchainImages)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult result;
|
||||
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
|
||||
|
||||
D3D12_Wait(driverData);
|
||||
|
||||
Uint32 swapchainCount;
|
||||
result = renderer->xr->xrEnumerateSwapchainImages(swapchain, 0, &swapchainCount, NULL);
|
||||
if (result != XR_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// We always want to destroy the swapchain images, so don't early return if xrDestroySwapchain fails for some reason
|
||||
for (Uint32 i = 0; i < swapchainCount; i++) {
|
||||
D3D12Texture *container = (D3D12Texture *)swapchainImages[i];
|
||||
|
||||
if (!container->externallyManaged) {
|
||||
SDL_SetError("Invalid GPU Texture handle.");
|
||||
return XR_ERROR_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
D3D12_INTERNAL_DestroyTexture(container);
|
||||
|
||||
// Free the container now that it's unused
|
||||
SDL_free(container);
|
||||
}
|
||||
|
||||
SDL_free(swapchainImages);
|
||||
|
||||
return renderer->xr->xrDestroySwapchain(swapchain);
|
||||
#else
|
||||
(void)driverData;
|
||||
(void)swapchain;
|
||||
(void)swapchainImages;
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_GPUTextureFormat* D3D12_GetXRSwapchainFormats(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
int *num_formats)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult result;
|
||||
Uint32 i, j, num_supported_formats;
|
||||
int64_t *supported_formats;
|
||||
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
|
||||
|
||||
result = renderer->xr->xrEnumerateSwapchainFormats(session, 0, &num_supported_formats, NULL);
|
||||
if (result != XR_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
supported_formats = SDL_stack_alloc(int64_t, num_supported_formats);
|
||||
result = renderer->xr->xrEnumerateSwapchainFormats(session, num_supported_formats, &num_supported_formats, supported_formats);
|
||||
if (result != XR_SUCCESS) {
|
||||
SDL_stack_free(supported_formats);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FIXME: For now we're just searching for the optimal format, not all supported formats.
|
||||
// FIXME: Expand this search for all SDL_GPU formats!
|
||||
|
||||
SDL_GPUTextureFormat sdlFormat;
|
||||
DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN;
|
||||
// The OpenXR spec recommends applications not submit linear data, so let's try to explicitly find an sRGB swapchain before we search the whole list
|
||||
if (!D3D12_INTERNAL_FindXRSrgbSwapchain(supported_formats, num_supported_formats, &sdlFormat, &dxgiFormat)) {
|
||||
// Iterate over all formats the runtime supports
|
||||
for (i = 0; i < num_supported_formats && dxgiFormat == DXGI_FORMAT_UNKNOWN; i++) {
|
||||
// Iterate over all formats we support
|
||||
for (j = 0; j < SDL_arraysize(SDLToD3D12_TextureFormat); j++) {
|
||||
// Pick the first format the runtime wants that we also support, the runtime should return these in order of preference
|
||||
if (SDLToD3D12_TextureFormat[j] == supported_formats[i]) {
|
||||
dxgiFormat = (DXGI_FORMAT)supported_formats[i];
|
||||
sdlFormat = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_stack_free(supported_formats);
|
||||
|
||||
if (dxgiFormat == DXGI_FORMAT_UNKNOWN) {
|
||||
SDL_SetError("Failed to find a swapchain format supported by both OpenXR and SDL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPUTextureFormat *retval = (SDL_GPUTextureFormat*) SDL_malloc(sizeof(SDL_GPUTextureFormat) * 2);
|
||||
retval[0] = sdlFormat;
|
||||
retval[1] = SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
*num_formats = 1;
|
||||
return retval;
|
||||
#else
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static XrResult D3D12_CreateXRSwapchain(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo *oldCreateInfo,
|
||||
SDL_GPUTextureFormat format,
|
||||
XrSwapchain *swapchain,
|
||||
SDL_GPUTexture ***textures)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult result;
|
||||
Uint32 layerIndex, levelIndex;
|
||||
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
|
||||
|
||||
XrSwapchainCreateInfo createInfo = *oldCreateInfo;
|
||||
createInfo.format = SDLToD3D12_TextureFormat[format];
|
||||
|
||||
result = renderer->xr->xrCreateSwapchain(session, &createInfo, swapchain);
|
||||
if (result != XR_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Uint32 swapchainImageCount;
|
||||
result = renderer->xr->xrEnumerateSwapchainImages(*swapchain, 0, &swapchainImageCount, NULL);
|
||||
if (result != XR_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
XrSwapchainImageD3D12KHR *swapchainImages = (XrSwapchainImageD3D12KHR *)SDL_calloc(swapchainImageCount, sizeof(XrSwapchainImageD3D12KHR));
|
||||
for (layerIndex = 0; layerIndex < swapchainImageCount; layerIndex++) {
|
||||
swapchainImages[layerIndex].type = XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR;
|
||||
}
|
||||
|
||||
result = renderer->xr->xrEnumerateSwapchainImages(*swapchain, swapchainImageCount, &swapchainImageCount, (XrSwapchainImageBaseHeader *)swapchainImages);
|
||||
if (result != XR_SUCCESS) {
|
||||
SDL_free(swapchainImages);
|
||||
return result;
|
||||
}
|
||||
|
||||
D3D12TextureContainer **textureContainers = (D3D12TextureContainer **)SDL_calloc(swapchainImageCount, sizeof(D3D12TextureContainer *));
|
||||
|
||||
Uint32 depth = 1;
|
||||
|
||||
for (Uint32 idx = 0; idx < swapchainImageCount; idx++) {
|
||||
ID3D12Resource *d3d12Texture = swapchainImages[idx].texture;
|
||||
|
||||
D3D12Texture *texture = (D3D12Texture *)SDL_calloc(1, sizeof(D3D12Texture));
|
||||
|
||||
texture->resource = d3d12Texture;
|
||||
texture->externallyManaged = true;
|
||||
SDL_SetAtomicInt(&texture->referenceCount, 0);
|
||||
|
||||
texture->subresourceCount = createInfo.arraySize * createInfo.mipCount;
|
||||
texture->subresources = (D3D12TextureSubresource *)SDL_calloc(
|
||||
texture->subresourceCount,
|
||||
sizeof(D3D12TextureSubresource));
|
||||
|
||||
for (layerIndex = 0; layerIndex < createInfo.arraySize; layerIndex += 1) {
|
||||
for (levelIndex = 0; levelIndex < createInfo.mipCount; levelIndex += 1) {
|
||||
Uint32 subresourceIndex = D3D12_INTERNAL_CalcSubresource(
|
||||
levelIndex,
|
||||
layerIndex,
|
||||
createInfo.mipCount);
|
||||
|
||||
texture->subresources[subresourceIndex].parent = texture;
|
||||
texture->subresources[subresourceIndex].layer = layerIndex;
|
||||
texture->subresources[subresourceIndex].level = levelIndex;
|
||||
texture->subresources[subresourceIndex].depth = depth;
|
||||
texture->subresources[subresourceIndex].index = subresourceIndex;
|
||||
|
||||
texture->subresources[subresourceIndex].rtvHandles = NULL;
|
||||
texture->subresources[subresourceIndex].uavHandle.heap = NULL;
|
||||
texture->subresources[subresourceIndex].dsvHandle.heap = NULL;
|
||||
|
||||
if (createInfo.usageFlags & XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
texture->subresources[subresourceIndex].rtvHandles = (D3D12StagingDescriptor *)SDL_calloc(depth, sizeof(D3D12StagingDescriptor));
|
||||
|
||||
for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) {
|
||||
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
|
||||
|
||||
D3D12_INTERNAL_AssignStagingDescriptorHandle(
|
||||
renderer,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
|
||||
&texture->subresources[subresourceIndex].rtvHandles[depthIndex]);
|
||||
|
||||
rtvDesc.Format = SDLToD3D12_TextureFormat[format];
|
||||
|
||||
// For XR we typically use 2D array textures for stereo rendering
|
||||
if (createInfo.arraySize > 1) {
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtvDesc.Texture2DArray.MipSlice = levelIndex;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
|
||||
rtvDesc.Texture2DArray.ArraySize = 1;
|
||||
rtvDesc.Texture2DArray.PlaneSlice = 0;
|
||||
} else {
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
rtvDesc.Texture2D.MipSlice = levelIndex;
|
||||
rtvDesc.Texture2D.PlaneSlice = 0;
|
||||
}
|
||||
|
||||
ID3D12Device_CreateRenderTargetView(
|
||||
renderer->device,
|
||||
texture->resource,
|
||||
&rtvDesc,
|
||||
texture->subresources[subresourceIndex].rtvHandles[depthIndex].cpuHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textureContainers[idx] = (D3D12TextureContainer *)SDL_malloc(sizeof(D3D12TextureContainer));
|
||||
D3D12TextureContainer *container = textureContainers[idx];
|
||||
SDL_zero(container->header.info);
|
||||
container->header.info.width = createInfo.width;
|
||||
container->header.info.height = createInfo.height;
|
||||
container->header.info.format = format;
|
||||
container->header.info.layer_count_or_depth = createInfo.arraySize;
|
||||
container->header.info.num_levels = createInfo.mipCount;
|
||||
container->header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
container->header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
|
||||
container->externallyManaged = true;
|
||||
container->canBeCycled = false;
|
||||
container->activeTexture = texture;
|
||||
container->textureCapacity = 1;
|
||||
container->textureCount = 1;
|
||||
container->textures = (D3D12Texture **)SDL_malloc(
|
||||
container->textureCapacity * sizeof(D3D12Texture *));
|
||||
container->textures[0] = container->activeTexture;
|
||||
container->debugName = NULL;
|
||||
|
||||
texture->container = container;
|
||||
texture->containerIndex = 0;
|
||||
}
|
||||
|
||||
*textures = (SDL_GPUTexture **)textureContainers;
|
||||
|
||||
SDL_free(swapchainImages);
|
||||
|
||||
return XR_SUCCESS;
|
||||
#else
|
||||
(void)driverData;
|
||||
(void)session;
|
||||
(void)oldCreateInfo;
|
||||
(void)format;
|
||||
(void)swapchain;
|
||||
(void)textures;
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static XrResult D3D12_CreateXRSession(
|
||||
SDL_GPURenderer *driverData,
|
||||
const XrSessionCreateInfo *createinfo,
|
||||
XrSession *session)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
|
||||
|
||||
// Copy out the existing next ptr so that we can append it to the end of the chain we create
|
||||
const void *XR_MAY_ALIAS currentNextPtr = createinfo->next;
|
||||
|
||||
XrGraphicsBindingD3D12KHR graphicsBinding = { XR_TYPE_GRAPHICS_BINDING_D3D12_KHR };
|
||||
graphicsBinding.device = renderer->device;
|
||||
graphicsBinding.queue = renderer->commandQueue;
|
||||
graphicsBinding.next = currentNextPtr;
|
||||
|
||||
XrSessionCreateInfo sessionCreateInfo = *createinfo;
|
||||
sessionCreateInfo.systemId = renderer->xrSystemId;
|
||||
sessionCreateInfo.next = &graphicsBinding;
|
||||
|
||||
return renderer->xr->xrCreateSession(renderer->xrInstance, &sessionCreateInfo, session);
|
||||
#else
|
||||
(void)driverData;
|
||||
(void)createinfo;
|
||||
(void)session;
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
|
||||
{
|
||||
SDL_GPUDevice *result;
|
||||
@@ -8942,29 +9404,100 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
||||
IDXGIFactory5_Release(factory5);
|
||||
}
|
||||
|
||||
// Select the appropriate device for rendering
|
||||
res = IDXGIFactory4_QueryInterface(
|
||||
renderer->factory,
|
||||
D3D_GUID(D3D_IID_IDXGIFactory6),
|
||||
(void **)&factory6);
|
||||
if (SUCCEEDED(res)) {
|
||||
res = IDXGIFactory6_EnumAdapterByGpuPreference(
|
||||
factory6,
|
||||
0,
|
||||
preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||
D3D_GUID(D3D_IID_IDXGIAdapter1),
|
||||
(void **)&renderer->adapter);
|
||||
IDXGIFactory6_Release(factory6);
|
||||
} else {
|
||||
res = IDXGIFactory4_EnumAdapters1(
|
||||
renderer->factory,
|
||||
0,
|
||||
&renderer->adapter);
|
||||
}
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
bool xr = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE_BOOLEAN, false);
|
||||
XrInstance *xrInstance = (XrInstance *)SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_INSTANCE_POINTER, NULL);
|
||||
XrSystemId *xrSystemId = (XrSystemId *)SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_SYSTEM_ID_POINTER, NULL);
|
||||
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
|
||||
if (FAILED(res)) {
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
CHECK_D3D12_ERROR_AND_RETURN("Could not find adapter for D3D12Device", NULL);
|
||||
if (xr) {
|
||||
XrExtensionProperties gpuExtension;
|
||||
|
||||
if (!xrInstance) {
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("You must specify an out pointer for the OpenXR instance", NULL);
|
||||
}
|
||||
|
||||
if (!xrSystemId) {
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("You must specify an out pointer for the OpenXR system ID", NULL);
|
||||
}
|
||||
|
||||
if (!SDL_OpenXR_LoadLibrary()) {
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("This should have failed in PrepareDevice first!", NULL);
|
||||
}
|
||||
|
||||
if (!D3D12_INTERNAL_SearchForOpenXrGpuExtension(&gpuExtension)) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to find a compatible OpenXR D3D12 extension");
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("Failed to find XR_KHR_D3D12_enable extension", NULL);
|
||||
}
|
||||
|
||||
if (!SDL_OPENXR_INTERNAL_GPUInitOpenXR(debugMode, gpuExtension, props, xrInstance, xrSystemId, &renderer->xr)) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to init OpenXR");
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("Failed to initialize OpenXR", NULL);
|
||||
}
|
||||
|
||||
renderer->xrInstance = *xrInstance;
|
||||
renderer->xrSystemId = *xrSystemId;
|
||||
|
||||
LUID xrAdapter;
|
||||
|
||||
if (D3D12_INTERNAL_GetXrGraphicsRequirements(*xrInstance, *xrSystemId, &featureLevel, &xrAdapter) != XR_SUCCESS) {
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("Failed to get XR graphics requirements", NULL);
|
||||
}
|
||||
|
||||
// Need factory1 again for adapter enumeration
|
||||
IDXGIFactory1 *factory1ForXr;
|
||||
res = pCreateDXGIFactory1(
|
||||
&D3D_IID_IDXGIFactory1,
|
||||
(void **)&factory1ForXr);
|
||||
if (FAILED(res)) {
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
CHECK_D3D12_ERROR_AND_RETURN("Could not create DXGIFactory for XR adapter lookup", NULL);
|
||||
}
|
||||
|
||||
if (!D3D12_INTERNAL_GetAdapterByLuid(xrAdapter, factory1ForXr, &renderer->adapter)) {
|
||||
IDXGIFactory1_Release(factory1ForXr);
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
SET_STRING_ERROR_AND_RETURN("Failed to find adapter matching XR LUID", NULL);
|
||||
}
|
||||
IDXGIFactory1_Release(factory1ForXr);
|
||||
} else
|
||||
#endif /* HAVE_GPU_OPENXR */
|
||||
{
|
||||
// Select the appropriate device for rendering
|
||||
res = IDXGIFactory4_QueryInterface(
|
||||
renderer->factory,
|
||||
D3D_GUID(D3D_IID_IDXGIFactory6),
|
||||
(void **)&factory6);
|
||||
if (SUCCEEDED(res)) {
|
||||
res = IDXGIFactory6_EnumAdapterByGpuPreference(
|
||||
factory6,
|
||||
0,
|
||||
preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||
D3D_GUID(D3D_IID_IDXGIAdapter1),
|
||||
(void **)&renderer->adapter);
|
||||
IDXGIFactory6_Release(factory6);
|
||||
} else {
|
||||
res = IDXGIFactory4_EnumAdapters1(
|
||||
renderer->factory,
|
||||
0,
|
||||
&renderer->adapter);
|
||||
}
|
||||
|
||||
if (FAILED(res)) {
|
||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||
CHECK_D3D12_ERROR_AND_RETURN("Could not find adapter for D3D12Device", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Get information about the selected adapter. Used for logging info.
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
#include <Metal/Metal.h>
|
||||
#include <QuartzCore/CoreAnimation.h>
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
#define XR_USE_GRAPHICS_API_METAL 1
|
||||
#include "../xr/SDL_openxr_internal.h"
|
||||
#include "../xr/SDL_openxrdyn.h"
|
||||
#endif
|
||||
|
||||
#include "../SDL_sysgpu.h"
|
||||
|
||||
// Defines
|
||||
@@ -4337,6 +4343,10 @@ static bool METAL_SupportsTextureFormat(
|
||||
|
||||
static bool METAL_PrepareDriver(SDL_VideoDevice *this, SDL_PropertiesID props)
|
||||
{
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE_BOOLEAN, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, false) &&
|
||||
!SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN, false)) {
|
||||
return false;
|
||||
@@ -4499,6 +4509,45 @@ static void METAL_INTERNAL_DestroyBlitResources(
|
||||
SDL_free(renderer->blitPipelines);
|
||||
}
|
||||
|
||||
static XrResult METAL_DestroyXRSwapchain(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSwapchain swapchain,
|
||||
SDL_GPUTexture **swapchainImages)
|
||||
{
|
||||
SDL_SetError("The metal backend does not currently support OpenXR");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static SDL_GPUTextureFormat* METAL_GetXRSwapchainFormats(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
int *num_formats)
|
||||
{
|
||||
SDL_SetError("The metal backend does not currently support OpenXR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static XrResult METAL_CreateXRSwapchain(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo *oldCreateInfo,
|
||||
SDL_GPUTextureFormat format,
|
||||
XrSwapchain *swapchain,
|
||||
SDL_GPUTexture ***textures)
|
||||
{
|
||||
SDL_SetError("The metal backend does not currently support OpenXR");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static XrResult METAL_CreateXRSession(
|
||||
SDL_GPURenderer *driverData,
|
||||
const XrSessionCreateInfo *createinfo,
|
||||
XrSession *session)
|
||||
{
|
||||
SDL_SetError("The metal backend does not currently support OpenXR");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include "../../video/khronos/vulkan/vulkan.h"
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
#define XR_USE_GRAPHICS_API_VULKAN 1
|
||||
#include "../xr/SDL_openxr_internal.h"
|
||||
#include "../xr/SDL_openxrdyn.h"
|
||||
#include "../xr/SDL_gpu_openxr.h"
|
||||
#endif
|
||||
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
|
||||
#include "../SDL_sysgpu.h"
|
||||
@@ -88,6 +95,37 @@ static VkPresentModeKHR SDLToVK_PresentMode[] = {
|
||||
VK_PRESENT_MODE_MAILBOX_KHR
|
||||
};
|
||||
|
||||
// NOTE: this is behind an ifdef guard because without, it would trigger an "unused variable" error when OpenXR support is disabled
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
typedef struct TextureFormatPair {
|
||||
VkFormat vk;
|
||||
SDL_GPUTextureFormat sdl;
|
||||
} TextureFormatPair;
|
||||
|
||||
static TextureFormatPair SDLToVK_TextureFormat_SrgbOnly[] = {
|
||||
{VK_FORMAT_R8G8B8A8_SRGB, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB},
|
||||
{VK_FORMAT_B8G8R8A8_SRGB, SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB},
|
||||
{VK_FORMAT_BC1_RGBA_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB},
|
||||
{VK_FORMAT_BC2_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB},
|
||||
{VK_FORMAT_BC3_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB},
|
||||
{VK_FORMAT_BC7_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_4x4_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_5x4_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_5x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_6x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_6x6_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_8x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_8x6_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_8x8_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_10x5_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_10x6_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_10x8_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_10x10_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_12x10_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB},
|
||||
{VK_FORMAT_ASTC_12x12_SRGB_BLOCK, SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB},
|
||||
};
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
static VkFormat SDLToVK_TextureFormat[] = {
|
||||
VK_FORMAT_UNDEFINED, // INVALID
|
||||
VK_FORMAT_R8_UNORM, // A8_UNORM
|
||||
@@ -609,6 +647,7 @@ struct VulkanTexture
|
||||
VulkanTextureSubresource *subresources;
|
||||
|
||||
bool markedForDestroy; // so that defrag doesn't double-free
|
||||
bool externallyManaged; // true for XR swapchain images
|
||||
SDL_AtomicInt referenceCount;
|
||||
};
|
||||
|
||||
@@ -624,6 +663,7 @@ struct VulkanTextureContainer
|
||||
|
||||
char *debugName;
|
||||
bool canBeCycled;
|
||||
bool externallyManaged; // true for XR swapchain images
|
||||
};
|
||||
|
||||
typedef enum VulkanBufferUsageMode
|
||||
@@ -1113,6 +1153,14 @@ struct VulkanRenderer
|
||||
Uint8 outofBARMemoryWarning;
|
||||
Uint8 fillModeOnlyWarning;
|
||||
|
||||
// OpenXR
|
||||
Uint32 minimumVkVersion;
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrInstance xrInstance; // a non-null instance also states this vk device was created by OpenXR
|
||||
XrSystemId xrSystemId;
|
||||
XrInstancePfns *xr;
|
||||
#endif
|
||||
|
||||
bool debugMode;
|
||||
bool preferLowPower;
|
||||
bool requireHardwareAcceleration;
|
||||
@@ -3026,7 +3074,8 @@ static void VULKAN_INTERNAL_DestroyTexture(
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (texture->image) {
|
||||
/* Don't free an externally managed VkImage (e.g. XR swapchain images) */
|
||||
if (texture->image && !texture->externallyManaged) {
|
||||
renderer->vkDestroyImage(
|
||||
renderer->logicalDevice,
|
||||
texture->image,
|
||||
@@ -11846,7 +11895,31 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer, VulkanFeat
|
||||
createInfo.enabledLayerCount = 0;
|
||||
}
|
||||
|
||||
vulkanResult = vkCreateInstance(&createInfo, NULL, &renderer->instance);
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
if (renderer->xrInstance) {
|
||||
XrResult xrResult;
|
||||
PFN_xrCreateVulkanInstanceKHR xrCreateVulkanInstanceKHR;
|
||||
if ((xrResult = xrGetInstanceProcAddr(renderer->xrInstance, "xrCreateVulkanInstanceKHR", (PFN_xrVoidFunction *)&xrCreateVulkanInstanceKHR)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get xrCreateVulkanInstanceKHR");
|
||||
SDL_stack_free((char *)instanceExtensionNames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
XrVulkanInstanceCreateInfoKHR xrCreateInfo = {XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR};
|
||||
xrCreateInfo.vulkanCreateInfo = &createInfo;
|
||||
xrCreateInfo.systemId = renderer->xrSystemId;
|
||||
xrCreateInfo.pfnGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();
|
||||
SDL_assert(xrCreateInfo.pfnGetInstanceProcAddr);
|
||||
if ((xrResult = xrCreateVulkanInstanceKHR(renderer->xrInstance, &xrCreateInfo, &renderer->instance, &vulkanResult)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to create vulkan instance, reason %d, %d", xrResult, vulkanResult);
|
||||
SDL_stack_free((char *)instanceExtensionNames);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
{
|
||||
vulkanResult = vkCreateInstance(&createInfo, NULL, &renderer->instance);
|
||||
}
|
||||
SDL_stack_free((char *)instanceExtensionNames);
|
||||
|
||||
if (vulkanResult != VK_SUCCESS) {
|
||||
@@ -12133,87 +12206,139 @@ static Uint8 VULKAN_INTERNAL_DeterminePhysicalDevice(VulkanRenderer *renderer, V
|
||||
Uint32 suitableQueueFamilyIndex;
|
||||
Uint64 highestRank;
|
||||
|
||||
vulkanResult = renderer->vkEnumeratePhysicalDevices(
|
||||
renderer->instance,
|
||||
&physicalDeviceCount,
|
||||
NULL);
|
||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkEnumeratePhysicalDevices, 0);
|
||||
|
||||
if (physicalDeviceCount == 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Failed to find any GPUs with Vulkan support");
|
||||
return 0;
|
||||
}
|
||||
|
||||
physicalDevices = SDL_stack_alloc(VkPhysicalDevice, physicalDeviceCount);
|
||||
physicalDeviceExtensions = SDL_stack_alloc(VulkanExtensions, physicalDeviceCount);
|
||||
|
||||
vulkanResult = renderer->vkEnumeratePhysicalDevices(
|
||||
renderer->instance,
|
||||
&physicalDeviceCount,
|
||||
physicalDevices);
|
||||
|
||||
/* This should be impossible to hit, but from what I can tell this can
|
||||
* be triggered not because the array is too small, but because there
|
||||
* were drivers that turned out to be bogus, so this is the loader's way
|
||||
* of telling us that the list is now smaller than expected :shrug:
|
||||
*/
|
||||
if (vulkanResult == VK_INCOMPLETE) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkEnumeratePhysicalDevices returned VK_INCOMPLETE, will keep trying anyway...");
|
||||
vulkanResult = VK_SUCCESS;
|
||||
}
|
||||
|
||||
if (vulkanResult != VK_SUCCESS) {
|
||||
SDL_LogWarn(
|
||||
SDL_LOG_CATEGORY_GPU,
|
||||
"vkEnumeratePhysicalDevices failed: %s",
|
||||
VkErrorMessages(vulkanResult));
|
||||
SDL_stack_free(physicalDevices);
|
||||
SDL_stack_free(physicalDeviceExtensions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Any suitable device will do, but we'd like the best
|
||||
suitableIndex = -1;
|
||||
suitableQueueFamilyIndex = 0;
|
||||
highestRank = 0;
|
||||
for (i = 0; i < physicalDeviceCount; i += 1) {
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
// When XR is enabled, let the OpenXR runtime choose the physical device
|
||||
if (renderer->xrInstance) {
|
||||
XrResult xrResult;
|
||||
VulkanExtensions xrPhysicalDeviceExtensions;
|
||||
Uint32 queueFamilyIndex;
|
||||
Uint64 deviceRank;
|
||||
PFN_xrGetVulkanGraphicsDevice2KHR xrGetVulkanGraphicsDevice2KHR;
|
||||
|
||||
xrResult = xrGetInstanceProcAddr(
|
||||
renderer->xrInstance,
|
||||
"xrGetVulkanGraphicsDevice2KHR",
|
||||
(PFN_xrVoidFunction *)&xrGetVulkanGraphicsDevice2KHR);
|
||||
if (xrResult != XR_SUCCESS) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to get xrGetVulkanGraphicsDevice2KHR, result: %d", xrResult);
|
||||
return 0;
|
||||
}
|
||||
|
||||
XrVulkanGraphicsDeviceGetInfoKHR graphicsDeviceGetInfo;
|
||||
SDL_zero(graphicsDeviceGetInfo);
|
||||
graphicsDeviceGetInfo.type = XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR;
|
||||
graphicsDeviceGetInfo.systemId = renderer->xrSystemId;
|
||||
graphicsDeviceGetInfo.vulkanInstance = renderer->instance;
|
||||
|
||||
xrResult = xrGetVulkanGraphicsDevice2KHR(
|
||||
renderer->xrInstance,
|
||||
&graphicsDeviceGetInfo,
|
||||
&renderer->physicalDevice);
|
||||
if (xrResult != XR_SUCCESS) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "xrGetVulkanGraphicsDevice2KHR failed, result: %d", xrResult);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify the XR-chosen device is suitable
|
||||
if (!VULKAN_INTERNAL_IsDeviceSuitable(
|
||||
renderer,
|
||||
features,
|
||||
physicalDevices[i],
|
||||
&physicalDeviceExtensions[i],
|
||||
renderer->physicalDevice,
|
||||
&xrPhysicalDeviceExtensions,
|
||||
&queueFamilyIndex)) {
|
||||
// Device does not meet the minimum requirements, skip it entirely
|
||||
continue;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "The physical device chosen by the OpenXR runtime is not suitable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
deviceRank = highestRank;
|
||||
if (VULKAN_INTERNAL_GetDeviceRank(
|
||||
renderer,
|
||||
physicalDevices[i],
|
||||
&physicalDeviceExtensions[i],
|
||||
&deviceRank)) {
|
||||
/* Use this for rendering.
|
||||
* Note that this may override a previous device that
|
||||
* supports rendering, but shares the same device rank.
|
||||
*/
|
||||
suitableIndex = i;
|
||||
suitableQueueFamilyIndex = queueFamilyIndex;
|
||||
highestRank = deviceRank;
|
||||
}
|
||||
}
|
||||
renderer->supports = xrPhysicalDeviceExtensions;
|
||||
renderer->queueFamilyIndex = queueFamilyIndex;
|
||||
} else
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
{
|
||||
vulkanResult = renderer->vkEnumeratePhysicalDevices(
|
||||
renderer->instance,
|
||||
&physicalDeviceCount,
|
||||
NULL);
|
||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkEnumeratePhysicalDevices, 0);
|
||||
|
||||
if (physicalDeviceCount == 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Failed to find any GPUs with Vulkan support");
|
||||
return 0;
|
||||
}
|
||||
|
||||
physicalDevices = SDL_stack_alloc(VkPhysicalDevice, physicalDeviceCount);
|
||||
physicalDeviceExtensions = SDL_stack_alloc(VulkanExtensions, physicalDeviceCount);
|
||||
|
||||
vulkanResult = renderer->vkEnumeratePhysicalDevices(
|
||||
renderer->instance,
|
||||
&physicalDeviceCount,
|
||||
physicalDevices);
|
||||
|
||||
/* This should be impossible to hit, but from what I can tell this can
|
||||
* be triggered not because the array is too small, but because there
|
||||
* were drivers that turned out to be bogus, so this is the loader's way
|
||||
* of telling us that the list is now smaller than expected :shrug:
|
||||
*/
|
||||
if (vulkanResult == VK_INCOMPLETE) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkEnumeratePhysicalDevices returned VK_INCOMPLETE, will keep trying anyway...");
|
||||
vulkanResult = VK_SUCCESS;
|
||||
}
|
||||
|
||||
if (vulkanResult != VK_SUCCESS) {
|
||||
SDL_LogWarn(
|
||||
SDL_LOG_CATEGORY_GPU,
|
||||
"vkEnumeratePhysicalDevices failed: %s",
|
||||
VkErrorMessages(vulkanResult));
|
||||
SDL_stack_free(physicalDevices);
|
||||
SDL_stack_free(physicalDeviceExtensions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Any suitable device will do, but we'd like the best
|
||||
suitableIndex = -1;
|
||||
suitableQueueFamilyIndex = 0;
|
||||
highestRank = 0;
|
||||
for (i = 0; i < physicalDeviceCount; i += 1) {
|
||||
Uint32 queueFamilyIndex;
|
||||
Uint64 deviceRank;
|
||||
|
||||
if (!VULKAN_INTERNAL_IsDeviceSuitable(
|
||||
renderer,
|
||||
features,
|
||||
physicalDevices[i],
|
||||
&physicalDeviceExtensions[i],
|
||||
&queueFamilyIndex)) {
|
||||
// Device does not meet the minimum requirements, skip it entirely
|
||||
continue;
|
||||
}
|
||||
|
||||
deviceRank = highestRank;
|
||||
if (VULKAN_INTERNAL_GetDeviceRank(
|
||||
renderer,
|
||||
physicalDevices[i],
|
||||
&physicalDeviceExtensions[i],
|
||||
&deviceRank)) {
|
||||
/* Use this for rendering.
|
||||
* Note that this may override a previous device that
|
||||
* supports rendering, but shares the same device rank.
|
||||
*/
|
||||
suitableIndex = i;
|
||||
suitableQueueFamilyIndex = queueFamilyIndex;
|
||||
highestRank = deviceRank;
|
||||
}
|
||||
}
|
||||
|
||||
if (suitableIndex != -1) {
|
||||
renderer->supports = physicalDeviceExtensions[suitableIndex];
|
||||
renderer->physicalDevice = physicalDevices[suitableIndex];
|
||||
renderer->queueFamilyIndex = suitableQueueFamilyIndex;
|
||||
} else {
|
||||
SDL_stack_free(physicalDevices);
|
||||
SDL_stack_free(physicalDeviceExtensions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (suitableIndex != -1) {
|
||||
renderer->supports = physicalDeviceExtensions[suitableIndex];
|
||||
renderer->physicalDevice = physicalDevices[suitableIndex];
|
||||
renderer->queueFamilyIndex = suitableQueueFamilyIndex;
|
||||
} else {
|
||||
SDL_stack_free(physicalDevices);
|
||||
SDL_stack_free(physicalDeviceExtensions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
renderer->physicalDeviceProperties.sType =
|
||||
@@ -12241,8 +12366,6 @@ static Uint8 VULKAN_INTERNAL_DeterminePhysicalDevice(VulkanRenderer *renderer, V
|
||||
renderer->physicalDevice,
|
||||
&renderer->memoryProperties);
|
||||
|
||||
SDL_stack_free(physicalDevices);
|
||||
SDL_stack_free(physicalDeviceExtensions);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -12384,11 +12507,36 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
|
||||
deviceCreateInfo.pEnabledFeatures = &features->desiredVulkan10DeviceFeatures;
|
||||
}
|
||||
|
||||
vulkanResult = renderer->vkCreateDevice(
|
||||
renderer->physicalDevice,
|
||||
&deviceCreateInfo,
|
||||
NULL,
|
||||
&renderer->logicalDevice);
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
if (renderer->xrInstance) {
|
||||
XrResult xrResult;
|
||||
PFN_xrCreateVulkanDeviceKHR xrCreateVulkanDeviceKHR;
|
||||
if ((xrResult = xrGetInstanceProcAddr(renderer->xrInstance, "xrCreateVulkanDeviceKHR", (PFN_xrVoidFunction *)&xrCreateVulkanDeviceKHR)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get xrCreateVulkanDeviceKHR");
|
||||
SDL_stack_free((void *)deviceExtensions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
XrVulkanDeviceCreateInfoKHR xrDeviceCreateInfo = {XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR};
|
||||
xrDeviceCreateInfo.vulkanCreateInfo = &deviceCreateInfo;
|
||||
xrDeviceCreateInfo.systemId = renderer->xrSystemId;
|
||||
xrDeviceCreateInfo.vulkanPhysicalDevice = renderer->physicalDevice;
|
||||
xrDeviceCreateInfo.pfnGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();
|
||||
SDL_assert(xrDeviceCreateInfo.pfnGetInstanceProcAddr);
|
||||
if ((xrResult = xrCreateVulkanDeviceKHR(renderer->xrInstance, &xrDeviceCreateInfo, &renderer->logicalDevice, &vulkanResult)) != XR_SUCCESS) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create OpenXR Vulkan logical device, result %d, %d", xrResult, vulkanResult);
|
||||
SDL_stack_free((void *)deviceExtensions);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
{
|
||||
vulkanResult = renderer->vkCreateDevice(
|
||||
renderer->physicalDevice,
|
||||
&deviceCreateInfo,
|
||||
NULL,
|
||||
&renderer->logicalDevice);
|
||||
}
|
||||
SDL_stack_free((void *)deviceExtensions);
|
||||
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateDevice, 0);
|
||||
|
||||
@@ -12487,6 +12635,67 @@ static bool VULKAN_INTERNAL_PrepareVulkan(
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
static bool VULKAN_INTERNAL_SearchForOpenXrGpuExtension(XrExtensionProperties *found_extension)
|
||||
{
|
||||
XrResult result;
|
||||
Uint32 extension_count;
|
||||
Uint32 i;
|
||||
|
||||
result = xrEnumerateInstanceExtensionProperties(NULL, 0, &extension_count, NULL);
|
||||
if (result != XR_SUCCESS)
|
||||
return false;
|
||||
|
||||
XrExtensionProperties *extension_properties = (XrExtensionProperties *)SDL_calloc(extension_count, sizeof(XrExtensionProperties));
|
||||
for (i = 0; i < extension_count; i++)
|
||||
extension_properties[i] = (XrExtensionProperties){XR_TYPE_EXTENSION_PROPERTIES};
|
||||
|
||||
result = xrEnumerateInstanceExtensionProperties(NULL, extension_count, &extension_count, extension_properties);
|
||||
if (result != XR_SUCCESS) {
|
||||
SDL_free(extension_properties);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < extension_count; i++) {
|
||||
XrExtensionProperties extension = extension_properties[i];
|
||||
|
||||
// NOTE: as generally recommended, we support KHR_vulkan_enable2 *only*
|
||||
// see https://fredemmott.com/blog/2024/11/25/best-practices-for-openxr-api-layers.html
|
||||
if (SDL_strcmp(extension.extensionName, XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME) == 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Found " XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME " extension");
|
||||
|
||||
*found_extension = extension;
|
||||
|
||||
SDL_free(extension_properties);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(extension_properties);
|
||||
return false;
|
||||
}
|
||||
|
||||
static XrResult VULKAN_INTERNAL_GetXrMinimumVulkanApiVersion(XrVersion *minimumVulkanApiVersion, XrInstance instance, XrSystemId systemId)
|
||||
{
|
||||
XrResult xrResult;
|
||||
|
||||
PFN_xrGetVulkanGraphicsRequirements2KHR xrGetVulkanGraphicsRequirements2KHR;
|
||||
if ((xrResult = xrGetInstanceProcAddr(instance, "xrGetVulkanGraphicsRequirements2KHR", (PFN_xrVoidFunction *)&xrGetVulkanGraphicsRequirements2KHR)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get xrGetVulkanGraphicsRequirements2KHR");
|
||||
return xrResult;
|
||||
}
|
||||
|
||||
XrGraphicsRequirementsVulkanKHR graphicsRequirementsVulkan = {XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR};
|
||||
if ((xrResult = xrGetVulkanGraphicsRequirements2KHR(instance, systemId, &graphicsRequirementsVulkan)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get vulkan graphics requirements, got OpenXR error %d", xrResult);
|
||||
return xrResult;
|
||||
}
|
||||
|
||||
*minimumVulkanApiVersion = graphicsRequirementsVulkan.minApiVersionSupported;
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
{
|
||||
// Set up dummy VulkanRenderer
|
||||
@@ -12506,6 +12715,79 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult xrResult;
|
||||
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_BOOLEAN, false);
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android/Quest, don't test XR in PrepareDriver. The Quest OpenXR runtime
|
||||
* can't handle having its instance created and destroyed during preparation
|
||||
* and then recreated during device creation. Just return true for XR mode
|
||||
* and let CreateDevice do the real work. */
|
||||
if (xr) {
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (xr) {
|
||||
if (!SDL_OpenXR_LoadLibrary()) {
|
||||
SDL_SetError("Failed to load OpenXR loader or a required symbol");
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
|
||||
XrExtensionProperties gpuExtension;
|
||||
if (!VULKAN_INTERNAL_SearchForOpenXrGpuExtension(&gpuExtension)) {
|
||||
SDL_SetError("Failed to find a suitable OpenXR GPU extension.");
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *extensionName = gpuExtension.extensionName;
|
||||
if ((xrResult = xrCreateInstance(&(XrInstanceCreateInfo){
|
||||
.type = XR_TYPE_INSTANCE_CREATE_INFO,
|
||||
.applicationInfo = {
|
||||
.apiVersion = SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_VERSION_NUMBER, XR_API_VERSION_1_0),
|
||||
.applicationName = "SDL",
|
||||
},
|
||||
.enabledExtensionCount = 1,
|
||||
.enabledExtensionNames = &extensionName,
|
||||
},
|
||||
&xrInstance)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to create OpenXR instance");
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
|
||||
instancePfns = SDL_OPENXR_LoadInstanceSymbols(xrInstance);
|
||||
if (!instancePfns) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to load needed OpenXR instance symbols");
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((xrResult = instancePfns->xrGetSystem(xrInstance, &(XrSystemGetInfo){
|
||||
.type = XR_TYPE_SYSTEM_GET_INFO,
|
||||
.formFactor = (XrFormFactor)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_FORM_FACTOR_NUMBER, XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY),
|
||||
},
|
||||
&xrSystemId)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get OpenXR system");
|
||||
instancePfns->xrDestroyInstance(xrInstance);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
SDL_free(instancePfns);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
|
||||
if (renderer) {
|
||||
// This needs to be set early for log filtering
|
||||
@@ -12513,11 +12795,44 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
|
||||
renderer->preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN, false);
|
||||
|
||||
renderer->minimumVkVersion = VK_API_VERSION_1_0;
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
renderer->xrInstance = xrInstance;
|
||||
renderer->xrSystemId = xrSystemId;
|
||||
|
||||
if (xr) {
|
||||
XrVersion minimumVkVersionXr;
|
||||
xrResult = VULKAN_INTERNAL_GetXrMinimumVulkanApiVersion(&minimumVkVersionXr, xrInstance, xrSystemId);
|
||||
if (xrResult != XR_SUCCESS) {
|
||||
SDL_SetError("Failed to get the minimum supported Vulkan API version.");
|
||||
instancePfns->xrDestroyInstance(xrInstance);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
SDL_free(instancePfns);
|
||||
SDL_free(renderer);
|
||||
return false;
|
||||
}
|
||||
renderer->minimumVkVersion = VK_MAKE_API_VERSION(
|
||||
0,
|
||||
XR_VERSION_MAJOR(minimumVkVersionXr),
|
||||
XR_VERSION_MINOR(minimumVkVersionXr),
|
||||
XR_VERSION_PATCH(minimumVkVersionXr));
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
result = VULKAN_INTERNAL_PrepareVulkan(renderer, &features, props);
|
||||
if (result) {
|
||||
renderer->vkDestroyInstance(renderer->instance, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
if (instancePfns) {
|
||||
instancePfns->xrDestroyInstance(xrInstance);
|
||||
SDL_free(instancePfns);
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
SDL_free(renderer);
|
||||
}
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
@@ -12525,6 +12840,278 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
return result;
|
||||
}
|
||||
|
||||
static XrResult VULKAN_DestroyXRSwapchain(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSwapchain swapchain,
|
||||
SDL_GPUTexture **swapchainImages)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult result;
|
||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||
|
||||
VULKAN_Wait(driverData);
|
||||
|
||||
Uint32 swapchainCount;
|
||||
result = renderer->xr->xrEnumerateSwapchainImages(swapchain, 0, &swapchainCount, NULL);
|
||||
if (result != XR_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// We always want to destroy the swapchain images, so don't early return if xrDestroySwapchain fails for some reason
|
||||
for (Uint32 i = 0; i < swapchainCount; i++) {
|
||||
VulkanTextureContainer *container = (VulkanTextureContainer *)swapchainImages[i];
|
||||
|
||||
if (!container->externallyManaged) {
|
||||
SDL_SetError("Invalid GPU Texture handle.");
|
||||
return XR_ERROR_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
VULKAN_INTERNAL_DestroyTexture(renderer, container->activeTexture);
|
||||
|
||||
// Free the container now that it's unused
|
||||
SDL_free(container);
|
||||
}
|
||||
|
||||
SDL_free(swapchainImages);
|
||||
|
||||
return renderer->xr->xrDestroySwapchain(swapchain);
|
||||
#else
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
static bool VULKAN_INTERNAL_FindXRSrgbSwapchain(int64_t *supportedFormats, Uint32 numFormats, SDL_GPUTextureFormat *sdlFormat, int64_t *vkFormat)
|
||||
{
|
||||
for (Uint32 i = 0; i < SDL_arraysize(SDLToVK_TextureFormat_SrgbOnly); i++) {
|
||||
for (Uint32 j = 0; j < numFormats; j++) {
|
||||
if (SDLToVK_TextureFormat_SrgbOnly[i].vk == supportedFormats[j]) {
|
||||
*sdlFormat = SDLToVK_TextureFormat_SrgbOnly[i].sdl;
|
||||
*vkFormat = SDLToVK_TextureFormat_SrgbOnly[i].vk;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
static SDL_GPUTextureFormat* VULKAN_GetXRSwapchainFormats(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
int *num_formats)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult result;
|
||||
Uint32 i, j, num_supported_formats;
|
||||
int64_t *supported_formats;
|
||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||
|
||||
result = renderer->xr->xrEnumerateSwapchainFormats(session, 0, &num_supported_formats, NULL);
|
||||
if (result != XR_SUCCESS) return NULL;
|
||||
supported_formats = SDL_stack_alloc(int64_t, num_supported_formats);
|
||||
result = renderer->xr->xrEnumerateSwapchainFormats(session, num_supported_formats, &num_supported_formats, supported_formats);
|
||||
if (result != XR_SUCCESS) {
|
||||
SDL_stack_free(supported_formats);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FIXME: For now we're just searching for the optimal format, not all supported formats.
|
||||
// FIXME: Expand this search for all SDL_GPU formats!
|
||||
|
||||
SDL_GPUTextureFormat sdlFormat;
|
||||
int64_t vkFormat = VK_FORMAT_UNDEFINED;
|
||||
// The OpenXR spec recommends applications not submit linear data, so let's try to explicitly find an sRGB swapchain before we search the whole list
|
||||
if (!VULKAN_INTERNAL_FindXRSrgbSwapchain(supported_formats, num_supported_formats, &sdlFormat, &vkFormat)) {
|
||||
// Iterate over all formats the runtime supports
|
||||
for (i = 0; i < num_supported_formats && vkFormat == VK_FORMAT_UNDEFINED; i++) {
|
||||
// Iterate over all formats we support
|
||||
for (j = 0; j < SDL_arraysize(SDLToVK_TextureFormat); j++) {
|
||||
// Pick the first format the runtime wants that we also support, the runtime should return these in order of preference
|
||||
if (SDLToVK_TextureFormat[j] == supported_formats[i]) {
|
||||
vkFormat = supported_formats[i];
|
||||
sdlFormat = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_stack_free(supported_formats);
|
||||
|
||||
if (vkFormat == VK_FORMAT_UNDEFINED) {
|
||||
SDL_SetError("Failed to find a swapchain format supported by both OpenXR and SDL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPUTextureFormat *retval = (SDL_GPUTextureFormat*) SDL_malloc(sizeof(SDL_GPUTextureFormat) * 2);
|
||||
retval[0] = sdlFormat;
|
||||
retval[1] = SDL_GPU_TEXTUREFORMAT_INVALID;
|
||||
*num_formats = 1;
|
||||
return retval;
|
||||
#else
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static XrResult VULKAN_CreateXRSwapchain(
|
||||
SDL_GPURenderer *driverData,
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo *oldCreateInfo,
|
||||
SDL_GPUTextureFormat format,
|
||||
XrSwapchain *swapchain,
|
||||
SDL_GPUTexture ***textures)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
XrResult result;
|
||||
Uint32 i, j;
|
||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||
|
||||
XrSwapchainCreateInfo createInfo = *oldCreateInfo;
|
||||
createInfo.format = SDLToVK_TextureFormat[format];
|
||||
|
||||
result = renderer->xr->xrCreateSwapchain(session, &createInfo, swapchain);
|
||||
if (result != XR_SUCCESS) return result;
|
||||
|
||||
Uint32 swapchainImageCount;
|
||||
result = renderer->xr->xrEnumerateSwapchainImages(*swapchain, 0, &swapchainImageCount, NULL);
|
||||
if (result != XR_SUCCESS) return result;
|
||||
|
||||
XrSwapchainImageVulkan2KHR *swapchainImages = (XrSwapchainImageVulkan2KHR *)SDL_calloc(swapchainImageCount, sizeof(XrSwapchainImageVulkan2KHR));
|
||||
for (i = 0; i < swapchainImageCount; i++) swapchainImages[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR;
|
||||
|
||||
result = renderer->xr->xrEnumerateSwapchainImages(*swapchain, swapchainImageCount, &swapchainImageCount, (XrSwapchainImageBaseHeader *)swapchainImages);
|
||||
if (result != XR_SUCCESS) {
|
||||
SDL_free(swapchainImages);
|
||||
return result;
|
||||
}
|
||||
|
||||
VulkanTextureContainer **textureContainers = (VulkanTextureContainer **)SDL_calloc(swapchainImageCount, sizeof(VulkanTextureContainer *));
|
||||
|
||||
for (Uint32 idx = 0; idx < swapchainImageCount; idx++) {
|
||||
VkImage vkImage = swapchainImages[idx].image;
|
||||
|
||||
VulkanTexture *texture = SDL_calloc(1, sizeof(VulkanTexture));
|
||||
|
||||
texture->swizzle = SwizzleForSDLFormat(format);
|
||||
texture->depth = 1;
|
||||
texture->usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
SDL_SetAtomicInt(&texture->referenceCount, 0);
|
||||
texture->image = vkImage;
|
||||
texture->externallyManaged = true;
|
||||
texture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
texture->subresourceCount = createInfo.arraySize * createInfo.mipCount;
|
||||
texture->subresources = SDL_calloc(
|
||||
texture->subresourceCount,
|
||||
sizeof(VulkanTextureSubresource));
|
||||
|
||||
for (i = 0; i < createInfo.arraySize; i += 1) {
|
||||
for (j = 0; j < createInfo.mipCount; j += 1) {
|
||||
Uint32 subresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
|
||||
j,
|
||||
i,
|
||||
createInfo.mipCount);
|
||||
|
||||
if (createInfo.usageFlags & XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
texture->subresources[subresourceIndex].renderTargetViews = SDL_malloc(sizeof(VkImageView));
|
||||
|
||||
if (!VULKAN_INTERNAL_CreateRenderTargetView(
|
||||
renderer,
|
||||
texture,
|
||||
i,
|
||||
j,
|
||||
SDLToVK_TextureFormat[format],
|
||||
texture->swizzle,
|
||||
&texture->subresources[subresourceIndex].renderTargetViews[0])) {
|
||||
VULKAN_INTERNAL_DestroyTexture(renderer, texture);
|
||||
SDL_SetError("Failed to create render target view");
|
||||
return XR_ERROR_RUNTIME_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
texture->subresources[subresourceIndex].parent = texture;
|
||||
texture->subresources[subresourceIndex].layer = i;
|
||||
texture->subresources[subresourceIndex].level = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Transition to the default barrier state
|
||||
VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
|
||||
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
||||
renderer,
|
||||
barrierCommandBuffer,
|
||||
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
||||
texture);
|
||||
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
|
||||
VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer);
|
||||
|
||||
textureContainers[idx] = SDL_malloc(sizeof(VulkanTextureContainer));
|
||||
VulkanTextureContainer *container = textureContainers[idx];
|
||||
SDL_zero(container->header.info);
|
||||
container->header.info.width = createInfo.width;
|
||||
container->header.info.height = createInfo.height;
|
||||
container->header.info.format = format;
|
||||
container->header.info.layer_count_or_depth = createInfo.arraySize;
|
||||
container->header.info.num_levels = createInfo.mipCount;
|
||||
container->header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
container->header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
|
||||
container->externallyManaged = true;
|
||||
container->canBeCycled = false;
|
||||
container->activeTexture = texture;
|
||||
container->textureCapacity = 1;
|
||||
container->textureCount = 1;
|
||||
container->textures = SDL_malloc(
|
||||
container->textureCapacity * sizeof(VulkanTexture *));
|
||||
container->textures[0] = container->activeTexture;
|
||||
container->debugName = NULL;
|
||||
}
|
||||
|
||||
*textures = (SDL_GPUTexture **)textureContainers;
|
||||
|
||||
SDL_free(swapchainImages);
|
||||
return XR_SUCCESS;
|
||||
#else
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static XrResult VULKAN_CreateXRSession(
|
||||
SDL_GPURenderer *driverData,
|
||||
const XrSessionCreateInfo *createinfo,
|
||||
XrSession *session)
|
||||
{
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||
|
||||
// Copy out the existing next ptr so that we can append it to the end of the chain we create
|
||||
const void *XR_MAY_ALIAS currentNextPtr = createinfo->next;
|
||||
|
||||
// KHR_vulkan_enable and KHR_vulkan_enable2 share this structure, so we don't need to change any logic here to handle both
|
||||
XrGraphicsBindingVulkanKHR graphicsBinding = {XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR};
|
||||
graphicsBinding.instance = renderer->instance;
|
||||
graphicsBinding.physicalDevice = renderer->physicalDevice;
|
||||
graphicsBinding.device = renderer->logicalDevice;
|
||||
graphicsBinding.queueFamilyIndex = renderer->queueFamilyIndex;
|
||||
graphicsBinding.queueIndex = 0; // we only ever have one queue, so hardcode queue index 0
|
||||
graphicsBinding.next = currentNextPtr;
|
||||
|
||||
XrSessionCreateInfo sessionCreateInfo = *createinfo;
|
||||
sessionCreateInfo.systemId = renderer->xrSystemId;
|
||||
sessionCreateInfo.next = &graphicsBinding;
|
||||
|
||||
return renderer->xr->xrCreateSession(renderer->xrInstance, &sessionCreateInfo, session);
|
||||
#else
|
||||
SDL_SetError("SDL not built with OpenXR support");
|
||||
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props)
|
||||
{
|
||||
VulkanRenderer *renderer;
|
||||
@@ -12552,9 +13139,83 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
||||
renderer->debugMode = debugMode;
|
||||
renderer->preferLowPower = preferLowPower;
|
||||
renderer->allowedFramesInFlight = 2;
|
||||
renderer->minimumVkVersion = VK_API_VERSION_1_0;
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
bool xr = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENABLE_BOOLEAN, false);
|
||||
XrInstance *xrInstance = SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_INSTANCE_POINTER, NULL);
|
||||
XrSystemId *xrSystemId = SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_SYSTEM_ID_POINTER, NULL);
|
||||
|
||||
if (xr) {
|
||||
XrExtensionProperties gpuExtension;
|
||||
|
||||
if (!xrInstance) {
|
||||
SDL_SetError("You must specify an out pointer for the OpenXR instance");
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!xrSystemId) {
|
||||
SDL_SetError("You must specify an out pointer for the OpenXR system ID");
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!SDL_OpenXR_LoadLibrary()) {
|
||||
SDL_assert(!"This should have failed in PrepareDevice first!");
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!VULKAN_INTERNAL_SearchForOpenXrGpuExtension(&gpuExtension)) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to find a compatible OpenXR vulkan extension");
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!SDL_OPENXR_INTERNAL_GPUInitOpenXR(debugMode, gpuExtension, props, xrInstance, xrSystemId, &renderer->xr)) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to init OpenXR");
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer->xrInstance = *xrInstance;
|
||||
renderer->xrSystemId = *xrSystemId;
|
||||
|
||||
XrVersion minimumVulkanApiVersion;
|
||||
if (VULKAN_INTERNAL_GetXrMinimumVulkanApiVersion(&minimumVulkanApiVersion, *xrInstance, *xrSystemId) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get OpenXR graphics requirements");
|
||||
renderer->xr->xrDestroyInstance(*xrInstance);
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
SDL_free(renderer->xr);
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer->minimumVkVersion = VK_MAKE_VERSION(
|
||||
XR_VERSION_MAJOR(minimumVulkanApiVersion),
|
||||
XR_VERSION_MINOR(minimumVulkanApiVersion),
|
||||
XR_VERSION_PATCH(minimumVulkanApiVersion));
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
|
||||
if (!VULKAN_INTERNAL_PrepareVulkan(renderer, &features, props)) {
|
||||
SET_STRING_ERROR("Failed to initialize Vulkan!");
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
if (xr) {
|
||||
renderer->xr->xrDestroyInstance(*xrInstance);
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
SDL_free(renderer->xr);
|
||||
}
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
return NULL;
|
||||
|
||||
199
src/gpu/xr/SDL_gpu_openxr.c
Normal file
199
src/gpu/xr/SDL_gpu_openxr.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
|
||||
#include "SDL_gpu_openxr.h"
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
#include "../../core/android/SDL_android.h"
|
||||
#endif
|
||||
|
||||
#define VALIDATION_LAYER_API_NAME "XR_APILAYER_LUNARG_core_validation"
|
||||
|
||||
/* On Android, the OpenXR loader is initialized by SDL_OpenXR_LoadLibrary() in SDL_openxrdyn.c
|
||||
* which must be called before this. That function handles the complex initialization using
|
||||
* direct SDL_LoadFunction calls to avoid issues with xrGetInstanceProcAddr from runtime
|
||||
* negotiation not supporting pre-instance calls. This stub is kept for API compatibility. */
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
static bool SDL_OPENXR_INTERNAL_InitializeAndroidLoader(void)
|
||||
{
|
||||
/* The loader should already be initialized by SDL_OpenXR_LoadLibrary().
|
||||
* We just verify that xrGetInstanceProcAddr is available. */
|
||||
if (xrGetInstanceProcAddr == NULL) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "xrGetInstanceProcAddr is NULL - SDL_OpenXR_LoadLibrary was not called first");
|
||||
return false;
|
||||
}
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Android OpenXR loader verified (was initialized by SDL_OpenXR_LoadLibrary)");
|
||||
return true;
|
||||
}
|
||||
#endif /* SDL_PLATFORM_ANDROID */
|
||||
|
||||
bool SDL_OPENXR_INTERNAL_ValidationLayerAvailable()
|
||||
{
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android/Quest, the xrGetInstanceProcAddr obtained through runtime negotiation
|
||||
* crashes when used for pre-instance global functions. Skip validation layer check. */
|
||||
return false;
|
||||
#endif
|
||||
|
||||
Uint32 apiLayerCount;
|
||||
if (XR_FAILED(xrEnumerateApiLayerProperties(0, &apiLayerCount, NULL))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (apiLayerCount <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XrApiLayerProperties *apiLayerProperties = SDL_stack_alloc(XrApiLayerProperties, apiLayerCount);
|
||||
if (XR_FAILED(xrEnumerateApiLayerProperties(apiLayerCount, &apiLayerCount, apiLayerProperties))) {
|
||||
SDL_stack_free(apiLayerProperties);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (Uint32 i = 0; i < apiLayerCount; i++) {
|
||||
XrApiLayerProperties apiLayer = apiLayerProperties[i];
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "api layer available: %s", apiLayer.layerName);
|
||||
if (SDL_strcmp(apiLayer.layerName, VALIDATION_LAYER_API_NAME) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_stack_free(apiLayerProperties);
|
||||
return found;
|
||||
}
|
||||
|
||||
XrResult SDL_OPENXR_INTERNAL_GPUInitOpenXR(
|
||||
bool debugMode,
|
||||
XrExtensionProperties gpuExtension,
|
||||
SDL_PropertiesID props,
|
||||
XrInstance *instance,
|
||||
XrSystemId *systemId,
|
||||
XrInstancePfns **xr)
|
||||
{
|
||||
XrResult xrResult;
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
// Android requires loader initialization before any other XR calls
|
||||
if (!SDL_OPENXR_INTERNAL_InitializeAndroidLoader()) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to initialize Android OpenXR loader");
|
||||
return XR_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool validationLayersAvailable = SDL_OPENXR_INTERNAL_ValidationLayerAvailable();
|
||||
|
||||
Uint32 userApiLayerCount = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_COUNT_NUMBER, 0);
|
||||
const char *const *userApiLayerNames = SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_NAMES_POINTER, NULL);
|
||||
|
||||
Uint32 userExtensionCount = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_COUNT_NUMBER, 0);
|
||||
const char *const *userExtensionNames = SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_NAMES_POINTER, NULL);
|
||||
|
||||
// allocate enough space for the validation layer + the user's api layers
|
||||
const char **apiLayerNames = SDL_stack_alloc(const char *, userApiLayerCount + 1);
|
||||
SDL_memcpy(apiLayerNames, userApiLayerNames, sizeof(const char *) * (userApiLayerCount));
|
||||
apiLayerNames[userApiLayerCount] = VALIDATION_LAYER_API_NAME;
|
||||
|
||||
// On Android, we need an extra extension for android_create_instance
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
const Uint32 platformExtensionCount = 2; // GPU extension + Android create instance
|
||||
#else
|
||||
const Uint32 platformExtensionCount = 1; // GPU extension only
|
||||
#endif
|
||||
|
||||
const char **extensionNames = SDL_stack_alloc(const char *, userExtensionCount + platformExtensionCount);
|
||||
SDL_memcpy(extensionNames, userExtensionNames, sizeof(const char *) * (userExtensionCount));
|
||||
extensionNames[userExtensionCount] = gpuExtension.extensionName;
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
extensionNames[userExtensionCount + 1] = XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME;
|
||||
#endif
|
||||
|
||||
XrInstanceCreateInfo xrInstanceCreateInfo = { XR_TYPE_INSTANCE_CREATE_INFO };
|
||||
xrInstanceCreateInfo.applicationInfo.apiVersion = SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_VERSION_NUMBER, XR_API_VERSION_1_0);
|
||||
xrInstanceCreateInfo.enabledApiLayerCount = userApiLayerCount + ((debugMode && validationLayersAvailable) ? 1 : 0); // in debug mode, we enable the validation layer
|
||||
xrInstanceCreateInfo.enabledApiLayerNames = apiLayerNames;
|
||||
xrInstanceCreateInfo.enabledExtensionCount = userExtensionCount + platformExtensionCount;
|
||||
xrInstanceCreateInfo.enabledExtensionNames = extensionNames;
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
// Get JNI environment and JavaVM for Android instance creation
|
||||
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
|
||||
JavaVM *vm = NULL;
|
||||
if (env) {
|
||||
(*env)->GetJavaVM(env, &vm);
|
||||
}
|
||||
void *activity = SDL_GetAndroidActivity();
|
||||
|
||||
XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = { XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR };
|
||||
instanceCreateInfoAndroid.applicationVM = vm;
|
||||
instanceCreateInfoAndroid.applicationActivity = activity;
|
||||
xrInstanceCreateInfo.next = &instanceCreateInfoAndroid;
|
||||
#endif
|
||||
|
||||
const char *applicationName = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_NAME_STRING, "SDL Application");
|
||||
Uint32 applicationVersion = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_VERSION_NUMBER, 0);
|
||||
|
||||
SDL_strlcpy(xrInstanceCreateInfo.applicationInfo.applicationName, applicationName, XR_MAX_APPLICATION_NAME_SIZE);
|
||||
xrInstanceCreateInfo.applicationInfo.applicationVersion = applicationVersion;
|
||||
|
||||
const char *engineName = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_NAME_STRING, "SDLGPU");
|
||||
uint32_t engineVersion = (uint32_t)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_VERSION_NUMBER, SDL_VERSION);
|
||||
|
||||
SDL_strlcpy(xrInstanceCreateInfo.applicationInfo.engineName, engineName, XR_MAX_APPLICATION_NAME_SIZE);
|
||||
xrInstanceCreateInfo.applicationInfo.engineVersion = engineVersion;
|
||||
|
||||
if ((xrResult = xrCreateInstance(&xrInstanceCreateInfo, instance)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to create OpenXR instance");
|
||||
SDL_stack_free(apiLayerNames);
|
||||
SDL_stack_free(extensionNames);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_stack_free(apiLayerNames);
|
||||
SDL_stack_free(extensionNames);
|
||||
|
||||
*xr = SDL_OPENXR_LoadInstanceSymbols(*instance);
|
||||
if (!*xr) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to load required OpenXR instance symbols");
|
||||
/* NOTE: we can't actually destroy the created OpenXR instance here,
|
||||
as we only get that function pointer by loading the instance symbols...
|
||||
let's just hope that doesn't happen. */
|
||||
return false;
|
||||
}
|
||||
|
||||
XrSystemGetInfo systemGetInfo = { XR_TYPE_SYSTEM_GET_INFO };
|
||||
systemGetInfo.formFactor = (XrFormFactor)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_FORM_FACTOR_NUMBER, XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY);
|
||||
if ((xrResult = (*xr)->xrGetSystem(*instance, &systemGetInfo, systemId)) != XR_SUCCESS) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get OpenXR system");
|
||||
(*xr)->xrDestroyInstance(*instance);
|
||||
SDL_free(*xr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* HAVE_GPU_OPENXR */
|
||||
30
src/gpu/xr/SDL_gpu_openxr.h
Normal file
30
src/gpu/xr/SDL_gpu_openxr.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_openxrdyn.h"
|
||||
|
||||
XrResult SDL_OPENXR_INTERNAL_GPUInitOpenXR(
|
||||
bool debugMode,
|
||||
XrExtensionProperties gpuExtension,
|
||||
SDL_PropertiesID props,
|
||||
XrInstance *instance,
|
||||
XrSystemId *systemId,
|
||||
XrInstancePfns **xr);
|
||||
52
src/gpu/xr/SDL_openxr_internal.h
Normal file
52
src/gpu/xr/SDL_openxr_internal.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This internal header provides access to the vendored OpenXR headers
|
||||
* without requiring include path modifications in project files.
|
||||
* Similar to SDL_vulkan_internal.h for Vulkan headers.
|
||||
*/
|
||||
|
||||
#ifndef SDL_openxr_internal_h_
|
||||
#define SDL_openxr_internal_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* Define platform-specific OpenXR macros BEFORE including openxr headers */
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
#include <jni.h>
|
||||
#define XR_USE_PLATFORM_ANDROID
|
||||
#endif
|
||||
|
||||
/* Include the vendored OpenXR headers using relative path */
|
||||
#include "../../video/khronos/openxr/openxr.h"
|
||||
#include "../../video/khronos/openxr/openxr_platform.h"
|
||||
|
||||
/* Compatibility: XR_API_VERSION_1_0 was added in OpenXR 1.1.x */
|
||||
#ifndef XR_API_VERSION_1_0
|
||||
#define XR_API_VERSION_1_0 XR_MAKE_VERSION(1, 0, XR_VERSION_PATCH(XR_CURRENT_API_VERSION))
|
||||
#endif
|
||||
|
||||
#define SDL_OPENXR_CHECK_VERSION(x, y, z) \
|
||||
(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION) > x || \
|
||||
(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION) == x && XR_VERSION_MINOR(XR_CURRENT_API_VERSION) > y) || \
|
||||
(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION) == x && XR_VERSION_MINOR(XR_CURRENT_API_VERSION) == y && XR_VERSION_PATCH(XR_CURRENT_API_VERSION) >= z))
|
||||
|
||||
#endif /* SDL_openxr_internal_h_ */
|
||||
414
src/gpu/xr/SDL_openxrdyn.c
Normal file
414
src/gpu/xr/SDL_openxrdyn.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_openxrdyn.h"
|
||||
|
||||
#ifdef HAVE_GPU_OPENXR
|
||||
|
||||
#include <SDL3/SDL_dlopennote.h>
|
||||
|
||||
#if defined(SDL_PLATFORM_APPLE)
|
||||
static const char *openxr_library_names[] = { "libopenxr_loader.dylib", NULL };
|
||||
#elif defined(SDL_PLATFORM_WINDOWS)
|
||||
static const char *openxr_library_names[] = { "openxr_loader.dll", NULL };
|
||||
#elif defined(SDL_PLATFORM_ANDROID)
|
||||
/* On Android, use the Khronos OpenXR loader (libopenxr_loader.so) which properly
|
||||
* exports xrGetInstanceProcAddr. This is bundled via the Gradle dependency:
|
||||
* implementation 'org.khronos.openxr:openxr_loader_for_android:X.Y.Z'
|
||||
*
|
||||
* The Khronos loader handles runtime discovery internally via the Android broker
|
||||
* pattern and properly supports all pre-instance global functions.
|
||||
*
|
||||
* Note: Do NOT use Meta's forwardloader (libopenxr_forwardloader.so) - it doesn't
|
||||
* export xrGetInstanceProcAddr directly and the function obtained via runtime
|
||||
* negotiation crashes on pre-instance calls (e.g., xrEnumerateApiLayerProperties). */
|
||||
static const char *openxr_library_names[] = { "libopenxr_loader.so", NULL };
|
||||
#else
|
||||
static const char *openxr_library_names[] = { "libopenxr_loader.so.1", "libopenxr_loader.so", NULL };
|
||||
SDL_ELF_NOTE_DLOPEN(
|
||||
"gpu-openxr",
|
||||
"Support for OpenXR with SDL_GPU rendering",
|
||||
SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
|
||||
"libopenxr_loader.so.1", "libopenxr_loader.so"
|
||||
)
|
||||
#endif
|
||||
|
||||
#define DEBUG_DYNAMIC_OPENXR 0
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_SharedObject *lib;
|
||||
} openxrdynlib;
|
||||
|
||||
static openxrdynlib openxr_loader = { NULL };
|
||||
|
||||
#ifndef SDL_PLATFORM_ANDROID
|
||||
static void *OPENXR_GetSym(const char *fnname, bool *failed)
|
||||
{
|
||||
void *fn = SDL_LoadFunction(openxr_loader.lib, fnname);
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
if (fn) {
|
||||
SDL_Log("OPENXR: Found '%s' in %s (%p)\n", fnname, dynlib->libname, fn);
|
||||
} else {
|
||||
SDL_Log("OPENXR: Symbol '%s' NOT FOUND!\n", fnname);
|
||||
}
|
||||
#endif
|
||||
|
||||
return fn;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define all the function pointers and wrappers...
|
||||
#define SDL_OPENXR_SYM(name) PFN_##name OPENXR_##name = NULL;
|
||||
#include "SDL_openxrsym.h"
|
||||
|
||||
static int openxr_load_refcount = 0;
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
#include <jni.h>
|
||||
#include "../../video/khronos/openxr/openxr_platform.h"
|
||||
|
||||
/* On Android, we need to initialize the loader with JNI context before use */
|
||||
static bool openxr_android_loader_initialized = false;
|
||||
|
||||
static bool OPENXR_InitializeAndroidLoader(void)
|
||||
{
|
||||
XrResult result;
|
||||
PFN_xrInitializeLoaderKHR initializeLoader = NULL;
|
||||
PFN_xrGetInstanceProcAddr loaderGetProcAddr = NULL;
|
||||
JNIEnv *env = NULL;
|
||||
JavaVM *vm = NULL;
|
||||
jobject activity = NULL;
|
||||
|
||||
if (openxr_android_loader_initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The Khronos OpenXR loader (libopenxr_loader.so) properly exports xrGetInstanceProcAddr.
|
||||
* Get it directly from the library - this is the standard approach. */
|
||||
loaderGetProcAddr = (PFN_xrGetInstanceProcAddr)SDL_LoadFunction(openxr_loader.lib, "xrGetInstanceProcAddr");
|
||||
|
||||
if (loaderGetProcAddr == NULL) {
|
||||
SDL_SetError("Failed to get xrGetInstanceProcAddr from OpenXR loader. "
|
||||
"Make sure you're using the Khronos loader (libopenxr_loader.so), "
|
||||
"not Meta's forwardloader.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Got xrGetInstanceProcAddr from loader: %p", (void*)loaderGetProcAddr);
|
||||
#endif
|
||||
|
||||
/* Get xrInitializeLoaderKHR via xrGetInstanceProcAddr */
|
||||
result = loaderGetProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", (PFN_xrVoidFunction*)&initializeLoader);
|
||||
if (XR_FAILED(result) || initializeLoader == NULL) {
|
||||
SDL_SetError("Failed to get xrInitializeLoaderKHR (result: %d)", (int)result);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Got xrInitializeLoaderKHR: %p", (void*)initializeLoader);
|
||||
#endif
|
||||
|
||||
/* Get Android environment info from SDL */
|
||||
env = (JNIEnv *)SDL_GetAndroidJNIEnv();
|
||||
if (!env) {
|
||||
SDL_SetError("Failed to get Android JNI environment");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((*env)->GetJavaVM(env, &vm) != 0) {
|
||||
SDL_SetError("Failed to get JavaVM from JNIEnv");
|
||||
return false;
|
||||
}
|
||||
|
||||
activity = (jobject)SDL_GetAndroidActivity();
|
||||
if (!activity) {
|
||||
SDL_SetError("Failed to get Android activity");
|
||||
return false;
|
||||
}
|
||||
|
||||
XrLoaderInitInfoAndroidKHR loaderInitInfo = {
|
||||
.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR,
|
||||
.next = NULL,
|
||||
.applicationVM = vm,
|
||||
.applicationContext = activity
|
||||
};
|
||||
|
||||
result = initializeLoader((XrLoaderInitInfoBaseHeaderKHR *)&loaderInitInfo);
|
||||
if (XR_FAILED(result)) {
|
||||
SDL_SetError("xrInitializeLoaderKHR failed with result %d", (int)result);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: xrInitializeLoaderKHR succeeded");
|
||||
#endif
|
||||
|
||||
/* Store the xrGetInstanceProcAddr function - this one properly handles
|
||||
* all pre-instance calls (unlike Meta's forwardloader runtime negotiation) */
|
||||
OPENXR_xrGetInstanceProcAddr = loaderGetProcAddr;
|
||||
xrGetInstanceProcAddr = loaderGetProcAddr;
|
||||
|
||||
openxr_android_loader_initialized = true;
|
||||
return true;
|
||||
}
|
||||
#endif /* SDL_PLATFORM_ANDROID */
|
||||
|
||||
SDL_DECLSPEC void SDLCALL SDL_OpenXR_UnloadLibrary(void)
|
||||
{
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: UnloadLibrary called, current refcount=%d", openxr_load_refcount);
|
||||
#endif
|
||||
|
||||
// Don't actually unload if more than one module is using the libs...
|
||||
if (openxr_load_refcount > 0) {
|
||||
if (--openxr_load_refcount == 0) {
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Refcount reached 0, unloading library");
|
||||
#endif
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android/Quest, don't actually unload the library or reset the loader state.
|
||||
* The Quest OpenXR runtime doesn't support being re-initialized after teardown.
|
||||
* xrInitializeLoaderKHR and xrNegotiateLoaderRuntimeInterface must only be called once.
|
||||
* We keep the library loaded and the loader initialized.
|
||||
*
|
||||
* IMPORTANT: We also keep xrGetInstanceProcAddr intact so we can reload other
|
||||
* function pointers on the next LoadLibrary call. Only NULL out the other symbols. */
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Android - keeping library loaded and loader initialized");
|
||||
#endif
|
||||
|
||||
// Only NULL out non-essential function pointers, keep xrGetInstanceProcAddr
|
||||
#define SDL_OPENXR_SYM(name) \
|
||||
if (SDL_strcmp(#name, "xrGetInstanceProcAddr") != 0) { \
|
||||
OPENXR_##name = NULL; \
|
||||
}
|
||||
#include "SDL_openxrsym.h"
|
||||
#else
|
||||
// On non-Android, NULL everything and unload
|
||||
#define SDL_OPENXR_SYM(name) OPENXR_##name = NULL;
|
||||
#include "SDL_openxrsym.h"
|
||||
|
||||
SDL_UnloadObject(openxr_loader.lib);
|
||||
openxr_loader.lib = NULL;
|
||||
#endif
|
||||
}
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
else {
|
||||
SDL_Log("SDL/OpenXR: Refcount is now %d, not unloading", openxr_load_refcount);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// returns non-zero if all needed symbols were loaded.
|
||||
SDL_DECLSPEC bool SDLCALL SDL_OpenXR_LoadLibrary(void)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: LoadLibrary called, current refcount=%d, lib=%p", openxr_load_refcount, (void*)openxr_loader.lib);
|
||||
#endif
|
||||
|
||||
// deal with multiple modules (gpu, openxr, etc) needing these symbols...
|
||||
if (openxr_load_refcount++ == 0) {
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android, the library may already be loaded if this is a reload after
|
||||
* unload (we don't actually unload on Android to preserve runtime state) */
|
||||
if (openxr_loader.lib == NULL) {
|
||||
#endif
|
||||
const char *path_hint = SDL_GetHint(SDL_HINT_OPENXR_LIBRARY);
|
||||
|
||||
// If a hint was specified, try that first
|
||||
if (path_hint && *path_hint) {
|
||||
openxr_loader.lib = SDL_LoadObject(path_hint);
|
||||
}
|
||||
|
||||
// If no hint or hint failed, try the default library names
|
||||
if (!openxr_loader.lib) {
|
||||
for (int i = 0; openxr_library_names[i] != NULL; i++) {
|
||||
openxr_loader.lib = SDL_LoadObject(openxr_library_names[i]);
|
||||
if (openxr_loader.lib) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!openxr_loader.lib) {
|
||||
SDL_SetError("Failed loading OpenXR library");
|
||||
openxr_load_refcount--;
|
||||
return false;
|
||||
}
|
||||
#if defined(SDL_PLATFORM_ANDROID)
|
||||
} else {
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Library already loaded (Android reload), skipping SDL_LoadObject");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android, we need to initialize the loader before other functions work.
|
||||
* OPENXR_InitializeAndroidLoader() will return early if already initialized. */
|
||||
if (!OPENXR_InitializeAndroidLoader()) {
|
||||
SDL_UnloadObject(openxr_loader.lib);
|
||||
openxr_loader.lib = NULL;
|
||||
openxr_load_refcount--;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool failed = false;
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android with Meta's forwardloader, we need special handling.
|
||||
* After calling xrInitializeLoaderKHR, the global functions should be available
|
||||
* either as direct exports from the forwardloader or via xrGetInstanceProcAddr(NULL, ...).
|
||||
*
|
||||
* Try getting functions directly from the forwardloader first since they'll go
|
||||
* through the proper forwarding path. */
|
||||
XrResult xrResult;
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Loading global functions...");
|
||||
#endif
|
||||
|
||||
/* First try to get functions directly from the forwardloader library */
|
||||
OPENXR_xrEnumerateApiLayerProperties = (PFN_xrEnumerateApiLayerProperties)SDL_LoadFunction(openxr_loader.lib, "xrEnumerateApiLayerProperties");
|
||||
OPENXR_xrCreateInstance = (PFN_xrCreateInstance)SDL_LoadFunction(openxr_loader.lib, "xrCreateInstance");
|
||||
OPENXR_xrEnumerateInstanceExtensionProperties = (PFN_xrEnumerateInstanceExtensionProperties)SDL_LoadFunction(openxr_loader.lib, "xrEnumerateInstanceExtensionProperties");
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Direct symbols - xrEnumerateApiLayerProperties=%p, xrCreateInstance=%p, xrEnumerateInstanceExtensionProperties=%p",
|
||||
(void*)OPENXR_xrEnumerateApiLayerProperties,
|
||||
(void*)OPENXR_xrCreateInstance,
|
||||
(void*)OPENXR_xrEnumerateInstanceExtensionProperties);
|
||||
#endif
|
||||
|
||||
/* If direct loading failed, fall back to xrGetInstanceProcAddr(NULL, ...) */
|
||||
if (OPENXR_xrEnumerateApiLayerProperties == NULL) {
|
||||
xrResult = xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrEnumerateApiLayerProperties", (PFN_xrVoidFunction*)&OPENXR_xrEnumerateApiLayerProperties);
|
||||
if (XR_FAILED(xrResult) || OPENXR_xrEnumerateApiLayerProperties == NULL) {
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Failed to get xrEnumerateApiLayerProperties via xrGetInstanceProcAddr");
|
||||
#endif
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (OPENXR_xrCreateInstance == NULL) {
|
||||
xrResult = xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrCreateInstance", (PFN_xrVoidFunction*)&OPENXR_xrCreateInstance);
|
||||
if (XR_FAILED(xrResult) || OPENXR_xrCreateInstance == NULL) {
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Failed to get xrCreateInstance via xrGetInstanceProcAddr");
|
||||
#endif
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (OPENXR_xrEnumerateInstanceExtensionProperties == NULL) {
|
||||
xrResult = xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrEnumerateInstanceExtensionProperties", (PFN_xrVoidFunction*)&OPENXR_xrEnumerateInstanceExtensionProperties);
|
||||
if (XR_FAILED(xrResult) || OPENXR_xrEnumerateInstanceExtensionProperties == NULL) {
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Failed to get xrEnumerateInstanceExtensionProperties via xrGetInstanceProcAddr");
|
||||
#endif
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
SDL_Log("SDL/OpenXR: Final symbols - xrEnumerateApiLayerProperties=%p, xrCreateInstance=%p, xrEnumerateInstanceExtensionProperties=%p",
|
||||
(void*)OPENXR_xrEnumerateApiLayerProperties,
|
||||
(void*)OPENXR_xrCreateInstance,
|
||||
(void*)OPENXR_xrEnumerateInstanceExtensionProperties);
|
||||
|
||||
SDL_Log("SDL/OpenXR: Global functions loading %s", failed ? "FAILED" : "succeeded");
|
||||
#endif
|
||||
#else
|
||||
#define SDL_OPENXR_SYM(name) OPENXR_##name = (PFN_##name)OPENXR_GetSym(#name, &failed);
|
||||
#include "SDL_openxrsym.h"
|
||||
#endif
|
||||
|
||||
if (failed) {
|
||||
// in case something got loaded...
|
||||
SDL_OpenXR_UnloadLibrary();
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
#if DEBUG_DYNAMIC_OPENXR
|
||||
else {
|
||||
SDL_Log("SDL/OpenXR: Library already loaded (refcount=%d), skipping", openxr_load_refcount);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SDL_DECLSPEC PFN_xrGetInstanceProcAddr SDLCALL SDL_OpenXR_GetXrGetInstanceProcAddr(void)
|
||||
{
|
||||
if (xrGetInstanceProcAddr == NULL) {
|
||||
SDL_SetError("The OpenXR loader has not been loaded");
|
||||
}
|
||||
|
||||
return xrGetInstanceProcAddr;
|
||||
}
|
||||
|
||||
XrInstancePfns *SDL_OPENXR_LoadInstanceSymbols(XrInstance instance)
|
||||
{
|
||||
XrResult result;
|
||||
|
||||
XrInstancePfns *pfns = SDL_calloc(1, sizeof(XrInstancePfns));
|
||||
|
||||
#define SDL_OPENXR_INSTANCE_SYM(name) \
|
||||
result = xrGetInstanceProcAddr(instance, #name, (PFN_xrVoidFunction *)&pfns->name); \
|
||||
if (result != XR_SUCCESS) { \
|
||||
SDL_free(pfns); \
|
||||
return NULL; \
|
||||
}
|
||||
#include "SDL_openxrsym.h"
|
||||
|
||||
return pfns;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
SDL_DECLSPEC bool SDLCALL SDL_OpenXR_LoadLibrary(void)
|
||||
{
|
||||
return SDL_SetError("OpenXR is not enabled in this build of SDL");
|
||||
}
|
||||
|
||||
SDL_DECLSPEC void SDLCALL SDL_OpenXR_UnloadLibrary(void)
|
||||
{
|
||||
SDL_SetError("OpenXR is not enabled in this build of SDL");
|
||||
}
|
||||
|
||||
SDL_DECLSPEC PFN_xrGetInstanceProcAddr SDLCALL SDL_OpenXR_GetXrGetInstanceProcAddr(void)
|
||||
{
|
||||
return (PFN_xrGetInstanceProcAddr)SDL_SetError("OpenXR is not enabled in this build of SDL");
|
||||
}
|
||||
|
||||
#endif // HAVE_GPU_OPENXR
|
||||
55
src/gpu/xr/SDL_openxrdyn.h
Normal file
55
src/gpu/xr/SDL_openxrdyn.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_openxrdyn_h_
|
||||
#define SDL_openxrdyn_h_
|
||||
|
||||
/* Use the internal header for vendored OpenXR includes */
|
||||
#include "SDL_openxr_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct XrInstancePfns
|
||||
{
|
||||
#define SDL_OPENXR_INSTANCE_SYM(name) \
|
||||
PFN_##name name;
|
||||
#include "SDL_openxrsym.h"
|
||||
} XrInstancePfns;
|
||||
|
||||
extern XrInstancePfns *SDL_OPENXR_LoadInstanceSymbols(XrInstance instance);
|
||||
|
||||
/* Define the function pointers */
|
||||
#define SDL_OPENXR_SYM(name) \
|
||||
extern PFN_##name OPENXR_##name;
|
||||
#include "SDL_openxrsym.h"
|
||||
|
||||
#define xrGetInstanceProcAddr OPENXR_xrGetInstanceProcAddr
|
||||
#define xrEnumerateApiLayerProperties OPENXR_xrEnumerateApiLayerProperties
|
||||
#define xrEnumerateInstanceExtensionProperties OPENXR_xrEnumerateInstanceExtensionProperties
|
||||
#define xrCreateInstance OPENXR_xrCreateInstance
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SDL_openxrdyn_h_
|
||||
49
src/gpu/xr/SDL_openxrsym.h
Normal file
49
src/gpu/xr/SDL_openxrsym.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
|
||||
#include "../../video/khronos/openxr/openxr.h"
|
||||
|
||||
#ifndef SDL_OPENXR_SYM
|
||||
#define SDL_OPENXR_SYM(name)
|
||||
#endif
|
||||
|
||||
#ifndef SDL_OPENXR_INSTANCE_SYM
|
||||
#define SDL_OPENXR_INSTANCE_SYM(name)
|
||||
#endif
|
||||
|
||||
SDL_OPENXR_SYM(xrGetInstanceProcAddr)
|
||||
SDL_OPENXR_SYM(xrEnumerateApiLayerProperties)
|
||||
SDL_OPENXR_SYM(xrCreateInstance)
|
||||
SDL_OPENXR_SYM(xrEnumerateInstanceExtensionProperties)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrEnumerateSwapchainFormats)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrCreateSession)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrGetSystem)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrCreateSwapchain)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrEnumerateSwapchainImages)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrDestroyInstance)
|
||||
SDL_OPENXR_INSTANCE_SYM(xrDestroySwapchain)
|
||||
|
||||
#undef SDL_OPENXR_SYM
|
||||
#undef SDL_OPENXR_INSTANCE_SYM
|
||||
|
||||
/* *INDENT-ON* */ // clang-format on
|
||||
8583
src/video/khronos/openxr/openxr.h
Normal file
8583
src/video/khronos/openxr/openxr.h
Normal file
File diff suppressed because it is too large
Load Diff
141
src/video/khronos/openxr/openxr_loader_negotiation.h
Normal file
141
src/video/khronos/openxr/openxr_loader_negotiation.h
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifndef OPENXR_LOADER_NEGOTIATION_H_
|
||||
#define OPENXR_LOADER_NEGOTIATION_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2017-2025 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is generated from the Khronos OpenXR XML API Registry.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "openxr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// XR_LOADER_VERSION_1_0 is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_LOADER_VERSION_1_0 1
|
||||
|
||||
#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
|
||||
|
||||
|
||||
#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
|
||||
|
||||
|
||||
#define XR_LOADER_INFO_STRUCT_VERSION 1
|
||||
|
||||
|
||||
#define XR_API_LAYER_INFO_STRUCT_VERSION 1
|
||||
|
||||
|
||||
#define XR_RUNTIME_INFO_STRUCT_VERSION 1
|
||||
|
||||
|
||||
#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
|
||||
|
||||
|
||||
#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
|
||||
|
||||
|
||||
#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
|
||||
|
||||
|
||||
typedef enum XrLoaderInterfaceStructs {
|
||||
XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0,
|
||||
XR_LOADER_INTERFACE_STRUCT_LOADER_INFO = 1,
|
||||
XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST = 2,
|
||||
XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST = 3,
|
||||
XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO = 4,
|
||||
XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO = 5,
|
||||
XR_LOADER_INTERFACE_STRUCTS_MAX_ENUM = 0x7FFFFFFF
|
||||
} XrLoaderInterfaceStructs;
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
|
||||
|
||||
typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo;
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
|
||||
const XrInstanceCreateInfo* info,
|
||||
const XrApiLayerCreateInfo* apiLayerInfo,
|
||||
XrInstance* instance);
|
||||
|
||||
typedef struct XrApiLayerNextInfo {
|
||||
XrLoaderInterfaceStructs structType;
|
||||
uint32_t structVersion;
|
||||
size_t structSize;
|
||||
char layerName[XR_MAX_API_LAYER_NAME_SIZE];
|
||||
PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr;
|
||||
PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance;
|
||||
struct XrApiLayerNextInfo* next;
|
||||
} XrApiLayerNextInfo;
|
||||
|
||||
typedef struct XrApiLayerCreateInfo {
|
||||
XrLoaderInterfaceStructs structType;
|
||||
uint32_t structVersion;
|
||||
size_t structSize;
|
||||
void* XR_MAY_ALIAS loaderInstance;
|
||||
char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE];
|
||||
XrApiLayerNextInfo* nextInfo;
|
||||
} XrApiLayerCreateInfo;
|
||||
|
||||
typedef struct XrNegotiateLoaderInfo {
|
||||
XrLoaderInterfaceStructs structType;
|
||||
uint32_t structVersion;
|
||||
size_t structSize;
|
||||
uint32_t minInterfaceVersion;
|
||||
uint32_t maxInterfaceVersion;
|
||||
XrVersion minApiVersion;
|
||||
XrVersion maxApiVersion;
|
||||
} XrNegotiateLoaderInfo;
|
||||
|
||||
typedef struct XrNegotiateRuntimeRequest {
|
||||
XrLoaderInterfaceStructs structType;
|
||||
uint32_t structVersion;
|
||||
size_t structSize;
|
||||
uint32_t runtimeInterfaceVersion;
|
||||
XrVersion runtimeApiVersion;
|
||||
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
|
||||
} XrNegotiateRuntimeRequest;
|
||||
|
||||
typedef struct XrNegotiateApiLayerRequest {
|
||||
XrLoaderInterfaceStructs structType;
|
||||
uint32_t structVersion;
|
||||
size_t structSize;
|
||||
uint32_t layerInterfaceVersion;
|
||||
XrVersion layerApiVersion;
|
||||
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
|
||||
PFN_xrCreateApiLayerInstance createApiLayerInstance;
|
||||
} XrNegotiateApiLayerRequest;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo* info, const XrApiLayerCreateInfo* layerInfo, XrInstance* instance);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo* loaderInfo, XrNegotiateRuntimeRequest* runtimeRequest);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo* loaderInfo, const char* layerName, XrNegotiateApiLayerRequest* apiLayerRequest);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrCreateApiLayerInstance(
|
||||
const XrInstanceCreateInfo* info,
|
||||
const XrApiLayerCreateInfo* layerInfo,
|
||||
XrInstance* instance);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrNegotiateLoaderRuntimeInterface(
|
||||
const XrNegotiateLoaderInfo* loaderInfo,
|
||||
XrNegotiateRuntimeRequest* runtimeRequest);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrNegotiateLoaderApiLayerInterface(
|
||||
const XrNegotiateLoaderInfo* loaderInfo,
|
||||
const char* layerName,
|
||||
XrNegotiateApiLayerRequest* apiLayerRequest);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
776
src/video/khronos/openxr/openxr_platform.h
Normal file
776
src/video/khronos/openxr/openxr_platform.h
Normal file
@@ -0,0 +1,776 @@
|
||||
#ifndef OPENXR_PLATFORM_H_
|
||||
#define OPENXR_PLATFORM_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2017-2025 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is generated from the Khronos OpenXR XML API Registry.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "openxr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
// XR_KHR_android_thread_settings is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_android_thread_settings 1
|
||||
#define XR_KHR_android_thread_settings_SPEC_VERSION 6
|
||||
#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings"
|
||||
|
||||
typedef enum XrAndroidThreadTypeKHR {
|
||||
XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
|
||||
XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
|
||||
XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
|
||||
XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
|
||||
XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
|
||||
} XrAndroidThreadTypeKHR;
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
|
||||
XrSession session,
|
||||
XrAndroidThreadTypeKHR threadType,
|
||||
uint32_t threadId);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
// XR_KHR_android_surface_swapchain is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_android_surface_swapchain 1
|
||||
#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4
|
||||
#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain"
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
|
||||
XrSession session,
|
||||
const XrSwapchainCreateInfo* info,
|
||||
XrSwapchain* swapchain,
|
||||
jobject* surface);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
// XR_KHR_android_create_instance is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_android_create_instance 1
|
||||
#define XR_KHR_android_create_instance_SPEC_VERSION 3
|
||||
#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance"
|
||||
// XrInstanceCreateInfoAndroidKHR extends XrInstanceCreateInfo
|
||||
typedef struct XrInstanceCreateInfoAndroidKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
void* XR_MAY_ALIAS applicationVM;
|
||||
void* XR_MAY_ALIAS applicationActivity;
|
||||
} XrInstanceCreateInfoAndroidKHR;
|
||||
|
||||
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
// XR_KHR_vulkan_swapchain_format_list is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_vulkan_swapchain_format_list 1
|
||||
#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 5
|
||||
#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list"
|
||||
typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
uint32_t viewFormatCount;
|
||||
const VkFormat* viewFormats;
|
||||
} XrVulkanSwapchainFormatListCreateInfoKHR;
|
||||
|
||||
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_OPENGL
|
||||
|
||||
// XR_KHR_opengl_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_opengl_enable 1
|
||||
#define XR_KHR_opengl_enable_SPEC_VERSION 10
|
||||
#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
// XrGraphicsBindingOpenGLWin32KHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingOpenGLWin32KHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
HDC hDC;
|
||||
HGLRC hGLRC;
|
||||
} XrGraphicsBindingOpenGLWin32KHR;
|
||||
#endif // XR_USE_PLATFORM_WIN32
|
||||
|
||||
#ifdef XR_USE_PLATFORM_XLIB
|
||||
// XrGraphicsBindingOpenGLXlibKHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingOpenGLXlibKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
Display* xDisplay;
|
||||
uint32_t visualid;
|
||||
GLXFBConfig glxFBConfig;
|
||||
GLXDrawable glxDrawable;
|
||||
GLXContext glxContext;
|
||||
} XrGraphicsBindingOpenGLXlibKHR;
|
||||
#endif // XR_USE_PLATFORM_XLIB
|
||||
|
||||
#ifdef XR_USE_PLATFORM_XCB
|
||||
// XrGraphicsBindingOpenGLXcbKHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingOpenGLXcbKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
xcb_connection_t* connection;
|
||||
uint32_t screenNumber;
|
||||
xcb_glx_fbconfig_t fbconfigid;
|
||||
xcb_visualid_t visualid;
|
||||
xcb_glx_drawable_t glxDrawable;
|
||||
xcb_glx_context_t glxContext;
|
||||
} XrGraphicsBindingOpenGLXcbKHR;
|
||||
#endif // XR_USE_PLATFORM_XCB
|
||||
|
||||
#ifdef XR_USE_PLATFORM_WAYLAND
|
||||
// XrGraphicsBindingOpenGLWaylandKHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingOpenGLWaylandKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
struct wl_display* display;
|
||||
} XrGraphicsBindingOpenGLWaylandKHR;
|
||||
#endif // XR_USE_PLATFORM_WAYLAND
|
||||
|
||||
typedef struct XrSwapchainImageOpenGLKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
uint32_t image;
|
||||
} XrSwapchainImageOpenGLKHR;
|
||||
|
||||
typedef struct XrGraphicsRequirementsOpenGLKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
XrVersion minApiVersionSupported;
|
||||
XrVersion maxApiVersionSupported;
|
||||
} XrGraphicsRequirementsOpenGLKHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_OPENGL */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||
|
||||
// XR_KHR_opengl_es_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_opengl_es_enable 1
|
||||
#define XR_KHR_opengl_es_enable_SPEC_VERSION 8
|
||||
#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable"
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
// XrGraphicsBindingOpenGLESAndroidKHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
EGLDisplay display;
|
||||
EGLConfig config;
|
||||
EGLContext context;
|
||||
} XrGraphicsBindingOpenGLESAndroidKHR;
|
||||
#endif // XR_USE_PLATFORM_ANDROID
|
||||
|
||||
typedef struct XrSwapchainImageOpenGLESKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
uint32_t image;
|
||||
} XrSwapchainImageOpenGLESKHR;
|
||||
|
||||
typedef struct XrGraphicsRequirementsOpenGLESKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
XrVersion minApiVersionSupported;
|
||||
XrVersion maxApiVersionSupported;
|
||||
} XrGraphicsRequirementsOpenGLESKHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
// XR_KHR_vulkan_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_vulkan_enable 1
|
||||
#define XR_KHR_vulkan_enable_SPEC_VERSION 8
|
||||
#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
|
||||
// XrGraphicsBindingVulkanKHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingVulkanKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
VkInstance instance;
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkDevice device;
|
||||
uint32_t queueFamilyIndex;
|
||||
uint32_t queueIndex;
|
||||
} XrGraphicsBindingVulkanKHR;
|
||||
|
||||
typedef struct XrSwapchainImageVulkanKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
VkImage image;
|
||||
} XrSwapchainImageVulkanKHR;
|
||||
|
||||
typedef struct XrGraphicsRequirementsVulkanKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
XrVersion minApiVersionSupported;
|
||||
XrVersion maxApiVersionSupported;
|
||||
} XrGraphicsRequirementsVulkanKHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
uint32_t bufferCapacityInput,
|
||||
uint32_t* bufferCountOutput,
|
||||
char* buffer);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
uint32_t bufferCapacityInput,
|
||||
uint32_t* bufferCountOutput,
|
||||
char* buffer);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
VkInstance vkInstance,
|
||||
VkPhysicalDevice* vkPhysicalDevice);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_D3D11
|
||||
|
||||
// XR_KHR_D3D11_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_D3D11_enable 1
|
||||
#define XR_KHR_D3D11_enable_SPEC_VERSION 9
|
||||
#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
|
||||
// XrGraphicsBindingD3D11KHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingD3D11KHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
ID3D11Device* device;
|
||||
} XrGraphicsBindingD3D11KHR;
|
||||
|
||||
typedef struct XrSwapchainImageD3D11KHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
ID3D11Texture2D* texture;
|
||||
} XrSwapchainImageD3D11KHR;
|
||||
|
||||
typedef struct XrGraphicsRequirementsD3D11KHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
LUID adapterLuid;
|
||||
D3D_FEATURE_LEVEL minFeatureLevel;
|
||||
} XrGraphicsRequirementsD3D11KHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_D3D11 */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||
|
||||
// XR_KHR_D3D12_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_D3D12_enable 1
|
||||
#define XR_KHR_D3D12_enable_SPEC_VERSION 9
|
||||
#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
|
||||
// XrGraphicsBindingD3D12KHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingD3D12KHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
ID3D12Device* device;
|
||||
ID3D12CommandQueue* queue;
|
||||
} XrGraphicsBindingD3D12KHR;
|
||||
|
||||
typedef struct XrSwapchainImageD3D12KHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
ID3D12Resource* texture;
|
||||
} XrSwapchainImageD3D12KHR;
|
||||
|
||||
typedef struct XrGraphicsRequirementsD3D12KHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
LUID adapterLuid;
|
||||
D3D_FEATURE_LEVEL minFeatureLevel;
|
||||
} XrGraphicsRequirementsD3D12KHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_D3D12 */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_METAL
|
||||
|
||||
// XR_KHR_metal_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_metal_enable 1
|
||||
#define XR_KHR_metal_enable_SPEC_VERSION 1
|
||||
#define XR_KHR_METAL_ENABLE_EXTENSION_NAME "XR_KHR_metal_enable"
|
||||
// XrGraphicsBindingMetalKHR extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingMetalKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
void* XR_MAY_ALIAS commandQueue;
|
||||
} XrGraphicsBindingMetalKHR;
|
||||
|
||||
typedef struct XrSwapchainImageMetalKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
void* XR_MAY_ALIAS texture;
|
||||
} XrSwapchainImageMetalKHR;
|
||||
|
||||
typedef struct XrGraphicsRequirementsMetalKHR {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
void* XR_MAY_ALIAS metalDevice;
|
||||
} XrGraphicsRequirementsMetalKHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetMetalGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsMetalKHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetMetalGraphicsRequirementsKHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsMetalKHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_METAL */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
|
||||
// XR_KHR_win32_convert_performance_counter_time is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_win32_convert_performance_counter_time 1
|
||||
#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1
|
||||
#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time"
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
|
||||
XrInstance instance,
|
||||
const LARGE_INTEGER* performanceCounter,
|
||||
XrTime* time);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
|
||||
XrInstance instance,
|
||||
XrTime time,
|
||||
LARGE_INTEGER* performanceCounter);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||
|
||||
#ifdef XR_USE_TIMESPEC
|
||||
|
||||
// XR_KHR_convert_timespec_time is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_convert_timespec_time 1
|
||||
#define XR_KHR_convert_timespec_time_SPEC_VERSION 1
|
||||
#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time"
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
|
||||
XrInstance instance,
|
||||
const struct timespec* timespecTime,
|
||||
XrTime* time);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
|
||||
XrInstance instance,
|
||||
XrTime time,
|
||||
struct timespec* timespecTime);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_TIMESPEC */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
// XR_KHR_loader_init_android is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_loader_init_android 1
|
||||
#define XR_KHR_loader_init_android_SPEC_VERSION 1
|
||||
#define XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME "XR_KHR_loader_init_android"
|
||||
typedef struct XrLoaderInitInfoAndroidKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
void* XR_MAY_ALIAS applicationVM;
|
||||
void* XR_MAY_ALIAS applicationContext;
|
||||
} XrLoaderInitInfoAndroidKHR;
|
||||
|
||||
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
// XR_KHR_vulkan_enable2 is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_KHR_vulkan_enable2 1
|
||||
#define XR_KHR_vulkan_enable2_SPEC_VERSION 2
|
||||
#define XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME "XR_KHR_vulkan_enable2"
|
||||
typedef XrFlags64 XrVulkanInstanceCreateFlagsKHR;
|
||||
|
||||
// Flag bits for XrVulkanInstanceCreateFlagsKHR
|
||||
|
||||
typedef XrFlags64 XrVulkanDeviceCreateFlagsKHR;
|
||||
|
||||
// Flag bits for XrVulkanDeviceCreateFlagsKHR
|
||||
|
||||
typedef struct XrVulkanInstanceCreateInfoKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
XrSystemId systemId;
|
||||
XrVulkanInstanceCreateFlagsKHR createFlags;
|
||||
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
|
||||
const VkInstanceCreateInfo* vulkanCreateInfo;
|
||||
const VkAllocationCallbacks* vulkanAllocator;
|
||||
} XrVulkanInstanceCreateInfoKHR;
|
||||
|
||||
typedef struct XrVulkanDeviceCreateInfoKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
XrSystemId systemId;
|
||||
XrVulkanDeviceCreateFlagsKHR createFlags;
|
||||
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
|
||||
VkPhysicalDevice vulkanPhysicalDevice;
|
||||
const VkDeviceCreateInfo* vulkanCreateInfo;
|
||||
const VkAllocationCallbacks* vulkanAllocator;
|
||||
} XrVulkanDeviceCreateInfoKHR;
|
||||
|
||||
typedef XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkan2KHR;
|
||||
|
||||
typedef struct XrVulkanGraphicsDeviceGetInfoKHR {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
XrSystemId systemId;
|
||||
VkInstance vulkanInstance;
|
||||
} XrVulkanGraphicsDeviceGetInfoKHR;
|
||||
|
||||
typedef XrSwapchainImageVulkanKHR XrSwapchainImageVulkan2KHR;
|
||||
|
||||
typedef XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkan2KHR;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanInstanceKHR)(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanDeviceKHR)(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* vulkanDevice, VkResult* vulkanResult);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDevice2KHR)(XrInstance instance, const XrVulkanGraphicsDeviceGetInfoKHR* getInfo, VkPhysicalDevice* vulkanPhysicalDevice);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirements2KHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanInstanceKHR(
|
||||
XrInstance instance,
|
||||
const XrVulkanInstanceCreateInfoKHR* createInfo,
|
||||
VkInstance* vulkanInstance,
|
||||
VkResult* vulkanResult);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanDeviceKHR(
|
||||
XrInstance instance,
|
||||
const XrVulkanDeviceCreateInfoKHR* createInfo,
|
||||
VkDevice* vulkanDevice,
|
||||
VkResult* vulkanResult);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDevice2KHR(
|
||||
XrInstance instance,
|
||||
const XrVulkanGraphicsDeviceGetInfoKHR* getInfo,
|
||||
VkPhysicalDevice* vulkanPhysicalDevice);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirements2KHR(
|
||||
XrInstance instance,
|
||||
XrSystemId systemId,
|
||||
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_EGL
|
||||
|
||||
// XR_MNDX_egl_enable is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_MNDX_egl_enable 1
|
||||
#define XR_MNDX_egl_enable_SPEC_VERSION 2
|
||||
#define XR_MNDX_EGL_ENABLE_EXTENSION_NAME "XR_MNDX_egl_enable"
|
||||
typedef PFN_xrVoidFunction (*PFN_xrEglGetProcAddressMNDX)(const char *name);
|
||||
// XrGraphicsBindingEGLMNDX extends XrSessionCreateInfo
|
||||
typedef struct XrGraphicsBindingEGLMNDX {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
PFN_xrEglGetProcAddressMNDX getProcAddress;
|
||||
EGLDisplay display;
|
||||
EGLConfig config;
|
||||
EGLContext context;
|
||||
} XrGraphicsBindingEGLMNDX;
|
||||
|
||||
#endif /* XR_USE_PLATFORM_EGL */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
|
||||
// XR_MSFT_perception_anchor_interop is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_MSFT_perception_anchor_interop 1
|
||||
#define XR_MSFT_perception_anchor_interop_SPEC_VERSION 1
|
||||
#define XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME "XR_MSFT_perception_anchor_interop"
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT)(XrSession session, IUnknown* perceptionAnchor, XrSpatialAnchorMSFT* anchor);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT)(XrSession session, XrSpatialAnchorMSFT anchor, IUnknown** perceptionAnchor);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPerceptionAnchorMSFT(
|
||||
XrSession session,
|
||||
IUnknown* perceptionAnchor,
|
||||
XrSpatialAnchorMSFT* anchor);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrTryGetPerceptionAnchorFromSpatialAnchorMSFT(
|
||||
XrSession session,
|
||||
XrSpatialAnchorMSFT anchor,
|
||||
IUnknown** perceptionAnchor);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
|
||||
// XR_MSFT_holographic_window_attachment is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_MSFT_holographic_window_attachment 1
|
||||
#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1
|
||||
#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment"
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
// XrHolographicWindowAttachmentMSFT extends XrSessionCreateInfo
|
||||
typedef struct XrHolographicWindowAttachmentMSFT {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
IUnknown* holographicSpace;
|
||||
IUnknown* coreWindow;
|
||||
} XrHolographicWindowAttachmentMSFT;
|
||||
#endif // XR_USE_PLATFORM_WIN32
|
||||
|
||||
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
// XR_FB_android_surface_swapchain_create is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_FB_android_surface_swapchain_create 1
|
||||
#define XR_FB_android_surface_swapchain_create_SPEC_VERSION 1
|
||||
#define XR_FB_ANDROID_SURFACE_SWAPCHAIN_CREATE_EXTENSION_NAME "XR_FB_android_surface_swapchain_create"
|
||||
typedef XrFlags64 XrAndroidSurfaceSwapchainFlagsFB;
|
||||
|
||||
// Flag bits for XrAndroidSurfaceSwapchainFlagsFB
|
||||
static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB = 0x00000001;
|
||||
static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB = 0x00000002;
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
// XrAndroidSurfaceSwapchainCreateInfoFB extends XrSwapchainCreateInfo
|
||||
typedef struct XrAndroidSurfaceSwapchainCreateInfoFB {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
XrAndroidSurfaceSwapchainFlagsFB createFlags;
|
||||
} XrAndroidSurfaceSwapchainCreateInfoFB;
|
||||
#endif // XR_USE_PLATFORM_ANDROID
|
||||
|
||||
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ML
|
||||
|
||||
// XR_ML_compat is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_ML_compat 1
|
||||
#define XR_ML_compat_SPEC_VERSION 1
|
||||
#define XR_ML_COMPAT_EXTENSION_NAME "XR_ML_compat"
|
||||
typedef struct XrCoordinateSpaceCreateInfoML {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
MLCoordinateFrameUID cfuid;
|
||||
XrPosef poseInCoordinateSpace;
|
||||
} XrCoordinateSpaceCreateInfoML;
|
||||
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrCreateSpaceFromCoordinateFrameUIDML)(XrSession session, const XrCoordinateSpaceCreateInfoML *createInfo, XrSpace* space);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpaceFromCoordinateFrameUIDML(
|
||||
XrSession session,
|
||||
const XrCoordinateSpaceCreateInfoML * createInfo,
|
||||
XrSpace* space);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_PLATFORM_ML */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_WIN32
|
||||
|
||||
// XR_OCULUS_audio_device_guid is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_OCULUS_audio_device_guid 1
|
||||
#define XR_OCULUS_audio_device_guid_SPEC_VERSION 1
|
||||
#define XR_OCULUS_AUDIO_DEVICE_GUID_EXTENSION_NAME "XR_OCULUS_audio_device_guid"
|
||||
#define XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS 128
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetAudioOutputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||
typedef XrResult (XRAPI_PTR *PFN_xrGetAudioInputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||
|
||||
#ifndef XR_NO_PROTOTYPES
|
||||
#ifdef XR_EXTENSION_PROTOTYPES
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioOutputDeviceGuidOculus(
|
||||
XrInstance instance,
|
||||
wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||
|
||||
XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioInputDeviceGuidOculus(
|
||||
XrInstance instance,
|
||||
wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||
#endif /* !XR_NO_PROTOTYPES */
|
||||
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
// XR_FB_foveation_vulkan is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_FB_foveation_vulkan 1
|
||||
#define XR_FB_foveation_vulkan_SPEC_VERSION 1
|
||||
#define XR_FB_FOVEATION_VULKAN_EXTENSION_NAME "XR_FB_foveation_vulkan"
|
||||
// XrSwapchainImageFoveationVulkanFB extends XrSwapchainImageVulkanKHR
|
||||
typedef struct XrSwapchainImageFoveationVulkanFB {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
VkImage image;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} XrSwapchainImageFoveationVulkanFB;
|
||||
|
||||
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
|
||||
// XR_FB_swapchain_update_state_android_surface is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_FB_swapchain_update_state_android_surface 1
|
||||
#define XR_FB_swapchain_update_state_android_surface_SPEC_VERSION 1
|
||||
#define XR_FB_SWAPCHAIN_UPDATE_STATE_ANDROID_SURFACE_EXTENSION_NAME "XR_FB_swapchain_update_state_android_surface"
|
||||
#ifdef XR_USE_PLATFORM_ANDROID
|
||||
typedef struct XrSwapchainStateAndroidSurfaceDimensionsFB {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} XrSwapchainStateAndroidSurfaceDimensionsFB;
|
||||
#endif // XR_USE_PLATFORM_ANDROID
|
||||
|
||||
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||
|
||||
// XR_FB_swapchain_update_state_opengl_es is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_FB_swapchain_update_state_opengl_es 1
|
||||
#define XR_FB_swapchain_update_state_opengl_es_SPEC_VERSION 1
|
||||
#define XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME "XR_FB_swapchain_update_state_opengl_es"
|
||||
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||
typedef struct XrSwapchainStateSamplerOpenGLESFB {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
EGLenum minFilter;
|
||||
EGLenum magFilter;
|
||||
EGLenum wrapModeS;
|
||||
EGLenum wrapModeT;
|
||||
EGLenum swizzleRed;
|
||||
EGLenum swizzleGreen;
|
||||
EGLenum swizzleBlue;
|
||||
EGLenum swizzleAlpha;
|
||||
float maxAnisotropy;
|
||||
XrColor4f borderColor;
|
||||
} XrSwapchainStateSamplerOpenGLESFB;
|
||||
#endif // XR_USE_GRAPHICS_API_OPENGL_ES
|
||||
|
||||
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
// XR_FB_swapchain_update_state_vulkan is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_FB_swapchain_update_state_vulkan 1
|
||||
#define XR_FB_swapchain_update_state_vulkan_SPEC_VERSION 1
|
||||
#define XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME "XR_FB_swapchain_update_state_vulkan"
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
typedef struct XrSwapchainStateSamplerVulkanFB {
|
||||
XrStructureType type;
|
||||
void* XR_MAY_ALIAS next;
|
||||
VkFilter minFilter;
|
||||
VkFilter magFilter;
|
||||
VkSamplerMipmapMode mipmapMode;
|
||||
VkSamplerAddressMode wrapModeS;
|
||||
VkSamplerAddressMode wrapModeT;
|
||||
VkComponentSwizzle swizzleRed;
|
||||
VkComponentSwizzle swizzleGreen;
|
||||
VkComponentSwizzle swizzleBlue;
|
||||
VkComponentSwizzle swizzleAlpha;
|
||||
float maxAnisotropy;
|
||||
XrColor4f borderColor;
|
||||
} XrSwapchainStateSamplerVulkanFB;
|
||||
#endif // XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||
|
||||
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||
|
||||
// XR_META_vulkan_swapchain_create_info is a preprocessor guard. Do not pass it to API calls.
|
||||
#define XR_META_vulkan_swapchain_create_info 1
|
||||
#define XR_META_vulkan_swapchain_create_info_SPEC_VERSION 1
|
||||
#define XR_META_VULKAN_SWAPCHAIN_CREATE_INFO_EXTENSION_NAME "XR_META_vulkan_swapchain_create_info"
|
||||
// XrVulkanSwapchainCreateInfoMETA extends XrSwapchainCreateInfo
|
||||
typedef struct XrVulkanSwapchainCreateInfoMETA {
|
||||
XrStructureType type;
|
||||
const void* XR_MAY_ALIAS next;
|
||||
VkImageCreateFlags additionalCreateFlags;
|
||||
VkImageUsageFlags additionalUsageFlags;
|
||||
} XrVulkanSwapchainCreateInfoMETA;
|
||||
|
||||
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
114
src/video/khronos/openxr/openxr_platform_defines.h
Normal file
114
src/video/khronos/openxr/openxr_platform_defines.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
** Copyright (c) 2017-2025 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#ifndef OPENXR_PLATFORM_DEFINES_H_
|
||||
#define OPENXR_PLATFORM_DEFINES_H_ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Platform-specific calling convention macros.
|
||||
*
|
||||
* Platforms should define these so that OpenXR clients call OpenXR functions
|
||||
* with the same calling conventions that the OpenXR implementation expects.
|
||||
*
|
||||
* XRAPI_ATTR - Placed before the return type in function declarations.
|
||||
* Useful for C++11 and GCC/Clang-style function attribute syntax.
|
||||
* XRAPI_CALL - Placed after the return type in function declarations.
|
||||
* Useful for MSVC-style calling convention syntax.
|
||||
* XRAPI_PTR - Placed between the '(' and '*' in function pointer types.
|
||||
*
|
||||
* Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void);
|
||||
* Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
#define XRAPI_ATTR
|
||||
// On Windows, functions use the stdcall convention
|
||||
#define XRAPI_CALL __stdcall
|
||||
#define XRAPI_PTR XRAPI_CALL
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||
#error "API not supported for the 'armeabi' NDK ABI"
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
||||
// On Android 32-bit ARM targets, functions use the "hardfloat"
|
||||
// calling convention, i.e. float parameters are passed in registers. This
|
||||
// is true even if the rest of the application passes floats on the stack,
|
||||
// as it does by default when compiling for the armeabi-v7a NDK ABI.
|
||||
#define XRAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
||||
#define XRAPI_CALL
|
||||
#define XRAPI_PTR XRAPI_ATTR
|
||||
#else
|
||||
// On other platforms, use the default calling convention
|
||||
#define XRAPI_ATTR
|
||||
#define XRAPI_CALL
|
||||
#define XRAPI_PTR
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if !defined(XR_NO_STDINT_H)
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#endif // !defined( XR_NO_STDINT_H )
|
||||
|
||||
// XR_PTR_SIZE (in bytes)
|
||||
#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))
|
||||
#define XR_PTR_SIZE 8
|
||||
#else
|
||||
#define XR_PTR_SIZE 4
|
||||
#endif
|
||||
|
||||
// Needed so we can use clang __has_feature portably.
|
||||
#if !defined(XR_COMPILER_HAS_FEATURE)
|
||||
#if defined(__clang__)
|
||||
#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)
|
||||
#else
|
||||
#define XR_COMPILER_HAS_FEATURE(x) 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Identifies if the current compiler has C++11 support enabled.
|
||||
// Does not by itself identify if any given C++11 feature is present.
|
||||
#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)
|
||||
#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#define XR_CPP11_ENABLED 1
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||
#define XR_CPP11_ENABLED 1
|
||||
#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.
|
||||
#define XR_CPP11_ENABLED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Identifies if the current compiler supports C++11 nullptr.
|
||||
#if !defined(XR_CPP_NULLPTR_SUPPORTED)
|
||||
#if defined(XR_CPP11_ENABLED) && \
|
||||
((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \
|
||||
(defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \
|
||||
(defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||
(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))
|
||||
#define XR_CPP_NULLPTR_SUPPORTED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(XR_CPP_NULLPTR_SUPPORTED)
|
||||
#define XR_CPP_NULLPTR_SUPPORTED 0
|
||||
#endif // !defined(XR_CPP_NULLPTR_SUPPORTED)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
7226
src/video/khronos/openxr/openxr_reflection.h
Normal file
7226
src/video/khronos/openxr/openxr_reflection.h
Normal file
File diff suppressed because it is too large
Load Diff
330
src/video/khronos/openxr/openxr_reflection_parent_structs.h
Normal file
330
src/video/khronos/openxr/openxr_reflection_parent_structs.h
Normal file
@@ -0,0 +1,330 @@
|
||||
#ifndef OPENXR_REFLECTION_PARENT_STRUCTS_H_
|
||||
#define OPENXR_REFLECTION_PARENT_STRUCTS_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright (c) 2017-2025 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is generated from the Khronos OpenXR XML API Registry.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "openxr.h"
|
||||
|
||||
/*
|
||||
This file contains expansion macros (X Macros) for OpenXR structures that have a parent type.
|
||||
*/
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrCompositionLayerBaseHeader
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrCompositionLayerBaseHeader_CORE(_avail, _unavail) \
|
||||
_avail(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \
|
||||
_avail(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \
|
||||
_avail(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \
|
||||
_avail(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \
|
||||
_avail(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \
|
||||
_avail(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \
|
||||
_avail(XrCompositionLayerPassthroughFB, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB) \
|
||||
_avail(XrCompositionLayerPassthroughHTC, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_HTC) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrEventDataBaseHeader
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrEventDataBaseHeader_CORE(_avail, _unavail) \
|
||||
_avail(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \
|
||||
_avail(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \
|
||||
_avail(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \
|
||||
_avail(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \
|
||||
_avail(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \
|
||||
_avail(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \
|
||||
_avail(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \
|
||||
_avail(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \
|
||||
_avail(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \
|
||||
_avail(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \
|
||||
_avail(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \
|
||||
_avail(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \
|
||||
_avail(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \
|
||||
_avail(XrEventDataLocalizationChangedML, XR_TYPE_EVENT_DATA_LOCALIZATION_CHANGED_ML) \
|
||||
_avail(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \
|
||||
_avail(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \
|
||||
_avail(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \
|
||||
_avail(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \
|
||||
_avail(XrEventDataSpaceShareCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB) \
|
||||
_avail(XrEventDataSpaceListSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB) \
|
||||
_avail(XrEventDataPassthroughLayerResumedMETA, XR_TYPE_EVENT_DATA_PASSTHROUGH_LAYER_RESUMED_META) \
|
||||
_avail(XrEventDataHeadsetFitChangedML, XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML) \
|
||||
_avail(XrEventDataEyeCalibrationChangedML, XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrHapticBaseHeader
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrHapticBaseHeader_CORE(_avail, _unavail) \
|
||||
_avail(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \
|
||||
_avail(XrHapticAmplitudeEnvelopeVibrationFB, XR_TYPE_HAPTIC_AMPLITUDE_ENVELOPE_VIBRATION_FB) \
|
||||
_avail(XrHapticPcmVibrationFB, XR_TYPE_HAPTIC_PCM_VIBRATION_FB) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSwapchainImageBaseHeader
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_CORE(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
|
||||
_avail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D11(_avail, _unavail) \
|
||||
_unavail(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
|
||||
_avail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_D3D12(_avail, _unavail) \
|
||||
_unavail(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
|
||||
_avail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL(_avail, _unavail) \
|
||||
_unavail(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
|
||||
_avail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
|
||||
_unavail(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
|
||||
_avail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainImageBaseHeader_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
|
||||
_unavail(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrLoaderInitInfoBaseHeaderKHR
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_CORE(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
|
||||
_avail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrLoaderInitInfoBaseHeaderKHR_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
|
||||
_unavail(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrBindingModificationBaseHeaderKHR
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrBindingModificationBaseHeaderKHR_CORE(_avail, _unavail) \
|
||||
_avail(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \
|
||||
_avail(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSwapchainStateBaseHeaderFB
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_CORE(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_CORE(_avail, _unavail) \
|
||||
_avail(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \
|
||||
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
|
||||
_avail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_OPENGL_ES(_avail, _unavail) \
|
||||
_unavail(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
|
||||
_avail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_GRAPHICS_API_VULKAN(_avail, _unavail) \
|
||||
_unavail(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
|
||||
_avail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
|
||||
|
||||
#else
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSwapchainStateBaseHeaderFB_XR_USE_PLATFORM_ANDROID(_avail, _unavail) \
|
||||
_unavail(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpatialAnchorsCreateInfoBaseHeaderML
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsCreateInfoBaseHeaderML_CORE(_avail, _unavail) \
|
||||
_avail(XrSpatialAnchorsCreateInfoFromPoseML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_POSE_ML) \
|
||||
_avail(XrSpatialAnchorsCreateInfoFromUuidsML, XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrFutureCompletionBaseHeaderEXT
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrFutureCompletionBaseHeaderEXT_CORE(_avail, _unavail) \
|
||||
_avail(XrCreateSpatialAnchorsCompletionML, XR_TYPE_CREATE_SPATIAL_ANCHORS_COMPLETION_ML) \
|
||||
_avail(XrSpatialAnchorsQueryCompletionML, XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML) \
|
||||
_avail(XrSpatialAnchorsPublishCompletionML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML) \
|
||||
_avail(XrSpatialAnchorsDeleteCompletionML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML) \
|
||||
_avail(XrSpatialAnchorsUpdateExpirationCompletionML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML) \
|
||||
_avail(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \
|
||||
_avail(XrWorldMeshStateRequestCompletionML, XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML) \
|
||||
_avail(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpatialAnchorsQueryInfoBaseHeaderML
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpatialAnchorsQueryInfoBaseHeaderML_CORE(_avail, _unavail) \
|
||||
_avail(XrSpatialAnchorsQueryInfoRadiusML, XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceQueryInfoBaseHeaderFB
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceQueryInfoBaseHeaderFB_CORE(_avail, _unavail) \
|
||||
_avail(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrSpaceFilterInfoBaseHeaderFB
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrSpaceFilterInfoBaseHeaderFB_CORE(_avail, _unavail) \
|
||||
_avail(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \
|
||||
_avail(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrShareSpacesRecipientBaseHeaderMETA
|
||||
#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA(_avail, _unavail) \
|
||||
_impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA_CORE(_avail, _unavail) \
|
||||
|
||||
|
||||
// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA()
|
||||
#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA_CORE(_avail, _unavail) \
|
||||
_avail(XrShareSpacesRecipientGroupsMETA, XR_TYPE_SHARE_SPACES_RECIPIENT_GROUPS_META) \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(void);
|
||||
|
||||
extern SDL_DECLSPEC void SDLCALL JNI_OnLoad(void);
|
||||
|
||||
#include <SDL3/SDL_openxr.h>
|
||||
|
||||
const static struct {
|
||||
const char *name;
|
||||
SDL_FunctionPointer address;
|
||||
|
||||
Reference in New Issue
Block a user