Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ValveSoftware/Proton.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile5
m---------OpenXR-SDK0
-rw-r--r--build/makefile_base.mak131
-rwxr-xr-xproton3
m---------wine0
-rw-r--r--wineopenxr/dxvk-interop.h362
-rw-r--r--wineopenxr/loader_structs.h30
-rwxr-xr-xwineopenxr/make_openxr2893
-rw-r--r--wineopenxr/openxr.c1441
-rw-r--r--wineopenxr/openxr_private.h85
-rw-r--r--wineopenxr/openxr_thunks.c561
-rw-r--r--wineopenxr/openxr_thunks.h212
-rw-r--r--wineopenxr/wineopenxr.h1957
-rw-r--r--wineopenxr/wineopenxr.spec3
-rw-r--r--wineopenxr/wineopenxr64.json6
16 files changed, 7688 insertions, 4 deletions
diff --git a/.gitmodules b/.gitmodules
index 9a4eef3b..41e09459 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,3 +28,6 @@
[submodule "vkd3d-proton"]
path = vkd3d-proton
url = https://github.com/HansKristian-Work/vkd3d-proton
+[submodule "OpenXR-SDK"]
+ path = OpenXR-SDK
+ url = https://github.com/KhronosGroup/OpenXR-SDK
diff --git a/Makefile b/Makefile
index ab6fe63f..220fe918 100644
--- a/Makefile
+++ b/Makefile
@@ -172,3 +172,8 @@ vrclient: configure
vagrant ssh -c 'make -C $(BUILD_DIR)/ $(UNSTRIPPED) $(CCACHE_FLAG) vrclient && \
cp -f $(BUILD_DIR)/dist/dist/lib/wine/vrclient.dll.so /vagrant/vrclient/lib/wine && \
cp -f $(BUILD_DIR)/dist/dist/lib64/wine/vrclient_x64.dll.so /vagrant/vrclient/lib64/wine'
+
+wineopenxr: configure
+ mkdir -p vagrant_share/wineopenxr/lib64/wine
+ vagrant ssh -c 'make -C $(BUILD_DIR)/ $(UNSTRIPPED) $(CCACHE_FLAG) wineopenxr && \
+ cp -f $(BUILD_DIR)/dist/dist/lib64/wine/wineopenxr.dll.so /vagrant/wineopenxr/lib64/wine'
diff --git a/OpenXR-SDK b/OpenXR-SDK
new file mode 160000
+Subproject 5197afbf199c026eca82a47a8573ed10b0c6fa4
diff --git a/build/makefile_base.mak b/build/makefile_base.mak
index 6acce47a..8d2554bc 100644
--- a/build/makefile_base.mak
+++ b/build/makefile_base.mak
@@ -238,6 +238,15 @@ LSTEAMCLIENT64 := ./syn-lsteamclient64/lsteamclient
LSTEAMCLIENT_OBJ32 := ./obj-lsteamclient32
LSTEAMCLIENT_OBJ64 := ./obj-lsteamclient64
+WINEOPENXR := $(SRCDIR)/wineopenxr
+WINEOPENXR64 := ./syn-wineopenxr64/wineopenxr
+WINEOPENXR_OBJ64 := ./obj-wineopenxr64
+WINEOPENXR_JSON64 := $(SRCDIR)/wineopenxr/wineopenxr64.json
+WINEOPENXR_FAKEDLL64 := $(WINEOPENXR_OBJ64)/wineopenxr.dll.fake
+
+OPENXR := $(SRCDIR)/OpenXR-SDK
+OPENXR_OBJ64 := ./obj-openxr64
+
STEAMEXE_SRC := $(SRCDIR)/steam_helper
STEAMEXE_OBJ := ./obj-steam
STEAMEXE_SYN := ./syn-steam/steam
@@ -289,6 +298,8 @@ OBJ_DIRS := $(TOOLS_DIR32) $(TOOLS_DIR64) \
$(FAUDIO_OBJ32) $(FAUDIO_OBJ64) \
$(JXRLIB_OBJ32) $(JXRLIB_OBJ64) \
$(LSTEAMCLIENT_OBJ32) $(LSTEAMCLIENT_OBJ64) \
+ $(WINEOPENXR_OBJ64) \
+ $(OPENXR_OBJ64) \
$(STEAMEXE_OBJ) \
$(WINE_OBJ32) $(WINE_OBJ64) \
$(VRCLIENT_OBJ32) $(VRCLIENT_OBJ64) \
@@ -366,6 +377,8 @@ DIST_GECKO64 := $(DIST_GECKO_DIR)/wine-gecko-$(GECKO_VER)-x86_64
DIST_WINEMONO_DIR := $(DST_DIR)/share/wine/mono
DIST_WINEMONO := $(DIST_WINEMONO_DIR)/wine-mono-$(WINEMONO_VER)
DIST_FONTS := $(DST_DIR)/share/fonts
+DIST_WINEOPENXR_JSON64 := $(DIST_PREFIX)/drive_c/openxr/wineopenxr64.json
+DIST_WINEOPENXR64 := $(DIST_PREFIX)/drive_c/windows/system32/wineopenxr.dll
DIST_TARGETS := $(DIST_COPY_TARGETS) $(DIST_OVR32) $(DIST_OVR64) \
$(DIST_GECKO32) $(DIST_GECKO64) $(DIST_WINEMONO) \
@@ -444,19 +457,31 @@ $(DIST_FONTS): fonts
cp $(FONTS_OBJ)/*.ttf "$@"
cp $(FONTS_OBJ)/*.otf "$@"
+$(DIST_WINEOPENXR_JSON64): $(WINEOPENXR_JSON64)
+ mkdir -p $(dir $@)
+ cp -a $< $@
+
+$(DIST_WINEOPENXR64): wineopenxr64
+ mkdir -p $(dir $@)
+ cp -a $(WINEOPENXR_FAKEDLL64) $@
+
.PHONY: dist
ALL_TARGETS += dist
GOAL_TARGETS += dist
-dist: $(DIST_TARGETS) wine gst_good vrclient lsteamclient steam dxvk vkd3d-proton mediaconv | $(DST_DIR)
- echo `date '+%s'` `GIT_DIR=$(abspath $(SRCDIR)/.git) git describe --tags` > $(DIST_VERSION)
- cp $(DIST_VERSION) $(DST_BASE)/
+dist_prefix: wine gst_good
find $(DST_DIR)/lib/wine -type f -execdir chmod a-w '{}' '+'
find $(DST_DIR)/lib64/wine -type f -execdir chmod a-w '{}' '+'
rm -rf $(abspath $(DIST_PREFIX))
python3 $(SRCDIR)/default_pfx.py $(abspath $(DIST_PREFIX)) $(abspath $(DST_DIR)) $(STEAM_RUNTIME_RUNSH)
+dist_wineopenxr: dist_prefix $(DIST_WINEOPENXR_JSON64) $(DIST_WINEOPENXR64)
+
+dist: $(DIST_TARGETS) vrclient lsteamclient wineopenxr steam dxvk vkd3d-proton mediaconv dist_wineopenxr | $(DST_DIR)
+ echo `date '+%s'` `GIT_DIR=$(abspath $(SRCDIR)/.git) git describe --tags` > $(DIST_VERSION)
+ cp $(DIST_VERSION) $(DST_BASE)/
+
deploy: dist | $(filter-out dist deploy install redist,$(MAKECMDGOALS))
mkdir -p $(DEPLOY_DIR) && \
cp -a $(DEPLOY_COPY_TARGETS) $(DEPLOY_DIR) && \
@@ -1052,6 +1077,104 @@ lsteamclient32: $(LSTEAMCLIENT_CONFIGURE_FILES32) | $(WINE_BUILDTOOLS32) $(filte
mkdir -pv $(DST_DIR)/lib/wine/
cp -af $(LSTEAMCLIENT_OBJ32)/lsteamclient.dll.so $(DST_DIR)/lib/wine/
+
+##
+## openxr
+## Note 32-bit is not supported by SteamVR, so we don't build it.
+##
+
+OPENXR_CMAKE_FLAGS = -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR="lib"
+
+OPENXR_TARGETS = openxr openxr64
+
+ALL_TARGETS += $(OPENXR_TARGETS)
+GOAL_TARGETS_LIBS += openxr
+
+.PHONY: openxr openxr64
+
+openxr: openxr64
+
+OPENXR_CONFIGURE_FILES64 := $(OPENXR_OBJ64)/Makefile
+
+$(OPENXR_CONFIGURE_FILES64): SHELL = $(CONTAINER_SHELL64)
+$(OPENXR_CONFIGURE_FILES64): $(OPENXR)/CMakeLists.txt $(MAKEFILE_DEP) | $(OPENXR_OBJ64)
+ cd $(dir $@) && \
+ CFLAGS="$(OPTIMIZE_FLAGS)" \
+ cmake $(abspath $(OPENXR)) \
+ -DCMAKE_INSTALL_PREFIX="$(abspath $(TOOLS_DIR64))" \
+ $(OPENXR_CMAKE_FLAGS)
+
+openxr64: SHELL = $(CONTAINER_SHELL64)
+openxr64: $(OPENXR_CONFIGURE_FILES64)
+ +$(MAKE) -C $(OPENXR_OBJ64) VERBOSE=1
+ +$(MAKE) -C $(OPENXR_OBJ64) install VERBOSE=1
+ mkdir -p $(DST_DIR)/lib64
+ cp -a $(TOOLS_DIR64)/lib/libopenxr_loader* $(DST_DIR)/lib64/
+ [ x"$(STRIP)" = x ] || $(STRIP) $(DST_DIR)/lib64/libopenxr_loader.so
+
+##
+## wineopenxr
+## Note 32-bit is not supported by SteamVR, so we don't build it.
+##
+
+# The source directory for wineopenxr is a synthetic symlink clone of the source directory, because we need to run
+# winemaker in tree and it can stomp itself in parallel builds.
+$(WINEOPENXR64)/.created: $(WINEOPENXR) $(MAKEFILE_DEP)
+ rm -rf ./$(WINEOPENXR64)
+ mkdir -p $(WINEOPENXR64)/
+ cd $(WINEOPENXR64)/ && ln -sfv ../../$(WINEOPENXR)/* .
+ touch $@
+
+$(WINEOPENXR64): $(WINEOPENXR64)/.created
+
+## Create & configure object directory for wineopenxr
+
+WINEOPENXR_CONFIGURE_FILES64 := $(WINEOPENXR_OBJ64)/Makefile
+
+# 64bit-configure
+$(WINEOPENXR_CONFIGURE_FILES64): SHELL = $(CONTAINER_SHELL64)
+$(WINEOPENXR_CONFIGURE_FILES64): $(WINEOPENXR64) $(MAKEFILE_DEP) | $(WINEOPENXR_OBJ64) $(WINEMAKER)
+ cd $(dir $@) && \
+ $(WINEMAKER) --nosource-fix --nolower-include --nodlls --nomsvcrt \
+ -I"../$(TOOLS_DIR64)"/include/ \
+ -I"../$(TOOLS_DIR64)"/include/wine/ \
+ -I"../$(TOOLS_DIR64)"/include/wine/windows/ \
+ -I"../$(WINE)"/include/ \
+ -I"$(abspath $(OPENXR))"/include/ \
+ -L"../$(TOOLS_DIR64)"/lib/ \
+ -l"openxr_loader" \
+ -l"dxgi" \
+ -l"vulkan" \
+ --dll ../$(WINEOPENXR64) && \
+ cp ../$(WINEOPENXR64)/Makefile . && \
+ echo >> ./Makefile 'SRCDIR := ../$(WINEOPENXR64)' && \
+ echo >> ./Makefile 'vpath % $$(SRCDIR)' && \
+ echo >> ./Makefile 'wineopenxr_dll_LDFLAGS := -ldl $$(patsubst %.spec,$$(SRCDIR)/%.spec,$$(wineopenxr_dll_LDFLAGS))'
+
+# -L"../$(TOOLS_DIR64)"/lib64/wine/ \
+## wineopenxr goals
+WINEOPENXR_TARGETS = wineopenxr wineopenxr_configure wineopenxr64 wineopenxr_configure64
+
+ALL_TARGETS += $(WINEOPENXR_TARGETS)
+GOAL_TARGETS_LIBS += wineopenxr
+
+.PHONY: $(WINEOPENXR_TARGETS)
+
+wineopenxr_configure: $(WINEOPENXR_CONFIGURE_FILES64)
+
+wineopenxr_configure64: $(WINEOPENXR_CONFIGURE_FILES64)
+
+wineopenxr: wineopenxr64
+
+wineopenxr64: SHELL = $(CONTAINER_SHELL64)
+wineopenxr64: $(WINEOPENXR_CONFIGURE_FILES64) openxr64 | $(WINE_BUILDTOOLS64) $(filter $(MAKECMDGOALS),wine64 wine32 wine)
+ +env PATH="$(abspath $(TOOLS_DIR64))/bin:$(PATH)" CFLAGS="$(COMMON_FLAGS) -g" \
+ $(MAKE) -C $(WINEOPENXR_OBJ64)
+ $(TOOLS_DIR64)/bin/winebuild -m64 --dll --fake-module -E $(abspath $(WINEOPENXR))/wineopenxr.spec -o $(WINEOPENXR_OBJ64)/wineopenxr.dll.fake
+ [ x"$(STRIP)" = x ] || $(STRIP) $(WINEOPENXR_OBJ64)/wineopenxr.dll.so
+ mkdir -pv $(DST_DIR)/lib64/wine/
+ cp -af $(WINEOPENXR_OBJ64)/wineopenxr.dll.so $(DST_DIR)/lib64/wine/
+
## steam.exe
$(STEAMEXE_SYN)/.created: $(STEAMEXE_SRC) $(MAKEFILE_DEP)
@@ -1322,7 +1445,7 @@ DXVK_CONFIGURE_FILES32 := $(DXVK_OBJ32)/build.ninja
DXVK_CONFIGURE_FILES64 := $(DXVK_OBJ64)/build.ninja
# 64bit-configure. Remove coredata file if already configured (due to e.g. makefile changing)
-$(DXVK_CONFIGURE_FILES64): $(MAKEFILE_DEP) $(DXVK)/build-win64.txt | $(DXVK_OBJ64)
+$(DXVK_CONFIGURE_FILES64): $(MAKEFILE_DEP) $(DXVK)/build-win64.txt wineopenxr64 | $(DXVK_OBJ64)
if [ -e "$(abspath $(DXVK_OBJ64))"/build.ninja ]; then \
rm -f "$(abspath $(DXVK_OBJ64))"/meson-private/coredata.dat; \
fi
diff --git a/proton b/proton
index 4d6e551d..2745753f 100755
--- a/proton
+++ b/proton
@@ -540,6 +540,9 @@ class CompatData:
try_copy(g_proton.lib_dir + "wine/dxvk/openvr_api_dxvk.dll", self.prefix_dir + "/drive_c/windows/syswow64/")
try_copy(g_proton.lib64_dir + "wine/dxvk/openvr_api_dxvk.dll", self.prefix_dir + "/drive_c/windows/system32/")
+ makedirs(self.prefix_dir + "/drive_c/openxr/")
+ try_copy(g_proton.default_pfx_dir + "drive_c/openxr/wineopenxr64.json", self.prefix_dir + "/drive_c/openxr/")
+
if use_wined3d:
dxvkfiles = ["dxvk_config"]
wined3dfiles = ["d3d11", "d3d10", "d3d10core", "d3d10_1", "d3d9"]
diff --git a/wine b/wine
-Subproject 7f9f4285c2dfb81234c01996f6d33fae0770162
+Subproject ee64c2b291290753eefdca064b89ad86e2e6fcb
diff --git a/wineopenxr/dxvk-interop.h b/wineopenxr/dxvk-interop.h
new file mode 100644
index 00000000..0871b91f
--- /dev/null
+++ b/wineopenxr/dxvk-interop.h
@@ -0,0 +1,362 @@
+/*** Autogenerated by WIDL 3.5 from /home/yorha-2b/Valve/Proton/wine/include/wine/dxvk-interop.idl - Do not edit ***/
+
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+
+#include <rpc.h>
+#include <rpcndr.h>
+
+#ifndef COM_NO_WINDOWS_H
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#ifndef __dxvk_interop_h__
+#define __dxvk_interop_h__
+
+/* Forward declarations */
+
+#ifndef __IDXGIVkInteropSurface_FWD_DEFINED__
+#define __IDXGIVkInteropSurface_FWD_DEFINED__
+typedef interface IDXGIVkInteropSurface IDXGIVkInteropSurface;
+#ifdef __cplusplus
+interface IDXGIVkInteropSurface;
+#endif /* __cplusplus */
+#endif
+
+#ifndef __IDXGIVkInteropDevice_FWD_DEFINED__
+#define __IDXGIVkInteropDevice_FWD_DEFINED__
+typedef interface IDXGIVkInteropDevice IDXGIVkInteropDevice;
+typedef interface IDXGIVkInteropDevice2 IDXGIVkInteropDevice2;
+#ifdef __cplusplus
+interface IDXGIVkInteropDevice;
+interface IDXGIVkInteropDevice2;
+#endif /* __cplusplus */
+#endif
+
+/* Headers for imported files */
+
+#include <d3d11.h>
+#include <vulkan/vulkan.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************
+ * IDXGIVkInteropSurface interface
+ */
+#ifndef __IDXGIVkInteropSurface_INTERFACE_DEFINED__
+#define __IDXGIVkInteropSurface_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIVkInteropSurface, 0x5546cf8c, 0x77e7, 0x4341, 0xb0,0x5d, 0x8d,0x4d,0x50,0x00,0xe7,0x7d);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("5546cf8c-77e7-4341-b05d-8d4d5000e77d")
+IDXGIVkInteropSurface : public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE GetDevice(
+ IDXGIVkInteropDevice** ppDevice) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVulkanImageInfo(
+ VkImage *pHandle,
+ VkImageLayout *pLayout,
+ VkImageCreateInfo *pInfo) = 0;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIVkInteropSurface, 0x5546cf8c, 0x77e7, 0x4341, 0xb0,0x5d, 0x8d,0x4d,0x50,0x00,0xe7,0x7d)
+#endif
+#else
+typedef struct IDXGIVkInteropSurfaceVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIVkInteropSurface *This,
+ REFIID riid,
+ void **ppvObject);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIVkInteropSurface *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIVkInteropSurface *This);
+
+ /*** IDXGIVkInteropSurface methods ***/
+ HRESULT (STDMETHODCALLTYPE *GetDevice)(
+ IDXGIVkInteropSurface *This,
+ IDXGIVkInteropDevice **ppDevice);
+
+ HRESULT (STDMETHODCALLTYPE *GetVulkanImageInfo)(
+ IDXGIVkInteropSurface *This,
+ VkImage *pHandle,
+ VkImageLayout *pLayout,
+ VkImageCreateInfo *pInfo);
+
+ END_INTERFACE
+} IDXGIVkInteropSurfaceVtbl;
+
+interface IDXGIVkInteropSurface {
+ CONST_VTBL IDXGIVkInteropSurfaceVtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIVkInteropSurface_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
+#define IDXGIVkInteropSurface_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIVkInteropSurface_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIVkInteropSurface methods ***/
+#define IDXGIVkInteropSurface_GetVulkanImageInfo(This,pHandle,pLayout,pInfo) (This)->lpVtbl->GetVulkanImageInfo(This,pHandle,pLayout,pInfo)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIVkInteropSurface_QueryInterface(IDXGIVkInteropSurface* This,REFIID riid,void **ppvObject) {
+ return This->lpVtbl->QueryInterface(This,riid,ppvObject);
+}
+static FORCEINLINE ULONG IDXGIVkInteropSurface_AddRef(IDXGIVkInteropSurface* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIVkInteropSurface_Release(IDXGIVkInteropSurface* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIVkInteropSurface methods ***/
+static FORCEINLINE HRESULT IDXGIVkInteropSurface_GetVulkanImageInfo(IDXGIVkInteropSurface* This,VkImage *pHandle,VkImageLayout *pLayout,VkImageCreateInfo *pInfo) {
+ return This->lpVtbl->GetVulkanImageInfo(This,pHandle,pLayout,pInfo);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIVkInteropSurface_INTERFACE_DEFINED__ */
+
+/*****************************************************************************
+ * IDXGIVkInteropDevice interface
+ */
+#ifndef __IDXGIVkInteropDevice_INTERFACE_DEFINED__
+#define __IDXGIVkInteropDevice_INTERFACE_DEFINED__
+
+DEFINE_GUID(IID_IDXGIVkInteropDevice, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x23);
+DEFINE_GUID(IID_IDXGIVkInteropDevice2, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x24);
+#if defined(__cplusplus) && !defined(CINTERFACE)
+MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323")
+IDXGIVkInteropDevice : public IUnknown
+{
+ virtual void STDMETHODCALLTYPE GetVulkanHandles(
+ VkInstance *pInstance,
+ VkPhysicalDevice *pPhysDev,
+ VkDevice *pDevice) = 0;
+
+ virtual void STDMETHODCALLTYPE GetSubmissionQueue(
+ VkQueue *pQueue,
+ uint32_t *pQueueFamilyIndex) = 0;
+
+ virtual void STDMETHODCALLTYPE TransitionSurfaceLayout(
+ IDXGIVkInteropSurface *pSurface,
+ const VkImageSubresourceRange *pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout) = 0;
+
+ virtual void STDMETHODCALLTYPE FlushRenderingCommands(
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE LockSubmissionQueue(
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE ReleaseSubmissionQueue(
+ ) = 0;
+
+};
+MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09324")
+IDXGIVkInteropDevice2 : public IDXGIVkInteropDevice
+{
+ virtual void STDMETHODCALLTYPE GetSubmissionQueue2(
+ VkQueue *pQueue,
+ uint32_t *pQueueIndex,
+ uint32_t *pQueueFamilyIndex) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateTexture2DFromVkImage(
+ const D3D11_TEXTURE2D_DESC1 *pDesc,
+ VkImage vkImage,
+ ID3D11Texture2D **ppTexture2D) = 0;
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(IDXGIVkInteropDevice, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x23)
+__CRT_UUID_DECL(IDXGIVkInteropDevice2, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x24)
+#endif
+#else
+typedef struct IDXGIVkInteropDeviceVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIVkInteropDevice *This,
+ REFIID riid,
+ void **ppvObject);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIVkInteropDevice *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIVkInteropDevice *This);
+
+ /*** IDXGIVkInteropDevice methods ***/
+ void (STDMETHODCALLTYPE *GetVulkanHandles)(
+ IDXGIVkInteropDevice *This,
+ VkInstance *pInstance,
+ VkPhysicalDevice *pPhysDev,
+ VkDevice *pDevice);
+
+ void (STDMETHODCALLTYPE *GetSubmissionQueue)(
+ IDXGIVkInteropDevice *This,
+ VkQueue *pQueue,
+ uint32_t *pQueueFamilyIndex);
+
+ void (STDMETHODCALLTYPE *TransitionSurfaceLayout)(
+ IDXGIVkInteropDevice *This,
+ IDXGIVkInteropSurface *pSurface,
+ const VkImageSubresourceRange *pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout);
+
+ void (STDMETHODCALLTYPE *FlushRenderingCommands)(
+ IDXGIVkInteropDevice *This);
+
+ void (STDMETHODCALLTYPE *LockSubmissionQueue)(
+ IDXGIVkInteropDevice *This);
+
+ void (STDMETHODCALLTYPE *ReleaseSubmissionQueue)(
+ IDXGIVkInteropDevice *This);
+
+ END_INTERFACE
+} IDXGIVkInteropDeviceVtbl;
+
+interface IDXGIVkInteropDevice {
+ CONST_VTBL IDXGIVkInteropDeviceVtbl* lpVtbl;
+};
+
+typedef struct IDXGIVkInteropDevice2Vtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IDXGIVkInteropDevice2 *This,
+ REFIID riid,
+ void **ppvObject);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IDXGIVkInteropDevice2 *This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IDXGIVkInteropDevice2 *This);
+
+ /*** IDXGIVkInteropDevice methods ***/
+ void (STDMETHODCALLTYPE *GetVulkanHandles)(
+ IDXGIVkInteropDevice2 *This,
+ VkInstance *pInstance,
+ VkPhysicalDevice *pPhysDev,
+ VkDevice *pDevice);
+
+ void (STDMETHODCALLTYPE *GetSubmissionQueue)(
+ IDXGIVkInteropDevice2 *This,
+ VkQueue *pQueue,
+ uint32_t *pQueueFamilyIndex);
+
+ void (STDMETHODCALLTYPE *TransitionSurfaceLayout)(
+ IDXGIVkInteropDevice2 *This,
+ IDXGIVkInteropSurface *pSurface,
+ const VkImageSubresourceRange *pSubresources,
+ VkImageLayout OldLayout,
+ VkImageLayout NewLayout);
+
+ void (STDMETHODCALLTYPE *FlushRenderingCommands)(
+ IDXGIVkInteropDevice2 *This);
+
+ void (STDMETHODCALLTYPE *LockSubmissionQueue)(
+ IDXGIVkInteropDevice2 *This);
+
+ void (STDMETHODCALLTYPE *ReleaseSubmissionQueue)(
+ IDXGIVkInteropDevice2 *This);
+
+ void (STDMETHODCALLTYPE *GetSubmissionQueue2)(
+ IDXGIVkInteropDevice2 *This,
+ VkQueue *pQueue,
+ uint32_t *pQueueIndex,
+ uint32_t *pQueueFamilyIndex);
+
+ HRESULT (STDMETHODCALLTYPE *CreateTexture2DFromVkImage)(
+ IDXGIVkInteropDevice2 *This,
+ const D3D11_TEXTURE2D_DESC1 *pDesc,
+ VkImage vkImage,
+ ID3D11Texture2D **ppTexture2D);
+
+ END_INTERFACE
+} IDXGIVkInteropDevice2Vtbl;
+
+interface IDXGIVkInteropDevice2 {
+ CONST_VTBL IDXGIVkInteropDevice2Vtbl* lpVtbl;
+};
+
+#ifdef COBJMACROS
+#ifndef WIDL_C_INLINE_WRAPPERS
+/*** IUnknown methods ***/
+#define IDXGIVkInteropDevice_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
+#define IDXGIVkInteropDevice_AddRef(This) (This)->lpVtbl->AddRef(This)
+#define IDXGIVkInteropDevice_Release(This) (This)->lpVtbl->Release(This)
+/*** IDXGIVkInteropDevice methods ***/
+#define IDXGIVkInteropDevice_GetVulkanHandles(This,pInstance,pPhysDev,pDevice) (This)->lpVtbl->GetVulkanHandles(This,pInstance,pPhysDev,pDevice)
+#define IDXGIVkInteropDevice_GetSubmissionQueue(This,pQueue,pQueueFamilyIndex) (This)->lpVtbl->GetSubmissionQueue(This,pQueue,pQueueFamilyIndex)
+#define IDXGIVkInteropDevice_TransitionSurfaceLayout(This,pSurface,pSubresources,OldLayout,NewLayout) (This)->lpVtbl->TransitionSurfaceLayout(This,pSurface,pSubresources,OldLayout,NewLayout)
+#define IDXGIVkInteropDevice_FlushRenderingCommands(This) (This)->lpVtbl->FlushRenderingCommands(This)
+#define IDXGIVkInteropDevice_LockSubmissionQueue(This) (This)->lpVtbl->LockSubmissionQueue(This)
+#define IDXGIVkInteropDevice_ReleaseSubmissionQueue(This) (This)->lpVtbl->ReleaseSubmissionQueue(This)
+#else
+/*** IUnknown methods ***/
+static FORCEINLINE HRESULT IDXGIVkInteropDevice_QueryInterface(IDXGIVkInteropDevice* This,REFIID riid,void **ppvObject) {
+ return This->lpVtbl->QueryInterface(This,riid,ppvObject);
+}
+static FORCEINLINE ULONG IDXGIVkInteropDevice_AddRef(IDXGIVkInteropDevice* This) {
+ return This->lpVtbl->AddRef(This);
+}
+static FORCEINLINE ULONG IDXGIVkInteropDevice_Release(IDXGIVkInteropDevice* This) {
+ return This->lpVtbl->Release(This);
+}
+/*** IDXGIVkInteropDevice methods ***/
+static FORCEINLINE void IDXGIVkInteropDevice_GetVulkanHandles(IDXGIVkInteropDevice* This,VkInstance *pInstance,VkPhysicalDevice *pPhysDev,VkDevice *pDevice) {
+ This->lpVtbl->GetVulkanHandles(This,pInstance,pPhysDev,pDevice);
+}
+static FORCEINLINE void IDXGIVkInteropDevice_GetSubmissionQueue(IDXGIVkInteropDevice* This,VkQueue *pQueue,uint32_t *pQueueFamilyIndex) {
+ This->lpVtbl->GetSubmissionQueue(This,pQueue,pQueueFamilyIndex);
+}
+static FORCEINLINE void IDXGIVkInteropDevice_TransitionSurfaceLayout(IDXGIVkInteropDevice* This,IDXGIVkInteropSurface *pSurface,const VkImageSubresourceRange *pSubresources,VkImageLayout OldLayout,VkImageLayout NewLayout) {
+ This->lpVtbl->TransitionSurfaceLayout(This,pSurface,pSubresources,OldLayout,NewLayout);
+}
+static FORCEINLINE void IDXGIVkInteropDevice_FlushRenderingCommands(IDXGIVkInteropDevice* This) {
+ This->lpVtbl->FlushRenderingCommands(This);
+}
+static FORCEINLINE void IDXGIVkInteropDevice_LockSubmissionQueue(IDXGIVkInteropDevice* This) {
+ This->lpVtbl->LockSubmissionQueue(This);
+}
+static FORCEINLINE void IDXGIVkInteropDevice_ReleaseSubmissionQueue(IDXGIVkInteropDevice* This) {
+ This->lpVtbl->ReleaseSubmissionQueue(This);
+}
+#endif
+#endif
+
+#endif
+
+
+#endif /* __IDXGIVkInteropDevice_INTERFACE_DEFINED__ */
+
+/* Begin additional prototypes for all interfaces */
+
+
+/* End additional prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __dxvk_interop_h__ */
diff --git a/wineopenxr/loader_structs.h b/wineopenxr/loader_structs.h
new file mode 100644
index 00000000..8a4ba66d
--- /dev/null
+++ b/wineopenxr/loader_structs.h
@@ -0,0 +1,30 @@
+typedef struct WINE_XR_STRUCT_NAME(XrNegotiateLoaderInfo) {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_LOADER_INFO
+ uint32_t structVersion; // XR_LOADER_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrNegotiateLoaderInfo)
+ uint32_t minInterfaceVersion;
+ uint32_t maxInterfaceVersion;
+ XrVersion minApiVersion;
+ XrVersion maxApiVersion;
+} WINE_XR_STRUCT_ATTR WINE_XR_STRUCT_NAME(XrNegotiateLoaderInfo);
+
+typedef struct WINE_XR_STRUCT_NAME(XrNegotiateRuntimeRequest) {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST
+ uint32_t structVersion; // XR_RUNTIME_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrNegotiateRuntimeRequest)
+ uint32_t runtimeInterfaceVersion; // CURRENT_LOADER_RUNTIME_VERSION
+ XrVersion runtimeApiVersion;
+ PFN_xrGetInstanceProcAddr getInstanceProcAddr;
+} WINE_XR_STRUCT_ATTR WINE_XR_STRUCT_NAME(XrNegotiateRuntimeRequest);
+
+/*
+typedef struct WINE_XR_STRUCT_NAME(XrNegotiateApiLayerRequest) {
+ XrLoaderInterfaceStructs structType;
+ uint32_t structVersion;
+ size_t structSize;
+ uint32_t layerInterfaceVersion;
+ XrVersion layerApiVersion;
+ PFN_xrGetInstanceProcAddr getInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance createApiLayerInstance;
+} WINE_XR_STRUCT_ATTR WINE_XR_STRUCT_NAME(XrNegotiateApiLayerRequest);
+*/
diff --git a/wineopenxr/make_openxr b/wineopenxr/make_openxr
new file mode 100755
index 00000000..4a41d0d9
--- /dev/null
+++ b/wineopenxr/make_openxr
@@ -0,0 +1,2893 @@
+#!/usr/bin/python3
+# Wine Vulkan generator
+#
+# Copyright 2017-2018 Roderick Colenbrander
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+
+import argparse
+import logging
+import os
+import re
+import sys
+import urllib.request
+import xml.etree.ElementTree as ET
+from collections import OrderedDict
+from collections.abc import Sequence
+from enum import Enum
+
+# This script generates code for a Wine Vulkan ICD driver from Vulkan's xr.xml.
+# Generating the code is like 10x worse than OpenGL, which is mostly a calling
+# convention passthrough.
+#
+# The script parses xr.xml and maps functions and types to helper objects. These
+# helper objects simplify the xml parsing and map closely to the Vulkan types.
+# The code generation utilizes the helper objects during code generation and
+# most of the ugly work is carried out by these objects.
+#
+# Vulkan ICD challenges:
+# - Vulkan ICD loader (vulkan-1.dll) relies on a section at the start of
+# 'dispatchable handles' (e.g. XrDevice, XrInstance) for it to insert
+# its private data. It uses this area to stare its own dispatch tables
+# for loader internal use. This means any dispatchable objects need wrapping.
+#
+# - Vulkan structures have different alignment between win32 and 32-bit Linux.
+# This means structures with alignment differences need conversion logic.
+# Often structures are nested, so the parent structure may not need any
+# conversion, but some child may need some.
+#
+# xr.xml parsing challenges:
+# - Contains type data for all platforms (generic Vulkan, Windows, Linux,..).
+# Parsing of extension information required to pull in types and functions
+# we really want to generate. Just tying all the data together is tricky.
+#
+# - Arrays are used all over the place for parameters or for structure members.
+# Array length is often stored in a previous parameter or another structure
+# member and thus needs careful parsing.
+
+LOGGER = logging.Logger("openxr")
+LOGGER.addHandler(logging.StreamHandler())
+
+XR_XML_VERSION = "1.0.11"
+WINE_XR_VERSION = (1, 0)
+
+# Filenames to create.
+WINE_OPENXR_H = "./wineopenxr.h"
+WINE_OPENXR_DRIVER_H = "./wineopenxr_driver.h"
+WINE_OPENXR_JSON = "./wineopenxr.json"
+WINE_OPENXR_THUNKS_C = "./openxr_thunks.c"
+WINE_OPENXR_THUNKS_H = "./openxr_thunks.h"
+
+# Extension enum values start at a certain offset (EXT_BASE).
+# Relative to the offset each extension has a block (EXT_BLOCK_SIZE)
+# of values.
+# Start for a given extension is:
+# EXT_BASE + (extension_number-1) * EXT_BLOCK_SIZE
+EXT_BASE = 1000000000
+EXT_BLOCK_SIZE = 1000
+
+UNSUPPORTED_EXTENSIONS = [
+ # Instance extensions
+ "XR_EXT_debug_report",
+ # Handling of XR_EXT_debug_report requires some consideration. The win32
+ # loader already provides it for us and it is somewhat usable. If we add
+ # plumbing down to the native layer, we will get each message twice as we
+ # use 2 loaders (win32+native), but we may get output from the driver.
+ # In any case callback conversion is required.
+ "XR_EXT_debug_utils",
+ "XR_EXT_validation_features",
+ "XR_EXT_validation_flags",
+ "XR_KHR_display", # Needs WSI work.
+ "XR_KHR_surface_protected_capabilities",
+
+ # Device extensions
+ "XR_AMD_display_native_hdr",
+ "XR_EXT_display_control", # Requires XR_EXT_display_surface_counter
+ "XR_EXT_full_screen_exclusive",
+ "XR_EXT_hdr_metadata", # Needs WSI work.
+ "XR_EXT_pipeline_creation_feedback",
+ "XR_GOOGLE_display_timing",
+ "XR_KHR_external_fence_win32",
+ "XR_KHR_external_memory_win32",
+ "XR_KHR_external_semaphore_win32",
+ # Relates to external_semaphore and needs type conversions in bitflags.
+ "XR_KHR_shared_presentable_image", # Needs WSI work.
+ "XR_KHR_win32_keyed_mutex",
+
+ # Extensions for other platforms
+ "XR_EXT_external_memory_dma_buf",
+ "XR_EXT_image_drm_format_modifier",
+ "XR_KHR_external_fence_fd",
+ "XR_KHR_external_memory_fd",
+ "XR_KHR_external_semaphore_fd",
+
+ # Deprecated extensions
+ "XR_NV_external_memory_capabilities",
+ "XR_NV_external_memory_win32",
+]
+
+ALLOWED_PROTECTS = [
+ "XR_USE_PLATFORM_WIN32",
+ "XR_USE_GRAPHICS_API_VULKAN",
+ "XR_USE_GRAPHICS_API_OPENGL",
+ "XR_USE_GRAPHICS_API_D3D11",
+ "XR_USE_GRAPHICS_API_D3D12",
+]
+
+# Functions part of our wineopenxr graphics driver interface.
+# DRIVER_VERSION should be bumped on any change to driver interface
+# in FUNCTION_OVERRIDES
+DRIVER_VERSION = 1
+
+# Table of functions for which we have a special implementation.
+# These are regular device / instance functions for which we need
+# to do more work compared to a regular thunk or because they are
+# part of the driver interface.
+# - dispatch set whether we need a function pointer in the device
+# / instance dispatch table.
+# - driver sets whether the API is part of the driver interface.
+# - thunk sets whether to create a thunk in openxr_thunks.c.
+FUNCTION_OVERRIDES = {
+ # Global functions
+ "xrCreateInstance" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "xrDestroyInstance" : {"dispatch" : False, "driver" : True, "thunk" : False},
+
+ "xrCreateSession" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrDestroySession" : {"dispatch" : True, "driver" : True, "thunk" : False},
+
+ "xrCreateHandTrackerEXT" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrDestroyHandTrackerEXT" : {"dispatch" : True, "driver" : True, "thunk" : False},
+
+ "xrCreateSpatialAnchorMSFT" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrDestroySpatialAnchorMSFT" : {"dispatch" : True, "driver" : True, "thunk" : False},
+
+ "xrGetInstanceProcAddr" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "xrEnumerateInstanceExtensionProperties" : {"dispatch" : False, "driver" : True, "thunk" : False},
+
+ "xrConvertTimeToWin32PerformanceCounterKHR" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "xrConvertWin32PerformanceCounterToTimeKHR" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "xrGetD3D11GraphicsRequirementsKHR" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "xrGetD3D12GraphicsRequirementsKHR" : {"dispatch" : False, "driver" : True, "thunk" : False},
+
+ "xrGetVulkanGraphicsDeviceKHR" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrGetVulkanDeviceExtensionsKHR" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrGetVulkanInstanceExtensionsKHR" : {"dispatch" : True, "driver" : True, "thunk" : False},
+
+ "xrPollEvent" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrEnumerateSwapchainImages" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrGetSystem" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrEnumerateSwapchainFormats" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrCreateSwapchain" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrDestroySwapchain" : {"dispatch" : True, "driver" : True, "thunk" : False},
+ "xrEndFrame" : {"dispatch" : True, "driver" : True, "thunk" : False},
+}
+
+STRUCT_CHAIN_CONVERSIONS = [
+ "XrInstanceCreateInfo",
+]
+
+
+class Direction(Enum):
+ """ Parameter direction: input, output, input_output. """
+ INPUT = 1
+ OUTPUT = 2
+ INPUT_OUTPUT = 3
+
+
+class XrBaseType(object):
+ def __init__(self, name, _type, text, alias=None, requires=None):
+ """ OpenXR base type class.
+
+ XrBaseType is mostly used by OpenXR to define its own
+ base types like XrFlags through typedef out of e.g. uint32_t.
+
+ Args:
+ name (:obj:'str'): Name of the base type.
+ _type (:obj:'str'): Underlying type
+ alias (bool): type is an alias or not.
+ requires (:obj:'str', optional): Other types required.
+ Often bitmask values pull in a *FlagBits type.
+ """
+ self.name = name
+ self.type = _type
+ self.alias = alias
+ self.requires = requires
+ self.required = False
+ self.text = text
+
+ def definition(self):
+ # Definition is similar for alias or non-alias as type
+ # is already set to alias.
+ return self.text + "\n"
+
+ def is_alias(self):
+ return bool(self.alias)
+
+
+class XrConstant(object):
+ def __init__(self, name, value):
+ self.name = name
+ self.value = value
+
+ def definition(self):
+ text = "#define {0} {1}\n".format(self.name, self.value)
+ return text
+
+
+class XrDefine(object):
+ def __init__(self, name, value):
+ self.name = name
+ self.value = value
+
+ @staticmethod
+ def from_xml(define):
+ name_elem = define.find("name")
+
+ if name_elem is None:
+ # <type category="define" name="some_name">some_value</type>
+ # At the time of writing there is only 1 define of this category
+ # 'XR_DEFINE_NON_DISPATCHABLE_HANDLE'.
+ name = define.attrib.get("name")
+
+ # We override behavior of XR_DEFINE_NON_DISPATCHABLE handle as the default
+ # definition various between 64-bit (uses pointers) and 32-bit (uses uint64_t).
+ # This complicates TRACEs in the thunks, so just use uint64_t.
+ if name == "XR_DEFINE_NON_DISPATCHABLE_HANDLE":
+ value = "#define XR_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;"
+ else:
+ value = define.text
+ return XrDefine(name, value)
+
+ # With a name element the structure is like:
+ # <type category="define"><name>some_name</name>some_value</type>
+ name = name_elem.text
+
+ # Perform minimal parsing for constants, which we don't need, but are referenced
+ # elsewhere in xr.xml.
+ # - XR_API_VERSION is a messy, deprecated constant and we don't want generate code for it.
+ # - AHardwareBuffer/ANativeWindow are forward declarations for Android types, which leaked
+ # into the define region.
+ if name in ["XR_API_VERSION", "ANativeWindow"]:
+ return XrDefine(name, None)
+
+ # The body of the define is basically unstructured C code. It is not meant for easy parsing.
+ # Some lines contain deprecated values or comments, which we try to filter out.
+ value = ""
+ for line in define.text.splitlines():
+ value += "\n"
+ # Skip comments or deprecated values.
+ if "//" in line:
+ continue
+ value += line
+
+ for child in define:
+ value += child.text
+ if child.tail is not None:
+ # Split comments for XR_API_VERSION_1_0 / XR_API_VERSION_1_1
+ if "//" in child.tail:
+ value += child.tail.split("//")[0]
+ else:
+ value += child.tail
+
+ return XrDefine(name, value.rstrip(' '))
+
+ def definition(self):
+ if self.value is None:
+ return ""
+
+ # Nothing to do as the value was already put in the right form during parsing.
+ return "{0}\n".format(self.value)
+
+ def is_alias(self):
+ return False
+
+
+class XrEnum(object):
+ def __init__(self, name, values, alias=None):
+ self.name = name
+ self.values = values
+ self.required = False
+ self.alias = alias
+ self.aliased_by = []
+
+ @staticmethod
+ def from_alias(enum, alias):
+ name = enum.attrib.get("name")
+ aliasee = XrEnum(name, alias.values, alias=alias)
+
+ alias.add_aliased_by(aliasee)
+ return aliasee
+
+ @staticmethod
+ def from_xml(enum):
+ name = enum.attrib.get("name")
+ values = []
+
+ for v in enum.findall("enum"):
+ # Value is either a value or a bitpos, only one can exist.
+ value = v.attrib.get("value")
+ alias_name = v.attrib.get("alias")
+ if alias_name:
+ alias = next(x for x in values if x.name == alias_name)
+ values.append(XrEnumValue(v.attrib.get("name"), value=alias.value, hex=alias.hex))
+ elif value:
+ # Some values are in hex form. We want to preserve the hex representation
+ # at least when we convert back to a string. Internally we want to use int.
+ if "0x" in value:
+ values.append(XrEnumValue(v.attrib.get("name"), value=int(value, 0), hex=True))
+ else:
+ values.append(XrEnumValue(v.attrib.get("name"), value=int(value, 0)))
+ else:
+ # bitmask
+ value = 1 << int(v.attrib.get("bitpos"))
+ values.append(XrEnumValue(v.attrib.get("name"), value=value, hex=True))
+
+ # vulkan.h contains a *_MAX_ENUM value set to 32-bit at the time of writing,
+ # which is to prepare for extensions as they can add values and hence affect
+ # the size definition.
+ max_name = re.sub(r'([0-9a-z_])([A-Z0-9])',r'\1_\2', name).upper() + "_MAX_ENUM"
+ values.append(XrEnumValue(max_name, value=0x7fffffff, hex=True))
+
+ return XrEnum(name, values)
+
+ def add(self, value):
+ """ Add a value to enum. """
+
+ # Extensions can add new enum values. When an extension is promoted to Core
+ # the registry defines the value twice once for old extension and once for
+ # new Core features. Add the duplicate if it's explicitly marked as an
+ # alias, otherwise ignore it.
+ for v in self.values:
+ if not value.is_alias() and v.value == value.value:
+ LOGGER.debug("Adding duplicate enum value {0} to {1}".format(v, self.name))
+ return
+ # Avoid adding duplicate aliases multiple times
+ if not any(x.name == value.name for x in self.values):
+ self.values.append(value)
+
+ def definition(self):
+ if self.is_alias():
+ return ""
+
+ text = "typedef enum {0}\n{{\n".format(self.name)
+
+ # Print values sorted, values can have been added in a random order.
+ values = sorted(self.values, key=lambda value: value.value if value.value is not None else 0x7ffffffe)
+ for value in values:
+ text += " {0},\n".format(value.definition())
+ text += "}} {0};\n".format(self.name)
+
+ for aliasee in self.aliased_by:
+ text += "typedef {0} {1};\n".format(self.name, aliasee.name)
+
+ text += "\n"
+ return text
+
+ def is_alias(self):
+ return bool(self.alias)
+
+ def add_aliased_by(self, aliasee):
+ self.aliased_by.append(aliasee)
+
+
+class XrEnumValue(object):
+ def __init__(self, name, value=None, hex=False, alias=None):
+ self.name = name
+ self.value = value
+ self.hex = hex
+ self.alias = alias
+
+ def __repr__(self):
+ if self.is_alias():
+ return "{0}={1}".format(self.name, self.alias)
+ return "{0}={1}".format(self.name, self.value)
+
+ def definition(self):
+ """ Convert to text definition e.g. XR_FOO = 1 """
+ if self.is_alias():
+ return "{0} = {1}".format(self.name, self.alias)
+
+ # Hex is commonly used for FlagBits and sometimes within
+ # a non-FlagBits enum for a bitmask value as well.
+ if self.hex:
+ return "{0} = 0x{1:08x}".format(self.name, self.value)
+ else:
+ return "{0} = {1}".format(self.name, self.value)
+
+ def is_alias(self):
+ return self.alias is not None
+
+
+class XrFunction(object):
+ def __init__(self, _type=None, name=None, params=[], extensions=[], alias=None):
+ self.extensions = []
+ self.name = name
+ self.type = _type
+ self.params = params
+ self.alias = alias
+
+ # For some functions we need some extra metadata from FUNCTION_OVERRIDES.
+ func_info = FUNCTION_OVERRIDES.get(self.name, None)
+ self.dispatch = func_info["dispatch"] if func_info else True
+ self.driver = func_info["driver"] if func_info else False
+ self.thunk_needed = func_info["thunk"] if func_info else True
+ self.private_thunk = func_info["private_thunk"] if func_info and "private_thunk" in func_info else False
+ if self.private_thunk:
+ self.thunk_needed = True
+
+ # Required is set while parsing which APIs and types are required
+ # and is used by the code generation.
+ self.required = True if func_info else False
+
+ @staticmethod
+ def from_alias(command, alias):
+ """ Create XrFunction from an alias command.
+
+ Args:
+ command: xml data for command
+ alias (XrFunction): function to use as a base for types / parameters.
+
+ Returns:
+ XrFunction
+ """
+ func_name = command.attrib.get("name")
+ func_type = alias.type
+ params = alias.params
+
+ return XrFunction(_type=func_type, name=func_name, params=params, alias=alias)
+
+ @staticmethod
+ def from_xml(command, types):
+ proto = command.find("proto")
+ func_name = proto.find("name").text
+ func_type = proto.find("type").text
+
+ params = []
+ for param in command.findall("param"):
+ xr_param = XrParam.from_xml(param, types)
+ params.append(xr_param)
+
+ return XrFunction(_type=func_type, name=func_name, params=params)
+
+ def get_conversions(self):
+ """ Get a list of conversion functions required for this function if any.
+ Parameters which are structures may require conversion between win32
+ and the host platform. This function returns a list of conversions
+ required.
+ """
+
+ conversions = []
+ for param in self.params:
+ convs = param.get_conversions()
+ if convs is not None:
+ conversions.extend(convs)
+
+ return conversions
+
+ def is_alias(self):
+ return bool(self.alias)
+
+ def is_core_func(self):
+ """ Returns whether the function is a core function.
+ Core functions are APIs defined by the spec to be part of the
+ Core API.
+ """
+ return not self.extensions
+
+ def is_driver_func(self):
+ """ Returns if function is part of Wine driver interface. """
+ return self.driver
+
+ def is_global_func(self):
+ # Treat xrGetInstanceProcAddr as a global function as it
+ # can operate with NULL for xrInstance.
+ if self.name == "xrGetInstanceProcAddr":
+ return True
+ # Global functions are not passed a dispatchable object.
+ elif self.params[0].is_dispatchable():
+ return False
+ return True
+
+ def is_instance_func(self):
+ # Instance functions are passed XrInstance.
+ if self.params[0].type in ["XrInstance"]:
+ return True
+ return False
+
+ def is_required(self):
+ return self.required
+
+ def needs_conversion(self):
+ """ Check if the function needs any input/output type conversion.
+ Functions need input/output conversion if struct parameters have
+ alignment differences between Win32 and Linux 32-bit.
+ """
+
+ for p in self.params:
+ if p.needs_conversion():
+ LOGGER.debug("Parameter {0} to {1} requires conversion".format(p.name, self.name))
+ return True
+
+ return False
+
+ def needs_dispatch(self):
+ return self.dispatch
+
+ def needs_thunk(self):
+ return self.thunk_needed
+
+ def needs_private_thunk(self):
+ return self.private_thunk
+
+ def pfn(self, prefix="p", call_conv=None, conv=False):
+ """ Create function pointer. """
+
+ if call_conv:
+ pfn = "{0} ({1} *{2}_{3})(".format(self.type, call_conv, prefix, self.name)
+ else:
+ pfn = "{0} (*{1}_{2})(".format(self.type, prefix, self.name)
+
+ for i, param in enumerate(self.params):
+ if param.const:
+ pfn += param.const + " "
+
+ pfn += param.type
+ if conv and param.needs_conversion():
+ pfn += "_host"
+
+ if param.is_pointer():
+ pfn += " " + param.pointer
+
+ if param.array_len is not None:
+ pfn += "[{0}]".format(param.array_len)
+
+ if i < len(self.params) - 1:
+ pfn += ", "
+ pfn += ")"
+ return pfn
+
+ def prototype(self, call_conv=None, prefix=None, postfix=None):
+ """ Generate prototype for given function.
+
+ Args:
+ call_conv (str, optional): calling convention e.g. WINAPI
+ prefix (str, optional): prefix to append prior to function name e.g. xrFoo -> wine_xrFoo
+ postfix (str, optional): text to append after function name but prior to semicolon e.g. DECLSPEC_HIDDEN
+ """
+
+ proto = "{0}".format(self.type)
+
+ if call_conv is not None:
+ proto += " {0}".format(call_conv)
+
+ if prefix is not None:
+ proto += " {0}{1}(".format(prefix, self.name)
+ else:
+ proto += " {0}(".format(self.name)
+
+ # Add all the parameters.
+ proto += ", ".join([p.definition() for p in self.params])
+
+ if postfix is not None:
+ proto += ") {0}".format(postfix)
+ else:
+ proto += ")"
+
+ return proto
+
+ def body(self):
+ body = ""
+
+ if not self.needs_private_thunk():
+ body += " {0}".format(self.trace())
+
+ params = ", ".join([p.variable(conv=False) for p in self.params])
+
+ # Call the native Vulkan function.
+ if self.is_core_func():
+ # core functions are exported by the native loader, so avoid dispatch for those
+ if self.type == "void":
+ body += " {0}({1});\n".format(self.name, params)
+ else:
+ body += " return {0}({1});\n".format(self.name, params)
+ else:
+ if self.type == "void":
+ body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
+ else:
+ body += " return {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
+
+ return body
+
+ def body_conversion(self):
+ body = ""
+
+ # Declare a variable to hold the result for non-void functions.
+ if self.type != "void":
+ body += " {0} result;\n".format(self.type)
+
+ # Declare any tmp parameters for conversion.
+ for p in self.params:
+ if not p.needs_conversion():
+ continue
+
+ if p.is_dynamic_array():
+ body += " {0}_host *{1}_host;\n".format(p.type, p.name)
+ else:
+ body += " {0}_host {1}_host;\n".format(p.type, p.name)
+
+ if not self.needs_private_thunk():
+ body += " {0}\n".format(self.trace())
+
+ # Call any win_to_host conversion calls.
+ for p in self.params:
+ if not p.needs_input_conversion():
+ continue
+
+ body += p.copy(Direction.INPUT)
+
+ # Build list of parameters containing converted and non-converted parameters.
+ # The param itself knows if conversion is needed and applies it when we set conv=True.
+ params = ", ".join([p.variable(conv=True) for p in self.params])
+
+ # Call the native function.
+ if self.type == "void":
+ body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
+ else:
+ body += " result = {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
+
+ body += "\n"
+
+ # Call any host_to_win conversion calls.
+ for p in self.params:
+ if not p.needs_output_conversion():
+ continue
+
+ body += p.copy(Direction.OUTPUT)
+
+ # Perform any required cleanups. Most of these are for array functions.
+ for p in self.params:
+ if not p.needs_free():
+ continue
+
+ body += p.free()
+
+ # Finally return the result.
+ if self.type != "void":
+ body += " return result;\n"
+
+ return body
+
+ def stub(self, call_conv=None, prefix=None):
+ stub = self.prototype(call_conv=call_conv, prefix=prefix)
+ stub += "\n{\n"
+ stub += " {0}".format(self.trace(message="stub: ", trace_func="WINE_FIXME"))
+
+ if self.type == "XrResult":
+ stub += " return XR_ERROR_OUT_OF_HOST_MEMORY;\n"
+ elif self.type == "XrBool32":
+ stub += " return XR_FALSE;\n"
+ elif self.type == "PFN_xrVoidFunction":
+ stub += " return NULL;\n"
+
+ stub += "}\n\n"
+ return stub
+
+ def thunk(self, call_conv=None, prefix=None):
+ thunk = self.prototype(call_conv=call_conv, prefix=prefix)
+ thunk += "\n{\n"
+
+ if self.needs_conversion():
+ thunk += "#if defined(USE_STRUCT_CONVERSION)\n"
+ thunk += self.body_conversion()
+ thunk += "#else\n"
+ thunk += self.body()
+ thunk += "#endif\n"
+ else:
+ thunk += self.body()
+
+ thunk += "}\n\n"
+ return thunk
+
+ def trace(self, message=None, trace_func=None):
+ """ Create a trace string including all parameters.
+
+ Args:
+ message (str, optional): text to print at start of trace message e.g. 'stub: '
+ trace_func (str, optional): used to override trace function e.g. FIXME, printf, etcetera.
+ """
+ if trace_func is not None:
+ trace = "{0}(\"".format(trace_func)
+ else:
+ trace = "WINE_TRACE(\""
+
+ if message is not None:
+ trace += message
+
+ # First loop is for all the format strings.
+ trace += ", ".join([p.format_string() for p in self.params])
+ trace += "\\n\""
+
+ # Second loop for parameter names and optional conversions.
+ for param in self.params:
+ if param.format_conv is not None:
+ trace += ", " + param.format_conv.format(param.name)
+ else:
+ trace += ", {0}".format(param.name)
+ trace += ");\n"
+
+ return trace
+
+
+class XrFunctionPointer(object):
+ def __init__(self, _type, name, members):
+ self.name = name
+ self.members = members
+ self.type = _type
+ self.required = False
+
+ @staticmethod
+ def from_xml(funcpointer):
+ members = []
+ begin = None
+
+ for t in funcpointer.findall("type"):
+ # General form:
+ # <type>void</type>* pUserData,
+ # Parsing of the tail (anything past </type>) is tricky since there
+ # can be other data on the next line like: const <type>int</type>..
+
+ const = True if begin and "const" in begin else False
+ _type = t.text
+ lines = t.tail.split(",\n")
+ if lines[0][0] == "*":
+ pointer = "*"
+ name = lines[0][1:].strip()
+ else:
+ pointer = None
+ name = lines[0].strip()
+
+ # Filter out ); if it is contained.
+ name = name.partition(");")[0]
+
+ # If tail encompasses multiple lines, assign the second line to begin
+ # for the next line.
+ try:
+ begin = lines[1].strip()
+ except IndexError:
+ begin = None
+
+ members.append(XrMember(const=const, _type=_type, pointer=pointer, name=name))
+
+ _type = funcpointer.text
+ name = funcpointer.find("name").text
+ return XrFunctionPointer(_type, name, members)
+
+ def definition(self):
+ text = "{0} {1})(\n".format(self.type, self.name)
+
+ first = True
+ if len(self.members) > 0:
+ for m in self.members:
+ if first:
+ text += " " + m.definition()
+ first = False
+ else:
+ text += ",\n " + m.definition()
+ else:
+ # Just make the compiler happy by adding a void parameter.
+ text += "void"
+ text += ");\n"
+ return text
+
+
+class XrHandle(object):
+ def __init__(self, name, _type, parent, alias=None):
+ self.name = name
+ self.type = _type
+ self.parent = parent
+ self.alias = alias
+ self.required = False
+
+ @staticmethod
+ def from_alias(handle, alias):
+ name = handle.attrib.get("name")
+ return XrHandle(name, alias.type, alias.parent, alias=alias)
+
+ @staticmethod
+ def from_xml(handle):
+ name = handle.find("name").text
+ _type = handle.find("type").text
+ parent = handle.attrib.get("parent")
+ return XrHandle(name, _type, parent)
+
+ def dispatch_table(self):
+ if not self.is_dispatchable():
+ return None
+
+ if self.parent is None:
+ # Should only happen for XrInstance
+ return "funcs"
+ if self.parent in ["XrInstance"]:
+ return "wine_instance->funcs"
+ if self.parent in ["XrSession"]:
+ return "wine_session->wine_instance->funcs"
+ if self.parent in ["XrActionSet"]:
+ return "wine_action_set->wine_instance->funcs"
+
+ LOGGER.error("Unhandled dispatchable parent: {0}".format(self.parent))
+
+ def definition(self):
+ """ Generates handle definition e.g. XR_DEFINE_HANDLE(xrInstance) """
+
+ # Legacy types are typedef'ed to the new type if they are aliases.
+ if self.is_alias():
+ return "typedef {0} {1};\n".format(self.alias.name, self.name)
+
+ return "{0}({1})\n".format(self.type, self.name)
+
+ def is_alias(self):
+ return self.alias is not None
+
+ def is_dispatchable(self):
+ """ Some handles, like XrInstance, are dispatchable objects,
+ which means they contain a dispatch table of function pointers.
+ """
+ return self.type == "XR_DEFINE_HANDLE"
+
+ def is_required(self):
+ return self.required
+
+ def native_handle(self, name):
+ """ Provide access to the native handle of a wrapped object. """
+
+ # Remember to add any new native handle whose parent is XrDevice
+ # to unwrap_object_handle() in openxr.c
+ if self.name == "XrCommandPool":
+ return "wine_cmd_pool_from_handle({0})->command_pool".format(name)
+
+ native_handle_name = None
+
+ if self.name == "XrInstance":
+ native_handle_name = "instance"
+ if self.name == "XrSession":
+ native_handle_name = "session"
+ if self.name == "XrHandTrackerEXT":
+ native_handle_name = "hand_tracker"
+ if self.name == "XrSpatialAnchorMSFT":
+ native_handle_name = "spatial_anchor"
+ if self.name == "XrSwapchain":
+ native_handle_name = "swapchain"
+ if self.name == "XrActionSet":
+ return None
+ if self.name == "XrAction":
+ return None
+ if self.name == "XrSpace":
+ return None
+
+ if native_handle_name:
+ return "((wine_{0} *){1})->{2}".format(self.name, name, native_handle_name)
+
+ if self.is_dispatchable():
+ LOGGER.error("Unhandled native handle for: {0}".format(self.name))
+ return None
+
+
+class XrMember(object):
+ def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None,
+ dyn_array_len=None, optional=False, values=None):
+ self.const = const
+ self.struct_fwd_decl = struct_fwd_decl
+ self.name = name
+ self.pointer = pointer
+ self.type = _type
+ self.type_info = None
+ self.array_len = array_len
+ self.dyn_array_len = dyn_array_len
+ self.optional = optional
+ self.values = values
+
+ def __eq__(self, other):
+ """ Compare member based on name against a string.
+
+ This method is for convenience by XrStruct, which holds a number of members and needs quick checking
+ if certain members exist.
+ """
+
+ return self.name == other
+
+ def __repr__(self):
+ return "{0} {1} {2} {3} {4} {5} {6}".format(self.const, self.struct_fwd_decl, self.type, self.pointer,
+ self.name, self.array_len, self.dyn_array_len)
+
+ @staticmethod
+ def from_xml(member):
+ """ Helper function for parsing a member tag within a struct or union. """
+
+ name_elem = member.find("name")
+ type_elem = member.find("type")
+
+ const = False
+ struct_fwd_decl = False
+ member_type = None
+ pointer = None
+ array_len = None
+
+ values = member.get("values")
+
+ if member.text:
+ if "const" in member.text:
+ const = True
+
+ # Some members contain forward declarations:
+ # - XrBaseInstructure has a member "const struct XrBaseInStructure *next"
+ # - XrWaylandSurfaceCreateInfoKHR has a member "struct wl_display *display"
+ if "struct" in member.text:
+ struct_fwd_decl = True
+
+ if type_elem is not None:
+ member_type = type_elem.text
+ if type_elem.tail is not None:
+ pointer = type_elem.tail.strip() if type_elem.tail.strip() != "" else None
+
+ # Name of other member within, which stores the number of
+ # elements pointed to be by this member.
+ dyn_array_len = member.get("len")
+
+ # Some members are optional, which is important for conversion code e.g. not dereference NULL pointer.
+ optional = True if member.get("optional") else False
+
+ # Usually we need to allocate memory for dynamic arrays. We need to do the same in a few other cases
+ # like for XrCommandBufferBeginInfo.pInheritanceInfo. Just threat such cases as dynamic arrays of
+ # size 1 to simplify code generation.
+ if dyn_array_len is None and pointer is not None:
+ dyn_array_len = 1
+
+ # Some members are arrays, attempt to parse these. Formats include:
+ # <member><type>char</type><name>extensionName</name>[<enum>XR_MAX_EXTENSION_NAME_SIZE</enum>]</member>
+ # <member><type>uint32_t</type><name>foo</name>[4]</member>
+ if name_elem.tail and name_elem.tail[0] == '[':
+ LOGGER.debug("Found array type")
+ enum_elem = member.find("enum")
+ if enum_elem is not None:
+ array_len = enum_elem.text
+ else:
+ # Remove brackets around length
+ array_len = name_elem.tail.strip("[]")
+
+ return XrMember(const=const, struct_fwd_decl=struct_fwd_decl, _type=member_type, pointer=pointer, name=name_elem.text,
+ array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, values=values)
+
+ def copy(self, input, output, direction):
+ """ Helper method for use by conversion logic to generate a C-code statement to copy this member. """
+
+ if self.needs_conversion():
+ if self.is_dynamic_array():
+ if direction == Direction.OUTPUT:
+ LOGGER.warn("TODO: implement copying of returnedonly dynamic array for {0}.{1}".format(self.type, self.name))
+ else:
+ # Array length is either a variable name (string) or an int.
+ count = self.dyn_array_len if isinstance(self.dyn_array_len, int) else "{0}{1}".format(input, self.dyn_array_len)
+ return "{0}{1} = convert_{2}_array_win_to_host({3}{1}, {4});\n".format(output, self.name, self.type, input, count)
+ elif self.is_static_array():
+ count = self.array_len
+ if direction == Direction.OUTPUT:
+ # Needed by XrMemoryHeap.memoryHeaps
+ return "convert_{0}_static_array_host_to_win({2}{1}, {3}{1}, {4});\n".format(self.type, self.name, input, output, count)
+ else:
+ # Nothing needed this yet.
+ LOGGER.warn("TODO: implement copying of static array for {0}.{1}".format(self.type, self.name))
+ else:
+ if direction == Direction.OUTPUT:
+ return "convert_{0}_host_to_win(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output)
+ else:
+ return "convert_{0}_win_to_host(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output)
+ elif self.is_static_array():
+ bytes_count = "{0} * sizeof({1})".format(self.array_len, self.type)
+ return "memcpy({0}{1}, {2}{1}, {3});\n".format(output, self.name, input, bytes_count)
+ else:
+ return "{0}{1} = {2}{1};\n".format(output, self.name, input)
+
+ def definition(self, align=False, conv=False):
+ """ Generate prototype for given function.
+
+ Args:
+ align (bool, optional): Enable alignment if a type needs it. This adds WINE_XR_ALIGN(8) to a member.
+ conv (bool, optional): Enable conversion if a type needs it. This appends '_host' to the name.
+ """
+
+ text = ""
+ if self.is_const():
+ text += "const "
+
+ if self.is_struct_forward_declaration():
+ text += "struct "
+
+ if conv and self.is_struct():
+ text += "{0}_host".format(self.type)
+ else:
+ text += self.type
+
+ if self.is_pointer():
+ text += " {0}{1}".format(self.pointer, self.name)
+ else:
+ if align and self.needs_alignment():
+ text += " WINE_XR_ALIGN(8) " + self.name
+ else:
+ text += " " + self.name
+
+ if self.is_static_array():
+ text += "[{0}]".format(self.array_len)
+
+ return text
+
+ def get_conversions(self):
+ """ Return any conversion description for this member and its children when conversion is needed. """
+
+ # Check if we need conversion either for this member itself or for any child members
+ # in case member represents a struct.
+ if not self.needs_conversion():
+ return None
+
+ conversions = []
+
+ # Collect any conversion for any member structs.
+ struct = self.type_info["data"]
+ for m in struct:
+ m.needs_struct_extensions_conversion()
+ if m.needs_conversion():
+ conversions.extend(m.get_conversions())
+
+ struct.needs_struct_extensions_conversion()
+
+ struct = self.type_info["data"]
+ direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT
+ if self.is_dynamic_array():
+ conversions.append(ConversionFunction(False, True, direction, struct))
+ elif self.is_static_array():
+ conversions.append(ConversionFunction(True, False, direction, struct))
+ else:
+ conversions.append(ConversionFunction(False, False, direction, struct))
+
+ if self.needs_free():
+ conversions.append(FreeFunction(self.is_dynamic_array(), struct))
+
+ return conversions
+
+ def is_const(self):
+ return self.const
+
+ def is_dynamic_array(self):
+ """ Returns if the member is an array element.
+ OpenXR uses this for dynamically sized arrays for which
+ there is a 'count' parameter.
+ """
+ return self.dyn_array_len is not None
+
+ def is_handle(self):
+ return self.type_info["category"] == "handle"
+
+ def is_pointer(self):
+ return self.pointer is not None
+
+ def is_static_array(self):
+ """ Returns if the member is an array.
+ OpenXR uses this often for fixed size arrays in which the
+ length is part of the member.
+ """
+ return self.array_len is not None
+
+ def is_struct(self):
+ return self.type_info["category"] == "struct"
+
+ def is_struct_forward_declaration(self):
+ return self.struct_fwd_decl
+
+ def is_union(self):
+ return self.type_info["category"] == "union"
+
+ def needs_alignment(self):
+ """ Check if this member needs alignment for 64-bit data.
+ Various structures need alignment on 64-bit variables due
+ to compiler differences on 32-bit between Win32 and Linux.
+ """
+
+ if self.is_pointer():
+ return False
+ elif self.type == "size_t":
+ return False
+ elif self.type in ["uint64_t"]:
+ return True
+ elif self.is_struct():
+ struct = self.type_info["data"]
+ return struct.needs_alignment()
+ elif self.is_handle():
+ # Dispatchable handles are pointers to objects, while
+ # non-dispatchable are uint64_t and hence need alignment.
+ handle = self.type_info["data"]
+ return False if handle.is_dispatchable() else True
+ return False
+
+ def needs_conversion(self):
+ """ Structures requiring alignment, need conversion between win32 and host. """
+
+ if not self.is_struct():
+ return False
+
+ struct = self.type_info["data"]
+ return struct.needs_conversion()
+
+ def needs_free(self):
+ if not self.needs_conversion():
+ return False
+
+ if self.is_dynamic_array():
+ return True
+
+ # TODO: some non-pointer structs and optional pointer structs may need freeing,
+ # though none of this type have been encountered yet.
+ return False
+
+ def needs_struct_extensions_conversion(self):
+ if not self.is_struct():
+ return False
+
+ struct = self.type_info["data"]
+ return struct.needs_struct_extensions_conversion()
+
+ def set_type_info(self, type_info):
+ """ Helper function to set type information from the type registry.
+ This is needed, because not all type data is available at time of
+ parsing.
+ """
+ self.type_info = type_info
+
+
+class XrParam(object):
+ """ Helper class which describes a parameter to a function call. """
+
+ def __init__(self, type_info, const=None, pointer=None, name=None, array_len=None, dyn_array_len=None):
+ self.const = const
+ self.name = name
+ self.array_len = array_len
+ self.dyn_array_len = dyn_array_len
+ self.pointer = pointer
+ self.type_info = type_info
+ self.type = type_info["name"] # For convenience
+ self.handle = type_info["data"] if type_info["category"] == "handle" else None
+ self.struct = type_info["data"] if type_info["category"] == "struct" else None
+
+ self._set_direction()
+ self._set_format_string()
+ self._set_conversions()
+
+ def __repr__(self):
+ return "{0} {1} {2} {3} {4} {5}".format(self.const, self.type, self.pointer, self.name, self.array_len, self.dyn_array_len)
+
+ @staticmethod
+ def from_xml(param, types):
+ """ Helper function to create XrParam from xml. """
+
+ # Parameter parsing is slightly tricky. All the data is contained within
+ # a param tag, but some data is within subtags while others are text
+ # before or after the type tag.
+ # Common structure:
+ # <param>const <type>char</type>* <name>pLayerName</name></param>
+
+ name_elem = param.find("name")
+ array_len = None
+ name = name_elem.text
+ # Tail contains array length e.g. for blendConstants param of xrSetBlendConstants
+ if name_elem.tail is not None:
+ array_len = name_elem.tail.strip("[]")
+
+ # Name of other parameter in function prototype, which stores the number of
+ # elements pointed to be by this parameter.
+ dyn_array_len = param.get("len", None)
+
+ const = param.text.strip() if param.text else None
+ type_elem = param.find("type")
+ pointer = type_elem.tail.strip() if type_elem.tail.strip() != "" else None
+
+ # Since we have parsed all types before hand, this should not happen.
+ type_info = types.get(type_elem.text, None)
+ if type_info is None:
+ LOGGER.err("type info not found for: {0}".format(type_elem.text))
+
+ return XrParam(type_info, const=const, pointer=pointer, name=name, array_len=array_len, dyn_array_len=dyn_array_len)
+
+ def _set_conversions(self):
+ """ Internal helper function to configure any needed conversion functions. """
+
+ self.free_func = None
+ self.input_conv = None
+ self.output_conv = None
+ if not self.needs_conversion():
+ return
+
+ # Input functions require win to host conversion.
+ if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]:
+ self.input_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.INPUT, self.struct)
+
+ # Output functions require host to win conversion.
+ if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]:
+ self.output_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.OUTPUT, self.struct)
+
+ # Dynamic arrays, but also some normal structs (e.g. XrCommandBufferBeginInfo) need memory
+ # allocation and thus some cleanup.
+ if self.is_dynamic_array() or self.struct.needs_free():
+ self.free_func = FreeFunction(self.is_dynamic_array(), self.struct)
+
+ def _set_direction(self):
+ """ Internal helper function to set parameter direction (input/output/input_output). """
+
+ # The parameter direction needs to be determined from hints in xr.xml like returnedonly,
+ # parameter constness and other heuristics.
+ # For now we need to get this right for structures as we need to convert these, we may have
+ # missed a few other edge cases (e.g. count variables).
+ # See also https://github.com/KhronosGroup/Vulkan-Docs/issues/610
+
+ if not self.is_pointer():
+ self._direction = Direction.INPUT
+ elif self.is_const() and self.is_pointer():
+ self._direction = Direction.INPUT
+ elif self.is_struct():
+ if not self.struct.returnedonly:
+ self._direction = Direction.INPUT
+ return
+
+ # Returnedonly hints towards output, however in some cases
+ # it is inputoutput. In particular if next / type exist,
+ # which are used to link in other structures without having
+ # to introduce new APIs. E.g. xrGetPhysicalDeviceProperties2KHR.
+ if "next" in self.struct:
+ self._direction = Direction.INPUT_OUTPUT
+ return
+
+ self._direction = Direction.OUTPUT
+ else:
+ # This should mostly be right. Count variables can be inout, but we don't care about these yet.
+ self._direction = Direction.OUTPUT
+
+ def _set_format_string(self):
+ """ Internal helper function to be used by constructor to set format string. """
+
+ # Determine a format string used by code generation for traces.
+ # 64-bit types need a conversion function.
+ self.format_conv = None
+ if self.is_static_array() or self.is_pointer():
+ self.format_str = "%p"
+ else:
+ if self.type_info["category"] in ["bitmask", "enum"]:
+ self.format_str = "%#x"
+ elif self.is_handle():
+ # We use uint64_t for non-dispatchable handles as opposed to pointers
+ # for dispatchable handles.
+ if self.handle.is_dispatchable():
+ self.format_str = "%p"
+ else:
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type == "float":
+ self.format_str = "%f"
+ elif self.type == "int":
+ self.format_str = "%d"
+ elif self.type == "int32_t":
+ self.format_str = "%d"
+ elif self.type == "size_t":
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type in ["uint16_t", "uint32_t", "XrBool32"]:
+ self.format_str = "%u"
+ elif self.type in ["uint64_t"]:
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type == "HANDLE":
+ self.format_str = "%p"
+ elif self.type in ["XrSystemId", "XrPath", "XrTime"]:
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type in ["XrVector2f"]:
+ self.format_str = "%f, %f"
+ self.format_conv = "{0}.x, {0}.y"
+ elif self.type in ["VisualID", "xcb_visualid_t", "VkInstance", "XrPosef"]:
+ # Don't care about Linux specific types.
+ self.format_str = ""
+ else:
+ LOGGER.warning("Unhandled type: {0}".format(self.type_info))
+
+ def copy(self, direction):
+ if direction == Direction.INPUT:
+ if self.is_dynamic_array():
+ return " {0}_host = convert_{1}_array_win_to_host({0}, {2});\n".format(self.name, self.type, self.dyn_array_len)
+ else:
+ return " convert_{0}_win_to_host({1}, &{1}_host);\n".format(self.type, self.name)
+ else:
+ if self.is_dynamic_array():
+ LOGGER.error("Unimplemented output conversion for: {0}".format(self.name))
+ else:
+ return " convert_{0}_host_to_win(&{1}_host, {1});\n".format(self.type, self.name)
+
+ def definition(self, postfix=None):
+ """ Return prototype for the parameter. E.g. 'const char *foo' """
+
+ proto = ""
+ if self.const:
+ proto += self.const + " "
+
+ proto += self.type
+
+ if self.is_pointer():
+ proto += " {0}{1}".format(self.pointer, self.name)
+ else:
+ proto += " " + self.name
+
+ # Allows appending something to the variable name useful for
+ # win32 to host conversion.
+ if postfix is not None:
+ proto += postfix
+
+ if self.is_static_array():
+ proto += "[{0}]".format(self.array_len)
+
+ return proto
+
+ def direction(self):
+ """ Returns parameter direction: input, output, input_output.
+
+ Parameter direction in OpenXR is not straight-forward, which this function determines.
+ """
+
+ return self._direction
+
+ def dispatch_table(self):
+ """ Return functions dispatch table pointer for dispatchable objects. """
+
+ if not self.is_dispatchable():
+ return None
+
+ return "((wine_{0} *){1})->{2}".format(self.type, self.name, self.handle.dispatch_table())
+
+ def format_string(self):
+ return self.format_str
+
+ def free(self):
+ if self.is_dynamic_array():
+ if self.struct.returnedonly:
+ # For returnedonly, counts is stored in a pointer.
+ return " free_{0}_array({1}_host, *{2});\n".format(self.type, self.name, self.dyn_array_len)
+ else:
+ return " free_{0}_array({1}_host, {2});\n".format(self.type, self.name, self.dyn_array_len)
+ else:
+ # We are operating on a single structure. Some structs (very rare) contain dynamic members,
+ # which would need freeing.
+ if self.struct.needs_free():
+ return " free_{0}(&{1}_host);\n".format(self.type, self.name)
+ return ""
+
+ def get_conversions(self):
+ """ Get a list of conversions required for this parameter if any.
+ Parameters which are structures may require conversion between win32
+ and the host platform. This function returns a list of conversions
+ required.
+ """
+
+ if not self.is_struct():
+ return None
+
+ self.struct.needs_struct_extensions_conversion()
+ for m in self.struct:
+ m.needs_struct_extensions_conversion()
+
+ if not self.needs_conversion():
+ return None
+
+ conversions = []
+
+ # Collect any member conversions first, so we can guarantee
+ # those functions will be defined prior to usage by the
+ # 'parent' param requiring conversion.
+ for m in self.struct:
+ if not m.is_struct():
+ continue
+
+ if not m.needs_conversion():
+ continue
+
+ conversions.extend(m.get_conversions())
+
+ # Conversion requirements for the 'parent' parameter.
+ if self.input_conv is not None:
+ conversions.append(self.input_conv)
+ if self.output_conv is not None:
+ conversions.append(self.output_conv)
+ if self.free_func is not None:
+ conversions.append(self.free_func)
+
+ return conversions
+
+ def is_const(self):
+ return self.const is not None
+
+ def is_dynamic_array(self):
+ return self.dyn_array_len is not None
+
+ def is_dispatchable(self):
+ if not self.is_handle():
+ return False
+
+ return self.handle.is_dispatchable()
+
+ def is_handle(self):
+ return self.handle is not None
+
+ def is_pointer(self):
+ return self.pointer is not None
+
+ def is_static_array(self):
+ return self.array_len is not None
+
+ def is_struct(self):
+ return self.struct is not None
+
+ def needs_conversion(self):
+ """ Returns if parameter needs conversion between win32 and host. """
+
+ if not self.is_struct():
+ return False
+
+ # If a structure needs alignment changes, it means we need to
+ # perform parameter conversion between win32 and host.
+ if self.struct.needs_conversion():
+ return True
+
+ return False
+
+ def needs_free(self):
+ return self.free_func is not None
+
+ def needs_input_conversion(self):
+ return self.input_conv is not None
+
+ def needs_output_conversion(self):
+ return self.output_conv is not None
+
+ def variable(self, conv=False):
+ """ Returns 'glue' code during generation of a function call on how to access the variable.
+ This function handles various scenarios such as 'unwrapping' if dispatchable objects and
+ renaming of parameters in case of win32 -> host conversion.
+
+ Args:
+ conv (bool, optional): Enable conversion if the param needs it. This appends '_host' to the name.
+ """
+
+ if conv and self.needs_conversion():
+ if self.is_dynamic_array():
+ return "{0}_host".format(self.name)
+ else:
+ return "&{0}_host".format(self.name)
+ else:
+ # We need to pass the native handle to the native calls.
+ native_handle = self.handle.native_handle(self.name) if self.is_handle() else None
+ return native_handle if native_handle else self.name
+
+
+class XrStruct(Sequence):
+ """ Class which represents the type union and struct. """
+
+ def __init__(self, name, members, returnedonly, structextends, alias=None, union=False):
+ self.name = name
+ self.members = members
+ self.returnedonly = returnedonly
+ self.structextends = structextends
+ self.required = False
+ self.alias = alias
+ self.union = union
+ self.type_info = None # To be set later.
+ self.struct_extensions = []
+ self.aliased_by = []
+
+ def __getitem__(self, i):
+ return self.members[i]
+
+ def __len__(self):
+ return len(self.members)
+
+ @staticmethod
+ def from_alias(struct, alias):
+ name = struct.attrib.get("name")
+ aliasee = XrStruct(name, alias.members, alias.returnedonly, alias.structextends, alias=alias)
+
+ alias.add_aliased_by(aliasee)
+ return aliasee
+
+ @staticmethod
+ def from_xml(struct):
+ # Unions and structs are the same parsing wise, but we need to
+ # know which one we are dealing with later on for code generation.
+ union = True if struct.attrib["category"] == "union" else False
+
+ name = struct.attrib.get("name")
+
+ # 'Output' structures for which data is filled in by the API are
+ # marked as 'returnedonly'.
+ returnedonly = True if struct.attrib.get("returnedonly") else False
+
+ structextends = struct.attrib.get("structextends")
+ structextends = structextends.split(",") if structextends else []
+
+ members = []
+ for member in struct.findall("member"):
+ xr_member = XrMember.from_xml(member)
+ members.append(xr_member)
+
+ return XrStruct(name, members, returnedonly, structextends, union=union)
+
+ @staticmethod
+ def decouple_structs(structs):
+ """ Helper function which decouples a list of structs.
+ Structures often depend on other structures. To make the C compiler
+ happy we need to define 'substructures' first. This function analyzes
+ the list of structures and reorders them in such a way that they are
+ decoupled.
+ """
+
+ tmp_structs = list(structs) # Don't modify the original structures.
+ decoupled_structs = []
+
+ while (len(tmp_structs) > 0):
+ for struct in tmp_structs:
+ dependends = False
+
+ if not struct.required:
+ tmp_structs.remove(struct)
+ continue
+
+ for m in struct:
+ if not (m.is_struct() or m.is_union()):
+ continue
+
+ # XrBaseInstructure and XrBaseOutStructure reference themselves.
+ if m.type == struct.name:
+ break
+
+ found = False
+ # Check if a struct we depend on has already been defined.
+ for s in decoupled_structs:
+ if s.name == m.type:
+ found = True
+ break
+
+ if not found:
+ # Check if the struct we depend on is even in the list of structs.
+ # If found now, it means we haven't met all dependencies before we
+ # can operate on the current struct.
+ # When generating 'host' structs we may not be able to find a struct
+ # as the list would only contain the structs requiring conversion.
+ for s in tmp_structs:
+ if s.name == m.type:
+ dependends = True
+ break
+
+ if dependends == False:
+ decoupled_structs.append(struct)
+ tmp_structs.remove(struct)
+
+ return decoupled_structs
+
+ def typedef(self):
+ if self.union:
+ text = "typedef union {0} {0};\n".format(self.name)
+ else:
+ text = "typedef struct {0} {0};\n".format(self.name)
+
+ for aliasee in self.aliased_by:
+ text += "typedef {0} {1};\n".format(self.name, aliasee.name)
+
+ return text
+
+ def definition(self, align=False, conv=False, postfix=None):
+ """ Convert structure to textual definition.
+
+ Args:
+ align (bool, optional): enable alignment to 64-bit for win32 struct compatibility.
+ conv (bool, optional): enable struct conversion if the struct needs it.
+ postfix (str, optional): text to append to end of struct name, useful for struct renaming.
+ """
+
+ # Only define alias structs when doing conversions
+ if self.is_alias() and not conv:
+ return ""
+
+ if self.union:
+ text = "union {0}".format(self.name)
+ else:
+ text = "struct {0}".format(self.name)
+
+ if postfix is not None:
+ text += postfix
+
+ text += "\n{\n"
+
+ for m in self:
+ if align and m.needs_alignment():
+ text += " {0};\n".format(m.definition(align=align))
+ elif conv and m.needs_conversion():
+ text += " {0};\n".format(m.definition(conv=conv))
+ else:
+ text += " {0};\n".format(m.definition())
+
+ if postfix is not None:
+ text += "}} {1};\n\n".format(self.name, postfix)
+ else:
+ text += "}};\n".format(self.name)
+
+ text += "\n"
+
+ return text
+
+ def is_alias(self):
+ return bool(self.alias)
+
+ def add_aliased_by(self, aliasee):
+ self.aliased_by.append(aliasee)
+
+ def needs_alignment(self):
+ """ Check if structure needs alignment for 64-bit data.
+ Various structures need alignment on 64-bit variables due
+ to compiler differences on 32-bit between Win32 and Linux.
+ """
+
+ for m in self.members:
+ if m.needs_alignment():
+ return True
+ return False
+
+ def needs_conversion(self):
+ """ Returns if struct members needs conversion between win32 and host.
+ Structures need conversion if they contain members requiring alignment
+ or if they include other structures which need alignment.
+ """
+
+ if self.needs_alignment():
+ return True
+
+ for m in self.members:
+ if m.needs_conversion():
+ return True
+ return False
+
+ def needs_free(self):
+ """ Check if any struct member needs some memory freeing."""
+
+ for m in self.members:
+ if m.needs_free():
+ return True
+
+ continue
+
+ return False
+
+ def needs_struct_extensions_conversion(self):
+ """ Checks if structure extensions in next chain need conversion. """
+ ret = False
+
+ for e in self.struct_extensions:
+ if e.required and e.needs_conversion():
+ LOGGER.error("Unhandled next chain conversion for {0}".format(e.name))
+ ret = True
+
+ return ret
+
+ def set_type_info(self, types):
+ """ Helper function to set type information from the type registry.
+ This is needed, because not all type data is available at time of
+ parsing.
+ """
+ for m in self.members:
+ type_info = types[m.type]
+ m.set_type_info(type_info)
+
+
+class ConversionFunction(object):
+ def __init__(self, array, dyn_array, direction, struct):
+ self.array = array
+ self.direction = direction
+ self.dyn_array = dyn_array
+ self.struct = struct
+ self.type = struct.name
+
+ self._set_name()
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def _generate_array_conversion_func(self):
+ """ Helper function for generating a conversion function for array structs. """
+
+ if self.direction == Direction.OUTPUT:
+ params = ["const {0}_host *in".format(self.type), "uint32_t count"]
+ return_type = self.type
+ else:
+ params = ["const {0} *in".format(self.type), "uint32_t count"]
+ return_type = "{0}_host".format(self.type)
+
+ # Generate function prototype.
+ body = "static inline {0} *{1}(".format(return_type, self.name)
+ body += ", ".join(p for p in params)
+ body += ")\n{\n"
+
+ body += " {0} *out;\n".format(return_type)
+ body += " unsigned int i;\n\n"
+ body += " if (!in) return NULL;\n\n"
+
+ body += " out = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*out));\n"
+
+ body += " for (i = 0; i < count; i++)\n"
+ body += " {\n"
+
+ for m in self.struct:
+ # TODO: support copying of next extension structures!
+ # Luckily though no extension struct at this point needs conversion.
+ body += " " + m.copy("in[i].", "out[i].", self.direction)
+
+ body += " }\n\n"
+ body += " return out;\n"
+ body += "}\n\n"
+ return body
+
+ def _generate_conversion_func(self):
+ """ Helper function for generating a conversion function for non-array structs. """
+
+ if self.direction == Direction.OUTPUT:
+ params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type)]
+ else:
+ params = ["const {0} *in".format(self.type), "{0}_host *out".format(self.type)]
+
+ body = "static inline void {0}(".format(self.name)
+
+ # Generate parameter list
+ body += ", ".join(p for p in params)
+ body += ")\n{\n"
+
+ body += " if (!in) return;\n\n"
+
+ if self.direction == Direction.INPUT and "next" in self.struct and self.struct.returnedonly:
+ # We are dealing with an input_output parameter. For these we only need to copy
+ # next and type as the other fields are filled in by the host. We do potentially
+ # have to iterate over next and perform conversions based on switch(type)!
+ # Luckily though no extension structs at this point need conversion.
+ # TODO: support copying of next extension structures!
+ body += " out->next = in->next;\n"
+ body += " out->type = in->type;\n"
+ else:
+ for m in self.struct:
+ # TODO: support copying of next extension structures!
+ body += " " + m.copy("in->", "out->", self.direction)
+
+ body += "}\n\n"
+ return body
+
+ def _generate_static_array_conversion_func(self):
+ """ Helper function for generating a conversion function for array structs. """
+
+ if self.direction == Direction.OUTPUT:
+ params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type), "uint32_t count"]
+ else:
+ params = ["const {0} *in".format(self.type), "{0} *out_host".format(self.type), "uint32_t count"]
+
+ # Generate function prototype.
+ body = "static inline void {0}(".format(self.name)
+ body += ", ".join(p for p in params)
+ body += ")\n{\n"
+ body += " unsigned int i;\n\n"
+ body += " if (!in) return;\n\n"
+ body += " for (i = 0; i < count; i++)\n"
+ body += " {\n"
+
+ for m in self.struct:
+ # TODO: support copying of next extension structures!
+ body += " " + m.copy("in[i].", "out[i].", self.direction)
+
+ body += " }\n"
+ body += "}\n\n"
+ return body
+
+ def _set_name(self):
+ if self.direction == Direction.INPUT:
+ if self.array:
+ name = "convert_{0}_static_array_win_to_host".format(self.type)
+ elif self.dyn_array:
+ name = "convert_{0}_array_win_to_host".format(self.type)
+ else:
+ name = "convert_{0}_win_to_host".format(self.type)
+ else: # Direction.OUTPUT
+ if self.array:
+ name = "convert_{0}_static_array_host_to_win".format(self.type)
+ elif self.dyn_array:
+ name = "convert_{0}_array_host_to_win".format(self.type)
+ else:
+ name = "convert_{0}_host_to_win".format(self.type)
+
+ self.name = name
+
+ def definition(self):
+ if self.array:
+ return self._generate_static_array_conversion_func()
+ elif self.dyn_array:
+ return self._generate_array_conversion_func()
+ else:
+ return self._generate_conversion_func()
+
+
+class FreeFunction(object):
+ def __init__(self, dyn_array, struct):
+ self.dyn_array = dyn_array
+ self.struct = struct
+ self.type = struct.name
+
+ if dyn_array:
+ self.name = "free_{0}_array".format(self.type)
+ else:
+ self.name = "free_{0}".format(self.type)
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def _generate_array_free_func(self):
+ """ Helper function for cleaning up temporary buffers required for array conversions. """
+
+ # Generate function prototype.
+ body = "static inline void {0}({1}_host *in, uint32_t count)\n{{\n".format(self.name, self.type)
+
+ # E.g. XrGraphicsPipelineCreateInfo_host needs freeing for pStages.
+ if self.struct.needs_free():
+ body += " unsigned int i;\n\n"
+ body += " if (!in) return;\n\n"
+ body += " for (i = 0; i < count; i++)\n"
+ body += " {\n"
+
+ for m in self.struct:
+ if m.needs_conversion() and m.is_dynamic_array():
+ if m.is_const():
+ # Add a cast to ignore const on conversion structs we allocated ourselves.
+ body += " free_{0}_array(({0}_host *)in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len)
+ else:
+ body += " free_{0}_array(in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len)
+ elif m.needs_conversion():
+ LOGGER.error("Unhandled conversion for {0}".format(m.name))
+ body += " }\n"
+ else:
+ body += " if (!in) return;\n\n"
+
+ body += " HeapFree(GetProcessHeap(), 0, in);\n"
+
+ body += "}\n\n"
+ return body
+
+ def _generate_free_func(self):
+ # E.g. XrCommandBufferBeginInfo.pInheritanceInfo needs freeing.
+ if not self.struct.needs_free():
+ return ""
+
+ # Generate function prototype.
+ body = "static inline void {0}({1}_host *in)\n{{\n".format(self.name, self.type)
+
+ for m in self.struct:
+ if m.needs_conversion() and m.is_dynamic_array():
+ count = m.dyn_array_len if isinstance(m.dyn_array_len, int) else "in->{0}".format(m.dyn_array_len)
+ if m.is_const():
+ # Add a cast to ignore const on conversion structs we allocated ourselves.
+ body += " free_{0}_array(({0}_host *)in->{1}, {2});\n".format(m.type, m.name, count)
+ else:
+ body += " free_{0}_array(in->{1}, {2});\n".format(m.type, m.name, count)
+
+ body += "}\n\n"
+ return body
+
+ def definition(self):
+ if self.dyn_array:
+ return self._generate_array_free_func()
+ else:
+ # Some structures need freeing too if they contain dynamic arrays.
+ # E.g. XrCommandBufferBeginInfo
+ return self._generate_free_func()
+
+
+class StructChainConversionFunction(object):
+ def __init__(self, direction, struct):
+ self.direction = direction
+ self.struct = struct
+ self.type = struct.name
+
+ self.name = "convert_{0}_struct_chain".format(self.type)
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def prototype(self, postfix=""):
+ return "XrResult {0}(const void *next, {1} *out_struct) {2}".format(self.name, self.type, postfix).strip()
+
+ def definition(self):
+ body = self.prototype()
+ body += "\n{\n"
+
+ body += " XrBaseOutStructure *out_header = (XrBaseOutStructure *)out_struct;\n";
+ body += " const XrBaseInStructure *in_header;\n\n";
+
+ body += " out_header->next = NULL;\n\n"
+
+ body += " for (in_header = next; in_header; in_header = in_header->next)\n"
+ body += " {\n"
+ body += " switch (in_header->type)\n"
+ body += " {\n"
+
+ # Ignore to not confuse host loader.
+ body += " case XR_TYPE_INSTANCE_CREATE_INFO:\n"
+ body += " break;\n\n"
+
+ for e in self.struct.struct_extensions:
+ if not e.required:
+ continue
+
+ stype = next(x for x in e.members if x.name == "type")
+
+ body += " case {0}:\n".format(stype.values)
+ body += " {\n"
+
+ body += " const {0} *in = (const {0} *)in_header;\n".format(e.name)
+ body += " {0} *out;\n\n".format(e.name)
+
+ body += " if (!(out = HeapAlloc(GetProcessHeap(), 0, sizeof(*out)))) goto out_of_memory;\n\n"
+
+ for m in e:
+ if m.name == "next":
+ body += " out->next = NULL;\n"
+ else:
+ body += " " + m.copy("in->", "out->", self.direction)
+
+ body += "\n out_header->next = (XrBaseOutStructure *)out;\n"
+ body += " out_header = out_header->next;\n"
+ body += " break;\n"
+ body += " }\n\n"
+
+ body += " default:\n"
+ body += " WINE_FIXME(\"Application requested a linked structure of type %u.\\n\", in_header->type);\n"
+
+ body += " }\n"
+ body += " }\n\n"
+
+ body += " return XR_SUCCESS;\n"
+
+ if any(x for x in self.struct.struct_extensions if x.required):
+ body += "\nout_of_memory:\n"
+ body += " free_{0}_struct_chain(out_struct);\n".format(self.type)
+ body += " return XR_ERROR_OUT_OF_HOST_MEMORY;\n"
+
+ body += "}\n\n"
+ return body
+
+class FreeStructChainFunction(object):
+ def __init__(self, struct):
+ self.struct = struct
+ self.type = struct.name
+
+ self.name = "free_{0}_struct_chain".format(self.type)
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def prototype(self, postfix=""):
+ return "void {0}({1} *s) {2}".format(self.name, self.type, postfix).strip()
+
+ def definition(self):
+ body = self.prototype()
+ body += "\n{\n"
+
+ body += " XrBaseOutStructure *header = (void *)s->next;\n\n";
+
+ body += " while (header)\n"
+ body += " {\n"
+ body += " void *prev = header;\n"
+ body += " header = header->next;\n"
+ body += " HeapFree(GetProcessHeap(), 0, prev);\n"
+ body += " }\n\n"
+
+ body += " s->next = NULL;\n"
+
+ body += "}\n\n"
+ return body
+
+
+class XrGenerator(object):
+ def __init__(self, registry):
+ self.registry = registry
+
+ # Build a list conversion functions for struct conversion.
+ self.conversions = []
+ self.struct_chain_conversions = []
+ self.host_structs = []
+ for func in self.registry.funcs.values():
+ if not func.is_required():
+ continue
+
+ if not func.needs_conversion():
+ continue
+
+ conversions = func.get_conversions()
+ for conv in conversions:
+ # Pull in any conversions for openxr_thunks.c.
+ if func.needs_thunk():
+ # Append if we don't already have this conversion.
+ if not any(c == conv for c in self.conversions):
+ self.conversions.append(conv)
+
+ # Structs can be used in different ways by different conversions
+ # e.g. array vs non-array. Just make sure we pull in each struct once.
+ if not any(s.name == conv.struct.name for s in self.host_structs):
+ self.host_structs.append(conv.struct)
+
+ for struct in self.registry.structs:
+ if struct.name in STRUCT_CHAIN_CONVERSIONS:
+ self.struct_chain_conversions.append(StructChainConversionFunction(Direction.INPUT, struct))
+ self.struct_chain_conversions.append(FreeStructChainFunction(struct))
+
+ def _generate_copyright(self, f, spec_file=False):
+ f.write("# " if spec_file else "/* ")
+ f.write("Automatically generated from OpenXR xr.xml; DO NOT EDIT!\n")
+ lines = ["", "This file is generated from OpenXR xr.xml file covered",
+ "by the following copyright and permission notice:"]
+ lines.extend([l.rstrip(" ") for l in self.registry.copyright.splitlines()])
+ for line in lines:
+ f.write("{0}{1}".format("# " if spec_file else " * ", line).rstrip(" ") + "\n")
+ f.write("\n" if spec_file else " */\n\n")
+
+ def generate_thunks_c(self, f, prefix):
+ self._generate_copyright(f)
+
+ f.write("#include \"wine/debug.h\"\n")
+ f.write("#include \"wine/vulkan.h\"\n")
+ f.write("#include \"d3d11.h\"\n")
+ f.write("#include \"d3d12.h\"\n")
+ f.write("#define WINE_XR_HOST\n")
+ f.write("#include \"wineopenxr.h\"\n")
+ f.write("#include \"openxr_private.h\"\n\n")
+
+ f.write("WINE_DEFAULT_DEBUG_CHANNEL(openxr);\n\n")
+
+ # Generate any conversion helper functions.
+ f.write("#if defined(USE_STRUCT_CONVERSION)\n")
+ for conv in self.conversions:
+ f.write(conv.definition())
+ f.write("#endif /* USE_STRUCT_CONVERSION */\n\n")
+
+ for conv in self.struct_chain_conversions:
+ f.write(conv.definition())
+
+ # Create thunks for instance and device functions.
+ # Global functions don't go through the thunks.
+ for xr_func in self.registry.funcs.values():
+ if not xr_func.is_required():
+ continue
+
+ #if xr_func.is_global_func():
+ # continue
+
+ if not xr_func.needs_thunk():
+ continue
+
+ # Exports symbols for Core functions.
+ if not xr_func.is_core_func() and not xr_func.needs_private_thunk():
+ f.write("static ")
+
+ if xr_func.needs_private_thunk():
+ f.write(xr_func.thunk(prefix="thunk_"))
+ else:
+ f.write(xr_func.thunk(prefix=prefix, call_conv="WINAPI"))
+
+ f.write("static const struct openxr_func xr_dispatch_table[] =\n{\n")
+ for xr_func in self.registry.instance_funcs:
+ if not xr_func.is_required():
+ continue
+ f.write(" {{\"{0}\", &{1}{0}}},\n".format(xr_func.name, prefix))
+ f.write("};\n\n")
+
+ f.write("void *wine_xr_proc_addr(const char *name)\n")
+ f.write("{\n")
+ f.write(" unsigned int i;\n")
+ f.write(" for (i = 0; i < ARRAY_SIZE(xr_dispatch_table); i++)\n")
+ f.write(" {\n")
+ f.write(" if (strcmp(xr_dispatch_table[i].name, name) == 0)\n")
+ f.write(" {\n")
+ f.write(" WINE_TRACE(\"Found name=%s in instance table\\n\", wine_dbgstr_a(name));\n")
+ f.write(" return xr_dispatch_table[i].func;\n")
+ f.write(" }\n")
+ f.write(" }\n")
+ f.write(" return NULL;\n")
+ f.write("}\n\n")
+
+ # Create array of instance extensions.
+ f.write("static const char * const xr_extensions[] =\n{\n")
+ for ext in self.registry.extensions:
+ f.write(" \"{0}\",\n".format(ext["name"]))
+ f.write("};\n\n")
+
+ f.write("BOOL wine_xr_extension_supported(const char *name)\n")
+ f.write("{\n")
+ f.write(" unsigned int i;\n")
+ f.write(" for (i = 0; i < ARRAY_SIZE(xr_extensions); i++)\n")
+ f.write(" {\n")
+ f.write(" if (strcmp(xr_extensions[i], name) == 0)\n")
+ f.write(" return TRUE;\n")
+ f.write(" }\n")
+ f.write(" return FALSE;\n")
+ f.write("}\n")
+
+ def generate_thunks_h(self, f, prefix):
+ self._generate_copyright(f)
+
+ f.write("#ifndef __WINE_OPENXR_THUNKS_H\n")
+ f.write("#define __WINE_OPENXR_THUNKS_H\n\n")
+
+ f.write("#define WINE_XR_VERSION XR_API_VERSION_{0}_{1}\n\n".format(WINE_XR_VERSION[0], WINE_XR_VERSION[1]))
+
+ # Generate prototypes for device and instance functions requiring a custom implementation.
+ f.write("/* Functions for which we have custom implementations outside of the thunks. */\n")
+ for xr_func in self.registry.funcs.values():
+ if not xr_func.is_required():# or xr_func.is_global_func():
+ continue
+ if xr_func.needs_thunk() and not xr_func.needs_private_thunk():
+ continue
+
+ if xr_func.is_core_func():
+ f.write("{0};\n".format(xr_func.prototype("WINAPI", prefix="wine_")))
+ else:
+ f.write("{0};\n".format(xr_func.prototype("WINAPI", prefix="wine_", postfix="DECLSPEC_HIDDEN")))
+ f.write("\n")
+
+ f.write("/* Private thunks */\n")
+ for xr_func in self.registry.funcs.values():
+ if xr_func.needs_private_thunk():
+ f.write("{0};\n".format(xr_func.prototype(prefix="thunk_", postfix="DECLSPEC_HIDDEN")))
+ f.write("\n")
+
+ for struct in self.host_structs:
+ f.write(struct.definition(align=False, conv=True, postfix="_host"))
+ f.write("\n")
+
+ for func in self.struct_chain_conversions:
+ f.write(func.prototype(postfix="DECLSPEC_HIDDEN") + ";\n")
+ f.write("\n")
+
+ f.write("/* For use by xrInstance and children */\n")
+ f.write("struct openxr_instance_funcs\n{\n")
+ for xr_func in self.registry.instance_funcs:
+ if not xr_func.is_required():
+ continue
+
+ if not xr_func.needs_dispatch():
+ LOGGER.debug("skipping {0} in openxr_instance_funcs".format(xr_func.name))
+ continue
+
+ if xr_func.needs_conversion():
+ f.write("#if defined(USE_STRUCT_CONVERSION)\n")
+ f.write(" {0};\n".format(xr_func.pfn(conv=True)))
+ f.write("#else\n")
+ f.write(" {0};\n".format(xr_func.pfn(conv=False)))
+ f.write("#endif\n")
+ else:
+ f.write(" {0};\n".format(xr_func.pfn(conv=False)))
+ f.write("};\n\n")
+
+ f.write("#define ALL_XR_INSTANCE_FUNCS() \\\n")
+ first = True
+ for xr_func in self.registry.instance_funcs:
+ if not xr_func.is_required():
+ continue
+
+ if not xr_func.needs_dispatch():
+ LOGGER.debug("skipping {0} in ALL_XR_INSTANCE_FUNCS".format(xr_func.name))
+ continue
+
+ if first:
+ f.write(" USE_XR_FUNC({0})".format(xr_func.name))
+ first = False
+ else:
+ f.write(" \\\n USE_XR_FUNC({0})".format(xr_func.name))
+ f.write("\n\n")
+
+ f.write("#endif /* __WINE_OPENXR_THUNKS_H */\n")
+
+ def generate_openxr_h(self, f):
+ self._generate_copyright(f)
+ f.write("#ifndef __WINE_OPENXR_H\n")
+ f.write("#define __WINE_OPENXR_H\n\n")
+
+ f.write("#include <windef.h>\n")
+ f.write("#include <stdint.h>\n\n")
+
+ f.write("/* Define WINE_XR_HOST to get 'host' headers. */\n")
+ f.write("#ifdef WINE_XR_HOST\n")
+ f.write("#define XRAPI_CALL\n")
+ f.write('#define WINE_XR_ALIGN(x)\n')
+ f.write("#endif\n\n")
+
+ f.write("#ifndef XRAPI_CALL\n")
+ f.write("#define XRAPI_CALL __stdcall\n")
+ f.write("#endif\n\n")
+
+ f.write("#ifndef XRAPI_PTR\n")
+ f.write("#define XRAPI_PTR XRAPI_CALL\n")
+ f.write("#endif\n\n")
+
+ f.write("#ifndef WINE_XR_ALIGN\n")
+ f.write("#define WINE_XR_ALIGN DECLSPEC_ALIGN\n")
+ f.write("#endif\n\n")
+
+ # The overall strategy is to define independent constants and datatypes,
+ # prior to complex structures and function calls to avoid forward declarations.
+ for const in self.registry.consts:
+ # For now just generate things we may not need. The amount of parsing needed
+ # to get some of the info is tricky as you need to figure out which structure
+ # references a certain constant.
+ f.write(const.definition())
+ f.write("\n")
+
+ for define in self.registry.defines:
+ f.write(define.definition())
+
+ for handle in self.registry.handles:
+ # For backward compatibility also create definitions for aliases.
+ # These types normally don't get pulled in as we use the new types
+ # even in legacy functions if they are aliases.
+ if handle.is_required() or handle.is_alias():
+ f.write(handle.definition())
+ f.write("\n")
+
+ for base_type in self.registry.base_types:
+ f.write(base_type.definition())
+ f.write("\n")
+
+ for bitmask in self.registry.bitmasks:
+ f.write(bitmask.definition())
+ f.write("\n")
+
+ # Define enums, this includes values for some of the bitmask types as well.
+ for enum in self.registry.enums.values():
+ if enum.required:
+ f.write(enum.definition())
+
+ # This generates both structures and unions. Since structures
+ # may depend on other structures/unions, we need a list of
+ # decoupled structs.
+ # Note: unions are stored in structs for dependency reasons,
+ # see comment in parsing section.
+ structs = XrStruct.decouple_structs(self.registry.structs)
+
+ for struct in structs:
+ f.write(struct.typedef())
+
+ for fp in self.registry.funcpointers:
+ if fp.required:
+ f.write(fp.definition())
+ f.write("\n")
+
+ for struct in structs:
+ LOGGER.debug("Generating struct: {0}".format(struct.name))
+ f.write(struct.definition(align=True))
+
+ for func in self.registry.funcs.values():
+ if not func.is_required():
+ LOGGER.debug("Skipping PFN definition for: {0}".format(func.name))
+ continue
+
+ f.write("typedef {0};\n".format(func.pfn(prefix="PFN", call_conv="XRAPI_PTR")))
+ f.write("\n")
+
+ f.write("#ifndef XR_NO_PROTOTYPES\n")
+ for func in self.registry.funcs.values():
+ if not func.is_required():
+ LOGGER.debug("Skipping API definition for: {0}".format(func.name))
+ continue
+
+ LOGGER.debug("Generating API definition for: {0}".format(func.name))
+ f.write("{0};\n".format(func.prototype(call_conv="XRAPI_CALL")))
+ f.write("#endif /* XR_NO_PROTOTYPES */\n\n")
+
+ f.write("#endif /* __WINE_OPENXR_H */\n")
+
+
+class XrRegistry(object):
+ def __init__(self, reg_filename):
+ # Used for storage of type information.
+ self.base_types = None
+ self.bitmasks = None
+ self.consts = None
+ self.defines = None
+ self.enums = None
+ self.funcpointers = None
+ self.handles = None
+ self.structs = None
+
+ # We aggregate all types in here for cross-referencing.
+ self.funcs = {}
+ self.types = {}
+
+ self.version_regex = re.compile(
+ r'^'
+ r'XR_VERSION_'
+ r'(?P<major>[0-9])'
+ r'_'
+ r'(?P<minor>[0-9])'
+ r'$'
+ )
+
+ # Overall strategy for parsing the registry is to first
+ # parse all type / function definitions. Then parse
+ # features and extensions to decide which types / functions
+ # to actually 'pull in' for code generation. For each type or
+ # function call we want we set a member 'required' to True.
+ tree = ET.parse(reg_filename)
+ root = tree.getroot()
+ self._parse_enums(root)
+ self._parse_types(root)
+ self._parse_commands(root)
+
+ # Pull in any required types and functions.
+ self._parse_features(root)
+ self._parse_extensions(root)
+
+ self.copyright = root.find('./comment').text
+
+ def _is_feature_supported(self, feature):
+ version = self.version_regex.match(feature)
+ if not version:
+ return True
+
+ version = tuple(map(int, version.group('major', 'minor')))
+ return version <= WINE_XR_VERSION
+
+ def _is_extension_supported(self, extension):
+ # We disable some extensions as either we haven't implemented
+ # support yet or because they are for platforms other than win32.
+ return extension not in UNSUPPORTED_EXTENSIONS
+
+ def mark_bitmask_dependencies(self, bitmask):
+ if bitmask.requires is not None:
+ self.types[bitmask.requires]["data"].required = True
+
+ def mark_funcpointer_dependencies(self, fp):
+ for m in fp.members:
+ type_info = self.types[m.type]
+
+ # Complex types have a matching definition e.g. XrStruct.
+ # Not needed for base types such as uint32_t.
+ if "data" in type_info:
+ self.types[m.type]["data"].required = True
+
+ def mark_struct_dependencies(self, struct):
+ for m in struct:
+ type_info = self.types[m.type]
+
+
+ # Complex types have a matching definition e.g. XrStruct.
+ # Not needed for base types such as uint32_t.
+ if "data" in type_info:
+ if self.types[m.type]["data"].required:
+ continue
+ self.types[m.type]["data"].required = True
+
+ if type_info["category"] == "struct":
+ # Yay, recurse
+ self.mark_struct_dependencies(type_info["data"])
+ elif type_info["category"] == "funcpointer":
+ self.mark_funcpointer_dependencies(type_info["data"])
+ elif type_info["category"] == "bitmask":
+ self.mark_bitmask_dependencies(type_info["data"])
+
+ def _mark_command_required(self, command):
+ """ Helper function to mark a certain command and the datatypes it needs as required."""
+ LOGGER.debug("marking " + command + " as required")
+ func = self.funcs[command]
+ func.required = True
+
+ # Pull in return type
+ if func.type != "void":
+ self.types[func.type]["data"].required = True
+
+ # Analyze parameter dependencies and pull in any type needed.
+ for p in func.params:
+ type_info = self.types[p.type]
+
+ # Check if we are dealing with a complex type e.g. XrEnum, XrStruct and others.
+ if "data" not in type_info:
+ continue
+
+ # Mark the complex type as required.
+ type_info["data"].required = True
+ if type_info["category"] == "struct":
+ struct = type_info["data"]
+ self.mark_struct_dependencies(struct)
+ elif type_info["category"] == "bitmask":
+ self.mark_bitmask_dependencies(type_info["data"])
+
+ def _parse_commands(self, root):
+ """ Parse command section containing the OpenXR function calls. """
+ funcs = {}
+ commands = root.findall("./commands/")
+
+ # As of Vulkan 1.1, various extensions got promoted to Core.
+ # The old commands (e.g. KHR) are available for backwards compatibility
+ # and are marked in xr.xml as 'alias' to the non-extension type.
+ # The registry likes to avoid data duplication, so parameters and other
+ # metadata need to be looked up from the Core command.
+ # We parse the alias commands in a second pass.
+ alias_commands = []
+ for command in commands:
+ alias_name = command.attrib.get("alias")
+ if alias_name:
+ alias_commands.append(command)
+ continue
+
+ func = XrFunction.from_xml(command, self.types)
+ funcs[func.name] = func
+
+ for command in alias_commands:
+ alias_name = command.attrib.get("alias")
+ alias = funcs[alias_name]
+ func = XrFunction.from_alias(command, alias)
+ funcs[func.name] = func
+
+ # To make life easy for the code generation, separate all function
+ # calls out in the 3 types of functions: device, global and instance.
+ instance_funcs = []
+ for func in funcs.values():
+ instance_funcs.append(func)
+
+ # Sort function lists by name and store them.
+ self.instance_funcs = sorted(instance_funcs, key=lambda func: func.name)
+
+ # The funcs dictionary is used as a convenient way to lookup function
+ # calls when needed e.g. to adjust member variables.
+ self.funcs = OrderedDict(sorted(funcs.items()))
+
+ def _parse_enums(self, root):
+ """ Parse enums section or better described as constants section. """
+ enums = {}
+ self.consts = []
+ for enum in root.findall("./enums"):
+ name = enum.attrib.get("name")
+ _type = enum.attrib.get("type")
+
+ if _type in ("enum", "bitmask"):
+ enums[name] = XrEnum.from_xml(enum)
+ else:
+ # If no type is set, we are dealing with API constants.
+ for value in enum.findall("enum"):
+ # If enum is an alias, set the value to the alias name.
+ # E.g. XR_LUID_SIZE_KHR is an alias to XR_LUID_SIZE.
+ alias = value.attrib.get("alias")
+ if alias:
+ self.consts.append(XrConstant(value.attrib.get("name"), alias))
+ else:
+ self.consts.append(XrConstant(value.attrib.get("name"), value.attrib.get("value")))
+
+ self.enums = OrderedDict(sorted(enums.items()))
+
+ def _process_require_enum(self, enum_elem, ext=None, only_aliased=False):
+ if "extends" in enum_elem.keys():
+ enum = self.types[enum_elem.attrib["extends"]]["data"]
+
+ # Need to define XrEnumValues which were aliased to by another value. This is necessary
+ # from XR spec version 1.2.135 where the provisional XR_KHR_ray_tracing extension was
+ # added which altered XR_NV_ray_tracing's XrEnumValues to alias to the provisional
+ # extension.
+ aliased = False
+ for _, t in self.types.items():
+ if t["category"] != "enum":
+ continue
+ if not t["data"]:
+ continue
+ for value in t["data"].values:
+ if value.alias == enum_elem.attrib["name"]:
+ aliased = True
+
+ if only_aliased and not aliased:
+ return
+
+ if "bitpos" in enum_elem.keys():
+ # We need to add an extra value to an existing enum type.
+ # E.g. XR_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG to XrFormatFeatureFlagBits.
+ enum.add(XrEnumValue(enum_elem.attrib["name"], value=(1 << int(enum_elem.attrib["bitpos"])), hex=True))
+
+ elif "offset" in enum_elem.keys():
+ # Extensions promoted to Core, have the extension number as part
+ # of the enum value. Else retrieve from the extension tag.
+ if enum_elem.attrib.get("extnumber"):
+ ext_number = int(enum_elem.attrib.get("extnumber"))
+ else:
+ ext_number = int(ext.attrib["number"])
+ offset = int(enum_elem.attrib["offset"])
+ value = EXT_BASE + (ext_number - 1) * EXT_BLOCK_SIZE + offset
+
+ # Deal with negative values.
+ direction = enum_elem.attrib.get("dir")
+ if direction is not None:
+ value = -value
+
+ enum.add(XrEnumValue(enum_elem.attrib["name"], value=value))
+
+ elif "value" in enum_elem.keys():
+ enum.add(XrEnumValue(enum_elem.attrib["name"], value=int(enum_elem.attrib["value"])))
+ elif "alias" in enum_elem.keys():
+ enum.add(XrEnumValue(enum_elem.attrib["name"], alias=enum_elem.attrib["alias"]))
+
+ elif "value" in enum_elem.keys():
+ # Constants are not aliased, no need to add them here, they'll get added later on.
+ if only_aliased:
+ return
+
+ self.consts.append(XrConstant(enum_elem.attrib["name"], enum_elem.attrib["value"]))
+
+ @staticmethod
+ def _require_type(type_info):
+ if type_info.is_alias():
+ type_info = type_info.alias
+ type_info.required = True
+ if type(type_info) == XrStruct:
+ for member in type_info.members:
+ if "data" in member.type_info:
+ XrRegistry._require_type(member.type_info["data"])
+
+ def _parse_extensions(self, root):
+ """ Parse extensions section and pull in any types and commands for this extension. """
+ extensions = []
+ exts = root.findall("./extensions/extension")
+ deferred_exts = []
+
+ def process_ext(ext, deferred=False):
+ ext_name = ext.attrib["name"]
+
+ # Set extension name on any functions calls part of this extension as we
+ # were not aware of the name during initial parsing.
+ commands = ext.findall("require/command")
+ for command in commands:
+ cmd_name = command.attrib["name"]
+ self.funcs[cmd_name].extensions.append(ext_name)
+
+ # Some extensions are not ready or have numbers reserved as a place holder.
+ if ext.attrib["supported"] == "disabled":
+ LOGGER.debug("Skipping disabled extension: {0}".format(ext_name))
+ return
+
+ protect = ext.attrib.get("protect", None)
+ if not protect is None and \
+ not protect in ALLOWED_PROTECTS:
+ return
+
+ # Defer extensions with 'sortorder' as they are order-dependent for spec-parsing.
+ if not deferred and "sortorder" in ext.attrib:
+ deferred_exts.append(ext)
+ return
+
+ # Disable highly experimental extensions as the APIs are unstable and can
+ # change between minor revisions until API is final and becomes KHR
+ # or NV.
+ if "KHX" in ext_name or "NVX" in ext_name:
+ LOGGER.debug("Skipping experimental extension: {0}".format(ext_name))
+ return
+
+ # Extensions can define XrEnumValues which alias to provisional extensions. Pre-process
+ # extensions to define any required XrEnumValues before the platform check below.
+ for require in ext.findall("require"):
+ # Extensions can add enum values to Core / extension enums, so add these.
+ for enum_elem in require.findall("enum"):
+ self._process_require_enum(enum_elem, ext, only_aliased=True)
+
+ platform = ext.attrib.get("platform")
+ if platform and platform != "win32":
+ LOGGER.debug("Skipping extensions {0} for platform {1}".format(ext_name, platform))
+ return
+
+ if not self._is_extension_supported(ext_name):
+ LOGGER.debug("Skipping unsupported extension: {0}".format(ext_name))
+ return
+ elif "requires" in ext.attrib:
+ # Check if this extension builds on top of another unsupported extension.
+ requires = ext.attrib["requires"].split(",")
+ if len(set(requires).intersection(UNSUPPORTED_EXTENSIONS)) > 0:
+ return
+
+ LOGGER.debug("Loading extension: {0}".format(ext_name))
+
+ # Extensions can define one or more require sections each requiring
+ # different features (e.g. Vulkan 1.1). Parse each require section
+ # separately, so we can skip sections we don't want.
+ for require in ext.findall("require"):
+ # Extensions can add enum values to Core / extension enums, so add these.
+ for enum_elem in require.findall("enum"):
+ self._process_require_enum(enum_elem, ext)
+
+ for t in require.findall("type"):
+ if t.attrib["name"] in self.types:
+ type_info = self.types[t.attrib["name"]]["data"]
+ self._require_type(type_info)
+ feature = require.attrib.get("feature")
+ if feature and not self._is_feature_supported(feature):
+ continue
+
+ required_extension = require.attrib.get("extension")
+ if required_extension and not self._is_extension_supported(required_extension):
+ continue
+
+ # Pull in any commands we need. We infer types to pull in from the command
+ # as well.
+ for command in require.findall("command"):
+ cmd_name = command.attrib["name"]
+ self._mark_command_required(cmd_name)
+
+
+ # Store a list with extensions.
+ ext_info = {"name" : ext_name, "type" : ext.attrib["type"]}
+ extensions.append(ext_info)
+
+
+ # Process extensions, allowing for sortorder to defer extension processing
+ for ext in exts:
+ process_ext(ext)
+
+ deferred_exts.sort(key=lambda ext: ext.attrib["sortorder"])
+
+ # Respect sortorder
+ for ext in deferred_exts:
+ process_ext(ext, deferred=True)
+
+ # Sort in alphabetical order.
+ self.extensions = sorted(extensions, key=lambda ext: ext["name"])
+
+ def _parse_features(self, root):
+ """ Parse the feature section, which describes Core commands and types needed. """
+
+ for feature in root.findall("./feature"):
+ feature_name = feature.attrib["name"]
+ for require in feature.findall("require"):
+ LOGGER.info("Including features for {0}".format(require.attrib.get("comment")))
+ for tag in require:
+ if tag.tag == "comment":
+ continue
+ elif tag.tag == "command":
+ if not self._is_feature_supported(feature_name):
+ continue
+ name = tag.attrib["name"]
+ LOGGER.debug("found command: " + name)
+ self._mark_command_required(name)
+ elif tag.tag == "enum":
+ self._process_require_enum(tag)
+ elif tag.tag == "type":
+ name = tag.attrib["name"]
+
+ # Skip pull in for openxr_platform_defines.h for now.
+ if name == "openxr_platform_defines":
+ continue
+
+ type_info = self.types[name]
+ type_info["data"].required = True
+
+ def _parse_types(self, root):
+ """ Parse types section, which contains all data types e.g. structs, typedefs etcetera. """
+ types = root.findall("./types/type")
+
+ base_types = []
+ bitmasks = []
+ defines = []
+ funcpointers = []
+ handles = []
+ structs = []
+
+ alias_types = []
+ for t in types:
+ type_info = {}
+ type_info["category"] = t.attrib.get("category", None)
+ type_info["requires"] = t.attrib.get("requires", None)
+
+ # We parse aliases in a second pass when we know more.
+ alias = t.attrib.get("alias")
+ if alias:
+ LOGGER.debug("Alias found: {0}".format(alias))
+ alias_types.append(t)
+ continue
+
+ protect = t.attrib.get("protect", None)
+ if not protect is None and \
+ not protect in ALLOWED_PROTECTS:
+ continue
+
+ if type_info["category"] in ["include"]:
+ continue
+
+ if type_info["category"] == "basetype":
+ name = t.find("name").text
+ _type = None
+ if not t.find("type") is None:
+ _type = t.find("type").text
+ basetype = XrBaseType(name, _type, collect_element_text(t))
+ base_types.append(basetype)
+ type_info["data"] = basetype
+
+ # Basic C types don't need us to define them, but we do need data for them
+ if type_info["requires"] == "xr_platform":
+ requires = type_info["requires"]
+ basic_c = XrBaseType(name, _type, collect_element_text(t), requires=requires)
+ type_info["data"] = basic_c
+
+ if type_info["category"] == "bitmask":
+ name = t.find("name").text
+ _type = t.find("type").text
+
+ # Most bitmasks have a requires attribute used to pull in
+ # required '*FlagBits" enum.
+ requires = type_info["requires"]
+ bitmask = XrBaseType(name, _type, collect_element_text(t), requires=requires)
+ bitmasks.append(bitmask)
+ type_info["data"] = bitmask
+
+ if type_info["category"] == "define":
+ define = XrDefine.from_xml(t)
+ defines.append(define)
+ type_info["data"] = define
+
+ if type_info["category"] == "enum":
+ name = t.attrib.get("name")
+ # The type section only contains enum names, not the actual definition.
+ # Since we already parsed the enum before, just link it in.
+ try:
+ type_info["data"] = self.enums[name]
+ except KeyError as e:
+ # Not all enums seem to be defined yet, typically that's for
+ # ones ending in 'FlagBits' where future extensions may add
+ # definitions.
+ type_info["data"] = None
+
+ if type_info["category"] == "funcpointer":
+ funcpointer = XrFunctionPointer.from_xml(t)
+ funcpointers.append(funcpointer)
+ type_info["data"] = funcpointer
+
+ if type_info["category"] == "handle":
+ handle = XrHandle.from_xml(t)
+ handles.append(handle)
+ type_info["data"] = handle
+
+ if type_info["category"] in ["struct", "union"]:
+ # We store unions among structs as some structs depend
+ # on unions. The types are very similar in parsing and
+ # generation anyway. The official Vulkan scripts use
+ # a similar kind of hack.
+ struct = XrStruct.from_xml(t)
+ structs.append(struct)
+ type_info["data"] = struct
+
+ # Name is in general within a name tag else it is an optional
+ # attribute on the type tag.
+ name_elem = t.find("name")
+ if name_elem is not None:
+ type_info["name"] = name_elem.text
+ else:
+ type_info["name"] = t.attrib.get("name", None)
+
+ # Store all type data in a shared dictionary, so we can easily
+ # look up information for a given type. There are no duplicate
+ # names.
+ self.types[type_info["name"]] = type_info
+
+ # Second pass for alias types, so we can retrieve all data from
+ # the aliased object.
+ for t in alias_types:
+ type_info = {}
+ type_info["category"] = t.attrib.get("category")
+ type_info["name"] = t.attrib.get("name")
+
+ alias = t.attrib.get("alias")
+
+ if type_info["category"] == "bitmask":
+ bitmask = XrBaseType(type_info["name"], alias, collect_element_text(t), alias=self.types[alias]["data"])
+ bitmasks.append(bitmask)
+ type_info["data"] = bitmask
+
+ if type_info["category"] == "enum":
+ enum = XrEnum.from_alias(t, self.types[alias]["data"])
+ type_info["data"] = enum
+ self.enums[enum.name] = enum
+
+ if type_info["category"] == "handle":
+ handle = XrHandle.from_alias(t, self.types[alias]["data"])
+ handles.append(handle)
+ type_info["data"] = handle
+
+ if type_info["category"] == "struct":
+ struct = XrStruct.from_alias(t, self.types[alias]["data"])
+ structs.append(struct)
+ type_info["data"] = struct
+
+ self.types[type_info["name"]] = type_info
+
+ # We need detailed type information during code generation
+ # on structs for alignment reasons. Unfortunately structs
+ # are parsed among other types, so there is no guarantee
+ # that any types needed have been parsed already, so set
+ # the data now.
+ for struct in structs:
+ struct.set_type_info(self.types)
+
+ # Alias structures have enum values equivalent to those of the
+ # structure which they are aliased against. we need to ignore alias
+ # structs when populating the struct extensions list, otherwise we
+ # will create duplicate case entries.
+ if struct.alias:
+ continue
+
+ for structextend in struct.structextends:
+ s = self.types[structextend]["data"]
+ s.struct_extensions.append(struct)
+
+ self.mark_struct_dependencies(struct)
+
+ # Guarantee everything is sorted, so code generation doesn't have
+ # to deal with this.
+ self.base_types = sorted(base_types, key=lambda base_type: base_type.name)
+ self.bitmasks = sorted(bitmasks, key=lambda bitmask: bitmask.name)
+ self.defines = defines
+ self.enums = OrderedDict(sorted(self.enums.items()))
+ self.funcpointers = sorted(funcpointers, key=lambda fp: fp.name)
+ self.handles = sorted(handles, key=lambda handle: handle.name)
+ self.structs = sorted(structs, key=lambda struct: struct.name)
+
+def collect_element_text(e):
+ return "".join(e.itertext())
+
+def set_working_directory():
+ path = os.path.abspath(__file__)
+ path = os.path.dirname(path)
+ os.chdir(path)
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-v", "--verbose", action="count", default=0, help="increase output verbosity")
+
+ args = parser.parse_args()
+ if args.verbose == 0:
+ LOGGER.setLevel(logging.WARNING)
+ elif args.verbose == 1:
+ LOGGER.setLevel(logging.INFO)
+ else: # > 1
+ LOGGER.setLevel(logging.DEBUG)
+
+ set_working_directory()
+
+ xr_xml = "xr.xml".format(XR_XML_VERSION)
+ registry = XrRegistry(xr_xml)
+ generator = XrGenerator(registry)
+
+ with open(WINE_OPENXR_H, "w") as f:
+ generator.generate_openxr_h(f)
+
+ with open(WINE_OPENXR_THUNKS_H, "w") as f:
+ generator.generate_thunks_h(f, "wine_")
+
+ with open(WINE_OPENXR_THUNKS_C, "w") as f:
+ generator.generate_thunks_c(f, "wine_")
+
+if __name__ == "__main__":
+ main()
diff --git a/wineopenxr/openxr.c b/wineopenxr/openxr.c
new file mode 100644
index 00000000..00468d1f
--- /dev/null
+++ b/wineopenxr/openxr.c
@@ -0,0 +1,1441 @@
+#include <stdint.h>
+#include <dlfcn.h>
+
+#define COBJMACROS
+#include "initguid.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "windows.h"
+#include "wine/debug.h"
+#include "dxgi.h"
+#include "d3d11.h"
+#include "d3d11_3.h"
+#include "d3d12.h"
+
+/* we want to use the native linux header */
+#pragma push_macro("_WIN32")
+#pragma push_macro("__cdecl")
+#undef _WIN32
+#undef __cdecl
+#define XR_USE_GRAPHICS_API_OPENGL 1
+#define XR_USE_GRAPHICS_API_VULKAN 1
+#define WINE_VK_HOST
+#include "wine/vulkan.h"
+#define VULKAN_H_ 1// tell dxvk-interop not to include vulkan.h
+#include "dxvk-interop.h"
+#undef WINE_VK_HOST
+#define XR_USE_GRAPHICS_API_D3D11 1
+#define XR_USE_GRAPHICS_API_D3D12 1
+#include <openxr/openxr_platform.h>
+#pragma pop_macro("_WIN32")
+#pragma pop_macro("__cdecl")
+
+#include "openxr_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(openxr);
+
+union CompositionLayer {
+ XrCompositionLayerProjection projection;
+ XrCompositionLayerQuad quad;
+ XrCompositionLayerCubeKHR cube;
+ XrCompositionLayerDepthInfoKHR depth_info;
+ XrCompositionLayerCylinderKHR cylinder;
+ XrCompositionLayerEquirectKHR equirect;
+ XrCompositionLayerColorScaleBiasKHR color_scale_bias;
+ XrCompositionLayerEquirect2KHR equirect2;
+};
+
+#define heap_alloc(s) HeapAlloc(GetProcessHeap(), 0, s)
+#define heap_alloc_zero(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, s)
+#define heap_free(p) HeapFree(GetProcessHeap(), 0, p)
+
+static void *heap_realloc(void *p, size_t s)
+{
+ if(!p) return heap_alloc(s);
+ return HeapReAlloc(GetProcessHeap(), 0, p, s);
+}
+
+static const char WINE_VULKAN_DEVICE_EXTENSION_NAME[] = "VK_WINE_openxr_device_extensions";
+static const char WINE_VULKAN_DEVICE_VARIABLE[] = "__WINE_OPENXR_VK_DEVICE_EXTENSIONS";
+
+static char *wineopenxr_strdup(const char *src)
+{
+ const size_t l = strlen(src) + 1;
+ char *r = heap_alloc(l);
+ strcpy(r, src);
+ return r;
+}
+
+VkDevice(WINAPI *get_native_VkDevice)(VkDevice);
+VkInstance(WINAPI *get_native_VkInstance)(VkInstance);
+VkPhysicalDevice(WINAPI *get_native_VkPhysicalDevice)(VkPhysicalDevice);
+VkPhysicalDevice(WINAPI *get_wrapped_VkPhysicalDevice)(VkInstance, VkPhysicalDevice);
+VkQueue(WINAPI *get_native_VkQueue)(VkQueue);
+
+static void load_vk_unwrappers(void)
+{
+ static HMODULE h = NULL;
+
+ if(h)
+ /* already loaded */
+ return;
+
+ h = LoadLibraryA("winevulkan");
+ if(!h){
+ WINE_ERR("unable to load winevulkan\n");
+ return;
+ }
+
+ get_native_VkDevice = (void*)GetProcAddress(h, "__wine_get_native_VkDevice");
+ get_native_VkInstance = (void*)GetProcAddress(h, "__wine_get_native_VkInstance");
+ get_native_VkPhysicalDevice = (void*)GetProcAddress(h, "__wine_get_native_VkPhysicalDevice");
+ get_wrapped_VkPhysicalDevice = (void*)GetProcAddress(h, "__wine_get_wrapped_VkPhysicalDevice");
+ get_native_VkQueue = (void*)GetProcAddress(h, "__wine_get_native_VkQueue");
+}
+
+#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
+#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
+#define XR_LOADER_INFO_STRUCT_VERSION 1
+#define XR_RUNTIME_INFO_STRUCT_VERSION 1
+
+typedef enum XrLoaderInterfaceStructs {
+ XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0,
+ XR_LOADER_INTERFACE_STRUCT_LOADER_INFO,
+ XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST,
+ XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST,
+ XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO,
+ XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO,
+} XrLoaderInterfaceStructs;
+
+typedef struct XrApiLayerNextInfo XrApiLayerNextInfo;
+
+#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
+#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
+typedef struct XrApiLayerCreateInfo {
+ XrLoaderInterfaceStructs structType;
+ uint32_t structVersion;
+ size_t structSize;
+ void *loaderInstance;
+ char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE];
+ XrApiLayerNextInfo *nextInfo;
+} XrApiLayerCreateInfo;
+
+typedef XrResult(__stdcall *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info,
+ const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance);
+
+#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
+struct XrApiLayerNextInfo {
+ XrLoaderInterfaceStructs structType;
+ uint32_t structVersion;
+ size_t structSize;
+ char layerName[XR_MAX_API_LAYER_NAME_SIZE];
+ PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance;
+ XrApiLayerNextInfo *next;
+};
+
+#define WINE_XR_STRUCT_NAME(x) x##_win
+#define WINE_XR_STRUCT_ATTR __attribute__((ms_struct))
+#include "loader_structs.h"
+#undef WINE_XR_STRUCT_ATTR
+#undef WINE_XR_STRUCT_NAME
+
+#define WINE_XR_STRUCT_NAME(x) x##_host
+#define WINE_XR_STRUCT_ATTR
+#include "loader_structs.h"
+#undef WINE_XR_STRUCT_ATTR
+#undef WINE_XR_STRUCT_NAME
+
+static char *g_instance_extensions, *g_device_extensions;
+static uint32_t g_physdev_vid, g_physdev_pid;
+
+static char *strdupA(const char *s)
+{
+ size_t l = strlen(s) + 1;
+ char *r = heap_alloc(l);
+ memcpy(r, s, l);
+ return r;
+}
+
+static CRITICAL_SECTION session_list_lock = { NULL, -1, 0, 0, 0, 0 };
+static struct list session_list = LIST_INIT(session_list);
+
+static wine_XrSession *get_wrapped_XrSession(XrSession native)
+{
+ wine_XrSession *cursor;
+
+ EnterCriticalSection(&session_list_lock);
+
+ LIST_FOR_EACH_ENTRY(cursor, &session_list, wine_XrSession, entry){
+ if(cursor->session == native)
+ break;
+ }
+
+ LeaveCriticalSection(&session_list_lock);
+
+ if(&cursor->entry == &session_list)
+ return NULL;
+
+ return cursor;
+}
+
+static void parse_extensions(const char *in, uint32_t *out_count,
+ char ***out_strs)
+{
+ char *iter, *start;
+ char **list, *str = strdupA(in);
+ uint32_t extension_count = 0, o = 0;
+
+ iter = str;
+ while(*iter){
+ if(*iter++ == ' ')
+ extension_count++;
+ }
+ /* count the one ending in NUL */
+ if(iter != str)
+ extension_count++;
+ if(!extension_count){
+ *out_count = 0;
+ *out_strs = NULL;
+ return;
+ }
+
+ list = heap_alloc(extension_count * sizeof(char *));
+
+ start = iter = str;
+ do{
+ if(*iter == ' '){
+ *iter = 0;
+ list[o++] = strdupA(start);
+ WINE_TRACE("added %s to list\n", list[o-1]);
+ iter++;
+ start = iter;
+ }else if(*iter == 0){
+ list[o++] = strdupA(start);
+ WINE_TRACE("added %s to list\n", list[o-1]);
+ break;
+ }else{
+ iter++;
+ }
+ }while(1);
+
+ *out_count = extension_count;
+ *out_strs = list;
+}
+
+XrResult load_host_openxr_loader(void)
+{
+ PFN_xrGetVulkanInstanceExtensionsKHR pxrGetVulkanInstanceExtensionsKHR;
+ PFN_xrGetSystem pxrGetSystem;
+ PFN_xrGetVulkanDeviceExtensionsKHR pxrGetVulkanDeviceExtensionsKHR;
+ PFN_xrGetVulkanGraphicsDeviceKHR pxrGetVulkanGraphicsDeviceKHR;
+ PFN_xrGetVulkanGraphicsRequirementsKHR pxrGetVulkanGraphicsRequirementsKHR;
+ PFN_xrGetInstanceProperties pxrGetInstanceProperties;
+ PFN_xrEnumerateViewConfigurations pxrEnumerateViewConfigurations;
+ uint32_t len, i;
+ XrInstance instance;
+ XrSystemId system;
+ XrResult res;
+ VkInstance vk_instance;
+ VkResult vk_res;
+ VkPhysicalDevice vk_physdev;
+ VkPhysicalDeviceProperties vk_dev_props;
+
+ static const char *xr_extensions[] = {
+ "XR_KHR_vulkan_enable",
+ };
+
+ if(g_instance_extensions || g_device_extensions)
+ /* already done */
+ return XR_SUCCESS;
+
+ load_vk_unwrappers();
+
+ XrInstanceCreateInfo xrCreateInfo = {
+ .type = XR_TYPE_INSTANCE_CREATE_INFO,
+ .next = NULL,
+ .createFlags = 0,
+ .applicationInfo = {
+ .applicationVersion = 0,
+ .engineVersion = 0,
+ .apiVersion = XR_CURRENT_API_VERSION,
+ },
+ .enabledApiLayerCount = 0,
+ .enabledApiLayerNames = NULL,
+ .enabledExtensionCount = ARRAY_SIZE(xr_extensions),
+ .enabledExtensionNames = xr_extensions,
+ };
+
+ strcpy(xrCreateInfo.applicationInfo.applicationName, "wineopenxr test instance");
+ strcpy(xrCreateInfo.applicationInfo.engineName, "wineopenxr test instance");
+
+ res = xrCreateInstance(&xrCreateInfo, &instance);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrCreateInstance failed: %d\n", res);
+ return res;
+ }
+
+ xrGetInstanceProcAddr(instance, "xrGetVulkanInstanceExtensionsKHR", (PFN_xrVoidFunction *)&pxrGetVulkanInstanceExtensionsKHR);
+ xrGetInstanceProcAddr(instance, "xrGetVulkanDeviceExtensionsKHR", (PFN_xrVoidFunction *)&pxrGetVulkanDeviceExtensionsKHR);
+ xrGetInstanceProcAddr(instance, "xrGetSystem", (PFN_xrVoidFunction *)&pxrGetSystem);
+ xrGetInstanceProcAddr(instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction *)&pxrGetVulkanGraphicsDeviceKHR);
+ xrGetInstanceProcAddr(instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction *)&pxrGetVulkanGraphicsRequirementsKHR);
+ xrGetInstanceProcAddr(instance, "xrGetInstanceProperties", (PFN_xrVoidFunction *)&pxrGetInstanceProperties);
+ xrGetInstanceProcAddr(instance, "xrEnumerateViewConfigurations", (PFN_xrVoidFunction *)&pxrEnumerateViewConfigurations);
+
+ XrInstanceProperties inst_props = {
+ .type = XR_TYPE_INSTANCE_PROPERTIES,
+ };
+ res = pxrGetInstanceProperties(instance, &inst_props);
+ if(res != XR_SUCCESS)
+ WINE_WARN("xrGetInstanceProperties failed: %d\n", res);
+
+ XrSystemGetInfo system_info = {
+ .type = XR_TYPE_SYSTEM_GET_INFO,
+ .formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY,
+ };
+ res = pxrGetSystem(instance, &system_info, &system);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetSystem failed: %d\n", res);
+ xrDestroyInstance(instance);
+ return res;
+ }
+
+ res = pxrEnumerateViewConfigurations(instance, system, 0, &len, NULL);
+ if(res != XR_SUCCESS)
+ WINE_WARN("xrEnumerateViewConfigurations failed: %d\n", res);
+ XrViewConfigurationType *configs = heap_alloc(len * sizeof(*configs));
+ res = pxrEnumerateViewConfigurations(instance, system, len, &len, configs);
+ if(res != XR_SUCCESS)
+ WINE_WARN("xrEnumerateViewConfigurations failed: %d\n", res);
+ heap_free(configs);
+
+ XrGraphicsRequirementsVulkanKHR reqs = {
+ .type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR,
+ };
+ res = pxrGetVulkanGraphicsRequirementsKHR(instance, system, &reqs);
+ if(res != XR_SUCCESS)
+ WINE_WARN("xrGetVulkanGraphicsRequirementsKHR failed: %d\n", res);
+
+ res = pxrGetVulkanInstanceExtensionsKHR(instance, system, 0, &len, NULL);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetVulkanInstanceExtensionsKHR failed: %d\n", res);
+ xrDestroyInstance(instance);
+ return res;
+ }
+ g_instance_extensions = heap_alloc(len);
+ res = pxrGetVulkanInstanceExtensionsKHR(instance, system, len, &len, g_instance_extensions);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetVulkanInstanceExtensionsKHR failed: %d\n", res);
+ xrDestroyInstance(instance);
+ heap_free(g_instance_extensions);
+ g_instance_extensions = NULL;
+ return res;
+ }
+
+ VkApplicationInfo vk_appinfo = {
+ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ .pNext = NULL,
+ .pApplicationName = "wineopenxr test instance",
+ .applicationVersion = 0,
+ .pEngineName = "wineopenxr test instance",
+ .engineVersion = VK_MAKE_VERSION(1, 0, 0),
+ .apiVersion = VK_MAKE_VERSION(1, 1, 0),
+ };
+
+ VkInstanceCreateInfo vk_createinfo = {
+ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ .pNext = NULL,
+ .flags = 0,
+ .pApplicationInfo = &vk_appinfo,
+ .enabledLayerCount = 0,
+ .ppEnabledLayerNames = NULL,
+ .enabledExtensionCount = 0,
+ .ppEnabledExtensionNames = NULL,
+ };
+
+ parse_extensions(g_instance_extensions,
+ &vk_createinfo.enabledExtensionCount,
+ (char ***)&vk_createinfo.ppEnabledExtensionNames);
+
+ vk_res = vkCreateInstance(&vk_createinfo, NULL, &vk_instance);
+ if(vk_res != VK_SUCCESS){
+ WINE_WARN("vkCreateInstance failed: %d\n", vk_res);
+ for(i = 0; i < vk_createinfo.enabledExtensionCount; ++i)
+ heap_free((void*)vk_createinfo.ppEnabledExtensionNames[i]);
+ heap_free((void*)vk_createinfo.ppEnabledExtensionNames);
+ xrDestroyInstance(instance);
+ heap_free(g_instance_extensions);
+ g_instance_extensions = NULL;
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+
+ for(i = 0; i < vk_createinfo.enabledExtensionCount; ++i)
+ heap_free((void*)vk_createinfo.ppEnabledExtensionNames[i]);
+ heap_free((void*)vk_createinfo.ppEnabledExtensionNames);
+
+ res = pxrGetVulkanGraphicsDeviceKHR(instance, system, vk_instance, &vk_physdev);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetVulkanGraphicsDeviceKHR failed: %d\n", res);
+ xrDestroyInstance(instance);
+ heap_free(g_instance_extensions);
+ g_instance_extensions = NULL;
+ return res;
+ }
+
+ vkGetPhysicalDeviceProperties(vk_physdev, &vk_dev_props);
+ g_physdev_vid = vk_dev_props.vendorID;
+ g_physdev_pid = vk_dev_props.deviceID;
+
+ res = pxrGetVulkanDeviceExtensionsKHR(instance, system, 0, &len, NULL);
+ if(res != XR_SUCCESS){
+ WINE_WARN("pxrGetVulkanDeviceExtensionsKHR fail: %d\n", res);
+ xrDestroyInstance(instance);
+ heap_free(g_instance_extensions);
+ g_instance_extensions = NULL;
+ return res;
+ }
+ g_device_extensions = heap_alloc(len);
+ res = pxrGetVulkanDeviceExtensionsKHR(instance, system, len, &len, g_device_extensions);
+ if(res != XR_SUCCESS){
+ WINE_WARN("pxrGetVulkanDeviceExtensionsKHR fail: %d\n", res);
+ xrDestroyInstance(instance);
+ heap_free(g_instance_extensions);
+ g_instance_extensions = NULL;
+ heap_free(g_device_extensions);
+ g_device_extensions = NULL;
+ return res;
+ }
+
+ vkDestroyInstance(vk_instance, NULL);
+ xrDestroyInstance(instance);
+
+ WINE_TRACE("Got required instance extensions: %s\n", g_instance_extensions);
+ WINE_TRACE("Got required device extensions: %s\n", g_device_extensions);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrEnumerateInstanceExtensionProperties(const char *layerName,
+ uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties)
+{
+ XrResult res;
+ uint32_t i;
+
+ static const char *extra_extensions[] = {
+ "XR_KHR_D3D11_enable",
+ };
+
+ WINE_TRACE("\n");
+
+ res = xrEnumerateInstanceExtensionProperties(layerName, propertyCapacityInput, propertyCountOutput, properties);
+
+ if(res == XR_SUCCESS){
+ if(properties){
+ for(i = 0; i < ARRAY_SIZE(extra_extensions); ++i){
+ strcpy(properties[*propertyCountOutput + i].extensionName, extra_extensions[i]);
+ }
+ *propertyCountOutput += ARRAY_SIZE(extra_extensions);
+ WINE_TRACE("Returning extensions:\n");
+ for(i = 0; i < *propertyCountOutput; ++i){
+ WINE_TRACE("\t-%s\n", properties[i].extensionName);
+ }
+ }else{
+ *propertyCountOutput += ARRAY_SIZE(extra_extensions);
+ }
+ }
+
+ return res;
+}
+
+XrResult WINAPI wine_xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance,
+ XrTime time, LARGE_INTEGER *performanceCounter)
+{
+ WINE_FIXME("unimplemented\n");
+ /* FIXME */
+ return XR_ERROR_INITIALIZATION_FAILED;
+}
+
+XrResult WINAPI wine_xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance,
+ const LARGE_INTEGER *performanceCounter, XrTime *time)
+{
+ WINE_FIXME("unimplemented\n");
+ /* FIXME */
+ return XR_ERROR_INITIALIZATION_FAILED;
+}
+
+XrResult WINAPI wine_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance,
+ XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements)
+{
+ IDXGIFactory1 *factory;
+ IDXGIAdapter *adapter;
+ DXGI_ADAPTER_DESC adapter_desc;
+ HRESULT hr;
+ DWORD i;
+
+ WINE_TRACE("\n");
+
+ hr = CreateDXGIFactory1(&IID_IDXGIFactory1, (void**)&factory);
+ if(FAILED(hr)){
+ WINE_WARN("CreateDXGIFactory1 failed: %08x\n", hr);
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+
+ i = 0;
+ while((hr = IDXGIFactory1_EnumAdapters(factory, i++, &adapter)) == S_OK){
+ hr = IDXGIAdapter_GetDesc(adapter, &adapter_desc);
+ if(FAILED(hr)){
+ WINE_WARN("GetDesc failed: %08x\n", hr);
+ IDXGIAdapter_Release(adapter);
+ continue;
+ }
+
+ IDXGIAdapter_Release(adapter);
+
+ /* FIXME: what if we have two of the same adapters? */
+ if(adapter_desc.VendorId == g_physdev_vid &&
+ adapter_desc.DeviceId == g_physdev_pid){
+ break;
+ }
+ }
+
+ if(hr == S_OK){
+ graphicsRequirements->adapterLuid = adapter_desc.AdapterLuid;
+ }else{
+ WINE_WARN("Couldn't find matching DXGI adapter for given VkPhysicalDevice! Choosing first one...\n");
+
+ hr = IDXGIFactory1_EnumAdapters(factory, 0, &adapter);
+ if(FAILED(hr)){
+ WINE_WARN("EnumAdapters(0) failed: %08x\n", hr);
+ IDXGIFactory1_Release(factory);
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+
+ hr = IDXGIAdapter_GetDesc(adapter, &adapter_desc);
+ if(FAILED(hr)){
+ WINE_WARN("GetDesc(0) failed: %08x\n", hr);
+ IDXGIAdapter_Release(adapter);
+ IDXGIFactory1_Release(factory);
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+
+ IDXGIAdapter_Release(adapter);
+
+ graphicsRequirements->adapterLuid = adapter_desc.AdapterLuid;
+ }
+
+ IDXGIFactory1_Release(factory);
+
+ /* XXX */
+ graphicsRequirements->minFeatureLevel = D3D_FEATURE_LEVEL_10_0;
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrGetD3D12GraphicsRequirementsKHR(XrInstance instance,
+ XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements)
+{
+ WINE_FIXME("unimplemented\n");
+ /* FIXME */
+ return XR_ERROR_INITIALIZATION_FAILED;
+}
+
+XrResult WINAPI wine_xrGetInstanceProcAddr(XrInstance instance, const char *fn_name, PFN_xrVoidFunction *out_fn)
+{
+ WINE_TRACE("%s\n", fn_name);
+
+ *out_fn = wine_xr_proc_addr(fn_name);
+ if(!*out_fn){
+ WINE_WARN("Unable to find requested function: %s\n", fn_name);
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrCreateInstance(const XrInstanceCreateInfo *createInfo, XrInstance *instance)
+{
+ XrResult res;
+ struct wine_XrInstance *wine_instance;
+ uint32_t i, j, type = 0;
+ XrInstanceCreateInfo our_createInfo;
+ uint32_t dst = 0;
+ char **new_list = NULL;
+
+ WINE_TRACE("%p, %p\n", createInfo, instance);
+
+ WINE_TRACE("Incoming extensions:\n");
+ for(i = 0; i < createInfo->enabledExtensionCount; ++i){
+ WINE_TRACE(" -%s\n", createInfo->enabledExtensionNames[i]);
+ if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_D3D11_enable")){
+ type = INSTANCE_TYPE_D3D11;
+ }else if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_D3D12_enable")){
+ type = INSTANCE_TYPE_D3D12;
+ }else if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_vulkan_enable")){
+ type = INSTANCE_TYPE_VULKAN;
+ }else if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_opengl_enable")){
+ type = INSTANCE_TYPE_OPENGL;
+ }
+ }
+
+ /* remove win32 extensions */
+ for(i = 0; i < createInfo->enabledExtensionCount; ++i){
+ if(strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_D3D11_enable") != 0){
+ if(i != dst){
+ new_list[dst] = wineopenxr_strdup(createInfo->enabledExtensionNames[i]);
+ }
+ dst++;
+ }else{
+ /* skip this one */
+ if(!new_list){
+ new_list = heap_alloc(createInfo->enabledExtensionCount * sizeof(char *));
+ for(j = 0; j < i; ++j){
+ new_list[j] = wineopenxr_strdup(createInfo->enabledExtensionNames[j]);
+ }
+ }
+ }
+ }
+ if(new_list){
+ /* we must have removed a d3d thing, so put vulkan here */
+ new_list[dst] = wineopenxr_strdup("XR_KHR_vulkan_enable");
+ dst++;
+
+ our_createInfo = *createInfo;
+ our_createInfo.enabledExtensionNames = (const char * const*)new_list;
+ our_createInfo.enabledExtensionCount = dst;
+ createInfo = &our_createInfo;
+ }
+
+ WINE_TRACE("Enabled extensions:\n");
+ for(i = 0; i < createInfo->enabledExtensionCount; ++i){
+ WINE_TRACE(" -%s\n", createInfo->enabledExtensionNames[i]);
+ }
+
+ wine_instance = heap_alloc_zero(sizeof(wine_XrInstance));
+
+ res = xrCreateInstance(createInfo, &wine_instance->instance);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrCreateInstance failed: %d\n", res);
+ heap_free(wine_instance);
+ goto cleanup;
+ }
+
+ WINE_TRACE("allocated wine instance %p for native instance %p\n",
+ wine_instance, wine_instance->instance);
+
+#define USE_XR_FUNC(x) \
+ xrGetInstanceProcAddr(wine_instance->instance, #x, (PFN_xrVoidFunction *)&wine_instance->funcs.p_##x);
+ ALL_XR_INSTANCE_FUNCS()
+#undef USE_XR_FUNC
+
+ wine_instance->instance_type = type;
+ *instance = (XrInstance)wine_instance;
+
+cleanup:
+ if(createInfo == &our_createInfo){
+ for(i = 0; i < our_createInfo.enabledExtensionCount; ++i){
+ heap_free((void*)our_createInfo.enabledExtensionNames[i]);
+ }
+ heap_free((void*)our_createInfo.enabledExtensionNames);
+ }
+ return res;
+}
+
+XrResult WINAPI wine_xrDestroyInstance(XrInstance instance)
+{
+ wine_XrInstance *wine_instance = (wine_XrInstance *)instance;
+ XrResult res;
+
+ WINE_TRACE("\n");
+
+ res = xrDestroyInstance(wine_instance->instance);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrDestroyInstance failed: %d\n", res);
+ return res;
+ }
+
+ if(wine_instance->dxvk_device)
+ wine_instance->dxvk_device->lpVtbl->Release(wine_instance->dxvk_device);
+
+ heap_free(wine_instance);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session)
+{
+ wine_XrInstance *wine_instance = (wine_XrInstance *)instance;
+ wine_XrSession *wine_session;
+ XrResult res;
+ XrSessionCreateInfo our_create_info;
+ XrGraphicsBindingVulkanKHR our_vk_binding;
+
+ WINE_TRACE("%p, %p, %p\n", instance, createInfo, session);
+
+ if(createInfo->next){
+ switch(((XrBaseInStructure *)createInfo->next)->type){
+ case XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR /* == XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR */:
+ {
+ const XrGraphicsBindingVulkanKHR *their_vk_binding = (const XrGraphicsBindingVulkanKHR *)createInfo->next;
+
+ our_vk_binding = *their_vk_binding;
+ our_vk_binding.instance = get_native_VkInstance(their_vk_binding->instance);
+ our_vk_binding.physicalDevice = get_native_VkPhysicalDevice(their_vk_binding->physicalDevice);
+ our_vk_binding.device = get_native_VkDevice(their_vk_binding->device);
+
+ our_create_info = *createInfo;
+ our_create_info.next = &our_vk_binding;
+ createInfo = &our_create_info;
+
+ break;
+ }
+ case XR_TYPE_GRAPHICS_BINDING_D3D11_KHR:
+ {
+ const XrGraphicsBindingD3D11KHR *their_d3d11_binding = (const XrGraphicsBindingD3D11KHR *)createInfo->next;
+ HRESULT hr;
+
+ hr = ID3D11Device_QueryInterface(their_d3d11_binding->device, &IID_IDXGIVkInteropDevice2, (void **)&wine_instance->dxvk_device);
+ if(FAILED(hr)){
+ WINE_WARN("Given ID3D11Device doesn't support IDXGIVkInteropDevice. Only DXVK is supported.\n");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ our_vk_binding.type = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR;
+ our_vk_binding.next = NULL;
+
+ wine_instance->dxvk_device->lpVtbl->GetVulkanHandles(wine_instance->dxvk_device,
+ &our_vk_binding.instance, &our_vk_binding.physicalDevice, &our_vk_binding.device);
+
+ wine_instance->dxvk_device->lpVtbl->GetSubmissionQueue2(wine_instance->dxvk_device,
+ NULL, &our_vk_binding.queueIndex, &our_vk_binding.queueFamilyIndex);
+
+ our_vk_binding.instance = get_native_VkInstance(our_vk_binding.instance);
+ our_vk_binding.physicalDevice = get_native_VkPhysicalDevice(our_vk_binding.physicalDevice);
+ our_vk_binding.device = get_native_VkDevice(our_vk_binding.device);
+
+ our_create_info = *createInfo;
+ our_create_info.next = &our_vk_binding;
+ createInfo = &our_create_info;
+
+ break;
+ }
+ default:
+ WINE_WARN("Unhandled graphics binding type: %d\n", ((XrBaseInStructure *)createInfo->next)->type);
+ break;
+ }
+ }
+
+ wine_session = heap_alloc_zero(sizeof(*wine_session));
+
+ res = xrCreateSession(wine_instance->instance, createInfo, &wine_session->session);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrCreateSession failed: %d\n", res);
+ heap_free(wine_session);
+ return res;
+ }
+
+ wine_session->wine_instance = wine_instance;
+
+ EnterCriticalSection(&session_list_lock);
+
+ list_add_tail(&session_list, &wine_session->entry);
+
+ LeaveCriticalSection(&session_list_lock);
+
+ *session = (XrSession)wine_session;
+
+ WINE_TRACE("allocated wine session %p for native session %p\n",
+ wine_session, wine_session->session);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrDestroySession(XrSession session)
+{
+ wine_XrSession *wine_session = (wine_XrSession *)session;
+ XrResult res;
+
+ WINE_TRACE("%p\n", session);
+
+ res = xrDestroySession(wine_session->session);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrDestroySession failed: %d\n", res);
+ return res;
+ }
+
+ heap_free(wine_session->projection_views);
+ heap_free(wine_session->composition_layers);
+ heap_free(wine_session);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrCreateHandTrackerEXT(XrSession session, const XrHandTrackerCreateInfoEXT *createInfo,
+ XrHandTrackerEXT *handTracker)
+{
+ wine_XrSession *wine_session = (wine_XrSession *)session;
+ wine_XrHandTrackerEXT *wine_handTracker;
+ XrResult res;
+
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, handTracker);
+
+ wine_handTracker = heap_alloc_zero(sizeof(*wine_handTracker));
+
+ res = wine_session->wine_instance->funcs.p_xrCreateHandTrackerEXT(wine_session->session, createInfo, &wine_handTracker->hand_tracker);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrCreateHandTrackerEXT failed: %d\n", res);
+ heap_free(wine_handTracker);
+ return res;
+ }
+
+ wine_handTracker->wine_session = wine_session;
+
+ *handTracker = (XrHandTrackerEXT)wine_handTracker;
+
+ WINE_TRACE("allocated wine handTracker %p for native handTracker %p\n",
+ wine_handTracker, wine_handTracker->hand_tracker);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker)
+{
+ wine_XrHandTrackerEXT *wine_handTracker = (wine_XrHandTrackerEXT *)handTracker;
+ XrResult res;
+
+ WINE_TRACE("%p\n", handTracker);
+
+ res = wine_handTracker->wine_session->wine_instance->funcs.p_xrDestroyHandTrackerEXT(wine_handTracker->hand_tracker);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrDestroyHandTrackerEXT failed: %d\n", res);
+ return res;
+ }
+
+ heap_free(wine_handTracker);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrCreateSpatialAnchorMSFT(XrSession session,
+ const XrSpatialAnchorCreateInfoMSFT *createInfo, XrSpatialAnchorMSFT *anchor)
+{
+ wine_XrSession *wine_session = (wine_XrSession *)session;
+ wine_XrSpatialAnchorMSFT *wine_anchor;
+ XrResult res;
+
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, anchor);
+
+ wine_anchor = heap_alloc_zero(sizeof(*wine_anchor));
+
+ res = wine_session->wine_instance->funcs.p_xrCreateSpatialAnchorMSFT(wine_session->session, createInfo, &wine_anchor->spatial_anchor);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrCreateSpatialAnchorMSFT failed: %d\n", res);
+ heap_free(wine_anchor);
+ return res;
+ }
+
+ wine_anchor->wine_session = wine_session;
+
+ *anchor = (XrSpatialAnchorMSFT)wine_anchor;
+
+ WINE_TRACE("allocated wine spatialAnchor %p for native spatialAnchor %p\n",
+ wine_anchor, wine_anchor->spatial_anchor);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrDestroySpatialAnchorMSFT(XrSpatialAnchorMSFT anchor)
+{
+ wine_XrSpatialAnchorMSFT *wine_anchor = (wine_XrSpatialAnchorMSFT *)anchor;
+ XrResult res;
+
+ WINE_TRACE("%p\n", anchor);
+
+ res = wine_anchor->wine_session->wine_instance->funcs.p_xrDestroySpatialAnchorMSFT(wine_anchor->spatial_anchor);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrDestroySpatialAnchorMSFT failed: %d\n", res);
+ return res;
+ }
+
+ heap_free(wine_anchor);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrNegotiateLoaderRuntimeInterface(
+ const XrNegotiateLoaderInfo_win *loaderInfo,
+ XrNegotiateRuntimeRequest_win *runtimeRequest)
+{
+ XrResult res;
+
+ if(!loaderInfo || !runtimeRequest)
+ return XR_ERROR_INITIALIZATION_FAILED;
+
+ if((res = load_host_openxr_loader()) != XR_SUCCESS){
+ WINE_TRACE("host openxr loader failed to load runtime: %d\n", res);
+ return res;
+ }
+
+ if(loaderInfo->structType != XR_LOADER_INTERFACE_STRUCT_LOADER_INFO ||
+ loaderInfo->structVersion != XR_LOADER_INFO_STRUCT_VERSION ||
+ loaderInfo->structSize != sizeof(XrNegotiateLoaderInfo_win)){
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ if(loaderInfo->minInterfaceVersion > XR_CURRENT_LOADER_RUNTIME_VERSION ||
+ loaderInfo->maxInterfaceVersion < XR_CURRENT_LOADER_RUNTIME_VERSION){
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ if(runtimeRequest->structType != XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST ||
+ runtimeRequest->structVersion != XR_RUNTIME_INFO_STRUCT_VERSION ||
+ runtimeRequest->structSize != sizeof(XrNegotiateRuntimeRequest_win)){
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ runtimeRequest->runtimeInterfaceVersion = XR_CURRENT_LOADER_RUNTIME_VERSION;
+ runtimeRequest->getInstanceProcAddr = (PFN_xrGetInstanceProcAddr)&wine_xrGetInstanceProcAddr;
+ runtimeRequest->runtimeApiVersion = XR_CURRENT_API_VERSION;
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrGetVulkanGraphicsDeviceKHR(XrInstance instance,
+ XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice *vkPhysicalDevice)
+{
+ XrResult res;
+ WINE_TRACE("%p, 0x%s, %p, %p\n", instance, wine_dbgstr_longlong(systemId), vkInstance, vkPhysicalDevice);
+ res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanGraphicsDeviceKHR(((wine_XrInstance *)instance)->instance, systemId, get_native_VkInstance(vkInstance), vkPhysicalDevice);
+ *vkPhysicalDevice = get_wrapped_VkPhysicalDevice(vkInstance, *vkPhysicalDevice);
+ return res;
+}
+
+XrResult WINAPI wine_xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer)
+{
+ XrResult res;
+ uint32_t buf_len = 0;
+ char *buf;
+
+ WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), bufferCapacityInput, bufferCountOutput, buffer);
+
+ if(bufferCapacityInput == 0){
+ *bufferCountOutput = sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME);
+ return XR_SUCCESS;
+ }
+
+ if(bufferCapacityInput < sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME)){
+ *bufferCountOutput = sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME);
+ return XR_ERROR_SIZE_INSUFFICIENT;
+ }
+
+ res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanDeviceExtensionsKHR(
+ ((wine_XrInstance *)instance)->instance, systemId,
+ 0, &buf_len, NULL);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetVulkanDeviceExtensionsKHR failed: %d\n", res);
+ return res;
+ }
+
+ buf = heap_alloc(buf_len);
+
+ res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanDeviceExtensionsKHR(
+ ((wine_XrInstance *)instance)->instance, systemId,
+ buf_len, &buf_len, buf);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetVulkanDeviceExtensionsKHR failed: %d\n", res);
+ heap_free(buf);
+ return res;
+ }
+
+ WINE_TRACE("got device extensions: %s\n", buf);
+ SetEnvironmentVariableA(WINE_VULKAN_DEVICE_VARIABLE, buf);
+
+ heap_free(buf);
+
+ memcpy(buffer, WINE_VULKAN_DEVICE_EXTENSION_NAME, sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME));
+ *bufferCountOutput = sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrGetVulkanInstanceExtensionsKHR(XrInstance instance,
+ XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput,
+ char *buffer)
+{
+ static const char win32_surface[] = "VK_KHR_surface VK_KHR_win32_surface";
+
+ XrResult res;
+ uint32_t lin_len;
+
+ WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), bufferCapacityInput, bufferCountOutput, buffer);
+
+ /* Linux SteamVR does not return xlib_surface, but Windows SteamVR _does_
+ * return win32_surface. Some games (including hello_xr) depend on that, so
+ * add it here. */
+
+ res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanInstanceExtensionsKHR(
+ ((wine_XrInstance *)instance)->instance, systemId,
+ bufferCapacityInput, bufferCountOutput, buffer);
+ if(res == XR_SUCCESS){
+
+ if(bufferCapacityInput > 0){
+ /* *bufferCountOutput is not required to (and sometimes does not) contain the offset to the NUL byte */
+ lin_len = strlen(buffer) + 1;
+
+ if(bufferCapacityInput < lin_len + sizeof(win32_surface))
+ return XR_ERROR_SIZE_INSUFFICIENT;
+
+ buffer[lin_len - 1] = ' ';
+ memcpy(&buffer[lin_len], win32_surface, sizeof(win32_surface));
+
+ WINE_TRACE("returning: %s\n", buffer);
+ *bufferCountOutput = lin_len + sizeof(win32_surface);
+ }else{
+ *bufferCountOutput += sizeof(win32_surface) /* NUL byte included for required ' ' */;
+ }
+ }
+
+ return res;
+}
+
+XrResult WINAPI wine_xrPollEvent(XrInstance instance, XrEventDataBuffer *eventData)
+{
+ XrResult res;
+
+ WINE_TRACE("%p, %p\n", instance, eventData);
+
+ res = xrPollEvent(((wine_XrInstance *)instance)->instance, eventData);
+
+ if(res == XR_SUCCESS){
+ switch(eventData->type){
+ case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
+ {
+ XrEventDataInteractionProfileChanged *evt = (XrEventDataInteractionProfileChanged *)eventData;
+ evt->session = (XrSession)get_wrapped_XrSession(evt->session);
+ break;
+ }
+ case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
+ {
+ XrEventDataSessionStateChanged *evt = (XrEventDataSessionStateChanged *)eventData;
+ evt->session = (XrSession)get_wrapped_XrSession(evt->session);
+ break;
+ }
+ case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR:
+ {
+ XrEventDataVisibilityMaskChangedKHR *evt = (XrEventDataVisibilityMaskChangedKHR *)eventData;
+ evt->session = (XrSession)get_wrapped_XrSession(evt->session);
+ break;
+ }
+ case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
+ {
+ XrEventDataReferenceSpaceChangePending *evt = (XrEventDataReferenceSpaceChangePending *)eventData;
+ evt->session = (XrSession)get_wrapped_XrSession(evt->session);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return res;
+}
+
+XrResult WINAPI wine_xrGetSystem(XrInstance instance, const XrSystemGetInfo *getInfo, XrSystemId *systemId)
+{
+ wine_XrInstance *wine_instance = (wine_XrInstance *)instance;
+ XrResult res;
+
+ WINE_TRACE("%p, %p, %p\n", instance, getInfo, systemId);
+
+ res = wine_instance->funcs.p_xrGetSystem(wine_instance->instance, getInfo, systemId);
+ if(res == XR_SUCCESS){
+ XrGraphicsRequirementsVulkanKHR vk_reqs;
+
+ wine_instance->systemId = *systemId;
+
+ /* required to call before graphics init stuff happens, so i stuck it here. */
+ vk_reqs.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
+ res = wine_instance->funcs.p_xrGetVulkanGraphicsRequirementsKHR(wine_instance->instance, *systemId, &vk_reqs);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrGetVulkanGraphicsRequirementsKHR failed: %d\n", res);
+ return res;
+ }
+ }
+
+ return res;
+}
+
+int64_t map_format_dxgi_to_vulkan(int64_t format)
+{
+ switch(format){
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ return VK_FORMAT_B8G8R8A8_SRGB;
+
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return VK_FORMAT_B8G8R8A8_UNORM;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return VK_FORMAT_R8G8B8A8_SRGB;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return VK_FORMAT_R8G8B8A8_UNORM;
+
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return VK_FORMAT_R32G32B32_SFLOAT;
+
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return VK_FORMAT_R16G16B16A16_SFLOAT;
+
+ case DXGI_FORMAT_D32_FLOAT:
+ return VK_FORMAT_D32_SFLOAT;
+
+ case DXGI_FORMAT_D16_UNORM:
+ return VK_FORMAT_D16_UNORM;
+
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return VK_FORMAT_D24_UNORM_S8_UINT;
+
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ return VK_FORMAT_D32_SFLOAT_S8_UINT;
+
+ default:
+ WINE_WARN("Unable to map DXGI format (%lu) to Vulkan format\n", format);
+ return VK_FORMAT_UNDEFINED;
+ }
+}
+
+int64_t map_format_vulkan_to_dxgi(int64_t format)
+{
+ switch(format){
+ case VK_FORMAT_B8G8R8A8_SRGB:
+ return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
+
+ case VK_FORMAT_B8G8R8A8_UNORM:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+
+ case VK_FORMAT_R8G8B8A8_SRGB:
+ return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+
+ case VK_FORMAT_R8G8B8A8_UNORM:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ case VK_FORMAT_R32G32B32A32_SFLOAT:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+
+ case VK_FORMAT_R32G32B32_SFLOAT:
+ return DXGI_FORMAT_R32G32B32_FLOAT;
+
+ case VK_FORMAT_R16G16B16A16_SFLOAT:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ case VK_FORMAT_D32_SFLOAT:
+ return DXGI_FORMAT_D32_FLOAT;
+
+ case VK_FORMAT_D16_UNORM:
+ return DXGI_FORMAT_D16_UNORM;
+
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
+
+ default:
+ WINE_WARN("Unable to map Vulkan format (%lu) to DXGI format\n", format);
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+XrResult WINAPI wine_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t *formatCountOutput, int64_t *formats)
+{
+ wine_XrSession *wine_session = (wine_XrSession *)session;
+ XrResult res;
+ uint32_t i, o;
+
+ WINE_TRACE("%p, %u, %p, %p\n", session, formatCapacityInput, formatCountOutput, formats);
+
+ res = xrEnumerateSwapchainFormats(wine_session->session, formatCapacityInput, formatCountOutput, formats);
+
+ if(wine_session->wine_instance->instance_type == INSTANCE_TYPE_D3D11){
+ if(res == XR_SUCCESS && formatCapacityInput && formats){
+ o = 0;
+ for(i = 0; i < *formatCountOutput; ++i){
+ int64_t mapped = map_format_vulkan_to_dxgi(formats[i]);
+ if(mapped != DXGI_FORMAT_UNKNOWN){
+ formats[o++] = mapped;
+ }
+ }
+ *formatCountOutput = o;
+ }
+ }
+
+ return res;
+}
+
+XrResult WINAPI wine_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo *createInfo, XrSwapchain *swapchain)
+{
+ wine_XrSession *wine_session = (wine_XrSession *)session;
+ wine_XrSwapchain *wine_swapchain;
+ XrSwapchainCreateInfo our_createInfo;
+ XrResult res;
+
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, swapchain);
+
+ wine_swapchain = heap_alloc_zero(sizeof(*wine_swapchain));
+ wine_swapchain->create_info = *createInfo;
+
+ if(wine_session->wine_instance->instance_type == INSTANCE_TYPE_D3D11){
+ our_createInfo = *createInfo;
+ our_createInfo.format = map_format_dxgi_to_vulkan(createInfo->format);
+ if(our_createInfo.format == VK_FORMAT_UNDEFINED){
+ WINE_ERR("unable to set Vulkan format\n");
+ heap_free(wine_swapchain);
+ return XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED;
+ }
+ createInfo = &our_createInfo;
+ }
+
+ res = xrCreateSwapchain(((wine_XrSession *)session)->session, createInfo, &wine_swapchain->swapchain);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrCreateSwapchain failed: %d\n", res);
+ heap_free(wine_swapchain);
+ return res;
+ }
+
+ wine_swapchain->wine_session = wine_session;
+ *swapchain = (XrSwapchain)wine_swapchain;
+
+ WINE_TRACE("allocated wine swapchain %p for native swapchain %p\n",
+ wine_swapchain, wine_swapchain->swapchain);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrDestroySwapchain(XrSwapchain swapchain)
+{
+ wine_XrSwapchain *wine_swapchain = (wine_XrSwapchain *)swapchain;
+ XrResult res;
+
+ WINE_TRACE("%p\n", swapchain);
+
+ res = xrDestroySwapchain(wine_swapchain->swapchain);
+ if(res != XR_SUCCESS){
+ WINE_WARN("xrDestroySwapchain failed: %d\n", res);
+ return res;
+ }
+
+ heap_free(wine_swapchain);
+
+ return XR_SUCCESS;
+}
+
+XrResult WINAPI wine_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t *imageCountOutput, XrSwapchainImageBaseHeader *images)
+{
+ wine_XrSwapchain *wine_swapchain = (wine_XrSwapchain *)swapchain;
+ wine_XrInstance *wine_instance = wine_swapchain->wine_session->wine_instance;
+ XrResult res;
+ XrSwapchainImageVulkanKHR *our_images;
+ XrSwapchainImageBaseHeader *their_images = images;
+ HRESULT hr;
+ uint32_t i;
+
+ WINE_TRACE("%p, %u, %p, %p\n", swapchain, imageCapacityInput, imageCountOutput, images);
+
+ if(images){
+ if(wine_instance->instance_type == INSTANCE_TYPE_D3D11){
+ our_images = heap_alloc(sizeof(*our_images) * imageCapacityInput);
+ for(i = 0; i < imageCapacityInput; ++i){
+ our_images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR;
+ }
+ images = (XrSwapchainImageBaseHeader *)our_images;
+ }
+ }
+
+ res = xrEnumerateSwapchainImages(wine_swapchain->swapchain, imageCapacityInput, imageCountOutput, images);
+
+ if(images && res == XR_SUCCESS){
+ if(wine_instance->instance_type == INSTANCE_TYPE_D3D11){
+ D3D11_TEXTURE2D_DESC1 desc;
+
+ desc.Width = wine_swapchain->create_info.width;
+ desc.Height = wine_swapchain->create_info.height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = wine_swapchain->create_info.format;
+ WINE_TRACE("creating dxvk texture with dxgi format %d (%x)\n",
+ desc.Format, desc.Format);
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+ desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
+
+ XrSwapchainImageD3D11KHR *their_d3d11 = (XrSwapchainImageD3D11KHR *)their_images;
+ for(i = 0; i < *imageCountOutput; ++i){
+ hr = wine_instance->dxvk_device->lpVtbl->CreateTexture2DFromVkImage(wine_instance->dxvk_device,
+ &desc, our_images[i].image, &their_d3d11[i].texture);
+ if(FAILED(hr)){
+ WINE_WARN("Failed to create DXVK texture from VkImage: %08x\n", hr);
+ return XR_ERROR_INSTANCE_LOST;
+ }
+ WINE_TRACE("Successfully allocated texture %p\n", their_d3d11[i].texture);
+ }
+
+ heap_free(our_images);
+ }
+ }
+
+ return res;
+}
+
+static XrCompositionLayerBaseHeader *convert_XrCompositionLayer(wine_XrSession *wine_session,
+ const XrCompositionLayerBaseHeader *in_layer, CompositionLayer *out_layer,
+ uint32_t *view_idx)
+{
+ uint32_t i;
+
+ switch(in_layer->type){
+ case XR_TYPE_COMPOSITION_LAYER_CUBE_KHR: {
+ out_layer->cube = *(const XrCompositionLayerCubeKHR *)in_layer;
+ out_layer->cube.swapchain = ((wine_XrSwapchain *)out_layer->cube.swapchain)->swapchain;
+ break;
+ }
+
+ case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR:
+ out_layer->cylinder = *(const XrCompositionLayerCylinderKHR *)in_layer;
+ out_layer->cylinder.subImage.swapchain = ((wine_XrSwapchain *)out_layer->cylinder.subImage.swapchain)->swapchain;
+ break;
+
+ case XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR:
+ out_layer->depth_info = *(const XrCompositionLayerDepthInfoKHR *)in_layer;
+ out_layer->depth_info.subImage.swapchain = ((wine_XrSwapchain *)out_layer->depth_info.subImage.swapchain)->swapchain;
+ break;
+
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR:
+ out_layer->equirect = *(const XrCompositionLayerEquirectKHR *)in_layer;
+ out_layer->equirect.subImage.swapchain = ((wine_XrSwapchain *)out_layer->equirect.subImage.swapchain)->swapchain;
+ break;
+
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR:
+ out_layer->equirect2 = *(const XrCompositionLayerEquirect2KHR *)in_layer;
+ out_layer->equirect2.subImage.swapchain = ((wine_XrSwapchain *)out_layer->equirect2.subImage.swapchain)->swapchain;
+ break;
+
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION:
+ out_layer->projection = *(const XrCompositionLayerProjection *)in_layer;
+
+ if(out_layer->projection.viewCount + *view_idx > wine_session->projection_view_count){
+ wine_session->projection_view_count = out_layer->projection.viewCount + *view_idx;
+ wine_session->projection_views = heap_realloc(wine_session->projection_views,
+ sizeof(XrCompositionLayerProjectionView) * wine_session->projection_view_count);
+ }
+
+ out_layer->projection.views = &wine_session->projection_views[*view_idx];
+ memcpy((void*)out_layer->projection.views, ((const XrCompositionLayerProjection *)in_layer)->views,
+ sizeof(XrCompositionLayerProjectionView) * out_layer->projection.viewCount);
+ for(i = 0; i < out_layer->projection.viewCount; ++i){
+ ((XrCompositionLayerProjectionView *)&out_layer->projection.views[i])->subImage.swapchain =
+ ((wine_XrSwapchain *)out_layer->projection.views[i].subImage.swapchain)->swapchain;
+ }
+
+ *view_idx += out_layer->projection.viewCount;
+ break;
+
+ case XR_TYPE_COMPOSITION_LAYER_QUAD:
+ out_layer->quad = *(const XrCompositionLayerQuad *)in_layer;
+ out_layer->quad.subImage.swapchain = ((wine_XrSwapchain *)out_layer->quad.subImage.swapchain)->swapchain;
+ break;
+
+ case XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR:
+ /* no conversion needed */
+ return (XrCompositionLayerBaseHeader *)in_layer;
+
+ default:
+ WINE_WARN("Unknown composition in_layer type: %d\n", in_layer->type);
+ return (XrCompositionLayerBaseHeader *)in_layer;
+ }
+
+ return (XrCompositionLayerBaseHeader *)out_layer;
+}
+
+XrResult WINAPI wine_xrEndFrame(XrSession session, const XrFrameEndInfo *frameEndInfo)
+{
+ wine_XrSession *wine_session = (wine_XrSession *)session;
+ XrFrameEndInfo our_frameEndInfo;
+ uint32_t i, view_idx = 0;
+
+ WINE_TRACE("%p, %p\n", session, frameEndInfo);
+
+ if(frameEndInfo->layerCount > wine_session->composition_layer_count){
+ heap_free(wine_session->composition_layers);
+ wine_session->composition_layers = heap_alloc(frameEndInfo->layerCount * sizeof(*wine_session->composition_layers));
+ heap_free(wine_session->composition_layer_ptrs);
+ wine_session->composition_layer_ptrs = heap_alloc(frameEndInfo->layerCount * sizeof(*wine_session->composition_layer_ptrs));
+ wine_session->composition_layer_count = frameEndInfo->layerCount;
+ }
+
+ for(i = 0; i < frameEndInfo->layerCount; ++i){
+ wine_session->composition_layer_ptrs[i] =
+ convert_XrCompositionLayer(wine_session,
+ frameEndInfo->layers[i], &wine_session->composition_layers[i],
+ &view_idx);
+ }
+
+ our_frameEndInfo = *frameEndInfo;
+ our_frameEndInfo.layers = (const XrCompositionLayerBaseHeader *const *)wine_session->composition_layer_ptrs;
+
+ return xrEndFrame(((wine_XrSession *)session)->session, &our_frameEndInfo);
+}
+
+/* wineopenxr API */
+XrResult WINAPI __wineopenxr_GetVulkanInstanceExtensions(uint32_t buflen, uint32_t *outlen, char *buf)
+{
+ XrResult res;
+
+ WINE_TRACE("\n");
+
+ if((res = load_host_openxr_loader()) != XR_SUCCESS){
+ WINE_TRACE("host openxr loader failed to load runtime: %d\n", res);
+ return res;
+ }
+
+ if(buflen < strlen(g_instance_extensions) + 1 || !buf){
+ *outlen = strlen(g_instance_extensions) + 1;
+ return XR_SUCCESS;
+ }
+
+ *outlen = strlen(g_instance_extensions) + 1;
+ strcpy(buf, g_instance_extensions);
+
+ return XR_SUCCESS;
+}
+
+/* wineopenxr API */
+XrResult WINAPI __wineopenxr_GetVulkanDeviceExtensions(uint32_t buflen, uint32_t *outlen, char *buf)
+{
+ XrResult res;
+
+ WINE_TRACE("\n");
+
+ if((res = load_host_openxr_loader()) != XR_SUCCESS){
+ WINE_TRACE("host openxr loader failed to load runtime: %d\n", res);
+ return res;
+ }
+
+ if(buflen < strlen(WINE_VULKAN_DEVICE_EXTENSION_NAME) + 1 || !buf){
+ *outlen = strlen(WINE_VULKAN_DEVICE_EXTENSION_NAME) + 1;
+ return XR_SUCCESS;
+ }
+
+ SetEnvironmentVariableA(WINE_VULKAN_DEVICE_VARIABLE, g_device_extensions);
+ *outlen = strlen(WINE_VULKAN_DEVICE_EXTENSION_NAME) + 1;
+ strcpy(buf, WINE_VULKAN_DEVICE_EXTENSION_NAME);
+
+ return XR_SUCCESS;
+}
diff --git a/wineopenxr/openxr_private.h b/wineopenxr/openxr_private.h
new file mode 100644
index 00000000..6d937444
--- /dev/null
+++ b/wineopenxr/openxr_private.h
@@ -0,0 +1,85 @@
+#include "openxr_thunks.h"
+
+#include "wine/list.h"
+
+#define INSTANCE_TYPE_VULKAN 1
+#define INSTANCE_TYPE_OPENGL 2
+#define INSTANCE_TYPE_D3D11 3
+#define INSTANCE_TYPE_D3D12 4
+
+struct IDXGIVkInteropDevice2;
+typedef struct IDXGIVkInteropDevice2 IDXGIVkInteropDevice2;
+
+typedef struct wine_XrInstance {
+ XrInstance instance;
+ struct openxr_instance_funcs funcs;
+
+ VkInstance vk_instance;
+ VkPhysicalDevice vk_phys_dev;
+
+ uint32_t instance_type;
+ XrSystemId systemId;
+
+ IDXGIVkInteropDevice2 *dxvk_device;
+} wine_XrInstance;
+
+union CompositionLayer;
+typedef union CompositionLayer CompositionLayer;
+
+typedef struct wine_XrSession {
+ XrSession session;
+ struct wine_XrInstance *wine_instance;
+
+ struct list entry;
+
+ uint32_t composition_layer_count;
+ CompositionLayer *composition_layers;
+ XrCompositionLayerBaseHeader **composition_layer_ptrs;
+
+ uint32_t projection_view_count;
+ XrCompositionLayerProjectionView *projection_views;
+} wine_XrSession;
+
+typedef struct wine_XrHandTrackerEXT {
+ XrHandTrackerEXT hand_tracker;
+ struct wine_XrSession *wine_session;
+} wine_XrHandTrackerEXT;
+
+typedef struct wine_XrSpatialAnchorMSFT {
+ XrSpatialAnchorMSFT spatial_anchor;
+ struct wine_XrSession *wine_session;
+} wine_XrSpatialAnchorMSFT;
+
+typedef struct wine_XrSwapchain{
+ XrSwapchain swapchain;
+ struct wine_XrSession *wine_session;
+
+ XrSwapchainCreateInfo create_info;
+} wine_XrSwapchain;
+
+struct openxr_func {
+ const char *name;
+ void *func;
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
+
+extern void *wine_xr_proc_addr(const char *name);
+
+extern XrResult WINAPI wine_xrEnumerateInstanceExtensionProperties(const char *layerName,
+ uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties);
+extern XrResult WINAPI wine_xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance,
+ XrTime time, LARGE_INTEGER *performanceCounter);
+extern XrResult WINAPI wine_xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance,
+ const LARGE_INTEGER *performanceCounter, XrTime *time);
+extern XrResult WINAPI wine_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance,
+ XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements);
+extern XrResult WINAPI wine_xrGetD3D12GraphicsRequirementsKHR(XrInstance instance,
+ XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements);
+
+extern VkDevice (WINAPI *get_native_VkDevice)(VkDevice);
+extern VkInstance (WINAPI *get_native_VkInstance)(VkInstance);
+extern VkPhysicalDevice (WINAPI *get_native_VkPhysicalDevice)(VkPhysicalDevice);
+extern VkPhysicalDevice (WINAPI *get_wrapped_VkPhysicalDevice)(VkInstance, VkPhysicalDevice);
+extern VkQueue (WINAPI *get_native_VkQueue)(VkQueue);
+extern XrResult load_host_openxr_loader(void);
diff --git a/wineopenxr/openxr_thunks.c b/wineopenxr/openxr_thunks.c
new file mode 100644
index 00000000..d2c2627c
--- /dev/null
+++ b/wineopenxr/openxr_thunks.c
@@ -0,0 +1,561 @@
+/* Automatically generated from OpenXR xr.xml; DO NOT EDIT!
+ *
+ * This file is generated from OpenXR xr.xml file covered
+ * by the following copyright and permission notice:
+ *
+ * Copyright (c) 2017-2020 The Khronos Group Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This file, xr.xml, is the OpenXR API Registry. It is a critically important
+ * and normative part of the OpenXR Specification, including a canonical
+ * machine-readable definition of the API, parameter and member validation
+ * language incorporated into the Specification and reference pages, and other
+ * material which is registered by Khronos, such as tags used by extension and
+ * layer authors. The only authoritative version of xr.xml is the one
+ * maintained in the master branch of the Khronos OpenXR GitHub project.
+ *
+ */
+
+#include "wine/debug.h"
+#include "wine/vulkan.h"
+#include "d3d11.h"
+#include "d3d12.h"
+#define WINE_XR_HOST
+#include "wineopenxr.h"
+#include "openxr_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(openxr);
+
+#if defined(USE_STRUCT_CONVERSION)
+#endif /* USE_STRUCT_CONVERSION */
+
+XrResult convert_XrInstanceCreateInfo_struct_chain(const void *next, XrInstanceCreateInfo *out_struct)
+{
+ XrBaseOutStructure *out_header = (XrBaseOutStructure *)out_struct;
+ const XrBaseInStructure *in_header;
+
+ out_header->next = NULL;
+
+ for (in_header = next; in_header; in_header = in_header->next)
+ {
+ switch (in_header->type)
+ {
+ case XR_TYPE_INSTANCE_CREATE_INFO:
+ break;
+
+ default:
+ WINE_FIXME("Application requested a linked structure of type %u.\n", in_header->type);
+ }
+ }
+
+ return XR_SUCCESS;
+}
+
+void free_XrInstanceCreateInfo_struct_chain(XrInstanceCreateInfo *s)
+{
+ XrBaseOutStructure *header = (void *)s->next;
+
+ while (header)
+ {
+ void *prev = header;
+ header = header->next;
+ HeapFree(GetProcessHeap(), 0, prev);
+ }
+
+ s->next = NULL;
+}
+
+XrResult WINAPI wine_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo *acquireInfo, uint32_t *index)
+{
+ WINE_TRACE("%p, %p, %p\n", swapchain, acquireInfo, index);
+ return xrAcquireSwapchainImage(((wine_XrSwapchain *)swapchain)->swapchain, acquireInfo, index);
+}
+
+XrResult WINAPI wine_xrApplyHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo, const XrHapticBaseHeader *hapticFeedback)
+{
+ WINE_TRACE("%p, %p, %p\n", session, hapticActionInfo, hapticFeedback);
+ return xrApplyHapticFeedback(((wine_XrSession *)session)->session, hapticActionInfo, hapticFeedback);
+}
+
+XrResult WINAPI wine_xrAttachSessionActionSets(XrSession session, const XrSessionActionSetsAttachInfo *attachInfo)
+{
+ WINE_TRACE("%p, %p\n", session, attachInfo);
+ return xrAttachSessionActionSets(((wine_XrSession *)session)->session, attachInfo);
+}
+
+XrResult WINAPI wine_xrBeginFrame(XrSession session, const XrFrameBeginInfo *frameBeginInfo)
+{
+ WINE_TRACE("%p, %p\n", session, frameBeginInfo);
+ return xrBeginFrame(((wine_XrSession *)session)->session, frameBeginInfo);
+}
+
+XrResult WINAPI wine_xrBeginSession(XrSession session, const XrSessionBeginInfo *beginInfo)
+{
+ WINE_TRACE("%p, %p\n", session, beginInfo);
+ return xrBeginSession(((wine_XrSession *)session)->session, beginInfo);
+}
+
+XrResult WINAPI wine_xrCreateAction(XrActionSet actionSet, const XrActionCreateInfo *createInfo, XrAction *action)
+{
+ WINE_TRACE("%p, %p, %p\n", actionSet, createInfo, action);
+ return xrCreateAction(actionSet, createInfo, action);
+}
+
+XrResult WINAPI wine_xrCreateActionSet(XrInstance instance, const XrActionSetCreateInfo *createInfo, XrActionSet *actionSet)
+{
+ WINE_TRACE("%p, %p, %p\n", instance, createInfo, actionSet);
+ return xrCreateActionSet(((wine_XrInstance *)instance)->instance, createInfo, actionSet);
+}
+
+XrResult WINAPI wine_xrCreateActionSpace(XrSession session, const XrActionSpaceCreateInfo *createInfo, XrSpace *space)
+{
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, space);
+ return xrCreateActionSpace(((wine_XrSession *)session)->session, createInfo, space);
+}
+
+static XrResult WINAPI wine_xrCreateHandMeshSpaceMSFT(XrHandTrackerEXT handTracker, const XrHandMeshSpaceCreateInfoMSFT *createInfo, XrSpace *space)
+{
+ WINE_TRACE("%p, %p, %p\n", handTracker, createInfo, space);
+ return ((wine_XrHandTrackerEXT *)handTracker)->wine_session->wine_instance->funcs.p_xrCreateHandMeshSpaceMSFT(((wine_XrHandTrackerEXT *)handTracker)->hand_tracker, createInfo, space);
+}
+
+XrResult WINAPI wine_xrCreateReferenceSpace(XrSession session, const XrReferenceSpaceCreateInfo *createInfo, XrSpace *space)
+{
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, space);
+ return xrCreateReferenceSpace(((wine_XrSession *)session)->session, createInfo, space);
+}
+
+static XrResult WINAPI wine_xrCreateSpatialAnchorSpaceMSFT(XrSession session, const XrSpatialAnchorSpaceCreateInfoMSFT *createInfo, XrSpace *space)
+{
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, space);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrCreateSpatialAnchorSpaceMSFT(((wine_XrSession *)session)->session, createInfo, space);
+}
+
+static XrResult WINAPI wine_xrCreateSpatialGraphNodeSpaceMSFT(XrSession session, const XrSpatialGraphNodeSpaceCreateInfoMSFT *createInfo, XrSpace *space)
+{
+ WINE_TRACE("%p, %p, %p\n", session, createInfo, space);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrCreateSpatialGraphNodeSpaceMSFT(((wine_XrSession *)session)->session, createInfo, space);
+}
+
+XrResult WINAPI wine_xrDestroyAction(XrAction action)
+{
+ WINE_TRACE("%p\n", action);
+ return xrDestroyAction(action);
+}
+
+XrResult WINAPI wine_xrDestroyActionSet(XrActionSet actionSet)
+{
+ WINE_TRACE("%p\n", actionSet);
+ return xrDestroyActionSet(actionSet);
+}
+
+XrResult WINAPI wine_xrDestroySpace(XrSpace space)
+{
+ WINE_TRACE("%p\n", space);
+ return xrDestroySpace(space);
+}
+
+XrResult WINAPI wine_xrEndSession(XrSession session)
+{
+ WINE_TRACE("%p\n", session);
+ return xrEndSession(((wine_XrSession *)session)->session);
+}
+
+XrResult WINAPI wine_xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrApiLayerProperties *properties)
+{
+ WINE_TRACE("%u, %p, %p\n", propertyCapacityInput, propertyCountOutput, properties);
+ return xrEnumerateApiLayerProperties(propertyCapacityInput, propertyCountOutput, properties);
+}
+
+XrResult WINAPI wine_xrEnumerateBoundSourcesForAction(XrSession session, const XrBoundSourcesForActionEnumerateInfo *enumerateInfo, uint32_t sourceCapacityInput, uint32_t *sourceCountOutput, XrPath *sources)
+{
+ WINE_TRACE("%p, %p, %u, %p, %p\n", session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+ return xrEnumerateBoundSourcesForAction(((wine_XrSession *)session)->session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+}
+
+XrResult WINAPI wine_xrEnumerateEnvironmentBlendModes(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t *environmentBlendModeCountOutput, XrEnvironmentBlendMode *environmentBlendModes)
+{
+ WINE_TRACE("%p, 0x%s, %#x, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+ return xrEnumerateEnvironmentBlendModes(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+}
+
+XrResult WINAPI wine_xrEnumerateReferenceSpaces(XrSession session, uint32_t spaceCapacityInput, uint32_t *spaceCountOutput, XrReferenceSpaceType *spaces)
+{
+ WINE_TRACE("%p, %u, %p, %p\n", session, spaceCapacityInput, spaceCountOutput, spaces);
+ return xrEnumerateReferenceSpaces(((wine_XrSession *)session)->session, spaceCapacityInput, spaceCountOutput, spaces);
+}
+
+XrResult WINAPI wine_xrEnumerateViewConfigurationViews(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrViewConfigurationView *views)
+{
+ WINE_TRACE("%p, 0x%s, %#x, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+ return xrEnumerateViewConfigurationViews(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+}
+
+XrResult WINAPI wine_xrEnumerateViewConfigurations(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t *viewConfigurationTypeCountOutput, XrViewConfigurationType *viewConfigurationTypes)
+{
+ WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+ return xrEnumerateViewConfigurations(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+}
+
+XrResult WINAPI wine_xrGetActionStateBoolean(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateBoolean *state)
+{
+ WINE_TRACE("%p, %p, %p\n", session, getInfo, state);
+ return xrGetActionStateBoolean(((wine_XrSession *)session)->session, getInfo, state);
+}
+
+XrResult WINAPI wine_xrGetActionStateFloat(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateFloat *state)
+{
+ WINE_TRACE("%p, %p, %p\n", session, getInfo, state);
+ return xrGetActionStateFloat(((wine_XrSession *)session)->session, getInfo, state);
+}
+
+XrResult WINAPI wine_xrGetActionStatePose(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStatePose *state)
+{
+ WINE_TRACE("%p, %p, %p\n", session, getInfo, state);
+ return xrGetActionStatePose(((wine_XrSession *)session)->session, getInfo, state);
+}
+
+XrResult WINAPI wine_xrGetActionStateVector2f(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateVector2f *state)
+{
+ WINE_TRACE("%p, %p, %p\n", session, getInfo, state);
+ return xrGetActionStateVector2f(((wine_XrSession *)session)->session, getInfo, state);
+}
+
+XrResult WINAPI wine_xrGetCurrentInteractionProfile(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState *interactionProfile)
+{
+ WINE_TRACE("%p, 0x%s, %p\n", session, wine_dbgstr_longlong(topLevelUserPath), interactionProfile);
+ return xrGetCurrentInteractionProfile(((wine_XrSession *)session)->session, topLevelUserPath, interactionProfile);
+}
+
+XrResult WINAPI wine_xrGetInputSourceLocalizedName(XrSession session, const XrInputSourceLocalizedNameGetInfo *getInfo, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer)
+{
+ WINE_TRACE("%p, %p, %u, %p, %p\n", session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+ return xrGetInputSourceLocalizedName(((wine_XrSession *)session)->session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+}
+
+XrResult WINAPI wine_xrGetInstanceProperties(XrInstance instance, XrInstanceProperties *instanceProperties)
+{
+ WINE_TRACE("%p, %p\n", instance, instanceProperties);
+ return xrGetInstanceProperties(((wine_XrInstance *)instance)->instance, instanceProperties);
+}
+
+static XrResult WINAPI wine_xrGetOpenGLGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR *graphicsRequirements)
+{
+ WINE_TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(systemId), graphicsRequirements);
+ return ((wine_XrInstance *)instance)->funcs.p_xrGetOpenGLGraphicsRequirementsKHR(((wine_XrInstance *)instance)->instance, systemId, graphicsRequirements);
+}
+
+XrResult WINAPI wine_xrGetReferenceSpaceBoundsRect(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df *bounds)
+{
+ WINE_TRACE("%p, %#x, %p\n", session, referenceSpaceType, bounds);
+ return xrGetReferenceSpaceBoundsRect(((wine_XrSession *)session)->session, referenceSpaceType, bounds);
+}
+
+XrResult WINAPI wine_xrGetSystemProperties(XrInstance instance, XrSystemId systemId, XrSystemProperties *properties)
+{
+ WINE_TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(systemId), properties);
+ return xrGetSystemProperties(((wine_XrInstance *)instance)->instance, systemId, properties);
+}
+
+XrResult WINAPI wine_xrGetViewConfigurationProperties(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties *configurationProperties)
+{
+ WINE_TRACE("%p, 0x%s, %#x, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationType, configurationProperties);
+ return xrGetViewConfigurationProperties(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationType, configurationProperties);
+}
+
+static XrResult WINAPI wine_xrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR *visibilityMask)
+{
+ WINE_TRACE("%p, %#x, %u, %#x, %p\n", session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrGetVisibilityMaskKHR(((wine_XrSession *)session)->session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask);
+}
+
+static XrResult WINAPI wine_xrGetVulkanGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR *graphicsRequirements)
+{
+ WINE_TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(systemId), graphicsRequirements);
+ return ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanGraphicsRequirementsKHR(((wine_XrInstance *)instance)->instance, systemId, graphicsRequirements);
+}
+
+static XrResult WINAPI wine_xrLocateHandJointsEXT(XrHandTrackerEXT handTracker, const XrHandJointsLocateInfoEXT *locateInfo, XrHandJointLocationsEXT *locations)
+{
+ WINE_TRACE("%p, %p, %p\n", handTracker, locateInfo, locations);
+ return ((wine_XrHandTrackerEXT *)handTracker)->wine_session->wine_instance->funcs.p_xrLocateHandJointsEXT(((wine_XrHandTrackerEXT *)handTracker)->hand_tracker, locateInfo, locations);
+}
+
+XrResult WINAPI wine_xrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation *location)
+{
+ WINE_TRACE("%p, %p, 0x%s, %p\n", space, baseSpace, wine_dbgstr_longlong(time), location);
+ return xrLocateSpace(space, baseSpace, time, location);
+}
+
+XrResult WINAPI wine_xrLocateViews(XrSession session, const XrViewLocateInfo *viewLocateInfo, XrViewState *viewState, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrView *views)
+{
+ WINE_TRACE("%p, %p, %p, %u, %p, %p\n", session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+ return xrLocateViews(((wine_XrSession *)session)->session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+}
+
+XrResult WINAPI wine_xrPathToString(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer)
+{
+ WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(path), bufferCapacityInput, bufferCountOutput, buffer);
+ return xrPathToString(((wine_XrInstance *)instance)->instance, path, bufferCapacityInput, bufferCountOutput, buffer);
+}
+
+static XrResult WINAPI wine_xrPerfSettingsSetPerformanceLevelEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level)
+{
+ WINE_TRACE("%p, %#x, %#x\n", session, domain, level);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrPerfSettingsSetPerformanceLevelEXT(((wine_XrSession *)session)->session, domain, level);
+}
+
+XrResult WINAPI wine_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo *releaseInfo)
+{
+ WINE_TRACE("%p, %p\n", swapchain, releaseInfo);
+ return xrReleaseSwapchainImage(((wine_XrSwapchain *)swapchain)->swapchain, releaseInfo);
+}
+
+XrResult WINAPI wine_xrRequestExitSession(XrSession session)
+{
+ WINE_TRACE("%p\n", session);
+ return xrRequestExitSession(((wine_XrSession *)session)->session);
+}
+
+XrResult WINAPI wine_xrResultToString(XrInstance instance, XrResult value, char buffer[])
+{
+ WINE_TRACE("%p, %#x, %p\n", instance, value, buffer);
+ return xrResultToString(((wine_XrInstance *)instance)->instance, value, buffer);
+}
+
+static XrResult WINAPI wine_xrSetInputDeviceActiveEXT(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive)
+{
+ WINE_TRACE("%p, 0x%s, 0x%s, %u\n", session, wine_dbgstr_longlong(interactionProfile), wine_dbgstr_longlong(topLevelPath), isActive);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceActiveEXT(((wine_XrSession *)session)->session, interactionProfile, topLevelPath, isActive);
+}
+
+static XrResult WINAPI wine_xrSetInputDeviceLocationEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose)
+{
+ WINE_TRACE("%p, 0x%s, 0x%s, %p, \n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), space, pose);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceLocationEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, space, pose);
+}
+
+static XrResult WINAPI wine_xrSetInputDeviceStateBoolEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state)
+{
+ WINE_TRACE("%p, 0x%s, 0x%s, %u\n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), state);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceStateBoolEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, state);
+}
+
+static XrResult WINAPI wine_xrSetInputDeviceStateFloatEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state)
+{
+ WINE_TRACE("%p, 0x%s, 0x%s, %f\n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), state);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceStateFloatEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, state);
+}
+
+static XrResult WINAPI wine_xrSetInputDeviceStateVector2fEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state)
+{
+ WINE_TRACE("%p, 0x%s, 0x%s, %f, %f\n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), state.x, state.y);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceStateVector2fEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, state);
+}
+
+XrResult WINAPI wine_xrStopHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo)
+{
+ WINE_TRACE("%p, %p\n", session, hapticActionInfo);
+ return xrStopHapticFeedback(((wine_XrSession *)session)->session, hapticActionInfo);
+}
+
+XrResult WINAPI wine_xrStringToPath(XrInstance instance, const char *pathString, XrPath *path)
+{
+ WINE_TRACE("%p, %p, %p\n", instance, pathString, path);
+ return xrStringToPath(((wine_XrInstance *)instance)->instance, pathString, path);
+}
+
+XrResult WINAPI wine_xrStructureTypeToString(XrInstance instance, XrStructureType value, char buffer[])
+{
+ WINE_TRACE("%p, %#x, %p\n", instance, value, buffer);
+ return xrStructureTypeToString(((wine_XrInstance *)instance)->instance, value, buffer);
+}
+
+XrResult WINAPI wine_xrSuggestInteractionProfileBindings(XrInstance instance, const XrInteractionProfileSuggestedBinding *suggestedBindings)
+{
+ WINE_TRACE("%p, %p\n", instance, suggestedBindings);
+ return xrSuggestInteractionProfileBindings(((wine_XrInstance *)instance)->instance, suggestedBindings);
+}
+
+XrResult WINAPI wine_xrSyncActions(XrSession session, const XrActionsSyncInfo *syncInfo)
+{
+ WINE_TRACE("%p, %p\n", session, syncInfo);
+ return xrSyncActions(((wine_XrSession *)session)->session, syncInfo);
+}
+
+static XrResult WINAPI wine_xrThermalGetTemperatureTrendEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsNotificationLevelEXT *notificationLevel, float *tempHeadroom, float *tempSlope)
+{
+ WINE_TRACE("%p, %#x, %p, %p, %p\n", session, domain, notificationLevel, tempHeadroom, tempSlope);
+ return ((wine_XrSession *)session)->wine_instance->funcs.p_xrThermalGetTemperatureTrendEXT(((wine_XrSession *)session)->session, domain, notificationLevel, tempHeadroom, tempSlope);
+}
+
+static XrResult WINAPI wine_xrUpdateHandMeshMSFT(XrHandTrackerEXT handTracker, const XrHandMeshUpdateInfoMSFT *updateInfo, XrHandMeshMSFT *handMesh)
+{
+ WINE_TRACE("%p, %p, %p\n", handTracker, updateInfo, handMesh);
+ return ((wine_XrHandTrackerEXT *)handTracker)->wine_session->wine_instance->funcs.p_xrUpdateHandMeshMSFT(((wine_XrHandTrackerEXT *)handTracker)->hand_tracker, updateInfo, handMesh);
+}
+
+XrResult WINAPI wine_xrWaitFrame(XrSession session, const XrFrameWaitInfo *frameWaitInfo, XrFrameState *frameState)
+{
+ WINE_TRACE("%p, %p, %p\n", session, frameWaitInfo, frameState);
+ return xrWaitFrame(((wine_XrSession *)session)->session, frameWaitInfo, frameState);
+}
+
+XrResult WINAPI wine_xrWaitSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageWaitInfo *waitInfo)
+{
+ WINE_TRACE("%p, %p\n", swapchain, waitInfo);
+ return xrWaitSwapchainImage(((wine_XrSwapchain *)swapchain)->swapchain, waitInfo);
+}
+
+static const struct openxr_func xr_dispatch_table[] =
+{
+ {"xrAcquireSwapchainImage", &wine_xrAcquireSwapchainImage},
+ {"xrApplyHapticFeedback", &wine_xrApplyHapticFeedback},
+ {"xrAttachSessionActionSets", &wine_xrAttachSessionActionSets},
+ {"xrBeginFrame", &wine_xrBeginFrame},
+ {"xrBeginSession", &wine_xrBeginSession},
+ {"xrConvertTimeToWin32PerformanceCounterKHR", &wine_xrConvertTimeToWin32PerformanceCounterKHR},
+ {"xrConvertWin32PerformanceCounterToTimeKHR", &wine_xrConvertWin32PerformanceCounterToTimeKHR},
+ {"xrCreateAction", &wine_xrCreateAction},
+ {"xrCreateActionSet", &wine_xrCreateActionSet},
+ {"xrCreateActionSpace", &wine_xrCreateActionSpace},
+ {"xrCreateHandMeshSpaceMSFT", &wine_xrCreateHandMeshSpaceMSFT},
+ {"xrCreateHandTrackerEXT", &wine_xrCreateHandTrackerEXT},
+ {"xrCreateInstance", &wine_xrCreateInstance},
+ {"xrCreateReferenceSpace", &wine_xrCreateReferenceSpace},
+ {"xrCreateSession", &wine_xrCreateSession},
+ {"xrCreateSpatialAnchorMSFT", &wine_xrCreateSpatialAnchorMSFT},
+ {"xrCreateSpatialAnchorSpaceMSFT", &wine_xrCreateSpatialAnchorSpaceMSFT},
+ {"xrCreateSpatialGraphNodeSpaceMSFT", &wine_xrCreateSpatialGraphNodeSpaceMSFT},
+ {"xrCreateSwapchain", &wine_xrCreateSwapchain},
+ {"xrDestroyAction", &wine_xrDestroyAction},
+ {"xrDestroyActionSet", &wine_xrDestroyActionSet},
+ {"xrDestroyHandTrackerEXT", &wine_xrDestroyHandTrackerEXT},
+ {"xrDestroyInstance", &wine_xrDestroyInstance},
+ {"xrDestroySession", &wine_xrDestroySession},
+ {"xrDestroySpace", &wine_xrDestroySpace},
+ {"xrDestroySpatialAnchorMSFT", &wine_xrDestroySpatialAnchorMSFT},
+ {"xrDestroySwapchain", &wine_xrDestroySwapchain},
+ {"xrEndFrame", &wine_xrEndFrame},
+ {"xrEndSession", &wine_xrEndSession},
+ {"xrEnumerateApiLayerProperties", &wine_xrEnumerateApiLayerProperties},
+ {"xrEnumerateBoundSourcesForAction", &wine_xrEnumerateBoundSourcesForAction},
+ {"xrEnumerateEnvironmentBlendModes", &wine_xrEnumerateEnvironmentBlendModes},
+ {"xrEnumerateInstanceExtensionProperties", &wine_xrEnumerateInstanceExtensionProperties},
+ {"xrEnumerateReferenceSpaces", &wine_xrEnumerateReferenceSpaces},
+ {"xrEnumerateSwapchainFormats", &wine_xrEnumerateSwapchainFormats},
+ {"xrEnumerateSwapchainImages", &wine_xrEnumerateSwapchainImages},
+ {"xrEnumerateViewConfigurationViews", &wine_xrEnumerateViewConfigurationViews},
+ {"xrEnumerateViewConfigurations", &wine_xrEnumerateViewConfigurations},
+ {"xrGetActionStateBoolean", &wine_xrGetActionStateBoolean},
+ {"xrGetActionStateFloat", &wine_xrGetActionStateFloat},
+ {"xrGetActionStatePose", &wine_xrGetActionStatePose},
+ {"xrGetActionStateVector2f", &wine_xrGetActionStateVector2f},
+ {"xrGetCurrentInteractionProfile", &wine_xrGetCurrentInteractionProfile},
+ {"xrGetD3D11GraphicsRequirementsKHR", &wine_xrGetD3D11GraphicsRequirementsKHR},
+ {"xrGetD3D12GraphicsRequirementsKHR", &wine_xrGetD3D12GraphicsRequirementsKHR},
+ {"xrGetInputSourceLocalizedName", &wine_xrGetInputSourceLocalizedName},
+ {"xrGetInstanceProcAddr", &wine_xrGetInstanceProcAddr},
+ {"xrGetInstanceProperties", &wine_xrGetInstanceProperties},
+ {"xrGetOpenGLGraphicsRequirementsKHR", &wine_xrGetOpenGLGraphicsRequirementsKHR},
+ {"xrGetReferenceSpaceBoundsRect", &wine_xrGetReferenceSpaceBoundsRect},
+ {"xrGetSystem", &wine_xrGetSystem},
+ {"xrGetSystemProperties", &wine_xrGetSystemProperties},
+ {"xrGetViewConfigurationProperties", &wine_xrGetViewConfigurationProperties},
+ {"xrGetVisibilityMaskKHR", &wine_xrGetVisibilityMaskKHR},
+ {"xrGetVulkanDeviceExtensionsKHR", &wine_xrGetVulkanDeviceExtensionsKHR},
+ {"xrGetVulkanGraphicsDeviceKHR", &wine_xrGetVulkanGraphicsDeviceKHR},
+ {"xrGetVulkanGraphicsRequirementsKHR", &wine_xrGetVulkanGraphicsRequirementsKHR},
+ {"xrGetVulkanInstanceExtensionsKHR", &wine_xrGetVulkanInstanceExtensionsKHR},
+ {"xrLocateHandJointsEXT", &wine_xrLocateHandJointsEXT},
+ {"xrLocateSpace", &wine_xrLocateSpace},
+ {"xrLocateViews", &wine_xrLocateViews},
+ {"xrPathToString", &wine_xrPathToString},
+ {"xrPerfSettingsSetPerformanceLevelEXT", &wine_xrPerfSettingsSetPerformanceLevelEXT},
+ {"xrPollEvent", &wine_xrPollEvent},
+ {"xrReleaseSwapchainImage", &wine_xrReleaseSwapchainImage},
+ {"xrRequestExitSession", &wine_xrRequestExitSession},
+ {"xrResultToString", &wine_xrResultToString},
+ {"xrSetInputDeviceActiveEXT", &wine_xrSetInputDeviceActiveEXT},
+ {"xrSetInputDeviceLocationEXT", &wine_xrSetInputDeviceLocationEXT},
+ {"xrSetInputDeviceStateBoolEXT", &wine_xrSetInputDeviceStateBoolEXT},
+ {"xrSetInputDeviceStateFloatEXT", &wine_xrSetInputDeviceStateFloatEXT},
+ {"xrSetInputDeviceStateVector2fEXT", &wine_xrSetInputDeviceStateVector2fEXT},
+ {"xrStopHapticFeedback", &wine_xrStopHapticFeedback},
+ {"xrStringToPath", &wine_xrStringToPath},
+ {"xrStructureTypeToString", &wine_xrStructureTypeToString},
+ {"xrSuggestInteractionProfileBindings", &wine_xrSuggestInteractionProfileBindings},
+ {"xrSyncActions", &wine_xrSyncActions},
+ {"xrThermalGetTemperatureTrendEXT", &wine_xrThermalGetTemperatureTrendEXT},
+ {"xrUpdateHandMeshMSFT", &wine_xrUpdateHandMeshMSFT},
+ {"xrWaitFrame", &wine_xrWaitFrame},
+ {"xrWaitSwapchainImage", &wine_xrWaitSwapchainImage},
+};
+
+void *wine_xr_proc_addr(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(xr_dispatch_table); i++)
+ {
+ if (strcmp(xr_dispatch_table[i].name, name) == 0)
+ {
+ WINE_TRACE("Found name=%s in instance table\n", wine_dbgstr_a(name));
+ return xr_dispatch_table[i].func;
+ }
+ }
+ return NULL;
+}
+
+static const char * const xr_extensions[] =
+{
+ "XR_EPIC_view_configuration_fov",
+ "XR_EXTX_overlay",
+ "XR_EXT_conformance_automation",
+ "XR_EXT_eye_gaze_interaction",
+ "XR_EXT_hand_tracking",
+ "XR_EXT_hp_mixed_reality_controller",
+ "XR_EXT_performance_settings",
+ "XR_EXT_samsung_odyssey_controller",
+ "XR_EXT_thermal_query",
+ "XR_EXT_view_configuration_depth_range",
+ "XR_EXT_win32_appcontainer_compatible",
+ "XR_HUAWEI_controller_interaction",
+ "XR_KHR_D3D11_enable",
+ "XR_KHR_D3D12_enable",
+ "XR_KHR_composition_layer_cube",
+ "XR_KHR_composition_layer_cylinder",
+ "XR_KHR_composition_layer_depth",
+ "XR_KHR_composition_layer_equirect",
+ "XR_KHR_opengl_enable",
+ "XR_KHR_visibility_mask",
+ "XR_KHR_vulkan_enable",
+ "XR_KHR_vulkan_swapchain_format_list",
+ "XR_KHR_win32_convert_performance_counter_time",
+ "XR_MND_headless",
+ "XR_MND_swapchain_usage_input_attachment_bit",
+ "XR_MSFT_first_person_observer",
+ "XR_MSFT_hand_interaction",
+ "XR_MSFT_hand_tracking_mesh",
+ "XR_MSFT_holographic_window_attachment",
+ "XR_MSFT_secondary_view_configuration",
+ "XR_MSFT_spatial_anchor",
+ "XR_MSFT_spatial_graph_bridge",
+ "XR_MSFT_unbounded_reference_space",
+ "XR_OCULUS_android_session_state_enable",
+ "XR_VALVE_analog_threshold",
+ "XR_VARJO_quad_views",
+};
+
+BOOL wine_xr_extension_supported(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(xr_extensions); i++)
+ {
+ if (strcmp(xr_extensions[i], name) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/wineopenxr/openxr_thunks.h b/wineopenxr/openxr_thunks.h
new file mode 100644
index 00000000..eb3a8340
--- /dev/null
+++ b/wineopenxr/openxr_thunks.h
@@ -0,0 +1,212 @@
+/* Automatically generated from OpenXR xr.xml; DO NOT EDIT!
+ *
+ * This file is generated from OpenXR xr.xml file covered
+ * by the following copyright and permission notice:
+ *
+ * Copyright (c) 2017-2020 The Khronos Group Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This file, xr.xml, is the OpenXR API Registry. It is a critically important
+ * and normative part of the OpenXR Specification, including a canonical
+ * machine-readable definition of the API, parameter and member validation
+ * language incorporated into the Specification and reference pages, and other
+ * material which is registered by Khronos, such as tags used by extension and
+ * layer authors. The only authoritative version of xr.xml is the one
+ * maintained in the master branch of the Khronos OpenXR GitHub project.
+ *
+ */
+
+#ifndef __WINE_OPENXR_THUNKS_H
+#define __WINE_OPENXR_THUNKS_H
+
+#define WINE_XR_VERSION XR_API_VERSION_1_0
+
+/* Functions for which we have custom implementations outside of the thunks. */
+XrResult WINAPI wine_xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, XrTime time, LARGE_INTEGER *performanceCounter) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, const LARGE_INTEGER *performanceCounter, XrTime *time) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrCreateHandTrackerEXT(XrSession session, const XrHandTrackerCreateInfoEXT *createInfo, XrHandTrackerEXT *handTracker) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrCreateInstance(const XrInstanceCreateInfo *createInfo, XrInstance *instance);
+XrResult WINAPI wine_xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session);
+XrResult WINAPI wine_xrCreateSpatialAnchorMSFT(XrSession session, const XrSpatialAnchorCreateInfoMSFT *createInfo, XrSpatialAnchorMSFT *anchor) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo *createInfo, XrSwapchain *swapchain);
+XrResult WINAPI wine_xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrDestroyInstance(XrInstance instance);
+XrResult WINAPI wine_xrDestroySession(XrSession session);
+XrResult WINAPI wine_xrDestroySpatialAnchorMSFT(XrSpatialAnchorMSFT anchor) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrDestroySwapchain(XrSwapchain swapchain);
+XrResult WINAPI wine_xrEndFrame(XrSession session, const XrFrameEndInfo *frameEndInfo);
+XrResult WINAPI wine_xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties);
+XrResult WINAPI wine_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t *formatCountOutput, int64_t *formats);
+XrResult WINAPI wine_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t *imageCountOutput, XrSwapchainImageBaseHeader *images);
+XrResult WINAPI wine_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrGetD3D12GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrGetInstanceProcAddr(XrInstance instance, const char *name, PFN_xrVoidFunction *function);
+XrResult WINAPI wine_xrGetSystem(XrInstance instance, const XrSystemGetInfo *getInfo, XrSystemId *systemId);
+XrResult WINAPI wine_xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrGetVulkanGraphicsDeviceKHR(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice *vkPhysicalDevice) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrGetVulkanInstanceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) DECLSPEC_HIDDEN;
+XrResult WINAPI wine_xrPollEvent(XrInstance instance, XrEventDataBuffer *eventData);
+
+/* Private thunks */
+
+
+XrResult convert_XrInstanceCreateInfo_struct_chain(const void *next, XrInstanceCreateInfo *out_struct) DECLSPEC_HIDDEN;
+void free_XrInstanceCreateInfo_struct_chain(XrInstanceCreateInfo *s) DECLSPEC_HIDDEN;
+
+/* For use by xrInstance and children */
+struct openxr_instance_funcs
+{
+ XrResult (*p_xrAcquireSwapchainImage)(XrSwapchain, const XrSwapchainImageAcquireInfo *, uint32_t *);
+ XrResult (*p_xrApplyHapticFeedback)(XrSession, const XrHapticActionInfo *, const XrHapticBaseHeader *);
+ XrResult (*p_xrAttachSessionActionSets)(XrSession, const XrSessionActionSetsAttachInfo *);
+ XrResult (*p_xrBeginFrame)(XrSession, const XrFrameBeginInfo *);
+ XrResult (*p_xrBeginSession)(XrSession, const XrSessionBeginInfo *);
+ XrResult (*p_xrCreateAction)(XrActionSet, const XrActionCreateInfo *, XrAction *);
+ XrResult (*p_xrCreateActionSet)(XrInstance, const XrActionSetCreateInfo *, XrActionSet *);
+ XrResult (*p_xrCreateActionSpace)(XrSession, const XrActionSpaceCreateInfo *, XrSpace *);
+ XrResult (*p_xrCreateHandMeshSpaceMSFT)(XrHandTrackerEXT, const XrHandMeshSpaceCreateInfoMSFT *, XrSpace *);
+ XrResult (*p_xrCreateHandTrackerEXT)(XrSession, const XrHandTrackerCreateInfoEXT *, XrHandTrackerEXT *);
+ XrResult (*p_xrCreateReferenceSpace)(XrSession, const XrReferenceSpaceCreateInfo *, XrSpace *);
+ XrResult (*p_xrCreateSession)(XrInstance, const XrSessionCreateInfo *, XrSession *);
+ XrResult (*p_xrCreateSpatialAnchorMSFT)(XrSession, const XrSpatialAnchorCreateInfoMSFT *, XrSpatialAnchorMSFT *);
+ XrResult (*p_xrCreateSpatialAnchorSpaceMSFT)(XrSession, const XrSpatialAnchorSpaceCreateInfoMSFT *, XrSpace *);
+ XrResult (*p_xrCreateSpatialGraphNodeSpaceMSFT)(XrSession, const XrSpatialGraphNodeSpaceCreateInfoMSFT *, XrSpace *);
+ XrResult (*p_xrCreateSwapchain)(XrSession, const XrSwapchainCreateInfo *, XrSwapchain *);
+ XrResult (*p_xrDestroyAction)(XrAction);
+ XrResult (*p_xrDestroyActionSet)(XrActionSet);
+ XrResult (*p_xrDestroyHandTrackerEXT)(XrHandTrackerEXT);
+ XrResult (*p_xrDestroySession)(XrSession);
+ XrResult (*p_xrDestroySpace)(XrSpace);
+ XrResult (*p_xrDestroySpatialAnchorMSFT)(XrSpatialAnchorMSFT);
+ XrResult (*p_xrDestroySwapchain)(XrSwapchain);
+ XrResult (*p_xrEndFrame)(XrSession, const XrFrameEndInfo *);
+ XrResult (*p_xrEndSession)(XrSession);
+ XrResult (*p_xrEnumerateApiLayerProperties)(uint32_t, uint32_t *, XrApiLayerProperties *);
+ XrResult (*p_xrEnumerateBoundSourcesForAction)(XrSession, const XrBoundSourcesForActionEnumerateInfo *, uint32_t, uint32_t *, XrPath *);
+ XrResult (*p_xrEnumerateEnvironmentBlendModes)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrEnvironmentBlendMode *);
+ XrResult (*p_xrEnumerateReferenceSpaces)(XrSession, uint32_t, uint32_t *, XrReferenceSpaceType *);
+ XrResult (*p_xrEnumerateSwapchainFormats)(XrSession, uint32_t, uint32_t *, int64_t *);
+ XrResult (*p_xrEnumerateSwapchainImages)(XrSwapchain, uint32_t, uint32_t *, XrSwapchainImageBaseHeader *);
+ XrResult (*p_xrEnumerateViewConfigurationViews)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrViewConfigurationView *);
+ XrResult (*p_xrEnumerateViewConfigurations)(XrInstance, XrSystemId, uint32_t, uint32_t *, XrViewConfigurationType *);
+ XrResult (*p_xrGetActionStateBoolean)(XrSession, const XrActionStateGetInfo *, XrActionStateBoolean *);
+ XrResult (*p_xrGetActionStateFloat)(XrSession, const XrActionStateGetInfo *, XrActionStateFloat *);
+ XrResult (*p_xrGetActionStatePose)(XrSession, const XrActionStateGetInfo *, XrActionStatePose *);
+ XrResult (*p_xrGetActionStateVector2f)(XrSession, const XrActionStateGetInfo *, XrActionStateVector2f *);
+ XrResult (*p_xrGetCurrentInteractionProfile)(XrSession, XrPath, XrInteractionProfileState *);
+ XrResult (*p_xrGetInputSourceLocalizedName)(XrSession, const XrInputSourceLocalizedNameGetInfo *, uint32_t, uint32_t *, char *);
+ XrResult (*p_xrGetInstanceProperties)(XrInstance, XrInstanceProperties *);
+ XrResult (*p_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsOpenGLKHR *);
+ XrResult (*p_xrGetReferenceSpaceBoundsRect)(XrSession, XrReferenceSpaceType, XrExtent2Df *);
+ XrResult (*p_xrGetSystem)(XrInstance, const XrSystemGetInfo *, XrSystemId *);
+ XrResult (*p_xrGetSystemProperties)(XrInstance, XrSystemId, XrSystemProperties *);
+ XrResult (*p_xrGetViewConfigurationProperties)(XrInstance, XrSystemId, XrViewConfigurationType, XrViewConfigurationProperties *);
+ XrResult (*p_xrGetVisibilityMaskKHR)(XrSession, XrViewConfigurationType, uint32_t, XrVisibilityMaskTypeKHR, XrVisibilityMaskKHR *);
+ XrResult (*p_xrGetVulkanDeviceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *);
+ XrResult (*p_xrGetVulkanGraphicsDeviceKHR)(XrInstance, XrSystemId, VkInstance, VkPhysicalDevice *);
+ XrResult (*p_xrGetVulkanGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsVulkanKHR *);
+ XrResult (*p_xrGetVulkanInstanceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *);
+ XrResult (*p_xrLocateHandJointsEXT)(XrHandTrackerEXT, const XrHandJointsLocateInfoEXT *, XrHandJointLocationsEXT *);
+ XrResult (*p_xrLocateSpace)(XrSpace, XrSpace, XrTime, XrSpaceLocation *);
+ XrResult (*p_xrLocateViews)(XrSession, const XrViewLocateInfo *, XrViewState *, uint32_t, uint32_t *, XrView *);
+ XrResult (*p_xrPathToString)(XrInstance, XrPath, uint32_t, uint32_t *, char *);
+ XrResult (*p_xrPerfSettingsSetPerformanceLevelEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsLevelEXT);
+ XrResult (*p_xrPollEvent)(XrInstance, XrEventDataBuffer *);
+ XrResult (*p_xrReleaseSwapchainImage)(XrSwapchain, const XrSwapchainImageReleaseInfo *);
+ XrResult (*p_xrRequestExitSession)(XrSession);
+ XrResult (*p_xrResultToString)(XrInstance, XrResult, char[]);
+ XrResult (*p_xrSetInputDeviceActiveEXT)(XrSession, XrPath, XrPath, XrBool32);
+ XrResult (*p_xrSetInputDeviceLocationEXT)(XrSession, XrPath, XrPath, XrSpace, XrPosef);
+ XrResult (*p_xrSetInputDeviceStateBoolEXT)(XrSession, XrPath, XrPath, XrBool32);
+ XrResult (*p_xrSetInputDeviceStateFloatEXT)(XrSession, XrPath, XrPath, float);
+ XrResult (*p_xrSetInputDeviceStateVector2fEXT)(XrSession, XrPath, XrPath, XrVector2f);
+ XrResult (*p_xrStopHapticFeedback)(XrSession, const XrHapticActionInfo *);
+ XrResult (*p_xrStringToPath)(XrInstance, const char *, XrPath *);
+ XrResult (*p_xrStructureTypeToString)(XrInstance, XrStructureType, char[]);
+ XrResult (*p_xrSuggestInteractionProfileBindings)(XrInstance, const XrInteractionProfileSuggestedBinding *);
+ XrResult (*p_xrSyncActions)(XrSession, const XrActionsSyncInfo *);
+ XrResult (*p_xrThermalGetTemperatureTrendEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsNotificationLevelEXT *, float *, float *);
+ XrResult (*p_xrUpdateHandMeshMSFT)(XrHandTrackerEXT, const XrHandMeshUpdateInfoMSFT *, XrHandMeshMSFT *);
+ XrResult (*p_xrWaitFrame)(XrSession, const XrFrameWaitInfo *, XrFrameState *);
+ XrResult (*p_xrWaitSwapchainImage)(XrSwapchain, const XrSwapchainImageWaitInfo *);
+};
+
+#define ALL_XR_INSTANCE_FUNCS() \
+ USE_XR_FUNC(xrAcquireSwapchainImage) \
+ USE_XR_FUNC(xrApplyHapticFeedback) \
+ USE_XR_FUNC(xrAttachSessionActionSets) \
+ USE_XR_FUNC(xrBeginFrame) \
+ USE_XR_FUNC(xrBeginSession) \
+ USE_XR_FUNC(xrCreateAction) \
+ USE_XR_FUNC(xrCreateActionSet) \
+ USE_XR_FUNC(xrCreateActionSpace) \
+ USE_XR_FUNC(xrCreateHandMeshSpaceMSFT) \
+ USE_XR_FUNC(xrCreateHandTrackerEXT) \
+ USE_XR_FUNC(xrCreateReferenceSpace) \
+ USE_XR_FUNC(xrCreateSession) \
+ USE_XR_FUNC(xrCreateSpatialAnchorMSFT) \
+ USE_XR_FUNC(xrCreateSpatialAnchorSpaceMSFT) \
+ USE_XR_FUNC(xrCreateSpatialGraphNodeSpaceMSFT) \
+ USE_XR_FUNC(xrCreateSwapchain) \
+ USE_XR_FUNC(xrDestroyAction) \
+ USE_XR_FUNC(xrDestroyActionSet) \
+ USE_XR_FUNC(xrDestroyHandTrackerEXT) \
+ USE_XR_FUNC(xrDestroySession) \
+ USE_XR_FUNC(xrDestroySpace) \
+ USE_XR_FUNC(xrDestroySpatialAnchorMSFT) \
+ USE_XR_FUNC(xrDestroySwapchain) \
+ USE_XR_FUNC(xrEndFrame) \
+ USE_XR_FUNC(xrEndSession) \
+ USE_XR_FUNC(xrEnumerateApiLayerProperties) \
+ USE_XR_FUNC(xrEnumerateBoundSourcesForAction) \
+ USE_XR_FUNC(xrEnumerateEnvironmentBlendModes) \
+ USE_XR_FUNC(xrEnumerateReferenceSpaces) \
+ USE_XR_FUNC(xrEnumerateSwapchainFormats) \
+ USE_XR_FUNC(xrEnumerateSwapchainImages) \
+ USE_XR_FUNC(xrEnumerateViewConfigurationViews) \
+ USE_XR_FUNC(xrEnumerateViewConfigurations) \
+ USE_XR_FUNC(xrGetActionStateBoolean) \
+ USE_XR_FUNC(xrGetActionStateFloat) \
+ USE_XR_FUNC(xrGetActionStatePose) \
+ USE_XR_FUNC(xrGetActionStateVector2f) \
+ USE_XR_FUNC(xrGetCurrentInteractionProfile) \
+ USE_XR_FUNC(xrGetInputSourceLocalizedName) \
+ USE_XR_FUNC(xrGetInstanceProperties) \
+ USE_XR_FUNC(xrGetOpenGLGraphicsRequirementsKHR) \
+ USE_XR_FUNC(xrGetReferenceSpaceBoundsRect) \
+ USE_XR_FUNC(xrGetSystem) \
+ USE_XR_FUNC(xrGetSystemProperties) \
+ USE_XR_FUNC(xrGetViewConfigurationProperties) \
+ USE_XR_FUNC(xrGetVisibilityMaskKHR) \
+ USE_XR_FUNC(xrGetVulkanDeviceExtensionsKHR) \
+ USE_XR_FUNC(xrGetVulkanGraphicsDeviceKHR) \
+ USE_XR_FUNC(xrGetVulkanGraphicsRequirementsKHR) \
+ USE_XR_FUNC(xrGetVulkanInstanceExtensionsKHR) \
+ USE_XR_FUNC(xrLocateHandJointsEXT) \
+ USE_XR_FUNC(xrLocateSpace) \
+ USE_XR_FUNC(xrLocateViews) \
+ USE_XR_FUNC(xrPathToString) \
+ USE_XR_FUNC(xrPerfSettingsSetPerformanceLevelEXT) \
+ USE_XR_FUNC(xrPollEvent) \
+ USE_XR_FUNC(xrReleaseSwapchainImage) \
+ USE_XR_FUNC(xrRequestExitSession) \
+ USE_XR_FUNC(xrResultToString) \
+ USE_XR_FUNC(xrSetInputDeviceActiveEXT) \
+ USE_XR_FUNC(xrSetInputDeviceLocationEXT) \
+ USE_XR_FUNC(xrSetInputDeviceStateBoolEXT) \
+ USE_XR_FUNC(xrSetInputDeviceStateFloatEXT) \
+ USE_XR_FUNC(xrSetInputDeviceStateVector2fEXT) \
+ USE_XR_FUNC(xrStopHapticFeedback) \
+ USE_XR_FUNC(xrStringToPath) \
+ USE_XR_FUNC(xrStructureTypeToString) \
+ USE_XR_FUNC(xrSuggestInteractionProfileBindings) \
+ USE_XR_FUNC(xrSyncActions) \
+ USE_XR_FUNC(xrThermalGetTemperatureTrendEXT) \
+ USE_XR_FUNC(xrUpdateHandMeshMSFT) \
+ USE_XR_FUNC(xrWaitFrame) \
+ USE_XR_FUNC(xrWaitSwapchainImage)
+
+#endif /* __WINE_OPENXR_THUNKS_H */
diff --git a/wineopenxr/wineopenxr.h b/wineopenxr/wineopenxr.h
new file mode 100644
index 00000000..9f11c5ab
--- /dev/null
+++ b/wineopenxr/wineopenxr.h
@@ -0,0 +1,1957 @@
+/* Automatically generated from OpenXR xr.xml; DO NOT EDIT!
+ *
+ * This file is generated from OpenXR xr.xml file covered
+ * by the following copyright and permission notice:
+ *
+ * Copyright (c) 2017-2020 The Khronos Group Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This file, xr.xml, is the OpenXR API Registry. It is a critically important
+ * and normative part of the OpenXR Specification, including a canonical
+ * machine-readable definition of the API, parameter and member validation
+ * language incorporated into the Specification and reference pages, and other
+ * material which is registered by Khronos, such as tags used by extension and
+ * layer authors. The only authoritative version of xr.xml is the one
+ * maintained in the master branch of the Khronos OpenXR GitHub project.
+ *
+ */
+
+#ifndef __WINE_OPENXR_H
+#define __WINE_OPENXR_H
+
+#include <windef.h>
+#include <stdint.h>
+
+/* Define WINE_XR_HOST to get 'host' headers. */
+#ifdef WINE_XR_HOST
+#define XRAPI_CALL
+#define WINE_XR_ALIGN(x)
+#endif
+
+#ifndef XRAPI_CALL
+#define XRAPI_CALL __stdcall
+#endif
+
+#ifndef XRAPI_PTR
+#define XRAPI_PTR XRAPI_CALL
+#endif
+
+#ifndef WINE_XR_ALIGN
+#define WINE_XR_ALIGN DECLSPEC_ALIGN
+#endif
+
+#define XR_TRUE 1
+#define XR_FALSE 0
+#define XR_MAX_EXTENSION_NAME_SIZE 128
+#define XR_MAX_API_LAYER_NAME_SIZE 256
+#define XR_MAX_API_LAYER_DESCRIPTION_SIZE 256
+#define XR_MAX_SYSTEM_NAME_SIZE 256
+#define XR_MAX_APPLICATION_NAME_SIZE 128
+#define XR_MAX_ENGINE_NAME_SIZE 128
+#define XR_MAX_RUNTIME_NAME_SIZE 128
+#define XR_MAX_PATH_LENGTH 256
+#define XR_MAX_STRUCTURE_NAME_SIZE 64
+#define XR_MAX_RESULT_STRING_SIZE 64
+#define XR_MAX_GRAPHICS_APIS_SUPPORTED 32
+#define XR_MAX_ACTION_SET_NAME_SIZE 64
+#define XR_MAX_ACTION_NAME_SIZE 64
+#define XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE 128
+#define XR_MAX_LOCALIZED_ACTION_NAME_SIZE 128
+#define XR_MIN_COMPOSITION_LAYERS_SUPPORTED 16
+#define XR_KHR_composition_layer_cube_SPEC_VERSION 8
+#define XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME "XR_KHR_composition_layer_cube"
+#define XR_KHR_composition_layer_depth_SPEC_VERSION 5
+#define XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME "XR_KHR_composition_layer_depth"
+#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 2
+#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list"
+#define XR_EXT_performance_settings_SPEC_VERSION 1
+#define XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME "XR_EXT_performance_settings"
+#define XR_EXT_thermal_query_SPEC_VERSION 1
+#define XR_EXT_THERMAL_QUERY_EXTENSION_NAME "XR_EXT_thermal_query"
+#define XR_KHR_composition_layer_cylinder_SPEC_VERSION 4
+#define XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME "XR_KHR_composition_layer_cylinder"
+#define XR_KHR_composition_layer_equirect_SPEC_VERSION 3
+#define XR_KHR_COMPOSITION_LAYER_EQUIRECT_EXTENSION_NAME "XR_KHR_composition_layer_equirect"
+#define XR_KHR_opengl_enable_SPEC_VERSION 9
+#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
+#define XR_KHR_vulkan_enable_SPEC_VERSION 7
+#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
+#define XR_KHR_D3D11_enable_SPEC_VERSION 5
+#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
+#define XR_KHR_D3D12_enable_SPEC_VERSION 7
+#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
+#define XR_EXT_eye_gaze_interaction_SPEC_VERSION 1
+#define XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME "XR_EXT_eye_gaze_interaction"
+#define XR_KHR_visibility_mask_SPEC_VERSION 2
+#define XR_KHR_VISIBILITY_MASK_EXTENSION_NAME "XR_KHR_visibility_mask"
+#define XR_EXTX_overlay_SPEC_VERSION 4
+#define XR_EXTX_OVERLAY_EXTENSION_NAME "XR_EXTX_overlay"
+#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"
+#define XR_VARJO_quad_views_SPEC_VERSION 1
+#define XR_VARJO_QUAD_VIEWS_EXTENSION_NAME "XR_VARJO_quad_views"
+#define XR_MSFT_unbounded_reference_space_SPEC_VERSION 1
+#define XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME "XR_MSFT_unbounded_reference_space"
+#define XR_MSFT_spatial_anchor_SPEC_VERSION 1
+#define XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME "XR_MSFT_spatial_anchor"
+#define XR_MND_headless_SPEC_VERSION 2
+#define XR_MND_HEADLESS_EXTENSION_NAME "XR_MND_headless"
+#define XR_OCULUS_android_session_state_enable_SPEC_VERSION 1
+#define XR_OCULUS_ANDROID_SESSION_STATE_ENABLE_EXTENSION_NAME "XR_OCULUS_android_session_state_enable"
+#define XR_EXT_view_configuration_depth_range_SPEC_VERSION 1
+#define XR_EXT_VIEW_CONFIGURATION_DEPTH_RANGE_EXTENSION_NAME "XR_EXT_view_configuration_depth_range"
+#define XR_EXT_conformance_automation_SPEC_VERSION 1
+#define XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME "XR_EXT_conformance_automation"
+#define XR_MSFT_spatial_graph_bridge_SPEC_VERSION 1
+#define XR_MSFT_SPATIAL_GRAPH_BRIDGE_EXTENSION_NAME "XR_MSFT_spatial_graph_bridge"
+#define XR_MSFT_hand_interaction_SPEC_VERSION 1
+#define XR_MSFT_HAND_INTERACTION_EXTENSION_NAME "XR_MSFT_hand_interaction"
+#define XR_EXT_hand_tracking_SPEC_VERSION 2
+#define XR_EXT_HAND_TRACKING_EXTENSION_NAME "XR_EXT_hand_tracking"
+#define XR_MSFT_hand_tracking_mesh_SPEC_VERSION 2
+#define XR_MSFT_HAND_TRACKING_MESH_EXTENSION_NAME "XR_MSFT_hand_tracking_mesh"
+#define XR_MSFT_secondary_view_configuration_SPEC_VERSION 1
+#define XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME "XR_MSFT_secondary_view_configuration"
+#define XR_MSFT_first_person_observer_SPEC_VERSION 1
+#define XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME "XR_MSFT_first_person_observer"
+#define XR_EXT_win32_appcontainer_compatible_SPEC_VERSION 1
+#define XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME "XR_EXT_win32_appcontainer_compatible"
+#define XR_EPIC_view_configuration_fov_SPEC_VERSION 2
+#define XR_EPIC_VIEW_CONFIGURATION_FOV_EXTENSION_NAME "XR_EPIC_view_configuration_fov"
+#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1
+#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment"
+#define XR_HUAWEI_controller_interaction_SPEC_VERSION 1
+#define XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_HUAWEI_controller_interaction"
+#define XR_VALVE_analog_threshold_SPEC_VERSION 1
+#define XR_VALVE_ANALOG_THRESHOLD_EXTENSION_NAME "XR_VALVE_analog_threshold"
+#define XR_EXT_samsung_odyssey_controller_SPEC_VERSION 1
+#define XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME "XR_EXT_samsung_odyssey_controller"
+#define XR_EXT_hp_mixed_reality_controller_SPEC_VERSION 1
+#define XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME "XR_EXT_hp_mixed_reality_controller"
+#define XR_MND_swapchain_usage_input_attachment_bit_SPEC_VERSION 2
+#define XR_MND_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_EXTENSION_NAME "XR_MND_swapchain_usage_input_attachment_bit"
+
+
+#define XR_MAKE_VERSION(major, minor, patch) \
+ ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))
+
+#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL)
+
+#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL)
+
+#define XR_VERSION_PATCH(version) (uint32_t)((uint64_t)(version) & 0xffffffffULL)
+
+
+#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 11)
+
+
+#if !defined(XR_MAY_ALIAS)
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4))
+#define XR_MAY_ALIAS __attribute__((__may_alias__))
+#else
+#define XR_MAY_ALIAS
+#endif
+#endif
+
+
+#if !defined(XR_DEFINE_HANDLE)
+#if (XR_PTR_SIZE == 8)
+ #define XR_DEFINE_HANDLE(object) typedef struct object##_T* object;
+#else
+ #define XR_DEFINE_HANDLE(object) typedef uint64_t object;
+#endif
+#endif
+
+
+
+#if !defined(XR_NULL_HANDLE)
+#if (XR_PTR_SIZE == 8) && XR_CPP_NULLPTR_SUPPORTED
+ #define XR_NULL_HANDLE nullptr
+#else
+ #define XR_NULL_HANDLE 0
+#endif
+#endif
+
+
+
+#if !defined(XR_DEFINE_ATOM)
+ #define XR_DEFINE_ATOM(object) typedef uint64_t object;
+#endif
+
+
+
+#define XR_NULL_PATH 0
+
+
+#define XR_NULL_SYSTEM_ID 0
+
+
+#define XR_SUCCEEDED(result) ((result) >= 0)
+
+
+#define XR_UNQUALIFIED_SUCCESS(result) ((result) == 0)
+
+
+#define XR_FAILED(result) ((result) < 0)
+
+
+#define XR_NO_DURATION 0
+
+
+#define XR_INFINITE_DURATION 0x7fffffffffffffffLL
+
+
+#define XR_MIN_HAPTIC_DURATION -1
+
+
+#define XR_FREQUENCY_UNSPECIFIED 0
+
+
+#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer)
+
+
+#define XR_HAND_JOINT_COUNT_EXT 26
+XR_DEFINE_HANDLE(XrAction)
+XR_DEFINE_HANDLE(XrActionSet)
+XR_DEFINE_HANDLE(XrHandTrackerEXT)
+XR_DEFINE_HANDLE(XrInstance)
+XR_DEFINE_HANDLE(XrSession)
+XR_DEFINE_HANDLE(XrSpace)
+XR_DEFINE_HANDLE(XrSpatialAnchorMSFT)
+XR_DEFINE_HANDLE(XrSwapchain)
+
+typedef uint32_t XrBool32;
+typedef int64_t XrDuration;
+typedef uint64_t XrFlags64;
+XR_DEFINE_ATOM(XrPath)
+XR_DEFINE_ATOM(XrSystemId)
+typedef int64_t XrTime;
+typedef uint64_t XrVersion;
+
+typedef XrFlags64 XrCompositionLayerFlags;
+typedef XrFlags64 XrDebugUtilsMessageSeverityFlagsEXT;
+typedef XrFlags64 XrDebugUtilsMessageTypeFlagsEXT;
+typedef XrFlags64 XrInputSourceLocalizedNameFlags;
+typedef XrFlags64 XrInstanceCreateFlags;
+typedef XrFlags64 XrOverlayMainSessionFlagsEXTX;
+typedef XrFlags64 XrOverlaySessionCreateFlagsEXTX;
+typedef XrFlags64 XrSessionCreateFlags;
+typedef XrFlags64 XrSpaceLocationFlags;
+typedef XrFlags64 XrSpaceVelocityFlags;
+typedef XrFlags64 XrSwapchainCreateFlags;
+typedef XrFlags64 XrSwapchainUsageFlags;
+typedef XrFlags64 XrViewStateFlags;
+
+typedef enum XrActionType
+{
+ XR_ACTION_TYPE_BOOLEAN_INPUT = 1,
+ XR_ACTION_TYPE_FLOAT_INPUT = 2,
+ XR_ACTION_TYPE_VECTOR2F_INPUT = 3,
+ XR_ACTION_TYPE_POSE_INPUT = 4,
+ XR_ACTION_TYPE_VIBRATION_OUTPUT = 100,
+ XR_ACTION_TYPE_MAX_ENUM = 0x7fffffff,
+} XrActionType;
+
+typedef enum XrEnvironmentBlendMode
+{
+ XR_ENVIRONMENT_BLEND_MODE_OPAQUE = 1,
+ XR_ENVIRONMENT_BLEND_MODE_ADDITIVE = 2,
+ XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND = 3,
+ XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM = 0x7fffffff,
+} XrEnvironmentBlendMode;
+
+typedef enum XrEyeVisibility
+{
+ XR_EYE_VISIBILITY_BOTH = 0,
+ XR_EYE_VISIBILITY_LEFT = 1,
+ XR_EYE_VISIBILITY_RIGHT = 2,
+ XR_EYE_VISIBILITY_MAX_ENUM = 0x7fffffff,
+} XrEyeVisibility;
+
+typedef enum XrFormFactor
+{
+ XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1,
+ XR_FORM_FACTOR_HANDHELD_DISPLAY = 2,
+ XR_FORM_FACTOR_MAX_ENUM = 0x7fffffff,
+} XrFormFactor;
+
+typedef enum XrHandEXT
+{
+ XR_HAND_LEFT_EXT = 1,
+ XR_HAND_RIGHT_EXT = 2,
+ XR_HAND_EXT_MAX_ENUM = 0x7fffffff,
+} XrHandEXT;
+
+typedef enum XrHandJointEXT
+{
+ XR_HAND_JOINT_PALM_EXT = 0,
+ XR_HAND_JOINT_WRIST_EXT = 1,
+ XR_HAND_JOINT_THUMB_METACARPAL_EXT = 2,
+ XR_HAND_JOINT_THUMB_PROXIMAL_EXT = 3,
+ XR_HAND_JOINT_THUMB_DISTAL_EXT = 4,
+ XR_HAND_JOINT_THUMB_TIP_EXT = 5,
+ XR_HAND_JOINT_INDEX_METACARPAL_EXT = 6,
+ XR_HAND_JOINT_INDEX_PROXIMAL_EXT = 7,
+ XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT = 8,
+ XR_HAND_JOINT_INDEX_DISTAL_EXT = 9,
+ XR_HAND_JOINT_INDEX_TIP_EXT = 10,
+ XR_HAND_JOINT_MIDDLE_METACARPAL_EXT = 11,
+ XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT = 12,
+ XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT = 13,
+ XR_HAND_JOINT_MIDDLE_DISTAL_EXT = 14,
+ XR_HAND_JOINT_MIDDLE_TIP_EXT = 15,
+ XR_HAND_JOINT_RING_METACARPAL_EXT = 16,
+ XR_HAND_JOINT_RING_PROXIMAL_EXT = 17,
+ XR_HAND_JOINT_RING_INTERMEDIATE_EXT = 18,
+ XR_HAND_JOINT_RING_DISTAL_EXT = 19,
+ XR_HAND_JOINT_RING_TIP_EXT = 20,
+ XR_HAND_JOINT_LITTLE_METACARPAL_EXT = 21,
+ XR_HAND_JOINT_LITTLE_PROXIMAL_EXT = 22,
+ XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT = 23,
+ XR_HAND_JOINT_LITTLE_DISTAL_EXT = 24,
+ XR_HAND_JOINT_LITTLE_TIP_EXT = 25,
+ XR_HAND_JOINT_EXT_MAX_ENUM = 0x7fffffff,
+} XrHandJointEXT;
+
+typedef enum XrHandJointSetEXT
+{
+ XR_HAND_JOINT_SET_DEFAULT_EXT = 0,
+ XR_HAND_JOINT_SET_EXT_MAX_ENUM = 0x7fffffff,
+} XrHandJointSetEXT;
+
+typedef enum XrHandPoseTypeMSFT
+{
+ XR_HAND_POSE_TYPE_TRACKED_MSFT = 0,
+ XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT = 1,
+ XR_HAND_POSE_TYPE_MSFT_MAX_ENUM = 0x7fffffff,
+} XrHandPoseTypeMSFT;
+
+typedef enum XrObjectType
+{
+ XR_OBJECT_TYPE_UNKNOWN = 0,
+ XR_OBJECT_TYPE_INSTANCE = 1,
+ XR_OBJECT_TYPE_SESSION = 2,
+ XR_OBJECT_TYPE_SWAPCHAIN = 3,
+ XR_OBJECT_TYPE_SPACE = 4,
+ XR_OBJECT_TYPE_ACTION_SET = 5,
+ XR_OBJECT_TYPE_ACTION = 6,
+ XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT = 1000039000,
+ XR_OBJECT_TYPE_HAND_TRACKER_EXT = 1000051000,
+ XR_OBJECT_TYPE_MAX_ENUM = 0x7fffffff,
+} XrObjectType;
+
+typedef enum XrPerfSettingsDomainEXT
+{
+ XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
+ XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
+ XR_PERF_SETTINGS_DOMAIN_EXT_MAX_ENUM = 0x7fffffff,
+} XrPerfSettingsDomainEXT;
+
+typedef enum XrPerfSettingsLevelEXT
+{
+ XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT = 0,
+ XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT = 25,
+ XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT = 50,
+ XR_PERF_SETTINGS_LEVEL_BOOST_EXT = 75,
+ XR_PERF_SETTINGS_LEVEL_EXT_MAX_ENUM = 0x7fffffff,
+} XrPerfSettingsLevelEXT;
+
+typedef enum XrPerfSettingsNotificationLevelEXT
+{
+ XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,
+ XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,
+ XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,
+ XR_PERF_SETTINGS_NOTIFICATION_LEVEL_EXT_MAX_ENUM = 0x7fffffff,
+} XrPerfSettingsNotificationLevelEXT;
+
+typedef enum XrPerfSettingsSubDomainEXT
+{
+ XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT = 1,
+ XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT = 2,
+ XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT = 3,
+ XR_PERF_SETTINGS_SUB_DOMAIN_EXT_MAX_ENUM = 0x7fffffff,
+} XrPerfSettingsSubDomainEXT;
+
+typedef enum XrReferenceSpaceType
+{
+ XR_REFERENCE_SPACE_TYPE_VIEW = 1,
+ XR_REFERENCE_SPACE_TYPE_LOCAL = 2,
+ XR_REFERENCE_SPACE_TYPE_STAGE = 3,
+ XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT = 1000038000,
+ XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7fffffff,
+} XrReferenceSpaceType;
+
+typedef enum XrResult
+{
+ XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT = -1000053000,
+ XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT = -1000039001,
+ XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING = -50,
+ XR_ERROR_LOCALIZED_NAME_INVALID = -49,
+ XR_ERROR_LOCALIZED_NAME_DUPLICATED = -48,
+ XR_ERROR_ACTIONSETS_ALREADY_ATTACHED = -47,
+ XR_ERROR_ACTIONSET_NOT_ATTACHED = -46,
+ XR_ERROR_NAME_INVALID = -45,
+ XR_ERROR_NAME_DUPLICATED = -44,
+ XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED = -42,
+ XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED = -41,
+ XR_ERROR_INDEX_OUT_OF_RANGE = -40,
+ XR_ERROR_POSE_INVALID = -39,
+ XR_ERROR_GRAPHICS_DEVICE_INVALID = -38,
+ XR_ERROR_CALL_ORDER_INVALID = -37,
+ XR_ERROR_API_LAYER_NOT_PRESENT = -36,
+ XR_ERROR_FORM_FACTOR_UNAVAILABLE = -35,
+ XR_ERROR_FORM_FACTOR_UNSUPPORTED = -34,
+ XR_ERROR_FILE_CONTENTS_INVALID = -33,
+ XR_ERROR_FILE_ACCESS_ERROR = -32,
+ XR_ERROR_REFERENCE_SPACE_UNSUPPORTED = -31,
+ XR_ERROR_TIME_INVALID = -30,
+ XR_ERROR_SESSION_NOT_STOPPING = -29,
+ XR_ERROR_SESSION_NOT_READY = -28,
+ XR_ERROR_ACTION_TYPE_MISMATCH = -27,
+ XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26,
+ XR_ERROR_SWAPCHAIN_RECT_INVALID = -25,
+ XR_ERROR_LAYER_LIMIT_EXCEEDED = -24,
+ XR_ERROR_LAYER_INVALID = -23,
+ XR_ERROR_PATH_UNSUPPORTED = -22,
+ XR_ERROR_PATH_FORMAT_INVALID = -21,
+ XR_ERROR_PATH_COUNT_EXCEEDED = -20,
+ XR_ERROR_PATH_INVALID = -19,
+ XR_ERROR_SYSTEM_INVALID = -18,
+ XR_ERROR_SESSION_LOST = -17,
+ XR_ERROR_SESSION_NOT_RUNNING = -16,
+ XR_ERROR_SESSION_RUNNING = -14,
+ XR_ERROR_INSTANCE_LOST = -13,
+ XR_ERROR_HANDLE_INVALID = -12,
+ XR_ERROR_SIZE_INSUFFICIENT = -11,
+ XR_ERROR_LIMIT_REACHED = -10,
+ XR_ERROR_EXTENSION_NOT_PRESENT = -9,
+ XR_ERROR_FEATURE_UNSUPPORTED = -8,
+ XR_ERROR_FUNCTION_UNSUPPORTED = -7,
+ XR_ERROR_INITIALIZATION_FAILED = -6,
+ XR_ERROR_API_VERSION_UNSUPPORTED = -4,
+ XR_ERROR_OUT_OF_MEMORY = -3,
+ XR_ERROR_RUNTIME_FAILURE = -2,
+ XR_ERROR_VALIDATION_FAILURE = -1,
+ XR_SUCCESS = 0,
+ XR_TIMEOUT_EXPIRED = 1,
+ XR_SESSION_LOSS_PENDING = 3,
+ XR_EVENT_UNAVAILABLE = 4,
+ XR_SPACE_BOUNDS_UNAVAILABLE = 7,
+ XR_SESSION_NOT_FOCUSED = 8,
+ XR_FRAME_DISCARDED = 9,
+ XR_RESULT_MAX_ENUM = 0x7fffffff,
+} XrResult;
+
+typedef enum XrSessionState
+{
+ XR_SESSION_STATE_UNKNOWN = 0,
+ XR_SESSION_STATE_IDLE = 1,
+ XR_SESSION_STATE_READY = 2,
+ XR_SESSION_STATE_SYNCHRONIZED = 3,
+ XR_SESSION_STATE_VISIBLE = 4,
+ XR_SESSION_STATE_FOCUSED = 5,
+ XR_SESSION_STATE_STOPPING = 6,
+ XR_SESSION_STATE_LOSS_PENDING = 7,
+ XR_SESSION_STATE_EXITING = 8,
+ XR_SESSION_STATE_MAX_ENUM = 0x7fffffff,
+} XrSessionState;
+
+typedef enum XrSpatialGraphNodeTypeMSFT
+{
+ XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT = 1,
+ XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT = 2,
+ XR_SPATIAL_GRAPH_NODE_TYPE_MSFT_MAX_ENUM = 0x7fffffff,
+} XrSpatialGraphNodeTypeMSFT;
+
+typedef enum XrStructureType
+{
+ XR_TYPE_UNKNOWN = 0,
+ XR_TYPE_API_LAYER_PROPERTIES = 1,
+ XR_TYPE_EXTENSION_PROPERTIES = 2,
+ XR_TYPE_INSTANCE_CREATE_INFO = 3,
+ XR_TYPE_SYSTEM_GET_INFO = 4,
+ XR_TYPE_SYSTEM_PROPERTIES = 5,
+ XR_TYPE_VIEW_LOCATE_INFO = 6,
+ XR_TYPE_VIEW = 7,
+ XR_TYPE_SESSION_CREATE_INFO = 8,
+ XR_TYPE_SWAPCHAIN_CREATE_INFO = 9,
+ XR_TYPE_SESSION_BEGIN_INFO = 10,
+ XR_TYPE_VIEW_STATE = 11,
+ XR_TYPE_FRAME_END_INFO = 12,
+ XR_TYPE_HAPTIC_VIBRATION = 13,
+ XR_TYPE_EVENT_DATA_BUFFER = 16,
+ XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING = 17,
+ XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED = 18,
+ XR_TYPE_ACTION_STATE_BOOLEAN = 23,
+ XR_TYPE_ACTION_STATE_FLOAT = 24,
+ XR_TYPE_ACTION_STATE_VECTOR2F = 25,
+ XR_TYPE_ACTION_STATE_POSE = 27,
+ XR_TYPE_ACTION_SET_CREATE_INFO = 28,
+ XR_TYPE_ACTION_CREATE_INFO = 29,
+ XR_TYPE_INSTANCE_PROPERTIES = 32,
+ XR_TYPE_FRAME_WAIT_INFO = 33,
+ XR_TYPE_COMPOSITION_LAYER_PROJECTION = 35,
+ XR_TYPE_COMPOSITION_LAYER_QUAD = 36,
+ XR_TYPE_REFERENCE_SPACE_CREATE_INFO = 37,
+ XR_TYPE_ACTION_SPACE_CREATE_INFO = 38,
+ XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING = 40,
+ XR_TYPE_VIEW_CONFIGURATION_VIEW = 41,
+ XR_TYPE_SPACE_LOCATION = 42,
+ XR_TYPE_SPACE_VELOCITY = 43,
+ XR_TYPE_FRAME_STATE = 44,
+ XR_TYPE_VIEW_CONFIGURATION_PROPERTIES = 45,
+ XR_TYPE_FRAME_BEGIN_INFO = 46,
+ XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW = 48,
+ XR_TYPE_EVENT_DATA_EVENTS_LOST = 49,
+ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING = 51,
+ XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED = 52,
+ XR_TYPE_INTERACTION_PROFILE_STATE = 53,
+ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO = 55,
+ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO = 56,
+ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO = 57,
+ XR_TYPE_ACTION_STATE_GET_INFO = 58,
+ XR_TYPE_HAPTIC_ACTION_INFO = 59,
+ XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO = 60,
+ XR_TYPE_ACTIONS_SYNC_INFO = 61,
+ XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO = 62,
+ XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO = 63,
+ XR_TYPE_COMPOSITION_LAYER_CUBE_KHR = 1000006000,
+ XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR = 1000010000,
+ XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR = 1000014000,
+ XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT = 1000015000,
+ XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR = 1000017000,
+ XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR = 1000018000,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR = 1000023000,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR = 1000023001,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR = 1000023002,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR = 1000023003,
+ XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR = 1000023004,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR = 1000023005,
+ XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR = 1000025000,
+ XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR = 1000025001,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR = 1000025002,
+ XR_TYPE_GRAPHICS_BINDING_D3D11_KHR = 1000027000,
+ XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR = 1000027001,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR = 1000027002,
+ XR_TYPE_GRAPHICS_BINDING_D3D12_KHR = 1000028000,
+ XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR = 1000028001,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR = 1000028002,
+ XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT = 1000030000,
+ XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT = 1000030001,
+ XR_TYPE_VISIBILITY_MASK_KHR = 1000031000,
+ XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001,
+ XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX = 1000033000,
+ XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX = 1000033003,
+ XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT = 1000039000,
+ XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT = 1000039001,
+ XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT = 1000046000,
+ XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT = 1000049000,
+ XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT = 1000051000,
+ XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT = 1000051001,
+ XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT = 1000051002,
+ XR_TYPE_HAND_JOINT_LOCATIONS_EXT = 1000051003,
+ XR_TYPE_HAND_JOINT_VELOCITIES_EXT = 1000051004,
+ XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT = 1000052000,
+ XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT = 1000052001,
+ XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT = 1000052002,
+ XR_TYPE_HAND_MESH_MSFT = 1000052003,
+ XR_TYPE_HAND_POSE_TYPE_INFO_MSFT = 1000052004,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT = 1000053000,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT = 1000053001,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT = 1000053002,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT = 1000053003,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT = 1000053004,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT = 1000053005,
+ XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC = 1000059000,
+ XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT = 1000063000,
+ XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE = 1000079000,
+ XR_STRUCTURE_TYPE_MAX_ENUM = 0x7fffffff,
+} XrStructureType;
+
+typedef enum XrViewConfigurationType
+{
+ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO = 1,
+ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO = 2,
+ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO = 1000037000,
+ XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT = 1000054000,
+ XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM = 0x7fffffff,
+} XrViewConfigurationType;
+
+typedef enum XrVisibilityMaskTypeKHR
+{
+ XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR = 1,
+ XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR = 2,
+ XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR = 3,
+ XR_VISIBILITY_MASK_TYPE_KHR_MAX_ENUM = 0x7fffffff,
+} XrVisibilityMaskTypeKHR;
+
+typedef struct XrActionCreateInfo XrActionCreateInfo;
+typedef struct XrActionStateBoolean XrActionStateBoolean;
+typedef struct XrActionStateGetInfo XrActionStateGetInfo;
+typedef struct XrActionSuggestedBinding XrActionSuggestedBinding;
+typedef struct XrActiveActionSet XrActiveActionSet;
+typedef struct XrApplicationInfo XrApplicationInfo;
+typedef struct XrBaseOutStructure XrBaseOutStructure;
+typedef struct XrColor4f XrColor4f;
+typedef struct XrDebugUtilsLabelEXT XrDebugUtilsLabelEXT;
+typedef struct XrEventDataBaseHeader XrEventDataBaseHeader;
+typedef struct XrEventDataEventsLost XrEventDataEventsLost;
+typedef struct XrEventDataInteractionProfileChanged XrEventDataInteractionProfileChanged;
+typedef struct XrEventDataPerfSettingsEXT XrEventDataPerfSettingsEXT;
+typedef struct XrEventDataSessionStateChanged XrEventDataSessionStateChanged;
+typedef struct XrExtensionProperties XrExtensionProperties;
+typedef struct XrExtent2Di XrExtent2Di;
+typedef struct XrFovf XrFovf;
+typedef struct XrFrameState XrFrameState;
+typedef struct XrGraphicsBindingD3D11KHR XrGraphicsBindingD3D11KHR;
+typedef struct XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkanKHR;
+typedef struct XrGraphicsRequirementsD3D12KHR XrGraphicsRequirementsD3D12KHR;
+typedef struct XrGraphicsRequirementsOpenGLKHR XrGraphicsRequirementsOpenGLKHR;
+typedef struct XrHandJointsLocateInfoEXT XrHandJointsLocateInfoEXT;
+typedef struct XrHandMeshUpdateInfoMSFT XrHandMeshUpdateInfoMSFT;
+typedef struct XrHandPoseTypeInfoMSFT XrHandPoseTypeInfoMSFT;
+typedef struct XrHapticActionInfo XrHapticActionInfo;
+typedef struct XrHapticVibration XrHapticVibration;
+typedef struct XrInputSourceLocalizedNameGetInfo XrInputSourceLocalizedNameGetInfo;
+typedef struct XrInteractionProfileState XrInteractionProfileState;
+typedef struct XrOffset2Df XrOffset2Df;
+typedef struct XrQuaternionf XrQuaternionf;
+typedef struct XrSecondaryViewConfigurationSessionBeginInfoMSFT XrSecondaryViewConfigurationSessionBeginInfoMSFT;
+typedef struct XrSecondaryViewConfigurationSwapchainCreateInfoMSFT XrSecondaryViewConfigurationSwapchainCreateInfoMSFT;
+typedef struct XrSessionBeginInfo XrSessionBeginInfo;
+typedef struct XrSessionCreateInfoOverlayEXTX XrSessionCreateInfoOverlayEXTX;
+typedef struct XrSwapchainCreateInfo XrSwapchainCreateInfo;
+typedef struct XrSwapchainImageBaseHeader XrSwapchainImageBaseHeader;
+typedef struct XrSwapchainImageD3D12KHR XrSwapchainImageD3D12KHR;
+typedef struct XrSwapchainImageOpenGLKHR XrSwapchainImageOpenGLKHR;
+typedef struct XrSwapchainImageVulkanKHR XrSwapchainImageVulkanKHR;
+typedef struct XrSystemEyeGazeInteractionPropertiesEXT XrSystemEyeGazeInteractionPropertiesEXT;
+typedef struct XrSystemGraphicsProperties XrSystemGraphicsProperties;
+typedef struct XrSystemHandTrackingPropertiesEXT XrSystemHandTrackingPropertiesEXT;
+typedef struct XrSystemTrackingProperties XrSystemTrackingProperties;
+typedef struct XrVector3f XrVector3f;
+typedef struct XrViewConfigurationDepthRangeEXT XrViewConfigurationDepthRangeEXT;
+typedef struct XrViewConfigurationView XrViewConfigurationView;
+typedef struct XrViewLocateInfo XrViewLocateInfo;
+typedef struct XrVulkanSwapchainFormatListCreateInfoKHR XrVulkanSwapchainFormatListCreateInfoKHR;
+typedef struct XrActionSetCreateInfo XrActionSetCreateInfo;
+typedef struct XrActionStateFloat XrActionStateFloat;
+typedef struct XrActionsSyncInfo XrActionsSyncInfo;
+typedef struct XrBaseInStructure XrBaseInStructure;
+typedef struct XrCompositionLayerBaseHeader XrCompositionLayerBaseHeader;
+typedef struct XrDebugUtilsObjectNameInfoEXT XrDebugUtilsObjectNameInfoEXT;
+typedef struct XrEventDataInstanceLossPending XrEventDataInstanceLossPending;
+typedef struct XrEventDataVisibilityMaskChangedKHR XrEventDataVisibilityMaskChangedKHR;
+typedef struct XrEyeGazeSampleTimeEXT XrEyeGazeSampleTimeEXT;
+typedef struct XrFrameEndInfo XrFrameEndInfo;
+typedef struct XrGraphicsBindingD3D12KHR XrGraphicsBindingD3D12KHR;
+typedef struct XrGraphicsRequirementsD3D11KHR XrGraphicsRequirementsD3D11KHR;
+typedef struct XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkanKHR;
+typedef struct XrHandJointVelocityEXT XrHandJointVelocityEXT;
+typedef struct XrHandMeshVertexMSFT XrHandMeshVertexMSFT;
+typedef struct XrHapticBaseHeader XrHapticBaseHeader;
+typedef struct XrInstanceCreateInfo XrInstanceCreateInfo;
+typedef struct XrInteractionProfileAnalogThresholdVALVE XrInteractionProfileAnalogThresholdVALVE;
+typedef struct XrOffset2Di XrOffset2Di;
+typedef struct XrRect2Di XrRect2Di;
+typedef struct XrSecondaryViewConfigurationLayerInfoMSFT XrSecondaryViewConfigurationLayerInfoMSFT;
+typedef struct XrSessionActionSetsAttachInfo XrSessionActionSetsAttachInfo;
+typedef struct XrSpaceVelocity XrSpaceVelocity;
+typedef struct XrSwapchainImageAcquireInfo XrSwapchainImageAcquireInfo;
+typedef struct XrSwapchainImageWaitInfo XrSwapchainImageWaitInfo;
+typedef struct XrSystemGetInfo XrSystemGetInfo;
+typedef struct XrSystemProperties XrSystemProperties;
+typedef struct XrVector4f XrVector4f;
+typedef struct XrViewConfigurationProperties XrViewConfigurationProperties;
+typedef struct XrViewState XrViewState;
+typedef struct XrActionStatePose XrActionStatePose;
+typedef struct XrApiLayerProperties XrApiLayerProperties;
+typedef struct XrCompositionLayerCubeKHR XrCompositionLayerCubeKHR;
+typedef struct XrDebugUtilsMessengerCallbackDataEXT XrDebugUtilsMessengerCallbackDataEXT;
+typedef struct XrEventDataMainSessionVisibilityChangedEXTX XrEventDataMainSessionVisibilityChangedEXTX;
+typedef struct XrExtent2Df XrExtent2Df;
+typedef struct XrFrameWaitInfo XrFrameWaitInfo;
+typedef struct XrHandJointVelocitiesEXT XrHandJointVelocitiesEXT;
+typedef struct XrHandMeshVertexBufferMSFT XrHandMeshVertexBufferMSFT;
+typedef struct XrHolographicWindowAttachmentMSFT XrHolographicWindowAttachmentMSFT;
+typedef struct XrInteractionProfileSuggestedBinding XrInteractionProfileSuggestedBinding;
+typedef struct XrRect2Df XrRect2Df;
+typedef struct XrSecondaryViewConfigurationFrameEndInfoMSFT XrSecondaryViewConfigurationFrameEndInfoMSFT;
+typedef struct XrSecondaryViewConfigurationStateMSFT XrSecondaryViewConfigurationStateMSFT;
+typedef struct XrSwapchainImageD3D11KHR XrSwapchainImageD3D11KHR;
+typedef struct XrSwapchainSubImage XrSwapchainSubImage;
+typedef struct XrVector2f XrVector2f;
+typedef struct XrViewConfigurationViewFovEPIC XrViewConfigurationViewFovEPIC;
+typedef struct XrActionStateVector2f XrActionStateVector2f;
+typedef struct XrCompositionLayerDepthInfoKHR XrCompositionLayerDepthInfoKHR;
+typedef struct XrEventDataBuffer XrEventDataBuffer;
+typedef struct XrFrameBeginInfo XrFrameBeginInfo;
+typedef struct XrHandMeshIndexBufferMSFT XrHandMeshIndexBufferMSFT;
+typedef struct XrHandTrackerCreateInfoEXT XrHandTrackerCreateInfoEXT;
+typedef struct XrPosef XrPosef;
+typedef struct XrSecondaryViewConfigurationFrameStateMSFT XrSecondaryViewConfigurationFrameStateMSFT;
+typedef struct XrSpaceLocation XrSpaceLocation;
+typedef struct XrSpatialAnchorSpaceCreateInfoMSFT XrSpatialAnchorSpaceCreateInfoMSFT;
+typedef struct XrSwapchainImageReleaseInfo XrSwapchainImageReleaseInfo;
+typedef struct XrView XrView;
+typedef struct XrActionSpaceCreateInfo XrActionSpaceCreateInfo;
+typedef struct XrCompositionLayerCylinderKHR XrCompositionLayerCylinderKHR;
+typedef struct XrCompositionLayerProjectionView XrCompositionLayerProjectionView;
+typedef struct XrEventDataReferenceSpaceChangePending XrEventDataReferenceSpaceChangePending;
+typedef struct XrHandJointLocationEXT XrHandJointLocationEXT;
+typedef struct XrHandMeshMSFT XrHandMeshMSFT;
+typedef struct XrInstanceProperties XrInstanceProperties;
+typedef struct XrSessionCreateInfo XrSessionCreateInfo;
+typedef struct XrSpatialGraphNodeSpaceCreateInfoMSFT XrSpatialGraphNodeSpaceCreateInfoMSFT;
+typedef struct XrVisibilityMaskKHR XrVisibilityMaskKHR;
+typedef struct XrBoundSourcesForActionEnumerateInfo XrBoundSourcesForActionEnumerateInfo;
+typedef struct XrCompositionLayerProjection XrCompositionLayerProjection;
+typedef struct XrGraphicsBindingOpenGLWin32KHR XrGraphicsBindingOpenGLWin32KHR;
+typedef struct XrHandMeshSpaceCreateInfoMSFT XrHandMeshSpaceCreateInfoMSFT;
+typedef struct XrSpatialAnchorCreateInfoMSFT XrSpatialAnchorCreateInfoMSFT;
+typedef struct XrCompositionLayerEquirectKHR XrCompositionLayerEquirectKHR;
+typedef struct XrHandJointLocationsEXT XrHandJointLocationsEXT;
+typedef struct XrSystemHandTrackingMeshPropertiesMSFT XrSystemHandTrackingMeshPropertiesMSFT;
+typedef struct XrCompositionLayerQuad XrCompositionLayerQuad;
+typedef struct XrReferenceSpaceCreateInfo XrReferenceSpaceCreateInfo;
+typedef XrBool32 (XRAPI_PTR * PFN_xrDebugUtilsMessengerCallbackEXT)(
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT *callbackData,
+ void *userData);
+typedef void (XRAPI_PTR * PFN_xrVoidFunction)(
+void);
+
+struct XrActionCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ char actionName[XR_MAX_ACTION_NAME_SIZE];
+ XrActionType actionType;
+ uint32_t countSubactionPaths;
+ const XrPath *subactionPaths;
+ char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE];
+};
+
+struct XrActionStateBoolean
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+};
+
+struct XrActionStateGetInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrAction action;
+ XrPath subactionPath;
+};
+
+struct XrActionSuggestedBinding
+{
+ XrAction action;
+ XrPath binding;
+};
+
+struct XrActiveActionSet
+{
+ XrActionSet actionSet;
+ XrPath subactionPath;
+};
+
+struct XrApplicationInfo
+{
+ char applicationName[XR_MAX_APPLICATION_NAME_SIZE];
+ uint32_t applicationVersion;
+ char engineName[XR_MAX_ENGINE_NAME_SIZE];
+ uint32_t engineVersion;
+ XrVersion apiVersion;
+};
+
+struct XrBaseOutStructure
+{
+ XrStructureType type;
+ struct XrBaseOutStructure *next;
+};
+
+struct XrColor4f
+{
+ float r;
+ float g;
+ float b;
+ float a;
+};
+
+struct XrDebugUtilsLabelEXT
+{
+ XrStructureType type;
+ const void *next;
+ const char *labelName;
+};
+
+struct XrEventDataBaseHeader
+{
+ XrStructureType type;
+ const void *next;
+};
+
+struct XrEventDataEventsLost
+{
+ XrStructureType type;
+ const void *next;
+ uint32_t lostEventCount;
+};
+
+struct XrEventDataInteractionProfileChanged
+{
+ XrStructureType type;
+ const void *next;
+ XrSession session;
+};
+
+struct XrEventDataPerfSettingsEXT
+{
+ XrStructureType type;
+ const void *next;
+ XrPerfSettingsDomainEXT domain;
+ XrPerfSettingsSubDomainEXT subDomain;
+ XrPerfSettingsNotificationLevelEXT fromLevel;
+ XrPerfSettingsNotificationLevelEXT toLevel;
+};
+
+struct XrEventDataSessionStateChanged
+{
+ XrStructureType type;
+ const void *next;
+ XrSession session;
+ XrSessionState state;
+ XrTime time;
+};
+
+struct XrExtensionProperties
+{
+ XrStructureType type;
+ void *next;
+ char extensionName[XR_MAX_EXTENSION_NAME_SIZE];
+ uint32_t extensionVersion;
+};
+
+struct XrExtent2Di
+{
+ int32_t width;
+ int32_t height;
+};
+
+struct XrFovf
+{
+ float angleLeft;
+ float angleRight;
+ float angleUp;
+ float angleDown;
+};
+
+struct XrFrameState
+{
+ XrStructureType type;
+ void *next;
+ XrTime predictedDisplayTime;
+ XrDuration predictedDisplayPeriod;
+ XrBool32 shouldRender;
+};
+
+struct XrGraphicsBindingD3D11KHR
+{
+ XrStructureType type;
+ const void *next;
+ ID3D11Device *device;
+};
+
+struct XrGraphicsBindingVulkanKHR
+{
+ XrStructureType type;
+ const void *next;
+ VkInstance instance;
+ VkPhysicalDevice physicalDevice;
+ VkDevice device;
+ uint32_t queueFamilyIndex;
+ uint32_t queueIndex;
+};
+
+struct XrGraphicsRequirementsD3D12KHR
+{
+ XrStructureType type;
+ void *next;
+ LUID adapterLuid;
+ D3D_FEATURE_LEVEL minFeatureLevel;
+};
+
+struct XrGraphicsRequirementsOpenGLKHR
+{
+ XrStructureType type;
+ void *next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+};
+
+struct XrHandJointsLocateInfoEXT
+{
+ XrStructureType type;
+ const void *next;
+ XrSpace baseSpace;
+ XrTime time;
+};
+
+struct XrHandMeshUpdateInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrTime time;
+ XrHandPoseTypeMSFT handPoseType;
+};
+
+struct XrHandPoseTypeInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrHandPoseTypeMSFT handPoseType;
+};
+
+struct XrHapticActionInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrAction action;
+ XrPath subactionPath;
+};
+
+struct XrHapticVibration
+{
+ XrStructureType type;
+ const void *next;
+ XrDuration duration;
+ float frequency;
+ float amplitude;
+};
+
+struct XrInputSourceLocalizedNameGetInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrPath sourcePath;
+ XrInputSourceLocalizedNameFlags whichComponents;
+};
+
+struct XrInteractionProfileState
+{
+ XrStructureType type;
+ void *next;
+ XrPath interactionProfile;
+};
+
+struct XrOffset2Df
+{
+ float x;
+ float y;
+};
+
+struct XrQuaternionf
+{
+ float x;
+ float y;
+ float z;
+ float w;
+};
+
+struct XrSecondaryViewConfigurationSessionBeginInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ uint32_t viewConfigurationCount;
+ const XrViewConfigurationType *enabledViewConfigurationTypes;
+};
+
+struct XrSecondaryViewConfigurationSwapchainCreateInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrViewConfigurationType viewConfigurationType;
+};
+
+struct XrSessionBeginInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrViewConfigurationType primaryViewConfigurationType;
+};
+
+struct XrSessionCreateInfoOverlayEXTX
+{
+ XrStructureType type;
+ const void *next;
+ XrOverlaySessionCreateFlagsEXTX createFlags;
+ uint32_t sessionLayersPlacement;
+};
+
+struct XrSwapchainCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrSwapchainCreateFlags createFlags;
+ XrSwapchainUsageFlags usageFlags;
+ int64_t format;
+ uint32_t sampleCount;
+ uint32_t width;
+ uint32_t height;
+ uint32_t faceCount;
+ uint32_t arraySize;
+ uint32_t mipCount;
+};
+
+struct XrSwapchainImageBaseHeader
+{
+ XrStructureType type;
+ void *next;
+};
+
+struct XrSwapchainImageD3D12KHR
+{
+ XrStructureType type;
+ void *next;
+ ID3D12Resource *texture;
+};
+
+struct XrSwapchainImageOpenGLKHR
+{
+ XrStructureType type;
+ void *next;
+ uint32_t image;
+};
+
+struct XrSwapchainImageVulkanKHR
+{
+ XrStructureType type;
+ void *next;
+ VkImage image;
+};
+
+struct XrSystemEyeGazeInteractionPropertiesEXT
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 supportsEyeGazeInteraction;
+};
+
+struct XrSystemGraphicsProperties
+{
+ uint32_t maxSwapchainImageHeight;
+ uint32_t maxSwapchainImageWidth;
+ uint32_t maxLayerCount;
+};
+
+struct XrSystemHandTrackingPropertiesEXT
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 supportsHandTracking;
+};
+
+struct XrSystemTrackingProperties
+{
+ XrBool32 orientationTracking;
+ XrBool32 positionTracking;
+};
+
+struct XrVector3f
+{
+ float x;
+ float y;
+ float z;
+};
+
+struct XrViewConfigurationDepthRangeEXT
+{
+ XrStructureType type;
+ void *next;
+ float recommendedNearZ;
+ float minNearZ;
+ float recommendedFarZ;
+ float maxFarZ;
+};
+
+struct XrViewConfigurationView
+{
+ XrStructureType type;
+ void *next;
+ uint32_t recommendedImageRectWidth;
+ uint32_t maxImageRectWidth;
+ uint32_t recommendedImageRectHeight;
+ uint32_t maxImageRectHeight;
+ uint32_t recommendedSwapchainSampleCount;
+ uint32_t maxSwapchainSampleCount;
+};
+
+struct XrViewLocateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrViewConfigurationType viewConfigurationType;
+ XrTime displayTime;
+ XrSpace space;
+};
+
+struct XrVulkanSwapchainFormatListCreateInfoKHR
+{
+ XrStructureType type;
+ const void *next;
+ uint32_t viewFormatCount;
+ const VkFormat *viewFormats;
+};
+
+struct XrActionSetCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE];
+ char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE];
+ uint32_t priority;
+};
+
+struct XrActionStateFloat
+{
+ XrStructureType type;
+ void *next;
+ float currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+};
+
+struct XrActionsSyncInfo
+{
+ XrStructureType type;
+ const void *next;
+ uint32_t countActiveActionSets;
+ const XrActiveActionSet *activeActionSets;
+};
+
+struct XrBaseInStructure
+{
+ XrStructureType type;
+ const struct XrBaseInStructure *next;
+};
+
+struct XrCompositionLayerBaseHeader
+{
+ XrStructureType type;
+ const void *next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+};
+
+struct XrDebugUtilsObjectNameInfoEXT
+{
+ XrStructureType type;
+ const void *next;
+ XrObjectType objectType;
+ uint64_t WINE_XR_ALIGN(8) objectHandle;
+ const char *objectName;
+};
+
+struct XrEventDataInstanceLossPending
+{
+ XrStructureType type;
+ const void *next;
+ XrTime lossTime;
+};
+
+struct XrEventDataVisibilityMaskChangedKHR
+{
+ XrStructureType type;
+ const void *next;
+ XrSession session;
+ XrViewConfigurationType viewConfigurationType;
+ uint32_t viewIndex;
+};
+
+struct XrEyeGazeSampleTimeEXT
+{
+ XrStructureType type;
+ void *next;
+ XrTime time;
+};
+
+struct XrFrameEndInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrTime displayTime;
+ XrEnvironmentBlendMode environmentBlendMode;
+ uint32_t layerCount;
+ const XrCompositionLayerBaseHeader * const*layers;
+};
+
+struct XrGraphicsBindingD3D12KHR
+{
+ XrStructureType type;
+ const void *next;
+ ID3D12Device *device;
+ ID3D12CommandQueue *queue;
+};
+
+struct XrGraphicsRequirementsD3D11KHR
+{
+ XrStructureType type;
+ void *next;
+ LUID adapterLuid;
+ D3D_FEATURE_LEVEL minFeatureLevel;
+};
+
+struct XrGraphicsRequirementsVulkanKHR
+{
+ XrStructureType type;
+ void *next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+};
+
+struct XrHandJointVelocityEXT
+{
+ XrSpaceVelocityFlags velocityFlags;
+ XrVector3f linearVelocity;
+ XrVector3f angularVelocity;
+};
+
+struct XrHandMeshVertexMSFT
+{
+ XrVector3f position;
+ XrVector3f normal;
+};
+
+struct XrHapticBaseHeader
+{
+ XrStructureType type;
+ const void *next;
+};
+
+struct XrInstanceCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrInstanceCreateFlags createFlags;
+ XrApplicationInfo applicationInfo;
+ uint32_t enabledApiLayerCount;
+ const char * const*enabledApiLayerNames;
+ uint32_t enabledExtensionCount;
+ const char * const*enabledExtensionNames;
+};
+
+struct XrInteractionProfileAnalogThresholdVALVE
+{
+ XrStructureType type;
+ const void *next;
+ XrAction action;
+ XrPath binding;
+ float onThreshold;
+ float offThreshold;
+ const XrHapticBaseHeader *onHaptic;
+ const XrHapticBaseHeader *offHaptic;
+};
+
+struct XrOffset2Di
+{
+ int32_t x;
+ int32_t y;
+};
+
+struct XrRect2Di
+{
+ XrOffset2Di offset;
+ XrExtent2Di extent;
+};
+
+struct XrSecondaryViewConfigurationLayerInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrViewConfigurationType viewConfigurationType;
+ XrEnvironmentBlendMode environmentBlendMode;
+ uint32_t layerCount;
+ const XrCompositionLayerBaseHeader * const*layers;
+};
+
+struct XrSessionActionSetsAttachInfo
+{
+ XrStructureType type;
+ const void *next;
+ uint32_t countActionSets;
+ const XrActionSet *actionSets;
+};
+
+struct XrSpaceVelocity
+{
+ XrStructureType type;
+ void *next;
+ XrSpaceVelocityFlags velocityFlags;
+ XrVector3f linearVelocity;
+ XrVector3f angularVelocity;
+};
+
+struct XrSwapchainImageAcquireInfo
+{
+ XrStructureType type;
+ const void *next;
+};
+
+struct XrSwapchainImageWaitInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrDuration timeout;
+};
+
+struct XrSystemGetInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrFormFactor formFactor;
+};
+
+struct XrSystemProperties
+{
+ XrStructureType type;
+ void *next;
+ XrSystemId systemId;
+ uint32_t vendorId;
+ char systemName[XR_MAX_SYSTEM_NAME_SIZE];
+ XrSystemGraphicsProperties graphicsProperties;
+ XrSystemTrackingProperties trackingProperties;
+};
+
+struct XrVector4f
+{
+ float x;
+ float y;
+ float z;
+ float w;
+};
+
+struct XrViewConfigurationProperties
+{
+ XrStructureType type;
+ void *next;
+ XrViewConfigurationType viewConfigurationType;
+ XrBool32 fovMutable;
+};
+
+struct XrViewState
+{
+ XrStructureType type;
+ void *next;
+ XrViewStateFlags viewStateFlags;
+};
+
+struct XrActionStatePose
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 isActive;
+};
+
+struct XrApiLayerProperties
+{
+ XrStructureType type;
+ void *next;
+ char layerName[XR_MAX_API_LAYER_NAME_SIZE];
+ XrVersion specVersion;
+ uint32_t layerVersion;
+ char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];
+};
+
+struct XrCompositionLayerCubeKHR
+{
+ XrStructureType type;
+ const void *next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchain swapchain;
+ uint32_t imageArrayIndex;
+ XrQuaternionf orientation;
+};
+
+struct XrDebugUtilsMessengerCallbackDataEXT
+{
+ XrStructureType type;
+ const void *next;
+ const char *messageId;
+ const char *functionName;
+ const char *message;
+ uint32_t objectCount;
+ XrDebugUtilsObjectNameInfoEXT *objects;
+ uint32_t sessionLabelCount;
+ XrDebugUtilsLabelEXT *sessionLabels;
+};
+
+struct XrEventDataMainSessionVisibilityChangedEXTX
+{
+ XrStructureType type;
+ const void *next;
+ XrBool32 visible;
+ XrOverlayMainSessionFlagsEXTX flags;
+};
+
+struct XrExtent2Df
+{
+ float width;
+ float height;
+};
+
+struct XrFrameWaitInfo
+{
+ XrStructureType type;
+ const void *next;
+};
+
+struct XrHandJointVelocitiesEXT
+{
+ XrStructureType type;
+ void *next;
+ uint32_t jointCount;
+ XrHandJointVelocityEXT *jointVelocities;
+};
+
+struct XrHandMeshVertexBufferMSFT
+{
+ XrTime vertexUpdateTime;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrHandMeshVertexMSFT *vertices;
+};
+
+struct XrHolographicWindowAttachmentMSFT
+{
+ XrStructureType type;
+ const void *next;
+ IUnknown *holographicSpace;
+ IUnknown *coreWindow;
+};
+
+struct XrInteractionProfileSuggestedBinding
+{
+ XrStructureType type;
+ const void *next;
+ XrPath interactionProfile;
+ uint32_t countSuggestedBindings;
+ const XrActionSuggestedBinding *suggestedBindings;
+};
+
+struct XrRect2Df
+{
+ XrOffset2Df offset;
+ XrExtent2Df extent;
+};
+
+struct XrSecondaryViewConfigurationFrameEndInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ uint32_t viewConfigurationCount;
+ const XrSecondaryViewConfigurationLayerInfoMSFT *viewConfigurationLayersInfo;
+};
+
+struct XrSecondaryViewConfigurationStateMSFT
+{
+ XrStructureType type;
+ void *next;
+ XrViewConfigurationType viewConfigurationType;
+ XrBool32 active;
+};
+
+struct XrSwapchainImageD3D11KHR
+{
+ XrStructureType type;
+ void *next;
+ ID3D11Texture2D *texture;
+};
+
+struct XrSwapchainSubImage
+{
+ XrSwapchain swapchain;
+ XrRect2Di imageRect;
+ uint32_t imageArrayIndex;
+};
+
+struct XrVector2f
+{
+ float x;
+ float y;
+};
+
+struct XrViewConfigurationViewFovEPIC
+{
+ XrStructureType type;
+ const void *next;
+ XrFovf recommendedFov;
+ XrFovf maxMutableFov;
+};
+
+struct XrActionStateVector2f
+{
+ XrStructureType type;
+ void *next;
+ XrVector2f currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+};
+
+struct XrCompositionLayerDepthInfoKHR
+{
+ XrStructureType type;
+ const void *next;
+ XrSwapchainSubImage subImage;
+ float minDepth;
+ float maxDepth;
+ float nearZ;
+ float farZ;
+};
+
+struct XrEventDataBuffer
+{
+ XrStructureType type;
+ const void *next;
+ uint8_t varying[4000];
+};
+
+struct XrFrameBeginInfo
+{
+ XrStructureType type;
+ const void *next;
+};
+
+struct XrHandMeshIndexBufferMSFT
+{
+ uint32_t indexBufferKey;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint32_t *indices;
+};
+
+struct XrHandTrackerCreateInfoEXT
+{
+ XrStructureType type;
+ const void *next;
+ XrHandEXT hand;
+ XrHandJointSetEXT handJointSet;
+};
+
+struct XrPosef
+{
+ XrQuaternionf orientation;
+ XrVector3f position;
+};
+
+struct XrSecondaryViewConfigurationFrameStateMSFT
+{
+ XrStructureType type;
+ void *next;
+ uint32_t viewConfigurationCount;
+ XrSecondaryViewConfigurationStateMSFT *viewConfigurationStates;
+};
+
+struct XrSpaceLocation
+{
+ XrStructureType type;
+ void *next;
+ XrSpaceLocationFlags locationFlags;
+ XrPosef pose;
+};
+
+struct XrSpatialAnchorSpaceCreateInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrSpatialAnchorMSFT anchor;
+ XrPosef poseInAnchorSpace;
+};
+
+struct XrSwapchainImageReleaseInfo
+{
+ XrStructureType type;
+ const void *next;
+};
+
+struct XrView
+{
+ XrStructureType type;
+ void *next;
+ XrPosef pose;
+ XrFovf fov;
+};
+
+struct XrActionSpaceCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrAction action;
+ XrPath subactionPath;
+ XrPosef poseInActionSpace;
+};
+
+struct XrCompositionLayerCylinderKHR
+{
+ XrStructureType type;
+ const void *next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ float centralAngle;
+ float aspectRatio;
+};
+
+struct XrCompositionLayerProjectionView
+{
+ XrStructureType type;
+ const void *next;
+ XrPosef pose;
+ XrFovf fov;
+ XrSwapchainSubImage subImage;
+};
+
+struct XrEventDataReferenceSpaceChangePending
+{
+ XrStructureType type;
+ const void *next;
+ XrSession session;
+ XrReferenceSpaceType referenceSpaceType;
+ XrTime changeTime;
+ XrBool32 poseValid;
+ XrPosef poseInPreviousSpace;
+};
+
+struct XrHandJointLocationEXT
+{
+ XrSpaceLocationFlags locationFlags;
+ XrPosef pose;
+ float radius;
+};
+
+struct XrHandMeshMSFT
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 isActive;
+ XrBool32 indexBufferChanged;
+ XrBool32 vertexBufferChanged;
+ XrHandMeshIndexBufferMSFT indexBuffer;
+ XrHandMeshVertexBufferMSFT vertexBuffer;
+};
+
+struct XrInstanceProperties
+{
+ XrStructureType type;
+ void *next;
+ XrVersion runtimeVersion;
+ char runtimeName[XR_MAX_RUNTIME_NAME_SIZE];
+};
+
+struct XrSessionCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrSessionCreateFlags createFlags;
+ XrSystemId systemId;
+};
+
+struct XrSpatialGraphNodeSpaceCreateInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrSpatialGraphNodeTypeMSFT nodeType;
+ uint8_t nodeId[16];
+ XrPosef pose;
+};
+
+struct XrVisibilityMaskKHR
+{
+ XrStructureType type;
+ void *next;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrVector2f *vertices;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint32_t *indices;
+};
+
+struct XrBoundSourcesForActionEnumerateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrAction action;
+};
+
+struct XrCompositionLayerProjection
+{
+ XrStructureType type;
+ const void *next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ uint32_t viewCount;
+ const XrCompositionLayerProjectionView *views;
+};
+
+struct XrGraphicsBindingOpenGLWin32KHR
+{
+ XrStructureType type;
+ const void *next;
+ HDC hDC;
+ HGLRC hGLRC;
+};
+
+struct XrHandMeshSpaceCreateInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrHandPoseTypeMSFT handPoseType;
+ XrPosef poseInHandMeshSpace;
+};
+
+struct XrSpatialAnchorCreateInfoMSFT
+{
+ XrStructureType type;
+ const void *next;
+ XrSpace space;
+ XrPosef pose;
+ XrTime time;
+};
+
+struct XrCompositionLayerEquirectKHR
+{
+ XrStructureType type;
+ const void *next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ XrVector2f scale;
+ XrVector2f bias;
+};
+
+struct XrHandJointLocationsEXT
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 isActive;
+ uint32_t jointCount;
+ XrHandJointLocationEXT *jointLocations;
+};
+
+struct XrSystemHandTrackingMeshPropertiesMSFT
+{
+ XrStructureType type;
+ void *next;
+ XrBool32 supportsHandTrackingMesh;
+ uint32_t maxHandMeshIndexCount;
+ uint32_t maxHandMeshVertexCount;
+};
+
+struct XrCompositionLayerQuad
+{
+ XrStructureType type;
+ const void *next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ XrExtent2Df size;
+};
+
+struct XrReferenceSpaceCreateInfo
+{
+ XrStructureType type;
+ const void *next;
+ XrReferenceSpaceType referenceSpaceType;
+ XrPosef poseInReferenceSpace;
+};
+
+typedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain, const XrSwapchainImageAcquireInfo *, uint32_t *);
+typedef XrResult (XRAPI_PTR *PFN_xrApplyHapticFeedback)(XrSession, const XrHapticActionInfo *, const XrHapticBaseHeader *);
+typedef XrResult (XRAPI_PTR *PFN_xrAttachSessionActionSets)(XrSession, const XrSessionActionSetsAttachInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrBeginFrame)(XrSession, const XrFrameBeginInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrBeginSession)(XrSession, const XrSessionBeginInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance, XrTime, LARGE_INTEGER *);
+typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance, const LARGE_INTEGER *, XrTime *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateAction)(XrActionSet, const XrActionCreateInfo *, XrAction *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSet)(XrInstance, const XrActionSetCreateInfo *, XrActionSet *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession, const XrActionSpaceCreateInfo *, XrSpace *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateHandMeshSpaceMSFT)(XrHandTrackerEXT, const XrHandMeshSpaceCreateInfoMSFT *, XrSpace *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateHandTrackerEXT)(XrSession, const XrHandTrackerCreateInfoEXT *, XrHandTrackerEXT *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateInstance)(const XrInstanceCreateInfo *, XrInstance *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession, const XrReferenceSpaceCreateInfo *, XrSpace *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSession)(XrInstance, const XrSessionCreateInfo *, XrSession *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorMSFT)(XrSession, const XrSpatialAnchorCreateInfoMSFT *, XrSpatialAnchorMSFT *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorSpaceMSFT)(XrSession, const XrSpatialAnchorSpaceCreateInfoMSFT *, XrSpace *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialGraphNodeSpaceMSFT)(XrSession, const XrSpatialGraphNodeSpaceCreateInfoMSFT *, XrSpace *);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchain)(XrSession, const XrSwapchainCreateInfo *, XrSwapchain *);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyAction)(XrAction);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyActionSet)(XrActionSet);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyHandTrackerEXT)(XrHandTrackerEXT);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyInstance)(XrInstance);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySession)(XrSession);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpace)(XrSpace);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorMSFT)(XrSpatialAnchorMSFT);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySwapchain)(XrSwapchain);
+typedef XrResult (XRAPI_PTR *PFN_xrEndFrame)(XrSession, const XrFrameEndInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrEndSession)(XrSession);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateApiLayerProperties)(uint32_t, uint32_t *, XrApiLayerProperties *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateBoundSourcesForAction)(XrSession, const XrBoundSourcesForActionEnumerateInfo *, uint32_t, uint32_t *, XrPath *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateEnvironmentBlendModes)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrEnvironmentBlendMode *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateInstanceExtensionProperties)(const char *, uint32_t, uint32_t *, XrExtensionProperties *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateReferenceSpaces)(XrSession, uint32_t, uint32_t *, XrReferenceSpaceType *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainFormats)(XrSession, uint32_t, uint32_t *, int64_t *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainImages)(XrSwapchain, uint32_t, uint32_t *, XrSwapchainImageBaseHeader *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurationViews)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrViewConfigurationView *);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurations)(XrInstance, XrSystemId, uint32_t, uint32_t *, XrViewConfigurationType *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateBoolean)(XrSession, const XrActionStateGetInfo *, XrActionStateBoolean *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateFloat)(XrSession, const XrActionStateGetInfo *, XrActionStateFloat *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStatePose)(XrSession, const XrActionStateGetInfo *, XrActionStatePose *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateVector2f)(XrSession, const XrActionStateGetInfo *, XrActionStateVector2f *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetCurrentInteractionProfile)(XrSession, XrPath, XrInteractionProfileState *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsD3D11KHR *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsD3D12KHR *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInputSourceLocalizedName)(XrSession, const XrInputSourceLocalizedNameGetInfo *, uint32_t, uint32_t *, char *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance, const char *, PFN_xrVoidFunction *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProperties)(XrInstance, XrInstanceProperties *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsOpenGLKHR *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetReferenceSpaceBoundsRect)(XrSession, XrReferenceSpaceType, XrExtent2Df *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSystem)(XrInstance, const XrSystemGetInfo *, XrSystemId *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSystemProperties)(XrInstance, XrSystemId, XrSystemProperties *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetViewConfigurationProperties)(XrInstance, XrSystemId, XrViewConfigurationType, XrViewConfigurationProperties *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVisibilityMaskKHR)(XrSession, XrViewConfigurationType, uint32_t, XrVisibilityMaskTypeKHR, XrVisibilityMaskKHR *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance, XrSystemId, VkInstance, VkPhysicalDevice *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsVulkanKHR *);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateHandJointsEXT)(XrHandTrackerEXT, const XrHandJointsLocateInfoEXT *, XrHandJointLocationsEXT *);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace, XrSpace, XrTime, XrSpaceLocation *);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateViews)(XrSession, const XrViewLocateInfo *, XrViewState *, uint32_t, uint32_t *, XrView *);
+typedef XrResult (XRAPI_PTR *PFN_xrPathToString)(XrInstance, XrPath, uint32_t, uint32_t *, char *);
+typedef XrResult (XRAPI_PTR *PFN_xrPerfSettingsSetPerformanceLevelEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsLevelEXT);
+typedef XrResult (XRAPI_PTR *PFN_xrPollEvent)(XrInstance, XrEventDataBuffer *);
+typedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain, const XrSwapchainImageReleaseInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrRequestExitSession)(XrSession);
+typedef XrResult (XRAPI_PTR *PFN_xrResultToString)(XrInstance, XrResult, char[]);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceActiveEXT)(XrSession, XrPath, XrPath, XrBool32);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceLocationEXT)(XrSession, XrPath, XrPath, XrSpace, XrPosef);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateBoolEXT)(XrSession, XrPath, XrPath, XrBool32);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateFloatEXT)(XrSession, XrPath, XrPath, float);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateVector2fEXT)(XrSession, XrPath, XrPath, XrVector2f);
+typedef XrResult (XRAPI_PTR *PFN_xrStopHapticFeedback)(XrSession, const XrHapticActionInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrStringToPath)(XrInstance, const char *, XrPath *);
+typedef XrResult (XRAPI_PTR *PFN_xrStructureTypeToString)(XrInstance, XrStructureType, char[]);
+typedef XrResult (XRAPI_PTR *PFN_xrSuggestInteractionProfileBindings)(XrInstance, const XrInteractionProfileSuggestedBinding *);
+typedef XrResult (XRAPI_PTR *PFN_xrSyncActions)(XrSession, const XrActionsSyncInfo *);
+typedef XrResult (XRAPI_PTR *PFN_xrThermalGetTemperatureTrendEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsNotificationLevelEXT *, float *, float *);
+typedef XrResult (XRAPI_PTR *PFN_xrUpdateHandMeshMSFT)(XrHandTrackerEXT, const XrHandMeshUpdateInfoMSFT *, XrHandMeshMSFT *);
+typedef XrResult (XRAPI_PTR *PFN_xrWaitFrame)(XrSession, const XrFrameWaitInfo *, XrFrameState *);
+typedef XrResult (XRAPI_PTR *PFN_xrWaitSwapchainImage)(XrSwapchain, const XrSwapchainImageWaitInfo *);
+
+#ifndef XR_NO_PROTOTYPES
+XrResult XRAPI_CALL xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo *acquireInfo, uint32_t *index);
+XrResult XRAPI_CALL xrApplyHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo, const XrHapticBaseHeader *hapticFeedback);
+XrResult XRAPI_CALL xrAttachSessionActionSets(XrSession session, const XrSessionActionSetsAttachInfo *attachInfo);
+XrResult XRAPI_CALL xrBeginFrame(XrSession session, const XrFrameBeginInfo *frameBeginInfo);
+XrResult XRAPI_CALL xrBeginSession(XrSession session, const XrSessionBeginInfo *beginInfo);
+XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, XrTime time, LARGE_INTEGER *performanceCounter);
+XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, const LARGE_INTEGER *performanceCounter, XrTime *time);
+XrResult XRAPI_CALL xrCreateAction(XrActionSet actionSet, const XrActionCreateInfo *createInfo, XrAction *action);
+XrResult XRAPI_CALL xrCreateActionSet(XrInstance instance, const XrActionSetCreateInfo *createInfo, XrActionSet *actionSet);
+XrResult XRAPI_CALL xrCreateActionSpace(XrSession session, const XrActionSpaceCreateInfo *createInfo, XrSpace *space);
+XrResult XRAPI_CALL xrCreateHandMeshSpaceMSFT(XrHandTrackerEXT handTracker, const XrHandMeshSpaceCreateInfoMSFT *createInfo, XrSpace *space);
+XrResult XRAPI_CALL xrCreateHandTrackerEXT(XrSession session, const XrHandTrackerCreateInfoEXT *createInfo, XrHandTrackerEXT *handTracker);
+XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *createInfo, XrInstance *instance);
+XrResult XRAPI_CALL xrCreateReferenceSpace(XrSession session, const XrReferenceSpaceCreateInfo *createInfo, XrSpace *space);
+XrResult XRAPI_CALL xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session);
+XrResult XRAPI_CALL xrCreateSpatialAnchorMSFT(XrSession session, const XrSpatialAnchorCreateInfoMSFT *createInfo, XrSpatialAnchorMSFT *anchor);
+XrResult XRAPI_CALL xrCreateSpatialAnchorSpaceMSFT(XrSession session, const XrSpatialAnchorSpaceCreateInfoMSFT *createInfo, XrSpace *space);
+XrResult XRAPI_CALL xrCreateSpatialGraphNodeSpaceMSFT(XrSession session, const XrSpatialGraphNodeSpaceCreateInfoMSFT *createInfo, XrSpace *space);
+XrResult XRAPI_CALL xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo *createInfo, XrSwapchain *swapchain);
+XrResult XRAPI_CALL xrDestroyAction(XrAction action);
+XrResult XRAPI_CALL xrDestroyActionSet(XrActionSet actionSet);
+XrResult XRAPI_CALL xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker);
+XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance);
+XrResult XRAPI_CALL xrDestroySession(XrSession session);
+XrResult XRAPI_CALL xrDestroySpace(XrSpace space);
+XrResult XRAPI_CALL xrDestroySpatialAnchorMSFT(XrSpatialAnchorMSFT anchor);
+XrResult XRAPI_CALL xrDestroySwapchain(XrSwapchain swapchain);
+XrResult XRAPI_CALL xrEndFrame(XrSession session, const XrFrameEndInfo *frameEndInfo);
+XrResult XRAPI_CALL xrEndSession(XrSession session);
+XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrApiLayerProperties *properties);
+XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(XrSession session, const XrBoundSourcesForActionEnumerateInfo *enumerateInfo, uint32_t sourceCapacityInput, uint32_t *sourceCountOutput, XrPath *sources);
+XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t *environmentBlendModeCountOutput, XrEnvironmentBlendMode *environmentBlendModes);
+XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties);
+XrResult XRAPI_CALL xrEnumerateReferenceSpaces(XrSession session, uint32_t spaceCapacityInput, uint32_t *spaceCountOutput, XrReferenceSpaceType *spaces);
+XrResult XRAPI_CALL xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t *formatCountOutput, int64_t *formats);
+XrResult XRAPI_CALL xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t *imageCountOutput, XrSwapchainImageBaseHeader *images);
+XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrViewConfigurationView *views);
+XrResult XRAPI_CALL xrEnumerateViewConfigurations(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t *viewConfigurationTypeCountOutput, XrViewConfigurationType *viewConfigurationTypes);
+XrResult XRAPI_CALL xrGetActionStateBoolean(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateBoolean *state);
+XrResult XRAPI_CALL xrGetActionStateFloat(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateFloat *state);
+XrResult XRAPI_CALL xrGetActionStatePose(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStatePose *state);
+XrResult XRAPI_CALL xrGetActionStateVector2f(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateVector2f *state);
+XrResult XRAPI_CALL xrGetCurrentInteractionProfile(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState *interactionProfile);
+XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements);
+XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements);
+XrResult XRAPI_CALL xrGetInputSourceLocalizedName(XrSession session, const XrInputSourceLocalizedNameGetInfo *getInfo, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer);
+XrResult XRAPI_CALL xrGetInstanceProcAddr(XrInstance instance, const char *name, PFN_xrVoidFunction *function);
+XrResult XRAPI_CALL xrGetInstanceProperties(XrInstance instance, XrInstanceProperties *instanceProperties);
+XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR *graphicsRequirements);
+XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df *bounds);
+XrResult XRAPI_CALL xrGetSystem(XrInstance instance, const XrSystemGetInfo *getInfo, XrSystemId *systemId);
+XrResult XRAPI_CALL xrGetSystemProperties(XrInstance instance, XrSystemId systemId, XrSystemProperties *properties);
+XrResult XRAPI_CALL xrGetViewConfigurationProperties(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties *configurationProperties);
+XrResult XRAPI_CALL xrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR *visibilityMask);
+XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer);
+XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice *vkPhysicalDevice);
+XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR *graphicsRequirements);
+XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer);
+XrResult XRAPI_CALL xrLocateHandJointsEXT(XrHandTrackerEXT handTracker, const XrHandJointsLocateInfoEXT *locateInfo, XrHandJointLocationsEXT *locations);
+XrResult XRAPI_CALL xrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation *location);
+XrResult XRAPI_CALL xrLocateViews(XrSession session, const XrViewLocateInfo *viewLocateInfo, XrViewState *viewState, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrView *views);
+XrResult XRAPI_CALL xrPathToString(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer);
+XrResult XRAPI_CALL xrPerfSettingsSetPerformanceLevelEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level);
+XrResult XRAPI_CALL xrPollEvent(XrInstance instance, XrEventDataBuffer *eventData);
+XrResult XRAPI_CALL xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo *releaseInfo);
+XrResult XRAPI_CALL xrRequestExitSession(XrSession session);
+XrResult XRAPI_CALL xrResultToString(XrInstance instance, XrResult value, char buffer[]);
+XrResult XRAPI_CALL xrSetInputDeviceActiveEXT(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive);
+XrResult XRAPI_CALL xrSetInputDeviceLocationEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose);
+XrResult XRAPI_CALL xrSetInputDeviceStateBoolEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state);
+XrResult XRAPI_CALL xrSetInputDeviceStateFloatEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state);
+XrResult XRAPI_CALL xrSetInputDeviceStateVector2fEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state);
+XrResult XRAPI_CALL xrStopHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo);
+XrResult XRAPI_CALL xrStringToPath(XrInstance instance, const char *pathString, XrPath *path);
+XrResult XRAPI_CALL xrStructureTypeToString(XrInstance instance, XrStructureType value, char buffer[]);
+XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(XrInstance instance, const XrInteractionProfileSuggestedBinding *suggestedBindings);
+XrResult XRAPI_CALL xrSyncActions(XrSession session, const XrActionsSyncInfo *syncInfo);
+XrResult XRAPI_CALL xrThermalGetTemperatureTrendEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsNotificationLevelEXT *notificationLevel, float *tempHeadroom, float *tempSlope);
+XrResult XRAPI_CALL xrUpdateHandMeshMSFT(XrHandTrackerEXT handTracker, const XrHandMeshUpdateInfoMSFT *updateInfo, XrHandMeshMSFT *handMesh);
+XrResult XRAPI_CALL xrWaitFrame(XrSession session, const XrFrameWaitInfo *frameWaitInfo, XrFrameState *frameState);
+XrResult XRAPI_CALL xrWaitSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageWaitInfo *waitInfo);
+#endif /* XR_NO_PROTOTYPES */
+
+#endif /* __WINE_OPENXR_H */
diff --git a/wineopenxr/wineopenxr.spec b/wineopenxr/wineopenxr.spec
new file mode 100644
index 00000000..e76d15f4
--- /dev/null
+++ b/wineopenxr/wineopenxr.spec
@@ -0,0 +1,3 @@
+@ stdcall xrNegotiateLoaderRuntimeInterface(ptr ptr) wine_xrNegotiateLoaderRuntimeInterface
+@ stdcall __wineopenxr_GetVulkanInstanceExtensions(ptr)
+@ stdcall __wineopenxr_GetVulkanDeviceExtensions(ptr)
diff --git a/wineopenxr/wineopenxr64.json b/wineopenxr/wineopenxr64.json
new file mode 100644
index 00000000..b82f743e
--- /dev/null
+++ b/wineopenxr/wineopenxr64.json
@@ -0,0 +1,6 @@
+{
+ "file_format_version": "1.0.0",
+ "runtime": {
+ "library_path": "C:\\windows\\system32\\wineopenxr.dll"
+ }
+}