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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--build_files/cmake/Modules/FindOpenXR-SDK.cmake67
-rw-r--r--build_files/cmake/Modules/presentation.cmake101
-rw-r--r--build_files/cmake/Modules/xr_platform_defines.cmake47
-rw-r--r--build_files/cmake/config/blender_full.cmake1
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/config/blender_release.cmake1
-rw-r--r--build_files/cmake/macros.cmake3
-rw-r--r--extern/CMakeLists.txt5
-rw-r--r--extern/jsoncpp/CMakeLists.txt20
-rw-r--r--extern/jsoncpp/include/json/allocator.h98
-rw-r--r--extern/jsoncpp/include/json/assertions.h54
-rw-r--r--extern/jsoncpp/include/json/autolink.h25
-rw-r--r--extern/jsoncpp/include/json/config.h184
-rw-r--r--extern/jsoncpp/include/json/features.h61
-rw-r--r--extern/jsoncpp/include/json/forwards.h37
-rw-r--r--extern/jsoncpp/include/json/json.h15
-rw-r--r--extern/jsoncpp/include/json/reader.h408
-rw-r--r--extern/jsoncpp/include/json/value.h888
-rw-r--r--extern/jsoncpp/include/json/version.h20
-rw-r--r--extern/jsoncpp/include/json/writer.h335
-rw-r--r--extern/jsoncpp/src/CMakeLists.txt80
-rw-r--r--extern/jsoncpp/src/json_reader.cpp2036
-rw-r--r--extern/jsoncpp/src/json_tool.h117
-rw-r--r--extern/jsoncpp/src/json_value.cpp1665
-rw-r--r--extern/jsoncpp/src/json_valueiterator.inl167
-rw-r--r--extern/jsoncpp/src/json_writer.cpp1223
-rw-r--r--extern/jsoncpp/src/sconscript8
-rw-r--r--extern/jsoncpp/src/version.h.in20
-rw-r--r--extern/openxr/CMakeLists.txt71
-rw-r--r--extern/openxr/LICENSE202
-rw-r--r--extern/openxr/include/CMakeLists.txt18
-rw-r--r--extern/openxr/include/openxr/CMakeLists.txt94
-rw-r--r--extern/openxr/include/openxr/openxr.h1538
-rw-r--r--extern/openxr/include/openxr/openxr_platform.h383
-rw-r--r--extern/openxr/include/openxr/openxr_platform_defines.h124
-rw-r--r--extern/openxr/include/openxr/openxr_reflection.h1004
-rw-r--r--extern/openxr/src/CMakeLists.txt194
-rw-r--r--extern/openxr/src/api_layers/CMakeLists.txt103
-rw-r--r--extern/openxr/src/api_layers/XrApiLayer_core_validation.def27
-rw-r--r--extern/openxr/src/api_layers/XrApiLayer_core_validation.json10
-rw-r--r--extern/openxr/src/api_layers/api_layer_platform_defines.h48
-rw-r--r--extern/openxr/src/api_layers/core_validation.cpp932
-rw-r--r--extern/openxr/src/api_layers/validation_utils.h324
-rw-r--r--extern/openxr/src/api_layers/xr_generated_core_validation.cpp15407
-rw-r--r--extern/openxr/src/api_layers/xr_generated_core_validation.hpp156
-rw-r--r--extern/openxr/src/cmake/FindVulkanHeaders.cmake86
-rw-r--r--extern/openxr/src/cmake/cmake_uninstall.cmake.in21
-rw-r--r--extern/openxr/src/cmake/presentation.cmake101
-rw-r--r--extern/openxr/src/common/extra_algorithms.h57
-rw-r--r--extern/openxr/src/common/filesystem_utils.cpp330
-rw-r--r--extern/openxr/src/common/filesystem_utils.hpp53
-rw-r--r--extern/openxr/src/common/hex_and_handles.cpp44
-rw-r--r--extern/openxr/src/common/hex_and_handles.h108
-rw-r--r--extern/openxr/src/common/loader_interfaces.h122
-rw-r--r--extern/openxr/src/common/platform_utils.hpp221
-rw-r--r--extern/openxr/src/common/xr_dependencies.h78
-rw-r--r--extern/openxr/src/common/xr_linear.h773
-rw-r--r--extern/openxr/src/common_cmake_config.h.in3
-rw-r--r--extern/openxr/src/loader/CMakeLists.txt183
-rw-r--r--extern/openxr/src/loader/api_layer_interface.cpp403
-rw-r--r--extern/openxr/src/loader/api_layer_interface.hpp65
-rw-r--r--extern/openxr/src/loader/exception_handling.hpp45
-rw-r--r--extern/openxr/src/loader/loader.rc98
-rw-r--r--extern/openxr/src/loader/loader_core.cpp650
-rw-r--r--extern/openxr/src/loader/loader_instance.cpp235
-rw-r--r--extern/openxr/src/loader/loader_instance.hpp155
-rw-r--r--extern/openxr/src/loader/loader_logger.cpp405
-rw-r--r--extern/openxr/src/loader/loader_logger.hpp289
-rw-r--r--extern/openxr/src/loader/loader_logger_recorders.cpp188
-rw-r--r--extern/openxr/src/loader/loader_logger_recorders.hpp40
-rw-r--r--extern/openxr/src/loader/loader_platform.hpp215
-rw-r--r--extern/openxr/src/loader/manifest_file.cpp977
-rw-r--r--extern/openxr/src/loader/manifest_file.hpp121
-rw-r--r--extern/openxr/src/loader/openxr.pc.in11
-rw-r--r--extern/openxr/src/loader/runtime_interface.cpp342
-rw-r--r--extern/openxr/src/loader/runtime_interface.hpp73
-rw-r--r--extern/openxr/src/loader/xr_generated_loader.cpp2568
-rw-r--r--extern/openxr/src/loader/xr_generated_loader.hpp307
-rw-r--r--extern/openxr/src/version.cmake41
-rw-r--r--extern/openxr/src/xr_generated_dispatch_table.c175
-rw-r--r--extern/openxr/src/xr_generated_dispatch_table.h181
-rw-r--r--extern/openxr/src/xr_generated_utilities.c488
-rw-r--r--extern/openxr/src/xr_generated_utilities.h43
-rw-r--r--intern/ghost/CMakeLists.txt39
-rw-r--r--intern/ghost/GHOST_C-api.h98
-rw-r--r--intern/ghost/GHOST_IContext.h10
-rw-r--r--intern/ghost/GHOST_ISystem.h6
-rw-r--r--intern/ghost/GHOST_IWindow.h9
-rw-r--r--intern/ghost/GHOST_IXrContext.h43
-rw-r--r--intern/ghost/GHOST_Types.h98
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp142
-rw-r--r--intern/ghost/intern/GHOST_Context.cpp65
-rw-r--r--intern/ghost/intern/GHOST_Context.h25
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm2
-rw-r--r--intern/ghost/intern/GHOST_ContextD3D.cpp500
-rw-r--r--intern/ghost/intern/GHOST_ContextD3D.h141
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp3
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h3
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.h3
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp34
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h5
-rw-r--r--intern/ghost/intern/GHOST_IXrGraphicsBinding.h73
-rw-r--r--intern/ghost/intern/GHOST_System.cpp10
-rw-r--r--intern/ghost/intern/GHOST_System.h13
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp110
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h9
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp15
-rw-r--r--intern/ghost/intern/GHOST_Window.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp14
-rw-r--r--intern/ghost/intern/GHOST_Xr.cpp64
-rw-r--r--intern/ghost/intern/GHOST_XrContext.cpp533
-rw-r--r--intern/ghost/intern/GHOST_XrContext.h111
-rw-r--r--intern/ghost/intern/GHOST_XrEvent.cpp60
-rw-r--r--intern/ghost/intern/GHOST_XrException.h47
-rw-r--r--intern/ghost/intern/GHOST_XrGraphicsBinding.cpp306
-rw-r--r--intern/ghost/intern/GHOST_XrSession.cpp554
-rw-r--r--intern/ghost/intern/GHOST_XrSession.h77
-rw-r--r--intern/ghost/intern/GHOST_Xr_intern.h123
-rw-r--r--intern/ghost/intern/GHOST_Xr_openxr_includes.h52
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py3
-rw-r--r--release/windows/batch/blender_oculus.cmd10
-rw-r--r--release/windows/batch/oculus.json7
-rw-r--r--source/blender/blenkernel/BKE_global.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenlib/BLI_math_geom.h7
-rw-r--r--source/blender/blenlib/intern/math_geom.c27
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/draw/DRW_engine.h9
-rw-r--r--source/blender/draw/intern/draw_manager.c40
-rw-r--r--source/blender/editors/include/ED_view3d.h18
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c82
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/intern/gpu_context.cpp10
-rw-r--r--source/blender/gpu/intern/gpu_context_private.h2
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c91
-rw-r--r--source/blender/gpu/intern/gpu_matrix_private.h35
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c3
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h1
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h6
-rw-r--r--source/blender/windowmanager/CMakeLists.txt7
-rw-r--r--source/blender/windowmanager/WM_api.h6
-rw-r--r--source/blender/windowmanager/intern/wm.c9
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c91
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c33
-rw-r--r--source/blender/windowmanager/intern/wm_surface.c128
-rw-r--r--source/blender/windowmanager/intern/wm_window.c247
-rw-r--r--source/blender/windowmanager/intern/wm_xr.c567
-rw-r--r--source/blender/windowmanager/wm.h11
-rw-r--r--source/blender/windowmanager/wm_surface.h57
-rw-r--r--source/blender/windowmanager/wm_window.h3
-rw-r--r--source/creator/CMakeLists.txt6
-rw-r--r--source/creator/creator_args.c24
156 files changed, 43451 insertions, 140 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 88295979fa7..efaff97ca5f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -234,6 +234,17 @@ option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
mark_as_advanced(WITH_SYSTEM_BULLET)
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
+option(WITH_OPENXR "Enable VR features through the OpenXR specification" ON)
+if(WITH_OPENXR)
+ option(OPENXR_USE_BUNDLED_SRC "Compile using the bundled OpenXR SDK sources (otherwise it has to be compiled manually)" ON)
+ if(NOT OPENXR_USE_BUNDLED_SRC)
+ find_package(OpenXR-SDK)
+ if(NOT OPENXR_SDK_FOUND)
+ message(WARNING "OpenXR-SDK was not found, disabling WITH_OPENXR")
+ set(WITH_OPENXR OFF)
+ endif()
+ endif()
+endif()
# Compositor
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
@@ -1764,6 +1775,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_CYCLES)
info_cfg_option(WITH_FREESTYLE)
info_cfg_option(WITH_OPENCOLORIO)
+ info_cfg_option(WITH_OPENXR)
info_cfg_option(WITH_OPENVDB)
info_cfg_option(WITH_ALEMBIC)
diff --git a/build_files/cmake/Modules/FindOpenXR-SDK.cmake b/build_files/cmake/Modules/FindOpenXR-SDK.cmake
new file mode 100644
index 00000000000..6682f665465
--- /dev/null
+++ b/build_files/cmake/Modules/FindOpenXR-SDK.cmake
@@ -0,0 +1,67 @@
+# - Find OpenXR-SDK library
+# Find the native OpenXR-SDK includes and library
+# This module defines
+# OPENXR_SDK_INCLUDE_DIRS, where to find OpenXR-SDK headers, Set when
+# OPENXR_SDK_INCLUDE_DIR is found.
+# OPENXR_SDK_LIBRARIES, libraries to link against to use OpenXR-SDK.
+# OPENXR_SDK_ROOT_DIR, the base directory to search for OpenXR-SDK.
+# This can also be an environment variable.
+# OPENXR_SDK_FOUND, if false, do not try to use OpenXR-SDK.
+#
+# also defined, but not for general use are
+# OPENXR_LOADER_LIBRARY, where to find the OpenXR-SDK library.
+
+#=============================================================================
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If OPENXR_SDK_ROOT_DIR was defined in the environment, use it.
+IF(NOT OPENXR_SDK_ROOT_DIR AND NOT $ENV{OPENXR_SDK_ROOT_DIR} STREQUAL "")
+ SET(OPENXR_SDK_ROOT_DIR $ENV{OPENXR_SDK_ROOT_DIR})
+ENDIF()
+
+SET(_openxr_sdk_SEARCH_DIRS
+ ${OPENXR_SDK_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+)
+
+FIND_PATH(OPENXR_SDK_INCLUDE_DIR
+ NAMES
+ openxr/openxr.h
+ HINTS
+ ${_openxr_sdk_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(OPENXR_LOADER_LIBRARY
+ NAMES
+ openxr_loader
+ HINTS
+ ${_openxr_sdk_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+)
+
+# handle the QUIETLY and REQUIRED arguments and set OPENXR_SDK_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENXR_SDK DEFAULT_MSG
+ OPENXR_LOADER_LIBRARY OPENXR_SDK_INCLUDE_DIR)
+
+IF(OPENXR_SDK_FOUND)
+ SET(OPENXR_SDK_LIBRARIES ${OPENXR_LOADER_LIBRARY})
+ SET(OPENXR_SDK_INCLUDE_DIRS ${OPENXR_SDK_INCLUDE_DIR})
+ENDIF(OPENXR_SDK_FOUND)
+
+MARK_AS_ADVANCED(
+ OPENXR_SDK_INCLUDE_DIR
+ OPENXR_LOADER_LIBRARY
+)
diff --git a/build_files/cmake/Modules/presentation.cmake b/build_files/cmake/Modules/presentation.cmake
new file mode 100644
index 00000000000..1abcc0e66f7
--- /dev/null
+++ b/build_files/cmake/Modules/presentation.cmake
@@ -0,0 +1,101 @@
+set(PRESENTATION_BACKENDS xlib xcb wayland)
+set(PRESENTATION_BACKEND xlib CACHE STRING
+ "Presentation backend chosen at configure time")
+set_property(CACHE PRESENTATION_BACKEND PROPERTY STRINGS
+ ${PRESENTATION_BACKENDS})
+
+list(FIND PRESENTATION_BACKENDS ${PRESENTATION_BACKEND} index)
+if(index EQUAL -1)
+ message(FATAL_ERROR "Presentation backend must be one of
+ ${PRESENTATION_BACKENDS}")
+endif()
+
+message(STATUS "Using presentation backend: ${PRESENTATION_BACKEND}")
+
+
+if( PRESENTATION_BACKEND MATCHES "xlib" )
+ find_package(X11 REQUIRED)
+ if ((NOT X11_Xxf86vm_LIB) OR (NOT X11_Xrandr_LIB))
+ message(FATAL_ERROR "OpenXR xlib backend requires Xxf86vm and Xrandr")
+ endif()
+
+ add_definitions( -DSUPPORT_X )
+ add_definitions( -DOS_LINUX_XLIB )
+ set( XLIB_LIBRARIES
+ ${X11_LIBRARIES}
+ ${X11_Xxf86vm_LIB}
+ ${X11_Xrandr_LIB} )
+
+elseif( PRESENTATION_BACKEND MATCHES "xcb" )
+ find_package(PkgConfig REQUIRED)
+ # XCB + XCB GLX is limited to OpenGL 2.1
+ # add_definitions( -DOS_LINUX_XCB )
+ # XCB + Xlib GLX 1.3
+ add_definitions( -DOS_LINUX_XCB_GLX )
+
+ pkg_search_module(X11 REQUIRED x11)
+ pkg_search_module(XCB REQUIRED xcb)
+ pkg_search_module(XCB_RANDR REQUIRED xcb-randr)
+ pkg_search_module(XCB_KEYSYMS REQUIRED xcb-keysyms)
+ pkg_search_module(XCB_GLX REQUIRED xcb-glx)
+ pkg_search_module(XCB_DRI2 REQUIRED xcb-dri2)
+ pkg_search_module(XCB_ICCCM REQUIRED xcb-icccm)
+
+ set( XCB_LIBRARIES
+ ${XCB_LIBRARIES}
+ ${XCB_KEYSYMS_LIBRARIES}
+ ${XCB_RANDR_LIBRARIES}
+ ${XCB_GLX_LIBRARIES}
+ ${XCB_DRI2_LIBRARIES}
+ ${X11_LIBRARIES} )
+
+elseif( PRESENTATION_BACKEND MATCHES "wayland" )
+ find_package(PkgConfig REQUIRED)
+ pkg_search_module(WAYLAND_CLIENT REQUIRED wayland-client)
+ pkg_search_module(WAYLAND_EGL REQUIRED wayland-egl)
+ pkg_search_module(WAYLAND_SCANNER REQUIRED wayland-scanner)
+ pkg_search_module(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.7)
+ pkg_search_module(EGL REQUIRED egl)
+
+ add_definitions( -DOS_LINUX_WAYLAND )
+ set( WAYLAND_LIBRARIES
+ ${EGL_LIBRARIES}
+ ${WAYLAND_CLIENT_LIBRARIES}
+ ${WAYLAND_EGL_LIBRARIES} )
+
+ # generate wayland protocols
+ set(WAYLAND_PROTOCOLS_DIR ${CMAKE_SOURCE_DIR}/wayland-protocols/)
+ file(MAKE_DIRECTORY ${WAYLAND_PROTOCOLS_DIR})
+
+ pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir)
+ pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
+
+ set(PROTOCOL xdg-shell-unstable-v6)
+ set(PROTOCOL_XML
+ ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/${PROTOCOL}.xml)
+
+ if( EXISTS ${PROTOCOL_XML} )
+ execute_process(COMMAND
+ ${WAYLAND_SCANNER}
+ code
+ ${PROTOCOL_XML}
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c)
+ execute_process(COMMAND
+ ${WAYLAND_SCANNER}
+ client-header
+ ${PROTOCOL_XML}
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h)
+
+ set( WAYLAND_PROTOCOL_SRC
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h )
+
+ include_directories(${WAYLAND_PROTOCOLS_DIR})
+ else()
+ message(FATAL_ERROR
+ "xdg-shell-unstable-v6.xml not found in "
+ ${WAYLAND_PROTOCOLS_DATADIR}
+ "\nYour wayland-protocols package does not "
+ "contain xdg-shell-unstable-v6.")
+ endif()
+endif()
diff --git a/build_files/cmake/Modules/xr_platform_defines.cmake b/build_files/cmake/Modules/xr_platform_defines.cmake
new file mode 100644
index 00000000000..cb1740a993d
--- /dev/null
+++ b/build_files/cmake/Modules/xr_platform_defines.cmake
@@ -0,0 +1,47 @@
+# Copyright (c) 2017 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+if(WIN32)
+ add_definitions(-DXR_OS_WINDOWS)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ add_definitions(-DXR_OS_LINUX)
+endif()
+
+# Determine the presentation backend for Linux systems.
+# Use an include because the code is pretty big.
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ include(presentation)
+endif()
+
+# Several files use these compile-time platform switches
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_definitions( -DXR_USE_PLATFORM_WIN32 )
+elseif( PRESENTATION_BACKEND MATCHES "xlib" )
+ add_definitions( -DXR_USE_PLATFORM_XLIB )
+elseif( PRESENTATION_BACKEND MATCHES "xcb" )
+ add_definitions( -DXR_USE_PLATFORM_XCB )
+elseif( PRESENTATION_BACKEND MATCHES "wayland" )
+ add_definitions( -DXR_USE_PLATFORM_WAYLAND )
+endif()
+
+add_definitions(-DXR_USE_GRAPHICS_API_OPENGL)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D)
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D10)
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D11)
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D12)
+endif()
+
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 6786cb5ce37..6523fc97126 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -40,6 +40,7 @@ set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
+set(WITH_OPENXR ON CACHE BOOL "" FORCE)
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index b85176d37f3..38a500dbfa8 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -45,6 +45,7 @@ set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
+set(WITH_OPENXR OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index 24032b6aed6..eeaa158e9e8 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -41,6 +41,7 @@ set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
+set(WITH_OPENXR ON CACHE BOOL "" FORCE)
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index c2f608de921..55adaee77fc 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -468,6 +468,9 @@ function(setup_liblinks
if(WITH_OPENSUBDIV)
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
endif()
+ if(WITH_OPENXR)
+ target_link_libraries(${target} ${OPENXR_SDK_LIBRARIES})
+ endif()
if(WITH_CYCLES_EMBREE)
target_link_libraries(${target} ${EMBREE_LIBRARIES})
endif()
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 3b2a8c172aa..104ac4307ca 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -105,3 +105,8 @@ if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
set(AUDASPACE_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/audaspace/blender_config.cmake)
add_subdirectory(audaspace)
endif()
+
+if(WITH_OPENXR AND OPENXR_USE_BUNDLED_SRC)
+ add_subdirectory(jsoncpp)
+ add_subdirectory(openxr)
+endif()
diff --git a/extern/jsoncpp/CMakeLists.txt b/extern/jsoncpp/CMakeLists.txt
new file mode 100644
index 00000000000..2890433dbce
--- /dev/null
+++ b/extern/jsoncpp/CMakeLists.txt
@@ -0,0 +1,20 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+add_subdirectory(src)
diff --git a/extern/jsoncpp/include/json/allocator.h b/extern/jsoncpp/include/json/allocator.h
new file mode 100644
index 00000000000..2492758cd71
--- /dev/null
+++ b/extern/jsoncpp/include/json/allocator.h
@@ -0,0 +1,98 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
+#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push, 8)
+
+namespace Json {
+template<typename T>
+class SecureAllocator {
+ public:
+ // Type definitions
+ using value_type = T;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ /**
+ * Allocate memory for N items using the standard allocator.
+ */
+ pointer allocate(size_type n) {
+ // allocate using "global operator new"
+ return static_cast<pointer>(::operator new(n * sizeof(T)));
+ }
+
+ /**
+ * Release memory which was allocated for N items at pointer P.
+ *
+ * The memory block is filled with zeroes before being released.
+ * The pointer argument is tagged as "volatile" to prevent the
+ * compiler optimizing out this critical step.
+ */
+ void deallocate(volatile pointer p, size_type n) {
+ std::memset(p, 0, n * sizeof(T));
+ // free using "global operator delete"
+ ::operator delete(p);
+ }
+
+ /**
+ * Construct an item in-place at pointer P.
+ */
+ template<typename... Args>
+ void construct(pointer p, Args&&... args) {
+ // construct using "placement new" and "perfect forwarding"
+ ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+ }
+
+ size_type max_size() const {
+ return size_t(-1) / sizeof(T);
+ }
+
+ pointer address( reference x ) const {
+ return std::addressof(x);
+ }
+
+ const_pointer address( const_reference x ) const {
+ return std::addressof(x);
+ }
+
+ /**
+ * Destroy an item in-place at pointer P.
+ */
+ void destroy(pointer p) {
+ // destroy using "explicit destructor"
+ p->~T();
+ }
+
+ // Boilerplate
+ SecureAllocator() {}
+ template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
+ template<typename U> struct rebind { using other = SecureAllocator<U>; };
+};
+
+
+template<typename T, typename U>
+bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+ return true;
+}
+
+template<typename T, typename U>
+bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+ return false;
+}
+
+} //namespace Json
+
+#pragma pack(pop)
+
+#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/assertions.h b/extern/jsoncpp/include/json/assertions.h
new file mode 100644
index 00000000000..9c5f8bc0fe5
--- /dev/null
+++ b/extern/jsoncpp/include/json/assertions.h
@@ -0,0 +1,54 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
+
+#include <stdlib.h>
+#include <sstream>
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+/** It should not be possible for a maliciously designed file to
+ * cause an abort() or seg-fault, so these macros are used only
+ * for pre-condition violations and internal logic errors.
+ */
+#if JSON_USE_EXCEPTION
+
+// @todo <= add detail about condition in exception
+# define JSON_ASSERT(condition) \
+ {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
+
+# define JSON_FAIL_MESSAGE(message) \
+ { \
+ JSONCPP_OSTRINGSTREAM oss; oss << message; \
+ Json::throwLogicError(oss.str()); \
+ abort(); \
+ }
+
+#else // JSON_USE_EXCEPTION
+
+# define JSON_ASSERT(condition) assert(condition)
+
+// The call to assert() will show the failure message in debug builds. In
+// release builds we abort, for a core-dump or debugger.
+# define JSON_FAIL_MESSAGE(message) \
+ { \
+ JSONCPP_OSTRINGSTREAM oss; oss << message; \
+ assert(false && oss.str().c_str()); \
+ abort(); \
+ }
+
+
+#endif
+
+#define JSON_ASSERT_MESSAGE(condition, message) \
+ if (!(condition)) { \
+ JSON_FAIL_MESSAGE(message); \
+ }
+
+#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/autolink.h b/extern/jsoncpp/include/json/autolink.h
new file mode 100644
index 00000000000..6fcc8afac57
--- /dev/null
+++ b/extern/jsoncpp/include/json/autolink.h
@@ -0,0 +1,25 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_AUTOLINK_H_INCLUDED
+#define JSON_AUTOLINK_H_INCLUDED
+
+#include "config.h"
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/cpptl_autolink.h>
+#endif
+
+#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \
+ !defined(JSON_IN_CPPTL)
+#define CPPTL_AUTOLINK_NAME "json"
+#undef CPPTL_AUTOLINK_DLL
+#ifdef JSON_DLL
+#define CPPTL_AUTOLINK_DLL
+#endif
+#include "autolink.h"
+#endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/config.h b/extern/jsoncpp/include/json/config.h
new file mode 100644
index 00000000000..6e3f3ac647e
--- /dev/null
+++ b/extern/jsoncpp/include/json/config.h
@@ -0,0 +1,184 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+#include <stddef.h>
+#include <string> //typedef String
+#include <stdint.h> //typedef int64_t, uint64_t
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//# define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of
+/// std::map
+/// as Value container.
+//# define JSON_USE_CPPTL_SMALLMAP 1
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/config.h>
+#ifndef JSON_USE_CPPTL
+#define JSON_USE_CPPTL 1
+#endif
+#endif
+
+#ifdef JSON_IN_CPPTL
+#define JSON_API CPPTL_API
+#elif defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_IN_CPPTL
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER) // MSVC
+# if _MSC_VER <= 1200 // MSVC 6
+ // Microsoft Visual Studio 6 only support conversion from __int64 to double
+ // (no conversion from unsigned __int64).
+# define JSON_USE_INT64_DOUBLE_CONVERSION 1
+ // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+ // characters in the debug information)
+ // All projects I've ever seen with VS6 were using this globally (not bothering
+ // with pragma push/pop).
+# pragma warning(disable : 4786)
+# endif // MSVC 6
+
+# if _MSC_VER >= 1500 // MSVC 2008
+ /// Indicates that the following function is deprecated.
+# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+# endif
+
+#endif // defined(_MSC_VER)
+
+// In c++11 the override keyword allows you to explicity define that a function
+// is intended to override the base-class version. This makes the code more
+// managable and fixes a set of common hard-to-find bugs.
+#if __cplusplus >= 201103L
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT noexcept
+#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT throw()
+#elif defined(_MSC_VER) && _MSC_VER >= 1900
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT noexcept
+#else
+# define JSONCPP_OVERRIDE
+# define JSONCPP_NOEXCEPT throw()
+#endif
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#ifdef __clang__
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
+# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+# endif // GNUC version
+#endif // __clang__ || __GNUC__
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+#if __GNUC__ >= 6
+# define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+# include "version.h"
+
+# if JSONCPP_USING_SECURE_MEMORY
+# include "allocator.h" //typedef Allocator
+# endif
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+typedef int Int;
+typedef unsigned int UInt;
+#if defined(JSON_NO_INT64)
+typedef int LargestInt;
+typedef unsigned int LargestUInt;
+#undef JSON_HAS_INT64
+#else // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else // if defined(_MSC_VER) // Other platforms, use long long
+typedef int64_t Int64;
+typedef uint64_t UInt64;
+#endif // if defined(_MSC_VER)
+typedef Int64 LargestInt;
+typedef UInt64 LargestUInt;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+#if JSONCPP_USING_SECURE_MEMORY
+#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
+#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_ISTREAM std::istream
+#else
+#define JSONCPP_STRING std::string
+#define JSONCPP_OSTRINGSTREAM std::ostringstream
+#define JSONCPP_OSTREAM std::ostream
+#define JSONCPP_ISTRINGSTREAM std::istringstream
+#define JSONCPP_ISTREAM std::istream
+#endif // if JSONCPP_USING_SECURE_MEMORY
+} // end namespace Json
+
+#endif // JSON_CONFIG_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/features.h b/extern/jsoncpp/include/json/features.h
new file mode 100644
index 00000000000..de45248fb31
--- /dev/null
+++ b/extern/jsoncpp/include/json/features.h
@@ -0,0 +1,61 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+#define CPPTL_JSON_FEATURES_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+#pragma pack(push, 8)
+
+namespace Json {
+
+/** \brief Configuration passed to reader and writer.
+ * This configuration object can be used to force the Reader or Writer
+ * to behave in a standard conforming way.
+ */
+class JSON_API Features {
+public:
+ /** \brief A configuration that allows all features and assumes all strings
+ * are UTF-8.
+ * - C & C++ comments are allowed
+ * - Root object can be any JSON value
+ * - Assumes Value strings are encoded in UTF-8
+ */
+ static Features all();
+
+ /** \brief A configuration that is strictly compatible with the JSON
+ * specification.
+ * - Comments are forbidden.
+ * - Root object must be either an array or an object value.
+ * - Assumes Value strings are encoded in UTF-8
+ */
+ static Features strictMode();
+
+ /** \brief Initialize the configuration like JsonConfig::allFeatures;
+ */
+ Features();
+
+ /// \c true if comments are allowed. Default: \c true.
+ bool allowComments_;
+
+ /// \c true if root must be either an array or an object value. Default: \c
+ /// false.
+ bool strictRoot_;
+
+ /// \c true if dropped null placeholders are allowed. Default: \c false.
+ bool allowDroppedNullPlaceholders_;
+
+ /// \c true if numeric object key are allowed. Default: \c false.
+ bool allowNumericKeys_;
+};
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/forwards.h b/extern/jsoncpp/include/json/forwards.h
new file mode 100644
index 00000000000..ccfe09abf4b
--- /dev/null
+++ b/extern/jsoncpp/include/json/forwards.h
@@ -0,0 +1,37 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class FastWriter;
+class StyledWriter;
+
+// reader.h
+class Reader;
+
+// features.h
+class Features;
+
+// value.h
+typedef unsigned int ArrayIndex;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/json.h b/extern/jsoncpp/include/json/json.h
new file mode 100644
index 00000000000..8f10ac2bf72
--- /dev/null
+++ b/extern/jsoncpp/include/json/json.h
@@ -0,0 +1,15 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_JSON_H_INCLUDED
+#define JSON_JSON_H_INCLUDED
+
+#include "autolink.h"
+#include "value.h"
+#include "reader.h"
+#include "writer.h"
+#include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/reader.h b/extern/jsoncpp/include/json/reader.h
new file mode 100644
index 00000000000..6ab5bdbf799
--- /dev/null
+++ b/extern/jsoncpp/include/json/reader.h
@@ -0,0 +1,408 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+#define CPPTL_JSON_READER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "features.h"
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <deque>
+#include <iosfwd>
+#include <stack>
+#include <string>
+#include <istream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
+namespace Json {
+
+/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
+ *Value.
+ *
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+class JSON_API Reader {
+public:
+ typedef char Char;
+ typedef const Char* Location;
+
+ /** \brief An error tagged with where in the JSON text it was encountered.
+ *
+ * The offsets give the [start, limit) range of bytes within the text. Note
+ * that this is bytes, not codepoints.
+ *
+ */
+ struct StructuredError {
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ JSONCPP_STRING message;
+ };
+
+ /** \brief Constructs a Reader allowing all features
+ * for parsing.
+ */
+ Reader();
+
+ /** \brief Constructs a Reader allowing the specified feature set
+ * for parsing.
+ */
+ Reader(const Features& features);
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+ * document.
+ * \param document UTF-8 encoded string containing the document to read.
+ * \param root [out] Contains the root value of the document if it was
+ * successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing them
+ * back during
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if
+ * Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an
+ * error occurred.
+ */
+ bool
+ parse(const std::string& document, Value& root, bool collectComments = true);
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+ document.
+ * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+ document to read.
+ * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+ document to read.
+ * Must be >= beginDoc.
+ * \param root [out] Contains the root value of the document if it was
+ * successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing them
+ back during
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if
+ Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an
+ error occurred.
+ */
+ bool parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments = true);
+
+ /// \brief Parse from input stream.
+ /// \see Json::operator>>(std::istream&, Json::Value&).
+ bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
+
+ /** \brief Returns a user friendly string that list errors in the parsed
+ * document.
+ * \return Formatted error message with the list of errors with their location
+ * in
+ * the parsed document. An empty string is returned if no error
+ * occurred
+ * during parsing.
+ * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+ */
+ JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
+ JSONCPP_STRING getFormatedErrorMessages() const;
+
+ /** \brief Returns a user friendly string that list errors in the parsed
+ * document.
+ * \return Formatted error message with the list of errors with their location
+ * in
+ * the parsed document. An empty string is returned if no error
+ * occurred
+ * during parsing.
+ */
+ JSONCPP_STRING getFormattedErrorMessages() const;
+
+ /** \brief Returns a vector of structured erros encounted while parsing.
+ * \return A (possibly empty) vector of StructuredError objects. Currently
+ * only one error can be returned, but the caller should tolerate
+ * multiple
+ * errors. This can occur if the parser recovers from a non-fatal
+ * parse error and then encounters additional errors.
+ */
+ std::vector<StructuredError> getStructuredErrors() const;
+
+ /** \brief Add a semantic error message.
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \return \c true if the error was successfully added, \c false if the
+ * Value offset exceeds the document size.
+ */
+ bool pushError(const Value& value, const JSONCPP_STRING& message);
+
+ /** \brief Add a semantic error message with extra context.
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \param extra Additional JSON Value location to contextualize the error
+ * \return \c true if the error was successfully added, \c false if either
+ * Value offset exceeds the document size.
+ */
+ bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+
+ /** \brief Return whether there are any errors.
+ * \return \c true if there are no errors to report \c false if
+ * errors have occurred.
+ */
+ bool good() const;
+
+private:
+ enum TokenType {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo {
+ public:
+ Token token_;
+ JSONCPP_STRING message_;
+ Location extra_;
+ };
+
+ typedef std::deque<ErrorInfo> Errors;
+
+ bool readToken(Token& token);
+ void skipSpaces();
+ bool match(Location pattern, int patternLength);
+ bool readComment();
+ bool readCStyleComment();
+ bool readCppStyleComment();
+ bool readString();
+ void readNumber();
+ bool readValue();
+ bool readObject(Token& token);
+ bool readArray(Token& token);
+ bool decodeNumber(Token& token);
+ bool decodeNumber(Token& token, Value& decoded);
+ bool decodeString(Token& token);
+ bool decodeString(Token& token, JSONCPP_STRING& decoded);
+ bool decodeDouble(Token& token);
+ bool decodeDouble(Token& token, Value& decoded);
+ bool decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+ bool recoverFromError(TokenType skipUntilToken);
+ bool addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
+ TokenType skipUntilToken);
+ void skipUntilSpace();
+ Value& currentValue();
+ Char getNextChar();
+ void
+ getLocationLineAndColumn(Location location, int& line, int& column) const;
+ JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+ void addComment(Location begin, Location end, CommentPlacement placement);
+ void skipCommentTokens(Token& token);
+
+ typedef std::stack<Value*> Nodes;
+ Nodes nodes_;
+ Errors errors_;
+ JSONCPP_STRING document_;
+ Location begin_;
+ Location end_;
+ Location current_;
+ Location lastValueEnd_;
+ Value* lastValue_;
+ JSONCPP_STRING commentsBefore_;
+ Features features_;
+ bool collectComments_;
+}; // Reader
+
+/** Interface for reading JSON from a char array.
+ */
+class JSON_API CharReader {
+public:
+ virtual ~CharReader() {}
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+ document.
+ * The document must be a UTF-8 encoded string containing the document to read.
+ *
+ * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+ document to read.
+ * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+ document to read.
+ * Must be >= beginDoc.
+ * \param root [out] Contains the root value of the document if it was
+ * successfully parsed.
+ * \param errs [out] Formatted error messages (if not NULL)
+ * a user friendly string that lists errors in the parsed
+ * document.
+ * \return \c true if the document was successfully parsed, \c false if an
+ error occurred.
+ */
+ virtual bool parse(
+ char const* beginDoc, char const* endDoc,
+ Value* root, JSONCPP_STRING* errs) = 0;
+
+ class JSON_API Factory {
+ public:
+ virtual ~Factory() {}
+ /** \brief Allocate a CharReader via operator new().
+ * \throw std::exception if something goes wrong (e.g. invalid settings)
+ */
+ virtual CharReader* newCharReader() const = 0;
+ }; // Factory
+}; // CharReader
+
+/** \brief Build a CharReader implementation.
+
+Usage:
+\code
+ using namespace Json;
+ CharReaderBuilder builder;
+ builder["collectComments"] = false;
+ Value value;
+ JSONCPP_STRING errs;
+ bool ok = parseFromStream(builder, std::cin, &value, &errs);
+\endcode
+*/
+class JSON_API CharReaderBuilder : public CharReader::Factory {
+public:
+ // Note: We use a Json::Value so that we can add data-members to this class
+ // without a major version bump.
+ /** Configuration of this builder.
+ These are case-sensitive.
+ Available settings (case-sensitive):
+ - `"collectComments": false or true`
+ - true to collect comment and allow writing them
+ back during serialization, false to discard comments.
+ This parameter is ignored if allowComments is false.
+ - `"allowComments": false or true`
+ - true if comments are allowed.
+ - `"strictRoot": false or true`
+ - true if root must be either an array or an object value
+ - `"allowDroppedNullPlaceholders": false or true`
+ - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
+ - `"allowNumericKeys": false or true`
+ - true if numeric object keys are allowed.
+ - `"allowSingleQuotes": false or true`
+ - true if '' are allowed for strings (both keys and values)
+ - `"stackLimit": integer`
+ - Exceeding stackLimit (recursive depth of `readValue()`) will
+ cause an exception.
+ - This is a security issue (seg-faults caused by deeply nested JSON),
+ so the default is low.
+ - `"failIfExtra": false or true`
+ - If true, `parse()` returns false when extra non-whitespace trails
+ the JSON value in the input string.
+ - `"rejectDupKeys": false or true`
+ - If true, `parse()` returns false when a key is duplicated within an object.
+ - `"allowSpecialFloats": false or true`
+ - If true, special float values (NaNs and infinities) are allowed
+ and their values are lossfree restorable.
+
+ You can examine 'settings_` yourself
+ to see the defaults. You can also write and read them just like any
+ JSON Value.
+ \sa setDefaults()
+ */
+ Json::Value settings_;
+
+ CharReaderBuilder();
+ ~CharReaderBuilder() JSONCPP_OVERRIDE;
+
+ CharReader* newCharReader() const JSONCPP_OVERRIDE;
+
+ /** \return true if 'settings' are legal and consistent;
+ * otherwise, indicate bad settings via 'invalid'.
+ */
+ bool validate(Json::Value* invalid) const;
+
+ /** A simple way to update a specific setting.
+ */
+ Value& operator[](JSONCPP_STRING key);
+
+ /** Called by ctor, but you can use this to reset settings_.
+ * \pre 'settings' != NULL (but Json::null is fine)
+ * \remark Defaults:
+ * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+ */
+ static void setDefaults(Json::Value* settings);
+ /** Same as old Features::strictMode().
+ * \pre 'settings' != NULL (but Json::null is fine)
+ * \remark Defaults:
+ * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+ */
+ static void strictMode(Json::Value* settings);
+};
+
+/** Consume entire stream and use its begin/end.
+ * Someday we might have a real StreamReader, but for now this
+ * is convenient.
+ */
+bool JSON_API parseFromStream(
+ CharReader::Factory const&,
+ JSONCPP_ISTREAM&,
+ Value* root, std::string* errs);
+
+/** \brief Read from 'sin' into 'root'.
+
+ Always keep comments from the input JSON.
+
+ This can be used to read a file into a particular sub-object.
+ For example:
+ \code
+ Json::Value root;
+ cin >> root["dir"]["file"];
+ cout << root;
+ \endcode
+ Result:
+ \verbatim
+ {
+ "dir": {
+ "file": {
+ // The input stream JSON would be nested here.
+ }
+ }
+ }
+ \endverbatim
+ \throw std::exception on parse error.
+ \see Json::operator<<()
+*/
+JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/value.h b/extern/jsoncpp/include/json/value.h
new file mode 100644
index 00000000000..ba7365c325e
--- /dev/null
+++ b/extern/jsoncpp/include/json/value.h
@@ -0,0 +1,888 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_H_INCLUDED
+#define CPPTL_JSON_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <string>
+#include <vector>
+#include <exception>
+
+#ifndef JSON_USE_CPPTL_SMALLMAP
+#include <map>
+#else
+#include <cpptl/smallmap.h>
+#endif
+#ifdef JSON_USE_CPPTL
+#include <cpptl/forwards.h>
+#endif
+
+//Conditional NORETURN attribute on the throw functions would:
+// a) suppress false positives from static code analysis
+// b) possibly improve optimization opportunities.
+#if !defined(JSONCPP_NORETURN)
+# if defined(_MSC_VER)
+# define JSONCPP_NORETURN __declspec(noreturn)
+# elif defined(__GNUC__)
+# define JSONCPP_NORETURN __attribute__ ((__noreturn__))
+# else
+# define JSONCPP_NORETURN
+# endif
+#endif
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+/** Base class for all exceptions we throw.
+ *
+ * We use nothing but these internally. Of course, STL can throw others.
+ */
+class JSON_API Exception : public std::exception {
+public:
+ Exception(JSONCPP_STRING const& msg);
+ ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+ char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+protected:
+ JSONCPP_STRING msg_;
+};
+
+/** Exceptions which the user cannot easily avoid.
+ *
+ * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
+ *
+ * \remark derived from Json::Exception
+ */
+class JSON_API RuntimeError : public Exception {
+public:
+ RuntimeError(JSONCPP_STRING const& msg);
+};
+
+/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
+ *
+ * These are precondition-violations (user bugs) and internal errors (our bugs).
+ *
+ * \remark derived from Json::Exception
+ */
+class JSON_API LogicError : public Exception {
+public:
+ LogicError(JSONCPP_STRING const& msg);
+};
+
+/// used internally
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
+/// used internally
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
+
+/** \brief Type of the value held by a Value object.
+ */
+enum ValueType {
+ nullValue = 0, ///< 'null' value
+ intValue, ///< signed integer value
+ uintValue, ///< unsigned integer value
+ realValue, ///< double value
+ stringValue, ///< UTF-8 string value
+ booleanValue, ///< bool value
+ arrayValue, ///< array value (ordered list)
+ objectValue ///< object value (collection of name/value pairs).
+};
+
+enum CommentPlacement {
+ commentBefore = 0, ///< a comment placed on the line before a value
+ commentAfterOnSameLine, ///< a comment just after a value on the same line
+ commentAfter, ///< a comment on the line after a value (only make sense for
+ /// root value)
+ numberOfCommentPlacement
+};
+
+//# ifdef JSON_USE_CPPTL
+// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+/** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignement takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+class JSON_API StaticString {
+public:
+ explicit StaticString(const char* czstring) : c_str_(czstring) {}
+
+ operator const char*() const { return c_str_; }
+
+ const char* c_str() const { return c_str_; }
+
+private:
+ const char* c_str_;
+};
+
+/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * Values of an #objectValue or #arrayValue can be accessed using operator[]()
+ * methods.
+ * Non-const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resized and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtain default value in the case the
+ * required element does not exist.
+ *
+ * It is possible to iterate over the list of a #objectValue values using
+ * the getMemberNames() method.
+ *
+ * \note #Value string-length fit in size_t, but keys must be < 2^30.
+ * (The reason is an implementation detail.) A #CharReader will raise an
+ * exception if a bound is exceeded to avoid security holes in your app,
+ * but the Value API does *not* check bounds. That is the responsibility
+ * of the caller.
+ */
+class JSON_API Value {
+ friend class ValueIteratorBase;
+public:
+ typedef std::vector<JSONCPP_STRING> Members;
+ typedef ValueIterator iterator;
+ typedef ValueConstIterator const_iterator;
+ typedef Json::UInt UInt;
+ typedef Json::Int Int;
+#if defined(JSON_HAS_INT64)
+ typedef Json::UInt64 UInt64;
+ typedef Json::Int64 Int64;
+#endif // defined(JSON_HAS_INT64)
+ typedef Json::LargestInt LargestInt;
+ typedef Json::LargestUInt LargestUInt;
+ typedef Json::ArrayIndex ArrayIndex;
+
+ static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
+ static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
+ static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
+
+ /// Minimum signed integer value that can be stored in a Json::Value.
+ static const LargestInt minLargestInt;
+ /// Maximum signed integer value that can be stored in a Json::Value.
+ static const LargestInt maxLargestInt;
+ /// Maximum unsigned integer value that can be stored in a Json::Value.
+ static const LargestUInt maxLargestUInt;
+
+ /// Minimum signed int value that can be stored in a Json::Value.
+ static const Int minInt;
+ /// Maximum signed int value that can be stored in a Json::Value.
+ static const Int maxInt;
+ /// Maximum unsigned int value that can be stored in a Json::Value.
+ static const UInt maxUInt;
+
+#if defined(JSON_HAS_INT64)
+ /// Minimum signed 64 bits int value that can be stored in a Json::Value.
+ static const Int64 minInt64;
+ /// Maximum signed 64 bits int value that can be stored in a Json::Value.
+ static const Int64 maxInt64;
+ /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
+ static const UInt64 maxUInt64;
+#endif // defined(JSON_HAS_INT64)
+
+private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+ class CZString {
+ public:
+ enum DuplicationPolicy {
+ noDuplication = 0,
+ duplicate,
+ duplicateOnCopy
+ };
+ CZString(ArrayIndex index);
+ CZString(char const* str, unsigned length, DuplicationPolicy allocate);
+ CZString(CZString const& other);
+#if JSON_HAS_RVALUE_REFERENCES
+ CZString(CZString&& other);
+#endif
+ ~CZString();
+ CZString& operator=(const CZString& other);
+
+#if JSON_HAS_RVALUE_REFERENCES
+ CZString& operator=(CZString&& other);
+#endif
+
+ bool operator<(CZString const& other) const;
+ bool operator==(CZString const& other) const;
+ ArrayIndex index() const;
+ //const char* c_str() const; ///< \deprecated
+ char const* data() const;
+ unsigned length() const;
+ bool isStaticString() const;
+
+ private:
+ void swap(CZString& other);
+
+ struct StringStorage {
+ unsigned policy_: 2;
+ unsigned length_: 30; // 1GB max
+ };
+
+ char const* cstr_; // actually, a prefixed string, unless policy is noDup
+ union {
+ ArrayIndex index_;
+ StringStorage storage_;
+ };
+ };
+
+public:
+#ifndef JSON_USE_CPPTL_SMALLMAP
+ typedef std::map<CZString, Value> ObjectValues;
+#else
+ typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#endif // ifndef JSON_USE_CPPTL_SMALLMAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+public:
+ /** \brief Create a default Value of the given type.
+
+ This is a very useful constructor.
+ To create an empty array, pass arrayValue.
+ To create an empty object, pass objectValue.
+ Another Value can then be set to this one by assignment.
+This is useful since clear() and resize() will not alter types.
+
+ Examples:
+\code
+Json::Value null_value; // null
+Json::Value arr_value(Json::arrayValue); // []
+Json::Value obj_value(Json::objectValue); // {}
+\endcode
+ */
+ Value(ValueType type = nullValue);
+ Value(Int value);
+ Value(UInt value);
+#if defined(JSON_HAS_INT64)
+ Value(Int64 value);
+ Value(UInt64 value);
+#endif // if defined(JSON_HAS_INT64)
+ Value(double value);
+ Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
+ Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
+ /** \brief Constructs a value from a static string.
+
+ * Like other value string constructor but do not duplicate the string for
+ * internal storage. The given string must remain alive after the call to this
+ * constructor.
+ * \note This works only for null-terminated strings. (We cannot change the
+ * size of this class, so we have nowhere to store the length,
+ * which might be computed later for various operations.)
+ *
+ * Example of usage:
+ * \code
+ * static StaticString foo("some text");
+ * Json::Value aValue(foo);
+ * \endcode
+ */
+ Value(const StaticString& value);
+ Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
+#ifdef JSON_USE_CPPTL
+ Value(const CppTL::ConstString& value);
+#endif
+ Value(bool value);
+ /// Deep copy.
+ Value(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+ /// Move constructor
+ Value(Value&& other);
+#endif
+ ~Value();
+
+ /// Deep copy, then swap(other).
+ /// \note Over-write existing comments. To preserve comments, use #swapPayload().
+ Value& operator=(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+ Value& operator=(Value&& other);
+#endif
+
+ /// Swap everything.
+ void swap(Value& other);
+ /// Swap values but leave comments and source offsets in place.
+ void swapPayload(Value& other);
+
+ /// copy everything.
+ void copy(const Value& other);
+ /// copy values but leave comments and source offsets in place.
+ void copyPayload(const Value& other);
+
+ ValueType type() const;
+
+ /// Compare payload only, not comments etc.
+ bool operator<(const Value& other) const;
+ bool operator<=(const Value& other) const;
+ bool operator>=(const Value& other) const;
+ bool operator>(const Value& other) const;
+ bool operator==(const Value& other) const;
+ bool operator!=(const Value& other) const;
+ int compare(const Value& other) const;
+
+ const char* asCString() const; ///< Embedded zeroes could cause you trouble!
+#if JSONCPP_USING_SECURE_MEMORY
+ unsigned getCStringLength() const; //Allows you to understand the length of the CString
+#endif
+ JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
+ /** Get raw char* of string-value.
+ * \return false if !string. (Seg-fault if str or end are NULL.)
+ */
+ bool getString(
+ char const** begin, char const** end) const;
+#ifdef JSON_USE_CPPTL
+ CppTL::ConstString asConstString() const;
+#endif
+ Int asInt() const;
+ UInt asUInt() const;
+#if defined(JSON_HAS_INT64)
+ Int64 asInt64() const;
+ UInt64 asUInt64() const;
+#endif // if defined(JSON_HAS_INT64)
+ LargestInt asLargestInt() const;
+ LargestUInt asLargestUInt() const;
+ float asFloat() const;
+ double asDouble() const;
+ bool asBool() const;
+
+ bool isNull() const;
+ bool isBool() const;
+ bool isInt() const;
+ bool isInt64() const;
+ bool isUInt() const;
+ bool isUInt64() const;
+ bool isIntegral() const;
+ bool isDouble() const;
+ bool isNumeric() const;
+ bool isString() const;
+ bool isArray() const;
+ bool isObject() const;
+
+ bool isConvertibleTo(ValueType other) const;
+
+ /// Number of values in array or object
+ ArrayIndex size() const;
+
+ /// \brief Return true if empty array, empty object, or null;
+ /// otherwise, false.
+ bool empty() const;
+
+ /// Return isNull()
+ bool operator!() const;
+
+ /// Remove all object members and array elements.
+ /// \pre type() is arrayValue, objectValue, or nullValue
+ /// \post type() is unchanged
+ void clear();
+
+ /// Resize the array to size elements.
+ /// New elements are initialized to null.
+ /// May only be called on nullValue or arrayValue.
+ /// \pre type() is arrayValue or nullValue
+ /// \post type() is arrayValue
+ void resize(ArrayIndex size);
+
+ /// Access an array element (zero based index ).
+ /// If the array contains less than index element, then null value are
+ /// inserted
+ /// in the array so that its size is index+1.
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ Value& operator[](ArrayIndex index);
+
+ /// Access an array element (zero based index ).
+ /// If the array contains less than index element, then null value are
+ /// inserted
+ /// in the array so that its size is index+1.
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ Value& operator[](int index);
+
+ /// Access an array element (zero based index )
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ const Value& operator[](ArrayIndex index) const;
+
+ /// Access an array element (zero based index )
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ const Value& operator[](int index) const;
+
+ /// If the array contains at least index+1 elements, returns the element
+ /// value,
+ /// otherwise returns defaultValue.
+ Value get(ArrayIndex index, const Value& defaultValue) const;
+ /// Return true if index < size().
+ bool isValidIndex(ArrayIndex index) const;
+ /// \brief Append value to array at the end.
+ ///
+ /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+ Value& append(const Value& value);
+
+#if JSON_HAS_RVALUE_REFERENCES
+ Value& append(Value&& value);
+#endif
+
+ /// Access an object value by name, create a null member if it does not exist.
+ /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+ /// Exceeding that will cause an exception.
+ Value& operator[](const char* key);
+ /// Access an object value by name, returns null if there is no member with
+ /// that name.
+ const Value& operator[](const char* key) const;
+ /// Access an object value by name, create a null member if it does not exist.
+ /// \param key may contain embedded nulls.
+ Value& operator[](const JSONCPP_STRING& key);
+ /// Access an object value by name, returns null if there is no member with
+ /// that name.
+ /// \param key may contain embedded nulls.
+ const Value& operator[](const JSONCPP_STRING& key) const;
+ /** \brief Access an object value by name, create a null member if it does not
+ exist.
+
+ * If the object has no entry for that name, then the member name used to store
+ * the new entry is not duplicated.
+ * Example of use:
+ * \code
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+ Value& operator[](const StaticString& key);
+#ifdef JSON_USE_CPPTL
+ /// Access an object value by name, create a null member if it does not exist.
+ Value& operator[](const CppTL::ConstString& key);
+ /// Access an object value by name, returns null if there is no member with
+ /// that name.
+ const Value& operator[](const CppTL::ConstString& key) const;
+#endif
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ Value get(const char* key, const Value& defaultValue) const;
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ /// \note key may contain embedded nulls.
+ Value get(const char* begin, const char* end, const Value& defaultValue) const;
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ /// \param key may contain embedded nulls.
+ Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
+#ifdef JSON_USE_CPPTL
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
+#endif
+ /// Most general and efficient version of isMember()const, get()const,
+ /// and operator[]const
+ /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+ Value const* find(char const* begin, char const* end) const;
+ /// Most general and efficient version of object-mutators.
+ /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+ /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
+ Value const* demand(char const* begin, char const* end);
+ /// \brief Remove and return the named member.
+ ///
+ /// Do nothing if it did not exist.
+ /// \return the removed Value, or null.
+ /// \pre type() is objectValue or nullValue
+ /// \post type() is unchanged
+ /// \deprecated
+ Value removeMember(const char* key);
+ /// Same as removeMember(const char*)
+ /// \param key may contain embedded nulls.
+ /// \deprecated
+ Value removeMember(const JSONCPP_STRING& key);
+ /// Same as removeMember(const char* begin, const char* end, Value* removed),
+ /// but 'key' is null-terminated.
+ bool removeMember(const char* key, Value* removed);
+ /** \brief Remove the named map member.
+
+ Update 'removed' iff removed.
+ \param key may contain embedded nulls.
+ \return true iff removed (no exceptions)
+ */
+ bool removeMember(JSONCPP_STRING const& key, Value* removed);
+ /// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
+ bool removeMember(const char* begin, const char* end, Value* removed);
+ /** \brief Remove the indexed array element.
+
+ O(n) expensive operations.
+ Update 'removed' iff removed.
+ \return true iff removed (no exceptions)
+ */
+ bool removeIndex(ArrayIndex i, Value* removed);
+
+ /// Return true if the object has a member named key.
+ /// \note 'key' must be null-terminated.
+ bool isMember(const char* key) const;
+ /// Return true if the object has a member named key.
+ /// \param key may contain embedded nulls.
+ bool isMember(const JSONCPP_STRING& key) const;
+ /// Same as isMember(JSONCPP_STRING const& key)const
+ bool isMember(const char* begin, const char* end) const;
+#ifdef JSON_USE_CPPTL
+ /// Return true if the object has a member named key.
+ bool isMember(const CppTL::ConstString& key) const;
+#endif
+
+ /// \brief Return a list of the member names.
+ ///
+ /// If null, return an empty list.
+ /// \pre type() is objectValue or nullValue
+ /// \post if type() was nullValue, it remains nullValue
+ Members getMemberNames() const;
+
+ //# ifdef JSON_USE_CPPTL
+ // EnumMemberNames enumMemberNames() const;
+ // EnumValues enumValues() const;
+ //# endif
+
+ /// \deprecated Always pass len.
+ JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
+ void setComment(const char* comment, CommentPlacement placement);
+ /// Comments must be //... or /* ... */
+ void setComment(const char* comment, size_t len, CommentPlacement placement);
+ /// Comments must be //... or /* ... */
+ void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
+ bool hasComment(CommentPlacement placement) const;
+ /// Include delimiters and embedded newlines.
+ JSONCPP_STRING getComment(CommentPlacement placement) const;
+
+ JSONCPP_STRING toStyledString() const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ iterator begin();
+ iterator end();
+
+ // Accessors for the [start, limit) range of bytes within the JSON text from
+ // which this value was parsed, if any.
+ void setOffsetStart(ptrdiff_t start);
+ void setOffsetLimit(ptrdiff_t limit);
+ ptrdiff_t getOffsetStart() const;
+ ptrdiff_t getOffsetLimit() const;
+
+private:
+ void initBasic(ValueType type, bool allocated = false);
+
+ Value& resolveReference(const char* key);
+ Value& resolveReference(const char* key, const char* end);
+
+ struct CommentInfo {
+ CommentInfo();
+ ~CommentInfo();
+
+ void setComment(const char* text, size_t len);
+
+ char* comment_;
+ };
+
+ // struct MemberNamesTransform
+ //{
+ // typedef const char *result_type;
+ // const char *operator()( const CZString &name ) const
+ // {
+ // return name.c_str();
+ // }
+ //};
+
+ union ValueHolder {
+ LargestInt int_;
+ LargestUInt uint_;
+ double real_;
+ bool bool_;
+ char* string_; // actually ptr to unsigned, followed by str, unless !allocated_
+ ObjectValues* map_;
+ } value_;
+ ValueType type_ : 8;
+ unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+ // If not allocated_, string_ must be null-terminated.
+ CommentInfo* comments_;
+
+ // [start, limit) byte offsets in the source JSON text from which this Value
+ // was extracted.
+ ptrdiff_t start_;
+ ptrdiff_t limit_;
+};
+
+/** \brief Experimental and untested: represents an element of the "path" to
+ * access a node.
+ */
+class JSON_API PathArgument {
+public:
+ friend class Path;
+
+ PathArgument();
+ PathArgument(ArrayIndex index);
+ PathArgument(const char* key);
+ PathArgument(const JSONCPP_STRING& key);
+
+private:
+ enum Kind {
+ kindNone = 0,
+ kindIndex,
+ kindKey
+ };
+ JSONCPP_STRING key_;
+ ArrayIndex index_;
+ Kind kind_;
+};
+
+/** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provied as parameter
+ */
+class JSON_API Path {
+public:
+ Path(const JSONCPP_STRING& path,
+ const PathArgument& a1 = PathArgument(),
+ const PathArgument& a2 = PathArgument(),
+ const PathArgument& a3 = PathArgument(),
+ const PathArgument& a4 = PathArgument(),
+ const PathArgument& a5 = PathArgument());
+
+ const Value& resolve(const Value& root) const;
+ Value resolve(const Value& root, const Value& defaultValue) const;
+ /// Creates the "path" to access the specified node and returns a reference on
+ /// the node.
+ Value& make(Value& root) const;
+
+private:
+ typedef std::vector<const PathArgument*> InArgs;
+ typedef std::vector<PathArgument> Args;
+
+ void makePath(const JSONCPP_STRING& path, const InArgs& in);
+ void addPathInArg(const JSONCPP_STRING& path,
+ const InArgs& in,
+ InArgs::const_iterator& itInArg,
+ PathArgument::Kind kind);
+ void invalidPath(const JSONCPP_STRING& path, int location);
+
+ Args args_;
+};
+
+/** \brief base class for Value iterators.
+ *
+ */
+class JSON_API ValueIteratorBase {
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef ValueIteratorBase SelfType;
+
+ bool operator==(const SelfType& other) const { return isEqual(other); }
+
+ bool operator!=(const SelfType& other) const { return !isEqual(other); }
+
+ difference_type operator-(const SelfType& other) const {
+ return other.computeDistance(*this);
+ }
+
+ /// Return either the index or the member name of the referenced value as a
+ /// Value.
+ Value key() const;
+
+ /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
+ UInt index() const;
+
+ /// Return the member name of the referenced Value, or "" if it is not an
+ /// objectValue.
+ /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
+ JSONCPP_STRING name() const;
+
+ /// Return the member name of the referenced Value. "" if it is not an
+ /// objectValue.
+ /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+ JSONCPP_DEPRECATED("Use `key = name();` instead.")
+ char const* memberName() const;
+ /// Return the member name of the referenced Value, or NULL if it is not an
+ /// objectValue.
+ /// \note Better version than memberName(). Allows embedded nulls.
+ char const* memberName(char const** end) const;
+
+protected:
+ Value& deref() const;
+
+ void increment();
+
+ void decrement();
+
+ difference_type computeDistance(const SelfType& other) const;
+
+ bool isEqual(const SelfType& other) const;
+
+ void copy(const SelfType& other);
+
+private:
+ Value::ObjectValues::iterator current_;
+ // Indicates that iterator is for a null value.
+ bool isNull_;
+
+public:
+ // For some reason, BORLAND needs these at the end, rather
+ // than earlier. No idea why.
+ ValueIteratorBase();
+ explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
+};
+
+/** \brief const iterator for object and array value.
+ *
+ */
+class JSON_API ValueConstIterator : public ValueIteratorBase {
+ friend class Value;
+
+public:
+ typedef const Value value_type;
+ //typedef unsigned int size_t;
+ //typedef int difference_type;
+ typedef const Value& reference;
+ typedef const Value* pointer;
+ typedef ValueConstIterator SelfType;
+
+ ValueConstIterator();
+ ValueConstIterator(ValueIterator const& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+ explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
+public:
+ SelfType& operator=(const ValueIteratorBase& other);
+
+ SelfType operator++(int) {
+ SelfType temp(*this);
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--(int) {
+ SelfType temp(*this);
+ --*this;
+ return temp;
+ }
+
+ SelfType& operator--() {
+ decrement();
+ return *this;
+ }
+
+ SelfType& operator++() {
+ increment();
+ return *this;
+ }
+
+ reference operator*() const { return deref(); }
+
+ pointer operator->() const { return &deref(); }
+};
+
+/** \brief Iterator for object and array value.
+ */
+class JSON_API ValueIterator : public ValueIteratorBase {
+ friend class Value;
+
+public:
+ typedef Value value_type;
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef Value& reference;
+ typedef Value* pointer;
+ typedef ValueIterator SelfType;
+
+ ValueIterator();
+ explicit ValueIterator(const ValueConstIterator& other);
+ ValueIterator(const ValueIterator& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+ explicit ValueIterator(const Value::ObjectValues::iterator& current);
+public:
+ SelfType& operator=(const SelfType& other);
+
+ SelfType operator++(int) {
+ SelfType temp(*this);
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--(int) {
+ SelfType temp(*this);
+ --*this;
+ return temp;
+ }
+
+ SelfType& operator--() {
+ decrement();
+ return *this;
+ }
+
+ SelfType& operator++() {
+ increment();
+ return *this;
+ }
+
+ reference operator*() const { return deref(); }
+
+ pointer operator->() const { return &deref(); }
+};
+
+} // namespace Json
+
+
+namespace std {
+/// Specialize std::swap() for Json::Value.
+template<>
+inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
+}
+
+#pragma pack(pop)
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/version.h b/extern/jsoncpp/include/json/version.h
new file mode 100644
index 00000000000..88f7bb70b02
--- /dev/null
+++ b/extern/jsoncpp/include/json/version.h
@@ -0,0 +1,20 @@
+// DO NOT EDIT. This file (and "version") is generated by CMake.
+// Run CMake configure step to update it.
+#ifndef JSON_VERSION_H_INCLUDED
+# define JSON_VERSION_H_INCLUDED
+
+# define JSONCPP_VERSION_STRING "1.8.1"
+# define JSONCPP_VERSION_MAJOR 1
+# define JSONCPP_VERSION_MINOR 8
+# define JSONCPP_VERSION_PATCH 1
+# define JSONCPP_VERSION_QUALIFIER
+# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
diff --git a/extern/jsoncpp/include/json/writer.h b/extern/jsoncpp/include/json/writer.h
new file mode 100644
index 00000000000..d0944eeb88c
--- /dev/null
+++ b/extern/jsoncpp/include/json/writer.h
@@ -0,0 +1,335 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_WRITER_H_INCLUDED
+#define JSON_WRITER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <vector>
+#include <string>
+#include <ostream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
+namespace Json {
+
+class Value;
+
+/**
+
+Usage:
+\code
+ using namespace Json;
+ void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
+ std::unique_ptr<StreamWriter> const writer(
+ factory.newStreamWriter());
+ writer->write(value, &std::cout);
+ std::cout << std::endl; // add lf and flush
+ }
+\endcode
+*/
+class JSON_API StreamWriter {
+protected:
+ JSONCPP_OSTREAM* sout_; // not owned; will not delete
+public:
+ StreamWriter();
+ virtual ~StreamWriter();
+ /** Write Value into document as configured in sub-class.
+ Do not take ownership of sout, but maintain a reference during function.
+ \pre sout != NULL
+ \return zero on success (For now, we always return zero, so check the stream instead.)
+ \throw std::exception possibly, depending on configuration
+ */
+ virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
+
+ /** \brief A simple abstract factory.
+ */
+ class JSON_API Factory {
+ public:
+ virtual ~Factory();
+ /** \brief Allocate a CharReader via operator new().
+ * \throw std::exception if something goes wrong (e.g. invalid settings)
+ */
+ virtual StreamWriter* newStreamWriter() const = 0;
+ }; // Factory
+}; // StreamWriter
+
+/** \brief Write into stringstream, then return string, for convenience.
+ * A StreamWriter will be created from the factory, used, and then deleted.
+ */
+JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
+
+
+/** \brief Build a StreamWriter implementation.
+
+Usage:
+\code
+ using namespace Json;
+ Value value = ...;
+ StreamWriterBuilder builder;
+ builder["commentStyle"] = "None";
+ builder["indentation"] = " "; // or whatever you like
+ std::unique_ptr<Json::StreamWriter> writer(
+ builder.newStreamWriter());
+ writer->write(value, &std::cout);
+ std::cout << std::endl; // add lf and flush
+\endcode
+*/
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
+public:
+ // Note: We use a Json::Value so that we can add data-members to this class
+ // without a major version bump.
+ /** Configuration of this builder.
+ Available settings (case-sensitive):
+ - "commentStyle": "None" or "All"
+ - "indentation": "<anything>"
+ - "enableYAMLCompatibility": false or true
+ - slightly change the whitespace around colons
+ - "dropNullPlaceholders": false or true
+ - Drop the "null" string from the writer's output for nullValues.
+ Strictly speaking, this is not valid JSON. But when the output is being
+ fed to a browser's Javascript, it makes for smaller output and the
+ browser can handle the output just fine.
+ - "useSpecialFloats": false or true
+ - If true, outputs non-finite floating point values in the following way:
+ NaN values as "NaN", positive infinity as "Infinity", and negative infinity
+ as "-Infinity".
+
+ You can examine 'settings_` yourself
+ to see the defaults. You can also write and read them just like any
+ JSON Value.
+ \sa setDefaults()
+ */
+ Json::Value settings_;
+
+ StreamWriterBuilder();
+ ~StreamWriterBuilder() JSONCPP_OVERRIDE;
+
+ /**
+ * \throw std::exception if something goes wrong (e.g. invalid settings)
+ */
+ StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
+
+ /** \return true if 'settings' are legal and consistent;
+ * otherwise, indicate bad settings via 'invalid'.
+ */
+ bool validate(Json::Value* invalid) const;
+ /** A simple way to update a specific setting.
+ */
+ Value& operator[](JSONCPP_STRING key);
+
+ /** Called by ctor, but you can use this to reset settings_.
+ * \pre 'settings' != NULL (but Json::null is fine)
+ * \remark Defaults:
+ * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+ */
+ static void setDefaults(Json::Value* settings);
+};
+
+/** \brief Abstract class for writers.
+ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
+ */
+class JSON_API Writer {
+public:
+ virtual ~Writer();
+
+ virtual JSONCPP_STRING write(const Value& root) = 0;
+};
+
+/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
+ *without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human'
+ *consumption,
+ * but may be usefull to support feature such as RPC where bandwith is limited.
+ * \sa Reader, Value
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API FastWriter : public Writer {
+
+public:
+ FastWriter();
+ ~FastWriter() JSONCPP_OVERRIDE {}
+
+ void enableYAMLCompatibility();
+
+ /** \brief Drop the "null" string from the writer's output for nullValues.
+ * Strictly speaking, this is not valid JSON. But when the output is being
+ * fed to a browser's Javascript, it makes for smaller output and the
+ * browser can handle the output just fine.
+ */
+ void dropNullPlaceholders();
+
+ void omitEndingLineFeed();
+
+public: // overridden from Writer
+ JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
+
+private:
+ void writeValue(const Value& value);
+
+ JSONCPP_STRING document_;
+ bool yamlCompatiblityEnabled_;
+ bool dropNullPlaceholders_;
+ bool omitEndingLineFeed_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ *human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per
+ *line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value
+ *types,
+ * and all the values fit on one lines, then print the array on a single
+ *line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ *#CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledWriter : public Writer {
+public:
+ StyledWriter();
+ ~StyledWriter() JSONCPP_OVERRIDE {}
+
+public: // overridden from Writer
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param root Value to serialize.
+ * \return String containing the JSON document that represents the root value.
+ */
+ JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
+
+private:
+ void writeValue(const Value& value);
+ void writeArrayValue(const Value& value);
+ bool isMultineArray(const Value& value);
+ void pushValue(const JSONCPP_STRING& value);
+ void writeIndent();
+ void writeWithIndent(const JSONCPP_STRING& value);
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue(const Value& root);
+ void writeCommentAfterValueOnSameLine(const Value& root);
+ bool hasCommentForValue(const Value& value);
+ static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
+
+ typedef std::vector<JSONCPP_STRING> ChildValues;
+
+ ChildValues childValues_;
+ JSONCPP_STRING document_;
+ JSONCPP_STRING indentString_;
+ unsigned int rightMargin_;
+ unsigned int indentSize_;
+ bool addChildValues_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ human friendly way,
+ to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per
+ line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value
+ types,
+ * and all the values fit on one lines, then print the array on a single
+ line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ #CommentPlacement.
+ *
+ * \param indentation Each level will be indented by this amount extra.
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledStreamWriter {
+public:
+ StyledStreamWriter(JSONCPP_STRING indentation = "\t");
+ ~StyledStreamWriter() {}
+
+public:
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param out Stream to write to. (Can be ostringstream, e.g.)
+ * \param root Value to serialize.
+ * \note There is no point in deriving from Writer, since write() should not
+ * return a value.
+ */
+ void write(JSONCPP_OSTREAM& out, const Value& root);
+
+private:
+ void writeValue(const Value& value);
+ void writeArrayValue(const Value& value);
+ bool isMultineArray(const Value& value);
+ void pushValue(const JSONCPP_STRING& value);
+ void writeIndent();
+ void writeWithIndent(const JSONCPP_STRING& value);
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue(const Value& root);
+ void writeCommentAfterValueOnSameLine(const Value& root);
+ bool hasCommentForValue(const Value& value);
+ static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
+
+ typedef std::vector<JSONCPP_STRING> ChildValues;
+
+ ChildValues childValues_;
+ JSONCPP_OSTREAM* document_;
+ JSONCPP_STRING indentString_;
+ unsigned int rightMargin_;
+ JSONCPP_STRING indentation_;
+ bool addChildValues_ : 1;
+ bool indented_ : 1;
+};
+
+#if defined(JSON_HAS_INT64)
+JSONCPP_STRING JSON_API valueToString(Int value);
+JSONCPP_STRING JSON_API valueToString(UInt value);
+#endif // if defined(JSON_HAS_INT64)
+JSONCPP_STRING JSON_API valueToString(LargestInt value);
+JSONCPP_STRING JSON_API valueToString(LargestUInt value);
+JSONCPP_STRING JSON_API valueToString(double value);
+JSONCPP_STRING JSON_API valueToString(bool value);
+JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
+
+/// \brief Output using the StyledStreamWriter.
+/// \see Json::operator>>()
+JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_WRITER_H_INCLUDED
diff --git a/extern/jsoncpp/src/CMakeLists.txt b/extern/jsoncpp/src/CMakeLists.txt
new file mode 100644
index 00000000000..1db47e032c7
--- /dev/null
+++ b/extern/jsoncpp/src/CMakeLists.txt
@@ -0,0 +1,80 @@
+IF( CMAKE_COMPILER_IS_GNUCXX )
+ #Get compiler version.
+ EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GNUCXX_VERSION )
+
+ #-Werror=* was introduced -after- GCC 4.1.2
+ IF( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
+ ENDIF()
+ENDIF( CMAKE_COMPILER_IS_GNUCXX )
+
+INCLUDE(CheckIncludeFileCXX)
+INCLUDE(CheckTypeSize)
+INCLUDE(CheckStructHasMember)
+INCLUDE(CheckCXXSymbolExists)
+
+check_include_file_cxx(clocale HAVE_CLOCALE)
+check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV)
+
+IF(CMAKE_VERSION VERSION_LESS 3.0.0)
+ # The "LANGUAGE CXX" parameter is not supported in CMake versions below 3,
+ # so the C compiler and header has to be used.
+ check_include_file(locale.h HAVE_LOCALE_H)
+ SET(CMAKE_EXTRA_INCLUDE_FILES locale.h)
+ check_type_size("struct lconv" LCONV_SIZE)
+ UNSET(CMAKE_EXTRA_INCLUDE_FILES)
+ check_struct_has_member("struct lconv" decimal_point locale.h HAVE_DECIMAL_POINT)
+ELSE()
+ SET(CMAKE_EXTRA_INCLUDE_FILES clocale)
+ check_type_size(lconv LCONV_SIZE LANGUAGE CXX)
+ UNSET(CMAKE_EXTRA_INCLUDE_FILES)
+ check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX)
+ENDIF()
+
+IF(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
+ MESSAGE(WARNING "Locale functionality is not supported")
+ ADD_DEFINITIONS(-DJSONCPP_NO_LOCALE_SUPPORT)
+ENDIF()
+
+SET( JSONCPP_INCLUDE_DIR ../include )
+
+SET( PUBLIC_HEADERS
+ ${JSONCPP_INCLUDE_DIR}/json/config.h
+ ${JSONCPP_INCLUDE_DIR}/json/forwards.h
+ ${JSONCPP_INCLUDE_DIR}/json/features.h
+ ${JSONCPP_INCLUDE_DIR}/json/value.h
+ ${JSONCPP_INCLUDE_DIR}/json/reader.h
+ ${JSONCPP_INCLUDE_DIR}/json/writer.h
+ ${JSONCPP_INCLUDE_DIR}/json/assertions.h
+ ${JSONCPP_INCLUDE_DIR}/json/version.h
+ )
+
+SOURCE_GROUP( "Public API" FILES ${PUBLIC_HEADERS} )
+
+SET(jsoncpp_sources
+ json_tool.h
+ json_reader.cpp
+ json_valueiterator.inl
+ json_value.cpp
+ json_writer.cpp
+ version.h.in
+ )
+
+# Install instructions for this target
+IF(JSONCPP_WITH_CMAKE_PACKAGE)
+ SET(INSTALL_EXPORT EXPORT jsoncpp)
+ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
+ SET(INSTALL_EXPORT)
+ENDIF()
+
+set(SRC
+ ${PUBLIC_HEADERS}
+ ${jsoncpp_sources}
+)
+
+set(INC
+ ../include
+)
+
+blender_add_lib(jsoncpp_lib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/extern/jsoncpp/src/json_reader.cpp b/extern/jsoncpp/src/json_reader.cpp
new file mode 100644
index 00000000000..ec7907525df
--- /dev/null
+++ b/extern/jsoncpp/src/json_reader.cpp
@@ -0,0 +1,2036 @@
+// Copyright 2007-2011 Baptiste Lepilleur
+// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/reader.h>
+#include <json/value.h>
+#include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <istream>
+#include <sstream>
+#include <memory>
+#include <set>
+#include <limits>
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define snprintf std::snprintf
+#endif
+#endif
+
+#if defined(__QNXNTO__)
+#define sscanf std::sscanf
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
+#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
+#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#endif
+
+static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<CharReader> CharReaderPtr;
+#else
+typedef std::auto_ptr<CharReader> CharReaderPtr;
+#endif
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+ : allowComments_(true), strictRoot_(false),
+ allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
+
+Features Features::all() { return Features(); }
+
+Features Features::strictMode() {
+ Features features;
+ features.allowComments_ = false;
+ features.strictRoot_ = true;
+ features.allowDroppedNullPlaceholders_ = false;
+ features.allowNumericKeys_ = false;
+ return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+static bool containsNewLine(Reader::Location begin, Reader::Location end) {
+ for (; begin < end; ++begin)
+ if (*begin == '\n' || *begin == '\r')
+ return true;
+ return false;
+}
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+ : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+ lastValue_(), commentsBefore_(), features_(Features::all()),
+ collectComments_() {}
+
+Reader::Reader(const Features& features)
+ : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+ lastValue_(), commentsBefore_(), features_(features), collectComments_() {
+}
+
+bool
+Reader::parse(const std::string& document, Value& root, bool collectComments) {
+ JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
+ std::swap(documentCopy, document_);
+ const char* begin = document_.c_str();
+ const char* end = begin + document_.length();
+ return parse(begin, end, root, collectComments);
+}
+
+bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
+ // std::istream_iterator<char> begin(sin);
+ // std::istream_iterator<char> end;
+ // Those would allow streamed input from a file, if parse() were a
+ // template function.
+
+ // Since JSONCPP_STRING is reference-counted, this at least does not
+ // create an extra copy.
+ JSONCPP_STRING doc;
+ std::getline(sin, doc, (char)EOF);
+ return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
+}
+
+bool Reader::parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_.clear();
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ bool successful = readValue();
+ Token token;
+ skipCommentTokens(token);
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
+ if (!root.isArray() && !root.isObject()) {
+ // Set error location to start of doc, ideally should be first token found
+ // in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
+ return false;
+ }
+ }
+ return successful;
+}
+
+bool Reader::readValue() {
+ // readValue() may call itself only if it calls readObject() or ReadArray().
+ // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
+ // parse() executes one nodes_.push(), so > instead of >=.
+ if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
+
+ Token token;
+ skipCommentTokens(token);
+ bool successful = true;
+
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_.clear();
+ }
+
+ switch (token.type_) {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue:
+ {
+ Value v(true);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenFalse:
+ {
+ Value v(false);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNull:
+ {
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // Else, fall through...
+ default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return addError("Syntax error: value, object or array expected.", token);
+ }
+
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
+ }
+
+ return successful;
+}
+
+void Reader::skipCommentTokens(Token& token) {
+ if (features_.allowComments_) {
+ do {
+ readToken(token);
+ } while (token.type_ == tokenComment);
+ } else {
+ readToken(token);
+ }
+}
+
+bool Reader::readToken(Token& token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch (c) {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return true;
+}
+
+void Reader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ ++current_;
+ else
+ break;
+ }
+}
+
+bool Reader::match(Location pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
+ return false;
+ int index = patternLength;
+ while (index--)
+ if (current_[index] != pattern[index])
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+bool Reader::readComment() {
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
+ bool successful = false;
+ if (c == '*')
+ successful = readCStyleComment();
+ else if (c == '/')
+ successful = readCppStyleComment();
+ if (!successful)
+ return false;
+
+ if (collectComments_) {
+ CommentPlacement placement = commentBefore;
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, current_))
+ placement = commentAfterOnSameLine;
+ }
+
+ addComment(commentBegin, current_, placement);
+ }
+ return true;
+}
+
+static JSONCPP_STRING normalizeEOL(Reader::Location begin, Reader::Location end) {
+ JSONCPP_STRING normalized;
+ normalized.reserve(static_cast<size_t>(end - begin));
+ Reader::Location current = begin;
+ while (current != end) {
+ char c = *current++;
+ if (c == '\r') {
+ if (current != end && *current == '\n')
+ // convert dos EOL
+ ++current;
+ // convert Mac EOL
+ normalized += '\n';
+ } else {
+ normalized += c;
+ }
+ }
+ return normalized;
+}
+
+void
+Reader::addComment(Location begin, Location end, CommentPlacement placement) {
+ assert(collectComments_);
+ const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
+ if (placement == commentAfterOnSameLine) {
+ assert(lastValue_ != 0);
+ lastValue_->setComment(normalized, placement);
+ } else {
+ commentsBefore_ += normalized;
+ }
+}
+
+bool Reader::readCStyleComment() {
+ while ((current_ + 1) < end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
+ break;
+ }
+ return getNextChar() == '/';
+}
+
+bool Reader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ // Consume DOS EOL. It will be normalized in addComment.
+ if (current_ != end_ && *current_ == '\n')
+ getNextChar();
+ // Break on Moc OS 9 EOL.
+ break;
+ }
+ }
+ return true;
+}
+
+void Reader::readNumber() {
+ const char *p = current_;
+ char c = '0'; // stopgap for already consumed character
+ // integral part
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ // fractional part
+ if (c == '.') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+ // exponential part
+ if (c == 'e' || c == 'E') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ if (c == '+' || c == '-')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+}
+
+bool Reader::readString() {
+ Char c = '\0';
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '"')
+ break;
+ }
+ return c == '"';
+}
+
+bool Reader::readObject(Token& tokenStart) {
+ Token tokenName;
+ JSONCPP_STRING name;
+ Value init(objectValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ while (readToken(tokenName)) {
+ bool initialTokenOk = true;
+ while (tokenName.type_ == tokenComment && initialTokenOk)
+ initialTokenOk = readToken(tokenName);
+ if (!initialTokenOk)
+ break;
+ if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+ return true;
+ name.clear();
+ if (tokenName.type_ == tokenString) {
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ Value numberName;
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
+ name = JSONCPP_STRING(numberName.asCString());
+ } else {
+ break;
+ }
+
+ Token colon;
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover(
+ "Missing ':' after object member name", colon, tokenObjectEnd);
+ }
+ Value& value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenObjectEnd);
+
+ Token comma;
+ if (!readToken(comma) ||
+ (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+ comma.type_ != tokenComment)) {
+ return addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ }
+ bool finalizeTokenOk = true;
+ while (comma.type_ == tokenComment && finalizeTokenOk)
+ finalizeTokenOk = readToken(comma);
+ if (comma.type_ == tokenObjectEnd)
+ return true;
+ }
+ return addErrorAndRecover(
+ "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool Reader::readArray(Token& tokenStart) {
+ Value init(arrayValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']') // empty array
+ {
+ Token endArray;
+ readToken(endArray);
+ return true;
+ }
+ int index = 0;
+ for (;;) {
+ Value& value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenArrayEnd);
+
+ Token token;
+ // Accept Comment after last item in the array.
+ ok = readToken(token);
+ while (token.type_ == tokenComment && ok) {
+ ok = readToken(token);
+ }
+ bool badTokenType =
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ if (!ok || badTokenType) {
+ return addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ }
+ if (token.type_ == tokenArrayEnd)
+ break;
+ }
+ return true;
+}
+
+bool Reader::decodeNumber(Token& token) {
+ Value decoded;
+ if (!decodeNumber(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool Reader::decodeNumber(Token& token, Value& decoded) {
+ // Attempts to parse the number as an integer. If the number is
+ // larger than the maximum supported value of an integer then
+ // we decode the number as a double.
+ Location current = token.start_;
+ bool isNegative = *current == '-';
+ if (isNegative)
+ ++current;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+ Value::LargestUInt maxIntegerValue =
+ isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
+ : Value::maxLargestUInt;
+ Value::LargestUInt threshold = maxIntegerValue / 10;
+ Value::LargestUInt value = 0;
+ while (current < token.end_) {
+ Char c = *current++;
+ if (c < '0' || c > '9')
+ return decodeDouble(token, decoded);
+ Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+ if (value >= threshold) {
+ // We've hit or exceeded the max value divided by 10 (rounded down). If
+ // a) we've only just touched the limit, b) this is the last digit, and
+ // c) it's small enough to fit in that rounding delta, we're okay.
+ // Otherwise treat this number as a double to avoid overflow.
+ if (value > threshold || current != token.end_ ||
+ digit > maxIntegerValue % 10) {
+ return decodeDouble(token, decoded);
+ }
+ }
+ value = value * 10 + digit;
+ }
+ if (isNegative && value == maxIntegerValue)
+ decoded = Value::minLargestInt;
+ else if (isNegative)
+ decoded = -Value::LargestInt(value);
+ else if (value <= Value::LargestUInt(Value::maxInt))
+ decoded = Value::LargestInt(value);
+ else
+ decoded = value;
+ return true;
+}
+
+bool Reader::decodeDouble(Token& token) {
+ Value decoded;
+ if (!decodeDouble(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool Reader::decodeDouble(Token& token, Value& decoded) {
+ double value = 0;
+ JSONCPP_STRING buffer(token.start_, token.end_);
+ JSONCPP_ISTRINGSTREAM is(buffer);
+ if (!(is >> value))
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+ "' is not a number.",
+ token);
+ decoded = value;
+ return true;
+}
+
+bool Reader::decodeString(Token& token) {
+ JSONCPP_STRING decoded_string;
+ if (!decodeString(token, decoded_string))
+ return false;
+ Value decoded(decoded_string);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+ decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while (current != end) {
+ Char c = *current++;
+ if (c == '"')
+ break;
+ else if (c == '\\') {
+ if (current == end)
+ return addError("Empty escape sequence in string", token, current);
+ Char escape = *current++;
+ switch (escape) {
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
+ }
+ } else {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool Reader::decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode) {
+
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token,
+ current);
+ unsigned int surrogatePair;
+ if (*(current++) == '\\' && *(current++) == 'u') {
+ if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ } else
+ return false;
+ } else
+ return addError("expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token,
+ current);
+ }
+ return true;
+}
+
+bool Reader::decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& ret_unicode) {
+ if (end - current < 4)
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.",
+ token,
+ current);
+ int unicode = 0;
+ for (int index = 0; index < 4; ++index) {
+ Char c = *current++;
+ unicode *= 16;
+ if (c >= '0' && c <= '9')
+ unicode += c - '0';
+ else if (c >= 'a' && c <= 'f')
+ unicode += c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ unicode += c - 'A' + 10;
+ else
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token,
+ current);
+ }
+ ret_unicode = static_cast<unsigned int>(unicode);
+ return true;
+}
+
+bool
+Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back(info);
+ return false;
+}
+
+bool Reader::recoverFromError(TokenType skipUntilToken) {
+ size_t const errorCount = errors_.size();
+ Token skip;
+ for (;;) {
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
+ if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+ break;
+ }
+ errors_.resize(errorCount);
+ return false;
+}
+
+bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
+}
+
+Value& Reader::currentValue() { return *(nodes_.top()); }
+
+Reader::Char Reader::getNextChar() {
+ if (current_ == end_)
+ return 0;
+ return *current_++;
+}
+
+void Reader::getLocationLineAndColumn(Location location,
+ int& line,
+ int& column) const {
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while (current < location && current != end_) {
+ Char c = *current++;
+ if (c == '\r') {
+ if (*current == '\n')
+ ++current;
+ lastLineStart = current;
+ ++line;
+ } else if (c == '\n') {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
+ int line, column;
+ getLocationLineAndColumn(location, line, column);
+ char buffer[18 + 16 + 16 + 1];
+ snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+ return buffer;
+}
+
+// Deprecated. Preserved for backward compatibility
+JSONCPP_STRING Reader::getFormatedErrorMessages() const {
+ return getFormattedErrorMessages();
+}
+
+JSONCPP_STRING Reader::getFormattedErrorMessages() const {
+ JSONCPP_STRING formattedMessage;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
+ const ErrorInfo& error = *itError;
+ formattedMessage +=
+ "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if (error.extra_)
+ formattedMessage +=
+ "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
+ std::vector<Reader::StructuredError> allErrors;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
+ const ErrorInfo& error = *itError;
+ Reader::StructuredError structured;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
+ structured.message = error.message_;
+ allErrors.push_back(structured);
+ }
+ return allErrors;
+}
+
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t const length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = end_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = 0;
+ errors_.push_back(info);
+ return true;
+}
+
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+ ptrdiff_t const length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length
+ || extra.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
+ return true;
+}
+
+bool Reader::good() const {
+ return !errors_.size();
+}
+
+// exact copy of Features
+class OurFeatures {
+public:
+ static OurFeatures all();
+ bool allowComments_;
+ bool strictRoot_;
+ bool allowDroppedNullPlaceholders_;
+ bool allowNumericKeys_;
+ bool allowSingleQuotes_;
+ bool failIfExtra_;
+ bool rejectDupKeys_;
+ bool allowSpecialFloats_;
+ int stackLimit_;
+}; // OurFeatures
+
+// exact copy of Implementation of class Features
+// ////////////////////////////////
+
+OurFeatures OurFeatures::all() { return OurFeatures(); }
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+// exact copy of Reader, renamed to OurReader
+class OurReader {
+public:
+ typedef char Char;
+ typedef const Char* Location;
+ struct StructuredError {
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ JSONCPP_STRING message;
+ };
+
+ OurReader(OurFeatures const& features);
+ bool parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments = true);
+ JSONCPP_STRING getFormattedErrorMessages() const;
+ std::vector<StructuredError> getStructuredErrors() const;
+ bool pushError(const Value& value, const JSONCPP_STRING& message);
+ bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+ bool good() const;
+
+private:
+ OurReader(OurReader const&); // no impl
+ void operator=(OurReader const&); // no impl
+
+ enum TokenType {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenNaN,
+ tokenPosInf,
+ tokenNegInf,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo {
+ public:
+ Token token_;
+ JSONCPP_STRING message_;
+ Location extra_;
+ };
+
+ typedef std::deque<ErrorInfo> Errors;
+
+ bool readToken(Token& token);
+ void skipSpaces();
+ bool match(Location pattern, int patternLength);
+ bool readComment();
+ bool readCStyleComment();
+ bool readCppStyleComment();
+ bool readString();
+ bool readStringSingleQuote();
+ bool readNumber(bool checkInf);
+ bool readValue();
+ bool readObject(Token& token);
+ bool readArray(Token& token);
+ bool decodeNumber(Token& token);
+ bool decodeNumber(Token& token, Value& decoded);
+ bool decodeString(Token& token);
+ bool decodeString(Token& token, JSONCPP_STRING& decoded);
+ bool decodeDouble(Token& token);
+ bool decodeDouble(Token& token, Value& decoded);
+ bool decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+ bool recoverFromError(TokenType skipUntilToken);
+ bool addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
+ TokenType skipUntilToken);
+ void skipUntilSpace();
+ Value& currentValue();
+ Char getNextChar();
+ void
+ getLocationLineAndColumn(Location location, int& line, int& column) const;
+ JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+ void addComment(Location begin, Location end, CommentPlacement placement);
+ void skipCommentTokens(Token& token);
+
+ typedef std::stack<Value*> Nodes;
+ Nodes nodes_;
+ Errors errors_;
+ JSONCPP_STRING document_;
+ Location begin_;
+ Location end_;
+ Location current_;
+ Location lastValueEnd_;
+ Value* lastValue_;
+ JSONCPP_STRING commentsBefore_;
+
+ OurFeatures const features_;
+ bool collectComments_;
+}; // OurReader
+
+// complete copy of Read impl, for OurReader
+
+OurReader::OurReader(OurFeatures const& features)
+ : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+ lastValue_(), commentsBefore_(),
+ features_(features), collectComments_() {
+}
+
+bool OurReader::parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_.clear();
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ bool successful = readValue();
+ Token token;
+ skipCommentTokens(token);
+ if (features_.failIfExtra_) {
+ if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
+ addError("Extra non-whitespace after JSON value.", token);
+ return false;
+ }
+ }
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
+ if (!root.isArray() && !root.isObject()) {
+ // Set error location to start of doc, ideally should be first token found
+ // in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
+ return false;
+ }
+ }
+ return successful;
+}
+
+bool OurReader::readValue() {
+ // To preserve the old behaviour we cast size_t to int.
+ if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+ Token token;
+ skipCommentTokens(token);
+ bool successful = true;
+
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_.clear();
+ }
+
+ switch (token.type_) {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue:
+ {
+ Value v(true);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenFalse:
+ {
+ Value v(false);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNull:
+ {
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNaN:
+ {
+ Value v(std::numeric_limits<double>::quiet_NaN());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenPosInf:
+ {
+ Value v(std::numeric_limits<double>::infinity());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenNegInf:
+ {
+ Value v(-std::numeric_limits<double>::infinity());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ }
+ break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // else, fall through ...
+ default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return addError("Syntax error: value, object or array expected.", token);
+ }
+
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
+ }
+
+ return successful;
+}
+
+void OurReader::skipCommentTokens(Token& token) {
+ if (features_.allowComments_) {
+ do {
+ readToken(token);
+ } while (token.type_ == tokenComment);
+ } else {
+ readToken(token);
+ }
+}
+
+bool OurReader::readToken(Token& token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch (c) {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '\'':
+ if (features_.allowSingleQuotes_) {
+ token.type_ = tokenString;
+ ok = readStringSingleQuote();
+ break;
+ } // else continue
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ token.type_ = tokenNumber;
+ readNumber(false);
+ break;
+ case '-':
+ if (readNumber(true)) {
+ token.type_ = tokenNumber;
+ } else {
+ token.type_ = tokenNegInf;
+ ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+ }
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case 'N':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenNaN;
+ ok = match("aN", 2);
+ } else {
+ ok = false;
+ }
+ break;
+ case 'I':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenPosInf;
+ ok = match("nfinity", 7);
+ } else {
+ ok = false;
+ }
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return true;
+}
+
+void OurReader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ ++current_;
+ else
+ break;
+ }
+}
+
+bool OurReader::match(Location pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
+ return false;
+ int index = patternLength;
+ while (index--)
+ if (current_[index] != pattern[index])
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+bool OurReader::readComment() {
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
+ bool successful = false;
+ if (c == '*')
+ successful = readCStyleComment();
+ else if (c == '/')
+ successful = readCppStyleComment();
+ if (!successful)
+ return false;
+
+ if (collectComments_) {
+ CommentPlacement placement = commentBefore;
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, current_))
+ placement = commentAfterOnSameLine;
+ }
+
+ addComment(commentBegin, current_, placement);
+ }
+ return true;
+}
+
+void
+OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
+ assert(collectComments_);
+ const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
+ if (placement == commentAfterOnSameLine) {
+ assert(lastValue_ != 0);
+ lastValue_->setComment(normalized, placement);
+ } else {
+ commentsBefore_ += normalized;
+ }
+}
+
+bool OurReader::readCStyleComment() {
+ while ((current_ + 1) < end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
+ break;
+ }
+ return getNextChar() == '/';
+}
+
+bool OurReader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ // Consume DOS EOL. It will be normalized in addComment.
+ if (current_ != end_ && *current_ == '\n')
+ getNextChar();
+ // Break on Moc OS 9 EOL.
+ break;
+ }
+ }
+ return true;
+}
+
+bool OurReader::readNumber(bool checkInf) {
+ const char *p = current_;
+ if (checkInf && p != end_ && *p == 'I') {
+ current_ = ++p;
+ return false;
+ }
+ char c = '0'; // stopgap for already consumed character
+ // integral part
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ // fractional part
+ if (c == '.') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+ // exponential part
+ if (c == 'e' || c == 'E') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ if (c == '+' || c == '-')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+ return true;
+}
+bool OurReader::readString() {
+ Char c = 0;
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '"')
+ break;
+ }
+ return c == '"';
+}
+
+
+bool OurReader::readStringSingleQuote() {
+ Char c = 0;
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '\'')
+ break;
+ }
+ return c == '\'';
+}
+
+bool OurReader::readObject(Token& tokenStart) {
+ Token tokenName;
+ JSONCPP_STRING name;
+ Value init(objectValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ while (readToken(tokenName)) {
+ bool initialTokenOk = true;
+ while (tokenName.type_ == tokenComment && initialTokenOk)
+ initialTokenOk = readToken(tokenName);
+ if (!initialTokenOk)
+ break;
+ if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+ return true;
+ name.clear();
+ if (tokenName.type_ == tokenString) {
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ Value numberName;
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
+ name = numberName.asString();
+ } else {
+ break;
+ }
+
+ Token colon;
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover(
+ "Missing ':' after object member name", colon, tokenObjectEnd);
+ }
+ if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
+ if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+ JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
+ return addErrorAndRecover(
+ msg, tokenName, tokenObjectEnd);
+ }
+ Value& value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenObjectEnd);
+
+ Token comma;
+ if (!readToken(comma) ||
+ (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+ comma.type_ != tokenComment)) {
+ return addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ }
+ bool finalizeTokenOk = true;
+ while (comma.type_ == tokenComment && finalizeTokenOk)
+ finalizeTokenOk = readToken(comma);
+ if (comma.type_ == tokenObjectEnd)
+ return true;
+ }
+ return addErrorAndRecover(
+ "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool OurReader::readArray(Token& tokenStart) {
+ Value init(arrayValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']') // empty array
+ {
+ Token endArray;
+ readToken(endArray);
+ return true;
+ }
+ int index = 0;
+ for (;;) {
+ Value& value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenArrayEnd);
+
+ Token token;
+ // Accept Comment after last item in the array.
+ ok = readToken(token);
+ while (token.type_ == tokenComment && ok) {
+ ok = readToken(token);
+ }
+ bool badTokenType =
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ if (!ok || badTokenType) {
+ return addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ }
+ if (token.type_ == tokenArrayEnd)
+ break;
+ }
+ return true;
+}
+
+bool OurReader::decodeNumber(Token& token) {
+ Value decoded;
+ if (!decodeNumber(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool OurReader::decodeNumber(Token& token, Value& decoded) {
+ // Attempts to parse the number as an integer. If the number is
+ // larger than the maximum supported value of an integer then
+ // we decode the number as a double.
+ Location current = token.start_;
+ bool isNegative = *current == '-';
+ if (isNegative)
+ ++current;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+ Value::LargestUInt maxIntegerValue =
+ isNegative ? Value::LargestUInt(-Value::minLargestInt)
+ : Value::maxLargestUInt;
+ Value::LargestUInt threshold = maxIntegerValue / 10;
+ Value::LargestUInt value = 0;
+ while (current < token.end_) {
+ Char c = *current++;
+ if (c < '0' || c > '9')
+ return decodeDouble(token, decoded);
+ Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+ if (value >= threshold) {
+ // We've hit or exceeded the max value divided by 10 (rounded down). If
+ // a) we've only just touched the limit, b) this is the last digit, and
+ // c) it's small enough to fit in that rounding delta, we're okay.
+ // Otherwise treat this number as a double to avoid overflow.
+ if (value > threshold || current != token.end_ ||
+ digit > maxIntegerValue % 10) {
+ return decodeDouble(token, decoded);
+ }
+ }
+ value = value * 10 + digit;
+ }
+ if (isNegative)
+ decoded = -Value::LargestInt(value);
+ else if (value <= Value::LargestUInt(Value::maxInt))
+ decoded = Value::LargestInt(value);
+ else
+ decoded = value;
+ return true;
+}
+
+bool OurReader::decodeDouble(Token& token) {
+ Value decoded;
+ if (!decodeDouble(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool OurReader::decodeDouble(Token& token, Value& decoded) {
+ double value = 0;
+ const int bufferSize = 32;
+ int count;
+ ptrdiff_t const length = token.end_ - token.start_;
+
+ // Sanity check to avoid buffer overflow exploits.
+ if (length < 0) {
+ return addError("Unable to parse token length", token);
+ }
+ size_t const ulength = static_cast<size_t>(length);
+
+ // Avoid using a string constant for the format control string given to
+ // sscanf, as this can cause hard to debug crashes on OS X. See here for more
+ // info:
+ //
+ // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
+ char format[] = "%lf";
+
+ if (length <= bufferSize) {
+ Char buffer[bufferSize + 1];
+ memcpy(buffer, token.start_, ulength);
+ buffer[length] = 0;
+ fixNumericLocaleInput(buffer, buffer + length);
+ count = sscanf(buffer, format, &value);
+ } else {
+ JSONCPP_STRING buffer(token.start_, token.end_);
+ count = sscanf(buffer.c_str(), format, &value);
+ }
+
+ if (count != 1)
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+ "' is not a number.",
+ token);
+ decoded = value;
+ return true;
+}
+
+bool OurReader::decodeString(Token& token) {
+ JSONCPP_STRING decoded_string;
+ if (!decodeString(token, decoded_string))
+ return false;
+ Value decoded(decoded_string);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+ decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while (current != end) {
+ Char c = *current++;
+ if (c == '"')
+ break;
+ else if (c == '\\') {
+ if (current == end)
+ return addError("Empty escape sequence in string", token, current);
+ Char escape = *current++;
+ switch (escape) {
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
+ }
+ } else {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool OurReader::decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode) {
+
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token,
+ current);
+ unsigned int surrogatePair;
+ if (*(current++) == '\\' && *(current++) == 'u') {
+ if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ } else
+ return false;
+ } else
+ return addError("expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token,
+ current);
+ }
+ return true;
+}
+
+bool OurReader::decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& ret_unicode) {
+ if (end - current < 4)
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.",
+ token,
+ current);
+ int unicode = 0;
+ for (int index = 0; index < 4; ++index) {
+ Char c = *current++;
+ unicode *= 16;
+ if (c >= '0' && c <= '9')
+ unicode += c - '0';
+ else if (c >= 'a' && c <= 'f')
+ unicode += c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ unicode += c - 'A' + 10;
+ else
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token,
+ current);
+ }
+ ret_unicode = static_cast<unsigned int>(unicode);
+ return true;
+}
+
+bool
+OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back(info);
+ return false;
+}
+
+bool OurReader::recoverFromError(TokenType skipUntilToken) {
+ size_t errorCount = errors_.size();
+ Token skip;
+ for (;;) {
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
+ if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+ break;
+ }
+ errors_.resize(errorCount);
+ return false;
+}
+
+bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
+ Token& token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
+}
+
+Value& OurReader::currentValue() { return *(nodes_.top()); }
+
+OurReader::Char OurReader::getNextChar() {
+ if (current_ == end_)
+ return 0;
+ return *current_++;
+}
+
+void OurReader::getLocationLineAndColumn(Location location,
+ int& line,
+ int& column) const {
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while (current < location && current != end_) {
+ Char c = *current++;
+ if (c == '\r') {
+ if (*current == '\n')
+ ++current;
+ lastLineStart = current;
+ ++line;
+ } else if (c == '\n') {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
+ int line, column;
+ getLocationLineAndColumn(location, line, column);
+ char buffer[18 + 16 + 16 + 1];
+ snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+ return buffer;
+}
+
+JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
+ JSONCPP_STRING formattedMessage;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
+ const ErrorInfo& error = *itError;
+ formattedMessage +=
+ "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if (error.extra_)
+ formattedMessage +=
+ "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+ std::vector<OurReader::StructuredError> allErrors;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
+ const ErrorInfo& error = *itError;
+ OurReader::StructuredError structured;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
+ structured.message = error.message_;
+ allErrors.push_back(structured);
+ }
+ return allErrors;
+}
+
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = end_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = 0;
+ errors_.push_back(info);
+ return true;
+}
+
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+ ptrdiff_t length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length
+ || extra.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
+ return true;
+}
+
+bool OurReader::good() const {
+ return !errors_.size();
+}
+
+
+class OurCharReader : public CharReader {
+ bool const collectComments_;
+ OurReader reader_;
+public:
+ OurCharReader(
+ bool collectComments,
+ OurFeatures const& features)
+ : collectComments_(collectComments)
+ , reader_(features)
+ {}
+ bool parse(
+ char const* beginDoc, char const* endDoc,
+ Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
+ bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
+ if (errs) {
+ *errs = reader_.getFormattedErrorMessages();
+ }
+ return ok;
+ }
+};
+
+CharReaderBuilder::CharReaderBuilder()
+{
+ setDefaults(&settings_);
+}
+CharReaderBuilder::~CharReaderBuilder()
+{}
+CharReader* CharReaderBuilder::newCharReader() const
+{
+ bool collectComments = settings_["collectComments"].asBool();
+ OurFeatures features = OurFeatures::all();
+ features.allowComments_ = settings_["allowComments"].asBool();
+ features.strictRoot_ = settings_["strictRoot"].asBool();
+ features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
+ features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
+ features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
+ features.stackLimit_ = settings_["stackLimit"].asInt();
+ features.failIfExtra_ = settings_["failIfExtra"].asBool();
+ features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+ features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+ return new OurCharReader(collectComments, features);
+}
+static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
+{
+ valid_keys->clear();
+ valid_keys->insert("collectComments");
+ valid_keys->insert("allowComments");
+ valid_keys->insert("strictRoot");
+ valid_keys->insert("allowDroppedNullPlaceholders");
+ valid_keys->insert("allowNumericKeys");
+ valid_keys->insert("allowSingleQuotes");
+ valid_keys->insert("stackLimit");
+ valid_keys->insert("failIfExtra");
+ valid_keys->insert("rejectDupKeys");
+ valid_keys->insert("allowSpecialFloats");
+}
+bool CharReaderBuilder::validate(Json::Value* invalid) const
+{
+ Json::Value my_invalid;
+ if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
+ Json::Value& inv = *invalid;
+ std::set<JSONCPP_STRING> valid_keys;
+ getValidReaderKeys(&valid_keys);
+ Value::Members keys = settings_.getMemberNames();
+ size_t n = keys.size();
+ for (size_t i = 0; i < n; ++i) {
+ JSONCPP_STRING const& key = keys[i];
+ if (valid_keys.find(key) == valid_keys.end()) {
+ inv[key] = settings_[key];
+ }
+ }
+ return 0u == inv.size();
+}
+Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
+{
+ return settings_[key];
+}
+// static
+void CharReaderBuilder::strictMode(Json::Value* settings)
+{
+//! [CharReaderBuilderStrictMode]
+ (*settings)["allowComments"] = false;
+ (*settings)["strictRoot"] = true;
+ (*settings)["allowDroppedNullPlaceholders"] = false;
+ (*settings)["allowNumericKeys"] = false;
+ (*settings)["allowSingleQuotes"] = false;
+ (*settings)["stackLimit"] = 1000;
+ (*settings)["failIfExtra"] = true;
+ (*settings)["rejectDupKeys"] = true;
+ (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderStrictMode]
+}
+// static
+void CharReaderBuilder::setDefaults(Json::Value* settings)
+{
+//! [CharReaderBuilderDefaults]
+ (*settings)["collectComments"] = true;
+ (*settings)["allowComments"] = true;
+ (*settings)["strictRoot"] = false;
+ (*settings)["allowDroppedNullPlaceholders"] = false;
+ (*settings)["allowNumericKeys"] = false;
+ (*settings)["allowSingleQuotes"] = false;
+ (*settings)["stackLimit"] = 1000;
+ (*settings)["failIfExtra"] = false;
+ (*settings)["rejectDupKeys"] = false;
+ (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderDefaults]
+}
+
+//////////////////////////////////
+// global functions
+
+bool parseFromStream(
+ CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
+ Value* root, JSONCPP_STRING* errs)
+{
+ JSONCPP_OSTRINGSTREAM ssin;
+ ssin << sin.rdbuf();
+ JSONCPP_STRING doc = ssin.str();
+ char const* begin = doc.data();
+ char const* end = begin + doc.size();
+ // Note that we do not actually need a null-terminator.
+ CharReaderPtr const reader(fact.newCharReader());
+ return reader->parse(begin, end, root, errs);
+}
+
+JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
+ CharReaderBuilder b;
+ JSONCPP_STRING errs;
+ bool ok = parseFromStream(b, sin, &root, &errs);
+ if (!ok) {
+ fprintf(stderr,
+ "Error from reader: %s",
+ errs.c_str());
+
+ throwRuntimeError(errs);
+ }
+ return sin;
+}
+
+} // namespace Json
diff --git a/extern/jsoncpp/src/json_tool.h b/extern/jsoncpp/src/json_tool.h
new file mode 100644
index 00000000000..41d0f49d218
--- /dev/null
+++ b/extern/jsoncpp/src/json_tool.h
@@ -0,0 +1,117 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+
+// Also support old flag NO_LOCALE_SUPPORT
+#ifdef NO_LOCALE_SUPPORT
+#define JSONCPP_NO_LOCALE_SUPPORT
+#endif
+
+#ifndef JSONCPP_NO_LOCALE_SUPPORT
+#include <clocale>
+#endif
+
+/* This header provides common string manipulation support, such as UTF-8,
+ * portable conversion from/to string...
+ *
+ * It is an internal header that must not be exposed.
+ */
+
+namespace Json {
+static char getDecimalPoint() {
+#ifdef JSONCPP_NO_LOCALE_SUPPORT
+ return '\0';
+#else
+ struct lconv* lc = localeconv();
+ return lc ? *(lc->decimal_point) : '\0';
+#endif
+}
+
+/// Converts a unicode code-point to UTF-8.
+static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
+ JSONCPP_STRING result;
+
+ // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+ if (cp <= 0x7f) {
+ result.resize(1);
+ result[0] = static_cast<char>(cp);
+ } else if (cp <= 0x7FF) {
+ result.resize(2);
+ result[1] = static_cast<char>(0x80 | (0x3f & cp));
+ result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+ } else if (cp <= 0xFFFF) {
+ result.resize(3);
+ result[2] = static_cast<char>(0x80 | (0x3f & cp));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
+ } else if (cp <= 0x10FFFF) {
+ result.resize(4);
+ result[3] = static_cast<char>(0x80 | (0x3f & cp));
+ result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+ result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+ }
+
+ return result;
+}
+
+/// Returns true if ch is a control character (in range [1,31]).
+static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
+
+enum {
+ /// Constant that specify the size of the buffer that must be passed to
+ /// uintToString.
+ uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
+};
+
+// Defines a char buffer for use with uintToString().
+typedef char UIntToStringBuffer[uintToStringBufferSize];
+
+/** Converts an unsigned integer to string.
+ * @param value Unsigned interger to convert to string
+ * @param current Input/Output string buffer.
+ * Must have at least uintToStringBufferSize chars free.
+ */
+static inline void uintToString(LargestUInt value, char*& current) {
+ *--current = 0;
+ do {
+ *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
+ value /= 10;
+ } while (value != 0);
+}
+
+/** Change ',' to '.' everywhere in buffer.
+ *
+ * We had a sophisticated way, but it did not work in WinCE.
+ * @see https://github.com/open-source-parsers/jsoncpp/pull/9
+ */
+static inline void fixNumericLocale(char* begin, char* end) {
+ while (begin < end) {
+ if (*begin == ',') {
+ *begin = '.';
+ }
+ ++begin;
+ }
+}
+
+static inline void fixNumericLocaleInput(char* begin, char* end) {
+ char decimalPoint = getDecimalPoint();
+ if (decimalPoint != '\0' && decimalPoint != '.') {
+ while (begin < end) {
+ if (*begin == '.') {
+ *begin = decimalPoint;
+ }
+ ++begin;
+ }
+ }
+}
+
+} // namespace Json {
+
+#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
diff --git a/extern/jsoncpp/src/json_value.cpp b/extern/jsoncpp/src/json_value.cpp
new file mode 100644
index 00000000000..5f5cf8bf086
--- /dev/null
+++ b/extern/jsoncpp/src/json_value.cpp
@@ -0,0 +1,1665 @@
+// Copyright 2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/value.h>
+#include <json/writer.h>
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <math.h>
+#include <sstream>
+#include <utility>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+#include <cpptl/conststring.h>
+#endif
+#include <cstddef> // size_t
+#include <algorithm> // min()
+
+#define JSON_ASSERT_UNREACHABLE assert(false)
+
+namespace Json {
+
+// This is a walkaround to avoid the static initialization of Value::null.
+// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
+// 8 (instead of 4) as a bit of future-proofing.
+#if defined(__ARMEL__)
+#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#else
+#define ALIGNAS(byte_alignment)
+#endif
+//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+//const unsigned char& kNullRef = kNull[0];
+//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+//const Value& Value::nullRef = null;
+
+// static
+Value const& Value::nullSingleton()
+{
+ static Value const nullStatic;
+ return nullStatic;
+}
+
+// for backwards compatibility, we'll leave these global references around, but DO NOT
+// use them in JSONCPP library code any more!
+Value const& Value::null = Value::nullSingleton();
+Value const& Value::nullRef = Value::nullSingleton();
+
+const Int Value::minInt = Int(~(UInt(-1) / 2));
+const Int Value::maxInt = Int(UInt(-1) / 2);
+const UInt Value::maxUInt = UInt(-1);
+#if defined(JSON_HAS_INT64)
+const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
+const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
+const UInt64 Value::maxUInt64 = UInt64(-1);
+// The constant is hard-coded because some compiler have trouble
+// converting Value::maxUInt64 to a double correctly (AIX/xlC).
+// Assumes that UInt64 is a 64 bits integer.
+static const double maxUInt64AsDouble = 18446744073709551615.0;
+#endif // defined(JSON_HAS_INT64)
+const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
+const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
+const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+ // The casts can lose precision, but we are looking only for
+ // an approximate range. Might fail on edge cases though. ~cdunn
+ //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
+ return d >= min && d <= max;
+}
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+static inline double integerToDouble(Json::UInt64 value) {
+ return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
+}
+
+template <typename T> static inline double integerToDouble(T value) {
+ return static_cast<double>(value);
+}
+
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+ return d >= integerToDouble(min) && d <= integerToDouble(max);
+}
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+
+/** Duplicates the specified string value.
+ * @param value Pointer to the string to duplicate. Must be zero-terminated if
+ * length is "unknown".
+ * @param length Length of the value. if equals to unknown, then it will be
+ * computed using strlen(value).
+ * @return Pointer on the duplicate instance of string.
+ */
+static inline char* duplicateStringValue(const char* value,
+ size_t length)
+{
+ // Avoid an integer overflow in the call to malloc below by limiting length
+ // to a sane value.
+ if (length >= static_cast<size_t>(Value::maxInt))
+ length = Value::maxInt - 1;
+
+ char* newString = static_cast<char*>(malloc(length + 1));
+ if (newString == NULL) {
+ throwRuntimeError(
+ "in Json::Value::duplicateStringValue(): "
+ "Failed to allocate string value buffer");
+ }
+ memcpy(newString, value, length);
+ newString[length] = 0;
+ return newString;
+}
+
+/* Record the length as a prefix.
+ */
+static inline char* duplicateAndPrefixStringValue(
+ const char* value,
+ unsigned int length)
+{
+ // Avoid an integer overflow in the call to malloc below by limiting length
+ // to a sane value.
+ JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
+ "in Json::Value::duplicateAndPrefixStringValue(): "
+ "length too big for prefixing");
+ unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
+ char* newString = static_cast<char*>(malloc(actualLength));
+ if (newString == 0) {
+ throwRuntimeError(
+ "in Json::Value::duplicateAndPrefixStringValue(): "
+ "Failed to allocate string value buffer");
+ }
+ *reinterpret_cast<unsigned*>(newString) = length;
+ memcpy(newString + sizeof(unsigned), value, length);
+ newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
+ return newString;
+}
+inline static void decodePrefixedString(
+ bool isPrefixed, char const* prefixed,
+ unsigned* length, char const** value)
+{
+ if (!isPrefixed) {
+ *length = static_cast<unsigned>(strlen(prefixed));
+ *value = prefixed;
+ } else {
+ *length = *reinterpret_cast<unsigned const*>(prefixed);
+ *value = prefixed + sizeof(unsigned);
+ }
+}
+/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
+ */
+#if JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+ unsigned length = 0;
+ char const* valueDecoded;
+ decodePrefixedString(true, value, &length, &valueDecoded);
+ size_t const size = sizeof(unsigned) + length + 1U;
+ memset(value, 0, size);
+ free(value);
+}
+static inline void releaseStringValue(char* value, unsigned length) {
+ // length==0 => we allocated the strings memory
+ size_t size = (length==0) ? strlen(value) : length;
+ memset(value, 0, size);
+ free(value);
+}
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+ free(value);
+}
+static inline void releaseStringValue(char* value, unsigned) {
+ free(value);
+}
+#endif // JSONCPP_USING_SECURE_MEMORY
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "json_valueiterator.inl"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+Exception::Exception(JSONCPP_STRING const& msg)
+ : msg_(msg)
+{}
+Exception::~Exception() JSONCPP_NOEXCEPT
+{}
+char const* Exception::what() const JSONCPP_NOEXCEPT
+{
+ return msg_.c_str();
+}
+RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
+ : Exception(msg)
+{}
+LogicError::LogicError(JSONCPP_STRING const& msg)
+ : Exception(msg)
+{}
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
+{
+ throw RuntimeError(msg);
+}
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
+{
+ throw LogicError(msg);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+Value::CommentInfo::CommentInfo() : comment_(0)
+{}
+
+Value::CommentInfo::~CommentInfo() {
+ if (comment_)
+ releaseStringValue(comment_, 0u);
+}
+
+void Value::CommentInfo::setComment(const char* text, size_t len) {
+ if (comment_) {
+ releaseStringValue(comment_, 0u);
+ comment_ = 0;
+ }
+ JSON_ASSERT(text != 0);
+ JSON_ASSERT_MESSAGE(
+ text[0] == '\0' || text[0] == '/',
+ "in Json::Value::setComment(): Comments must start with /");
+ // It seems that /**/ style comments are acceptable as well.
+ comment_ = duplicateStringValue(text, len);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+// Notes: policy_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
+
+Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+ : cstr_(str) {
+ // allocate != duplicate
+ storage_.policy_ = allocate & 0x3;
+ storage_.length_ = ulength & 0x3FFFFFFF;
+}
+
+Value::CZString::CZString(const CZString& other) {
+ cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
+ ? duplicateStringValue(other.cstr_, other.storage_.length_)
+ : other.cstr_);
+ storage_.policy_ = static_cast<unsigned>(other.cstr_
+ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
+ ? noDuplication : duplicate)
+ : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
+ storage_.length_ = other.storage_.length_;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString::CZString(CZString&& other)
+ : cstr_(other.cstr_), index_(other.index_) {
+ other.cstr_ = nullptr;
+}
+#endif
+
+Value::CZString::~CZString() {
+ if (cstr_ && storage_.policy_ == duplicate) {
+ releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
+ }
+}
+
+void Value::CZString::swap(CZString& other) {
+ std::swap(cstr_, other.cstr_);
+ std::swap(index_, other.index_);
+}
+
+Value::CZString& Value::CZString::operator=(const CZString& other) {
+ cstr_ = other.cstr_;
+ index_ = other.index_;
+ return *this;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString& Value::CZString::operator=(CZString&& other) {
+ cstr_ = other.cstr_;
+ index_ = other.index_;
+ other.cstr_ = nullptr;
+ return *this;
+}
+#endif
+
+bool Value::CZString::operator<(const CZString& other) const {
+ if (!cstr_) return index_ < other.index_;
+ //return strcmp(cstr_, other.cstr_) < 0;
+ // Assume both are strings.
+ unsigned this_len = this->storage_.length_;
+ unsigned other_len = other.storage_.length_;
+ unsigned min_len = std::min<unsigned>(this_len, other_len);
+ JSON_ASSERT(this->cstr_ && other.cstr_);
+ int comp = memcmp(this->cstr_, other.cstr_, min_len);
+ if (comp < 0) return true;
+ if (comp > 0) return false;
+ return (this_len < other_len);
+}
+
+bool Value::CZString::operator==(const CZString& other) const {
+ if (!cstr_) return index_ == other.index_;
+ //return strcmp(cstr_, other.cstr_) == 0;
+ // Assume both are strings.
+ unsigned this_len = this->storage_.length_;
+ unsigned other_len = other.storage_.length_;
+ if (this_len != other_len) return false;
+ JSON_ASSERT(this->cstr_ && other.cstr_);
+ int comp = memcmp(this->cstr_, other.cstr_, this_len);
+ return comp == 0;
+}
+
+ArrayIndex Value::CZString::index() const { return index_; }
+
+//const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const { return cstr_; }
+unsigned Value::CZString::length() const { return storage_.length_; }
+bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value(ValueType vtype) {
+ static char const emptyString[] = "";
+ initBasic(vtype);
+ switch (vtype) {
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ value_.int_ = 0;
+ break;
+ case realValue:
+ value_.real_ = 0.0;
+ break;
+ case stringValue:
+ // allocated_ == false, so this is safe.
+ value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues();
+ break;
+ case booleanValue:
+ value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+Value::Value(Int value) {
+ initBasic(intValue);
+ value_.int_ = value;
+}
+
+Value::Value(UInt value) {
+ initBasic(uintValue);
+ value_.uint_ = value;
+}
+#if defined(JSON_HAS_INT64)
+Value::Value(Int64 value) {
+ initBasic(intValue);
+ value_.int_ = value;
+}
+Value::Value(UInt64 value) {
+ initBasic(uintValue);
+ value_.uint_ = value;
+}
+#endif // defined(JSON_HAS_INT64)
+
+Value::Value(double value) {
+ initBasic(realValue);
+ value_.real_ = value;
+}
+
+Value::Value(const char* value) {
+ initBasic(stringValue, true);
+ JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
+ value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+}
+
+Value::Value(const char* beginValue, const char* endValue) {
+ initBasic(stringValue, true);
+ value_.string_ =
+ duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+}
+
+Value::Value(const JSONCPP_STRING& value) {
+ initBasic(stringValue, true);
+ value_.string_ =
+ duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+}
+
+Value::Value(const StaticString& value) {
+ initBasic(stringValue);
+ value_.string_ = const_cast<char*>(value.c_str());
+}
+
+#ifdef JSON_USE_CPPTL
+Value::Value(const CppTL::ConstString& value) {
+ initBasic(stringValue, true);
+ value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
+}
+#endif
+
+Value::Value(bool value) {
+ initBasic(booleanValue);
+ value_.bool_ = value;
+}
+
+Value::Value(Value const& other)
+ : type_(other.type_), allocated_(false)
+ ,
+ comments_(0), start_(other.start_), limit_(other.limit_)
+{
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if (other.value_.string_ && other.allocated_) {
+ unsigned len;
+ char const* str;
+ decodePrefixedString(other.allocated_, other.value_.string_,
+ &len, &str);
+ value_.string_ = duplicateAndPrefixStringValue(str, len);
+ allocated_ = true;
+ } else {
+ value_.string_ = other.value_.string_;
+ allocated_ = false;
+ }
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues(*other.value_.map_);
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ if (other.comments_) {
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
+ const CommentInfo& otherComment = other.comments_[comment];
+ if (otherComment.comment_)
+ comments_[comment].setComment(
+ otherComment.comment_, strlen(otherComment.comment_));
+ }
+ }
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+// Move constructor
+Value::Value(Value&& other) {
+ initBasic(nullValue);
+ swap(other);
+}
+#endif
+
+Value::~Value() {
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if (allocated_)
+ releasePrefixedStringValue(value_.string_);
+ break;
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+
+ delete[] comments_;
+
+ value_.uint_ = 0;
+}
+
+Value& Value::operator=(const Value& other) {
+ swap(const_cast<Value&>(other));
+ return *this;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value& Value::operator=(Value&& other) {
+ initBasic(nullValue);
+ swap(other);
+ return *this;
+}
+#endif
+
+void Value::swapPayload(Value& other) {
+ ValueType temp = type_;
+ type_ = other.type_;
+ other.type_ = temp;
+ std::swap(value_, other.value_);
+ int temp2 = allocated_;
+ allocated_ = other.allocated_;
+ other.allocated_ = temp2 & 0x1;
+}
+
+void Value::copyPayload(const Value& other) {
+ type_ = other.type_;
+ value_ = other.value_;
+ allocated_ = other.allocated_;
+}
+
+void Value::swap(Value& other) {
+ swapPayload(other);
+ std::swap(comments_, other.comments_);
+ std::swap(start_, other.start_);
+ std::swap(limit_, other.limit_);
+}
+
+void Value::copy(const Value& other) {
+ copyPayload(other);
+ comments_ = other.comments_;
+ start_ = other.start_;
+ limit_ = other.limit_;
+}
+
+ValueType Value::type() const { return type_; }
+
+int Value::compare(const Value& other) const {
+ if (*this < other)
+ return -1;
+ if (*this > other)
+ return 1;
+ return 0;
+}
+
+bool Value::operator<(const Value& other) const {
+ int typeDelta = type_ - other.type_;
+ if (typeDelta)
+ return typeDelta < 0 ? true : false;
+ switch (type_) {
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ < other.value_.int_;
+ case uintValue:
+ return value_.uint_ < other.value_.uint_;
+ case realValue:
+ return value_.real_ < other.value_.real_;
+ case booleanValue:
+ return value_.bool_ < other.value_.bool_;
+ case stringValue:
+ {
+ if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+ if (other.value_.string_) return true;
+ else return false;
+ }
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+ unsigned min_len = std::min<unsigned>(this_len, other_len);
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, min_len);
+ if (comp < 0) return true;
+ if (comp > 0) return false;
+ return (this_len < other_len);
+ }
+ case arrayValue:
+ case objectValue: {
+ int delta = int(value_.map_->size() - other.value_.map_->size());
+ if (delta)
+ return delta < 0;
+ return (*value_.map_) < (*other.value_.map_);
+ }
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable
+}
+
+bool Value::operator<=(const Value& other) const { return !(other < *this); }
+
+bool Value::operator>=(const Value& other) const { return !(*this < other); }
+
+bool Value::operator>(const Value& other) const { return other < *this; }
+
+bool Value::operator==(const Value& other) const {
+ // if ( type_ != other.type_ )
+ // GCC 2.95.3 says:
+ // attempt to take address of bit-field structure member `Json::Value::type_'
+ // Beats me, but a temp solves the problem.
+ int temp = other.type_;
+ if (type_ != temp)
+ return false;
+ switch (type_) {
+ case nullValue:
+ return true;
+ case intValue:
+ return value_.int_ == other.value_.int_;
+ case uintValue:
+ return value_.uint_ == other.value_.uint_;
+ case realValue:
+ return value_.real_ == other.value_.real_;
+ case booleanValue:
+ return value_.bool_ == other.value_.bool_;
+ case stringValue:
+ {
+ if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+ return (value_.string_ == other.value_.string_);
+ }
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+ if (this_len != other_len) return false;
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, this_len);
+ return comp == 0;
+ }
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() == other.value_.map_->size() &&
+ (*value_.map_) == (*other.value_.map_);
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable
+}
+
+bool Value::operator!=(const Value& other) const { return !(*this == other); }
+
+const char* Value::asCString() const {
+ JSON_ASSERT_MESSAGE(type_ == stringValue,
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0) return 0;
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ return this_str;
+}
+
+#if JSONCPP_USING_SECURE_MEMORY
+unsigned Value::getCStringLength() const {
+ JSON_ASSERT_MESSAGE(type_ == stringValue,
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0) return 0;
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ return this_len;
+}
+#endif
+
+bool Value::getString(char const** str, char const** cend) const {
+ if (type_ != stringValue) return false;
+ if (value_.string_ == 0) return false;
+ unsigned length;
+ decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
+ *cend = *str + length;
+ return true;
+}
+
+JSONCPP_STRING Value::asString() const {
+ switch (type_) {
+ case nullValue:
+ return "";
+ case stringValue:
+ {
+ if (value_.string_ == 0) return "";
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ return JSONCPP_STRING(this_str, this_len);
+ }
+ case booleanValue:
+ return value_.bool_ ? "true" : "false";
+ case intValue:
+ return valueToString(value_.int_);
+ case uintValue:
+ return valueToString(value_.uint_);
+ case realValue:
+ return valueToString(value_.real_);
+ default:
+ JSON_FAIL_MESSAGE("Type is not convertible to string");
+ }
+}
+
+#ifdef JSON_USE_CPPTL
+CppTL::ConstString Value::asConstString() const {
+ unsigned len;
+ char const* str;
+ decodePrefixedString(allocated_, value_.string_,
+ &len, &str);
+ return CppTL::ConstString(str, len);
+}
+#endif
+
+Value::Int Value::asInt() const {
+ switch (type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
+ return Int(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
+ return Int(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
+ "double out of Int range");
+ return Int(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to Int.");
+}
+
+Value::UInt Value::asUInt() const {
+ switch (type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
+ return UInt(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
+ return UInt(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
+ "double out of UInt range");
+ return UInt(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
+}
+
+#if defined(JSON_HAS_INT64)
+
+Value::Int64 Value::asInt64() const {
+ switch (type_) {
+ case intValue:
+ return Int64(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
+ return Int64(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
+ "double out of Int64 range");
+ return Int64(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
+}
+
+Value::UInt64 Value::asUInt64() const {
+ switch (type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
+ return UInt64(value_.int_);
+ case uintValue:
+ return UInt64(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
+ "double out of UInt64 range");
+ return UInt64(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
+}
+#endif // if defined(JSON_HAS_INT64)
+
+LargestInt Value::asLargestInt() const {
+#if defined(JSON_NO_INT64)
+ return asInt();
+#else
+ return asInt64();
+#endif
+}
+
+LargestUInt Value::asLargestUInt() const {
+#if defined(JSON_NO_INT64)
+ return asUInt();
+#else
+ return asUInt64();
+#endif
+}
+
+double Value::asDouble() const {
+ switch (type_) {
+ case intValue:
+ return static_cast<double>(value_.int_);
+ case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return static_cast<double>(value_.uint_);
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return integerToDouble(value_.uint_);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ case realValue:
+ return value_.real_;
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return value_.bool_ ? 1.0 : 0.0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to double.");
+}
+
+float Value::asFloat() const {
+ switch (type_) {
+ case intValue:
+ return static_cast<float>(value_.int_);
+ case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return static_cast<float>(value_.uint_);
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ // This can fail (silently?) if the value is bigger than MAX_FLOAT.
+ return static_cast<float>(integerToDouble(value_.uint_));
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ case realValue:
+ return static_cast<float>(value_.real_);
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return value_.bool_ ? 1.0f : 0.0f;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to float.");
+}
+
+bool Value::asBool() const {
+ switch (type_) {
+ case booleanValue:
+ return value_.bool_;
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ ? true : false;
+ case uintValue:
+ return value_.uint_ ? true : false;
+ case realValue:
+ // This is kind of strange. Not recommended.
+ return (value_.real_ != 0.0) ? true : false;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to bool.");
+}
+
+bool Value::isConvertibleTo(ValueType other) const {
+ switch (other) {
+ case nullValue:
+ return (isNumeric() && asDouble() == 0.0) ||
+ (type_ == booleanValue && value_.bool_ == false) ||
+ (type_ == stringValue && asString().empty()) ||
+ (type_ == arrayValue && value_.map_->size() == 0) ||
+ (type_ == objectValue && value_.map_->size() == 0) ||
+ type_ == nullValue;
+ case intValue:
+ return isInt() ||
+ (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
+ type_ == booleanValue || type_ == nullValue;
+ case uintValue:
+ return isUInt() ||
+ (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
+ type_ == booleanValue || type_ == nullValue;
+ case realValue:
+ return isNumeric() || type_ == booleanValue || type_ == nullValue;
+ case booleanValue:
+ return isNumeric() || type_ == booleanValue || type_ == nullValue;
+ case stringValue:
+ return isNumeric() || type_ == booleanValue || type_ == stringValue ||
+ type_ == nullValue;
+ case arrayValue:
+ return type_ == arrayValue || type_ == nullValue;
+ case objectValue:
+ return type_ == objectValue || type_ == nullValue;
+ }
+ JSON_ASSERT_UNREACHABLE;
+ return false;
+}
+
+/// Number of values in array or object
+ArrayIndex Value::size() const {
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+ case arrayValue: // size of the array is highest index + 1
+ if (!value_.map_->empty()) {
+ ObjectValues::const_iterator itLast = value_.map_->end();
+ --itLast;
+ return (*itLast).first.index() + 1;
+ }
+ return 0;
+ case objectValue:
+ return ArrayIndex(value_.map_->size());
+ }
+ JSON_ASSERT_UNREACHABLE;
+ return 0; // unreachable;
+}
+
+bool Value::empty() const {
+ if (isNull() || isArray() || isObject())
+ return size() == 0u;
+ else
+ return false;
+}
+
+bool Value::operator!() const { return isNull(); }
+
+void Value::clear() {
+ JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
+ type_ == objectValue,
+ "in Json::Value::clear(): requires complex value");
+ start_ = 0;
+ limit_ = 0;
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ value_.map_->clear();
+ break;
+ default:
+ break;
+ }
+}
+
+void Value::resize(ArrayIndex newSize) {
+ JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::resize(): requires arrayValue");
+ if (type_ == nullValue)
+ *this = Value(arrayValue);
+ ArrayIndex oldSize = size();
+ if (newSize == 0)
+ clear();
+ else if (newSize > oldSize)
+ (*this)[newSize - 1];
+ else {
+ for (ArrayIndex index = newSize; index < oldSize; ++index) {
+ value_.map_->erase(index);
+ }
+ JSON_ASSERT(size() == newSize);
+ }
+}
+
+Value& Value::operator[](ArrayIndex index) {
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+ if (type_ == nullValue)
+ *this = Value(arrayValue);
+ CZString key(index);
+ ObjectValues::iterator it = value_.map_->lower_bound(key);
+ if (it != value_.map_->end() && (*it).first == key)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(key, nullSingleton());
+ it = value_.map_->insert(it, defaultValue);
+ return (*it).second;
+}
+
+Value& Value::operator[](int index) {
+ JSON_ASSERT_MESSAGE(
+ index >= 0,
+ "in Json::Value::operator[](int index): index cannot be negative");
+ return (*this)[ArrayIndex(index)];
+}
+
+const Value& Value::operator[](ArrayIndex index) const {
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+ if (type_ == nullValue)
+ return nullSingleton();
+ CZString key(index);
+ ObjectValues::const_iterator it = value_.map_->find(key);
+ if (it == value_.map_->end())
+ return nullSingleton();
+ return (*it).second;
+}
+
+const Value& Value::operator[](int index) const {
+ JSON_ASSERT_MESSAGE(
+ index >= 0,
+ "in Json::Value::operator[](int index) const: index cannot be negative");
+ return (*this)[ArrayIndex(index)];
+}
+
+void Value::initBasic(ValueType vtype, bool allocated) {
+ type_ = vtype;
+ allocated_ = allocated;
+ comments_ = 0;
+ start_ = 0;
+ limit_ = 0;
+}
+
+// Access an object value by name, create a null member if it does not exist.
+// @pre Type of '*this' is object or null.
+// @param key is null-terminated.
+Value& Value::resolveReference(const char* key) {
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(): requires objectValue");
+ if (type_ == nullValue)
+ *this = Value(objectValue);
+ CZString actualKey(
+ key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
+ ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
+ it = value_.map_->insert(it, defaultValue);
+ Value& value = (*it).second;
+ return value;
+}
+
+// @param key is not null-terminated.
+Value& Value::resolveReference(char const* key, char const* cend)
+{
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(key, end): requires objectValue");
+ if (type_ == nullValue)
+ *this = Value(objectValue);
+ CZString actualKey(
+ key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
+ ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
+ it = value_.map_->insert(it, defaultValue);
+ Value& value = (*it).second;
+ return value;
+}
+
+Value Value::get(ArrayIndex index, const Value& defaultValue) const {
+ const Value* value = &((*this)[index]);
+ return value == &nullSingleton() ? defaultValue : *value;
+}
+
+bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
+
+Value const* Value::find(char const* key, char const* cend) const
+{
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::find(key, end, found): requires objectValue or nullValue");
+ if (type_ == nullValue) return NULL;
+ CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+ ObjectValues::const_iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end()) return NULL;
+ return &(*it).second;
+}
+const Value& Value::operator[](const char* key) const
+{
+ Value const* found = find(key, key + strlen(key));
+ if (!found) return nullSingleton();
+ return *found;
+}
+Value const& Value::operator[](JSONCPP_STRING const& key) const
+{
+ Value const* found = find(key.data(), key.data() + key.length());
+ if (!found) return nullSingleton();
+ return *found;
+}
+
+Value& Value::operator[](const char* key) {
+ return resolveReference(key, key + strlen(key));
+}
+
+Value& Value::operator[](const JSONCPP_STRING& key) {
+ return resolveReference(key.data(), key.data() + key.length());
+}
+
+Value& Value::operator[](const StaticString& key) {
+ return resolveReference(key.c_str());
+}
+
+#ifdef JSON_USE_CPPTL
+Value& Value::operator[](const CppTL::ConstString& key) {
+ return resolveReference(key.c_str(), key.end_c_str());
+}
+Value const& Value::operator[](CppTL::ConstString const& key) const
+{
+ Value const* found = find(key.c_str(), key.end_c_str());
+ if (!found) return nullSingleton();
+ return *found;
+}
+#endif
+
+Value& Value::append(const Value& value) { return (*this)[size()] = value; }
+
+#if JSON_HAS_RVALUE_REFERENCES
+ Value& Value::append(Value&& value) { return (*this)[size()] = value; }
+#endif
+
+Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
+{
+ Value const* found = find(key, cend);
+ return !found ? defaultValue : *found;
+}
+Value Value::get(char const* key, Value const& defaultValue) const
+{
+ return get(key, key + strlen(key), defaultValue);
+}
+Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
+{
+ return get(key.data(), key.data() + key.length(), defaultValue);
+}
+
+
+bool Value::removeMember(const char* key, const char* cend, Value* removed)
+{
+ if (type_ != objectValue) {
+ return false;
+ }
+ CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+ ObjectValues::iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end())
+ return false;
+ *removed = it->second;
+ value_.map_->erase(it);
+ return true;
+}
+bool Value::removeMember(const char* key, Value* removed)
+{
+ return removeMember(key, key + strlen(key), removed);
+}
+bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
+{
+ return removeMember(key.data(), key.data() + key.length(), removed);
+}
+Value Value::removeMember(const char* key)
+{
+ JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+ "in Json::Value::removeMember(): requires objectValue");
+ if (type_ == nullValue)
+ return nullSingleton();
+
+ Value removed; // null
+ removeMember(key, key + strlen(key), &removed);
+ return removed; // still null if removeMember() did nothing
+}
+Value Value::removeMember(const JSONCPP_STRING& key)
+{
+ return removeMember(key.c_str());
+}
+
+bool Value::removeIndex(ArrayIndex index, Value* removed) {
+ if (type_ != arrayValue) {
+ return false;
+ }
+ CZString key(index);
+ ObjectValues::iterator it = value_.map_->find(key);
+ if (it == value_.map_->end()) {
+ return false;
+ }
+ *removed = it->second;
+ ArrayIndex oldSize = size();
+ // shift left all items left, into the place of the "removed"
+ for (ArrayIndex i = index; i < (oldSize - 1); ++i){
+ CZString keey(i);
+ (*value_.map_)[keey] = (*this)[i + 1];
+ }
+ // erase the last one ("leftover")
+ CZString keyLast(oldSize - 1);
+ ObjectValues::iterator itLast = value_.map_->find(keyLast);
+ value_.map_->erase(itLast);
+ return true;
+}
+
+#ifdef JSON_USE_CPPTL
+Value Value::get(const CppTL::ConstString& key,
+ const Value& defaultValue) const {
+ return get(key.c_str(), key.end_c_str(), defaultValue);
+}
+#endif
+
+bool Value::isMember(char const* key, char const* cend) const
+{
+ Value const* value = find(key, cend);
+ return NULL != value;
+}
+bool Value::isMember(char const* key) const
+{
+ return isMember(key, key + strlen(key));
+}
+bool Value::isMember(JSONCPP_STRING const& key) const
+{
+ return isMember(key.data(), key.data() + key.length());
+}
+
+#ifdef JSON_USE_CPPTL
+bool Value::isMember(const CppTL::ConstString& key) const {
+ return isMember(key.c_str(), key.end_c_str());
+}
+#endif
+
+Value::Members Value::getMemberNames() const {
+ JSON_ASSERT_MESSAGE(
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::getMemberNames(), value must be objectValue");
+ if (type_ == nullValue)
+ return Value::Members();
+ Members members;
+ members.reserve(value_.map_->size());
+ ObjectValues::const_iterator it = value_.map_->begin();
+ ObjectValues::const_iterator itEnd = value_.map_->end();
+ for (; it != itEnd; ++it) {
+ members.push_back(JSONCPP_STRING((*it).first.data(),
+ (*it).first.length()));
+ }
+ return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+// EnumMemberNames
+// Value::enumMemberNames() const
+//{
+// if ( type_ == objectValue )
+// {
+// return CppTL::Enum::any( CppTL::Enum::transform(
+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+// MemberNamesTransform() ) );
+// }
+// return EnumMemberNames();
+//}
+//
+//
+// EnumValues
+// Value::enumValues() const
+//{
+// if ( type_ == objectValue || type_ == arrayValue )
+// return CppTL::Enum::anyValues( *(value_.map_),
+// CppTL::Type<const Value &>() );
+// return EnumValues();
+//}
+//
+//# endif
+
+static bool IsIntegral(double d) {
+ double integral_part;
+ return modf(d, &integral_part) == 0.0;
+}
+
+bool Value::isNull() const { return type_ == nullValue; }
+
+bool Value::isBool() const { return type_ == booleanValue; }
+
+bool Value::isInt() const {
+ switch (type_) {
+ case intValue:
+#if defined(JSON_HAS_INT64)
+ return value_.int_ >= minInt && value_.int_ <= maxInt;
+#else
+ return true;
+#endif
+ case uintValue:
+ return value_.uint_ <= UInt(maxInt);
+ case realValue:
+ return value_.real_ >= minInt && value_.real_ <= maxInt &&
+ IsIntegral(value_.real_);
+ default:
+ break;
+ }
+ return false;
+}
+
+bool Value::isUInt() const {
+ switch (type_) {
+ case intValue:
+#if defined(JSON_HAS_INT64)
+ return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+#else
+ return value_.int_ >= 0;
+#endif
+ case uintValue:
+#if defined(JSON_HAS_INT64)
+ return value_.uint_ <= maxUInt;
+#else
+ return true;
+#endif
+ case realValue:
+ return value_.real_ >= 0 && value_.real_ <= maxUInt &&
+ IsIntegral(value_.real_);
+ default:
+ break;
+ }
+ return false;
+}
+
+bool Value::isInt64() const {
+#if defined(JSON_HAS_INT64)
+ switch (type_) {
+ case intValue:
+ return true;
+ case uintValue:
+ return value_.uint_ <= UInt64(maxInt64);
+ case realValue:
+ // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+ // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= double(minInt64) &&
+ value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
+ default:
+ break;
+ }
+#endif // JSON_HAS_INT64
+ return false;
+}
+
+bool Value::isUInt64() const {
+#if defined(JSON_HAS_INT64)
+ switch (type_) {
+ case intValue:
+ return value_.int_ >= 0;
+ case uintValue:
+ return true;
+ case realValue:
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
+ IsIntegral(value_.real_);
+ default:
+ break;
+ }
+#endif // JSON_HAS_INT64
+ return false;
+}
+
+bool Value::isIntegral() const {
+ switch (type_) {
+ case intValue:
+ case uintValue:
+ return true;
+ case realValue:
+#if defined(JSON_HAS_INT64)
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
+#else
+ return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
+#endif // JSON_HAS_INT64
+ default:
+ break;
+ }
+ return false;
+}
+
+bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
+
+bool Value::isNumeric() const { return isDouble(); }
+
+bool Value::isString() const { return type_ == stringValue; }
+
+bool Value::isArray() const { return type_ == arrayValue; }
+
+bool Value::isObject() const { return type_ == objectValue; }
+
+void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
+ if (!comments_)
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ if ((len > 0) && (comment[len-1] == '\n')) {
+ // Always discard trailing newline, to aid indentation.
+ len -= 1;
+ }
+ comments_[placement].setComment(comment, len);
+}
+
+void Value::setComment(const char* comment, CommentPlacement placement) {
+ setComment(comment, strlen(comment), placement);
+}
+
+void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
+ setComment(comment.c_str(), comment.length(), placement);
+}
+
+bool Value::hasComment(CommentPlacement placement) const {
+ return comments_ != 0 && comments_[placement].comment_ != 0;
+}
+
+JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
+ if (hasComment(placement))
+ return comments_[placement].comment_;
+ return "";
+}
+
+void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
+
+void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
+
+ptrdiff_t Value::getOffsetStart() const { return start_; }
+
+ptrdiff_t Value::getOffsetLimit() const { return limit_; }
+
+JSONCPP_STRING Value::toStyledString() const {
+ StyledWriter writer;
+ return writer.write(*this);
+}
+
+Value::const_iterator Value::begin() const {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->begin());
+ break;
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+Value::const_iterator Value::end() const {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->end());
+ break;
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+Value::iterator Value::begin() {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->begin());
+ break;
+ default:
+ break;
+ }
+ return iterator();
+}
+
+Value::iterator Value::end() {
+ switch (type_) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->end());
+ break;
+ default:
+ break;
+ }
+ return iterator();
+}
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
+
+PathArgument::PathArgument(ArrayIndex index)
+ : key_(), index_(index), kind_(kindIndex) {}
+
+PathArgument::PathArgument(const char* key)
+ : key_(key), index_(), kind_(kindKey) {}
+
+PathArgument::PathArgument(const JSONCPP_STRING& key)
+ : key_(key.c_str()), index_(), kind_(kindKey) {}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path(const JSONCPP_STRING& path,
+ const PathArgument& a1,
+ const PathArgument& a2,
+ const PathArgument& a3,
+ const PathArgument& a4,
+ const PathArgument& a5) {
+ InArgs in;
+ in.reserve(5);
+ in.push_back(&a1);
+ in.push_back(&a2);
+ in.push_back(&a3);
+ in.push_back(&a4);
+ in.push_back(&a5);
+ makePath(path, in);
+}
+
+void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
+ const char* current = path.c_str();
+ const char* end = current + path.length();
+ InArgs::const_iterator itInArg = in.begin();
+ while (current != end) {
+ if (*current == '[') {
+ ++current;
+ if (*current == '%')
+ addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+ else {
+ ArrayIndex index = 0;
+ for (; current != end && *current >= '0' && *current <= '9'; ++current)
+ index = index * 10 + ArrayIndex(*current - '0');
+ args_.push_back(index);
+ }
+ if (current == end || *++current != ']')
+ invalidPath(path, int(current - path.c_str()));
+ } else if (*current == '%') {
+ addPathInArg(path, in, itInArg, PathArgument::kindKey);
+ ++current;
+ } else if (*current == '.' || *current == ']') {
+ ++current;
+ } else {
+ const char* beginName = current;
+ while (current != end && !strchr("[.", *current))
+ ++current;
+ args_.push_back(JSONCPP_STRING(beginName, current));
+ }
+ }
+}
+
+void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
+ const InArgs& in,
+ InArgs::const_iterator& itInArg,
+ PathArgument::Kind kind) {
+ if (itInArg == in.end()) {
+ // Error: missing argument %d
+ } else if ((*itInArg)->kind_ != kind) {
+ // Error: bad argument type
+ } else {
+ args_.push_back(**itInArg++);
+ }
+}
+
+void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
+ // Error: invalid path.
+}
+
+const Value& Path::resolve(const Value& root) const {
+ const Value* node = &root;
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ const PathArgument& arg = *it;
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray() || !node->isValidIndex(arg.index_)) {
+ // Error: unable to resolve path (array value expected at position...
+ return Value::null;
+ }
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject()) {
+ // Error: unable to resolve path (object value expected at position...)
+ return Value::null;
+ }
+ node = &((*node)[arg.key_]);
+ if (node == &Value::nullSingleton()) {
+ // Error: unable to resolve path (object has no member named '' at
+ // position...)
+ return Value::null;
+ }
+ }
+ }
+ return *node;
+}
+
+Value Path::resolve(const Value& root, const Value& defaultValue) const {
+ const Value* node = &root;
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ const PathArgument& arg = *it;
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray() || !node->isValidIndex(arg.index_))
+ return defaultValue;
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject())
+ return defaultValue;
+ node = &((*node)[arg.key_]);
+ if (node == &Value::nullSingleton())
+ return defaultValue;
+ }
+ }
+ return *node;
+}
+
+Value& Path::make(Value& root) const {
+ Value* node = &root;
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ const PathArgument& arg = *it;
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray()) {
+ // Error: node is not an array at position ...
+ }
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject()) {
+ // Error: node is not an object at position...
+ }
+ node = &((*node)[arg.key_]);
+ }
+ }
+ return *node;
+}
+
+} // namespace Json
diff --git a/extern/jsoncpp/src/json_valueiterator.inl b/extern/jsoncpp/src/json_valueiterator.inl
new file mode 100644
index 00000000000..b45162b4a61
--- /dev/null
+++ b/extern/jsoncpp/src/json_valueiterator.inl
@@ -0,0 +1,167 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+// included by json_value.cpp
+
+namespace Json {
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+ : current_(), isNull_(true) {
+}
+
+ValueIteratorBase::ValueIteratorBase(
+ const Value::ObjectValues::iterator& current)
+ : current_(current), isNull_(false) {}
+
+Value& ValueIteratorBase::deref() const {
+ return current_->second;
+}
+
+void ValueIteratorBase::increment() {
+ ++current_;
+}
+
+void ValueIteratorBase::decrement() {
+ --current_;
+}
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance(const SelfType& other) const {
+#ifdef JSON_USE_CPPTL_SMALLMAP
+ return other.current_ - current_;
+#else
+ // Iterator for null value are initialized using the default
+ // constructor, which initialize current_ to the default
+ // std::map::iterator. As begin() and end() are two instance
+ // of the default std::map::iterator, they can not be compared.
+ // To allow this, we handle this comparison specifically.
+ if (isNull_ && other.isNull_) {
+ return 0;
+ }
+
+ // Usage of std::distance is not portable (does not compile with Sun Studio 12
+ // RogueWave STL,
+ // which is the one used by default).
+ // Using a portable hand-made version for non random iterator instead:
+ // return difference_type( std::distance( current_, other.current_ ) );
+ difference_type myDistance = 0;
+ for (Value::ObjectValues::iterator it = current_; it != other.current_;
+ ++it) {
+ ++myDistance;
+ }
+ return myDistance;
+#endif
+}
+
+bool ValueIteratorBase::isEqual(const SelfType& other) const {
+ if (isNull_) {
+ return other.isNull_;
+ }
+ return current_ == other.current_;
+}
+
+void ValueIteratorBase::copy(const SelfType& other) {
+ current_ = other.current_;
+ isNull_ = other.isNull_;
+}
+
+Value ValueIteratorBase::key() const {
+ const Value::CZString czstring = (*current_).first;
+ if (czstring.data()) {
+ if (czstring.isStaticString())
+ return Value(StaticString(czstring.data()));
+ return Value(czstring.data(), czstring.data() + czstring.length());
+ }
+ return Value(czstring.index());
+}
+
+UInt ValueIteratorBase::index() const {
+ const Value::CZString czstring = (*current_).first;
+ if (!czstring.data())
+ return czstring.index();
+ return Value::UInt(-1);
+}
+
+JSONCPP_STRING ValueIteratorBase::name() const {
+ char const* keey;
+ char const* end;
+ keey = memberName(&end);
+ if (!keey) return JSONCPP_STRING();
+ return JSONCPP_STRING(keey, end);
+}
+
+char const* ValueIteratorBase::memberName() const {
+ const char* cname = (*current_).first.data();
+ return cname ? cname : "";
+}
+
+char const* ValueIteratorBase::memberName(char const** end) const {
+ const char* cname = (*current_).first.data();
+ if (!cname) {
+ *end = NULL;
+ return NULL;
+ }
+ *end = cname + (*current_).first.length();
+ return cname;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator() {}
+
+ValueConstIterator::ValueConstIterator(
+ const Value::ObjectValues::iterator& current)
+ : ValueIteratorBase(current) {}
+
+ValueConstIterator::ValueConstIterator(ValueIterator const& other)
+ : ValueIteratorBase(other) {}
+
+ValueConstIterator& ValueConstIterator::
+operator=(const ValueIteratorBase& other) {
+ copy(other);
+ return *this;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator() {}
+
+ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
+ : ValueIteratorBase(current) {}
+
+ValueIterator::ValueIterator(const ValueConstIterator& other)
+ : ValueIteratorBase(other) {
+ throwRuntimeError("ConstIterator to Iterator should never be allowed.");
+}
+
+ValueIterator::ValueIterator(const ValueIterator& other)
+ : ValueIteratorBase(other) {}
+
+ValueIterator& ValueIterator::operator=(const SelfType& other) {
+ copy(other);
+ return *this;
+}
+
+} // namespace Json
diff --git a/extern/jsoncpp/src/json_writer.cpp b/extern/jsoncpp/src/json_writer.cpp
new file mode 100644
index 00000000000..4fb186dd508
--- /dev/null
+++ b/extern/jsoncpp/src/json_writer.cpp
@@ -0,0 +1,1223 @@
+// Copyright 2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/writer.h>
+#include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <iomanip>
+#include <memory>
+#include <sstream>
+#include <utility>
+#include <set>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+#include <float.h>
+#define isfinite _finite
+#elif defined(__sun) && defined(__SVR4) //Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
+#elif defined(_AIX)
+#if !defined(isfinite)
+#include <math.h>
+#define isfinite finite
+#endif
+#elif defined(__hpux)
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+ _Isfinitef(x) : _IsFinite(x)))
+#else
+#include <math.h>
+#define isfinite finite
+#endif
+#endif
+#else
+#include <cmath>
+#if !(defined(__QNXNTO__)) // QNX already defines isfinite
+#define isfinite std::isfinite
+#endif
+#endif
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define snprintf std::snprintf
+#endif
+#endif
+
+#if defined(__BORLANDC__)
+#include <float.h>
+#define isfinite _finite
+#define snprintf _snprintf
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+#else
+typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+#endif
+
+static bool containsControlCharacter(const char* str) {
+ while (*str) {
+ if (isControlCharacter(*(str++)))
+ return true;
+ }
+ return false;
+}
+
+static bool containsControlCharacter0(const char* str, unsigned len) {
+ char const* end = str + len;
+ while (end != str) {
+ if (isControlCharacter(*str) || 0==*str)
+ return true;
+ ++str;
+ }
+ return false;
+}
+
+JSONCPP_STRING valueToString(LargestInt value) {
+ UIntToStringBuffer buffer;
+ char* current = buffer + sizeof(buffer);
+ if (value == Value::minLargestInt) {
+ uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
+ *--current = '-';
+ } else if (value < 0) {
+ uintToString(LargestUInt(-value), current);
+ *--current = '-';
+ } else {
+ uintToString(LargestUInt(value), current);
+ }
+ assert(current >= buffer);
+ return current;
+}
+
+JSONCPP_STRING valueToString(LargestUInt value) {
+ UIntToStringBuffer buffer;
+ char* current = buffer + sizeof(buffer);
+ uintToString(value, current);
+ assert(current >= buffer);
+ return current;
+}
+
+#if defined(JSON_HAS_INT64)
+
+JSONCPP_STRING valueToString(Int value) {
+ return valueToString(LargestInt(value));
+}
+
+JSONCPP_STRING valueToString(UInt value) {
+ return valueToString(LargestUInt(value));
+}
+
+#endif // # if defined(JSON_HAS_INT64)
+
+namespace {
+JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
+ // Allocate a buffer that is more than large enough to store the 16 digits of
+ // precision requested below.
+ char buffer[36];
+ int len = -1;
+
+ char formatString[15];
+ snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
+
+ // Print into the buffer. We need not request the alternative representation
+ // that always has a decimal point because JSON doesn't distingish the
+ // concepts of reals and integers.
+ if (isfinite(value)) {
+ len = snprintf(buffer, sizeof(buffer), formatString, value);
+ fixNumericLocale(buffer, buffer + len);
+
+ // try to ensure we preserve the fact that this was given to us as a double on input
+ if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
+ strcat(buffer, ".0");
+ }
+
+ } else {
+ // IEEE standard states that NaN values will not compare to themselves
+ if (value != value) {
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
+ } else if (value < 0) {
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
+ } else {
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
+ }
+ }
+ assert(len >= 0);
+ return buffer;
+}
+}
+
+JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
+
+JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
+
+JSONCPP_STRING valueToQuotedString(const char* value) {
+ if (value == NULL)
+ return "";
+ // Not sure how to handle unicode...
+ if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
+ !containsControlCharacter(value))
+ return JSONCPP_STRING("\"") + value + "\"";
+ // We have to walk value and escape any special characters.
+ // Appending to JSONCPP_STRING is not efficient, but this should be rare.
+ // (Note: forward slashes are *not* rare, but I am not escaping them.)
+ JSONCPP_STRING::size_type maxsize =
+ strlen(value) * 2 + 3; // allescaped+quotes+NULL
+ JSONCPP_STRING result;
+ result.reserve(maxsize); // to avoid lots of mallocs
+ result += "\"";
+ for (const char* c = value; *c != 0; ++c) {
+ switch (*c) {
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if (isControlCharacter(*c)) {
+ JSONCPP_OSTRINGSTREAM oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
+static char const* strnpbrk(char const* s, char const* accept, size_t n) {
+ assert((s || !n) && accept);
+
+ char const* const end = s + n;
+ for (char const* cur = s; cur < end; ++cur) {
+ int const c = *cur;
+ for (char const* a = accept; *a; ++a) {
+ if (*a == c) {
+ return cur;
+ }
+ }
+ }
+ return NULL;
+}
+static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
+ if (value == NULL)
+ return "";
+ // Not sure how to handle unicode...
+ if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
+ !containsControlCharacter0(value, length))
+ return JSONCPP_STRING("\"") + value + "\"";
+ // We have to walk value and escape any special characters.
+ // Appending to JSONCPP_STRING is not efficient, but this should be rare.
+ // (Note: forward slashes are *not* rare, but I am not escaping them.)
+ JSONCPP_STRING::size_type maxsize =
+ length * 2 + 3; // allescaped+quotes+NULL
+ JSONCPP_STRING result;
+ result.reserve(maxsize); // to avoid lots of mallocs
+ result += "\"";
+ char const* end = value + length;
+ for (const char* c = value; c != end; ++c) {
+ switch (*c) {
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.)
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if ((isControlCharacter(*c)) || (*c == 0)) {
+ JSONCPP_OSTRINGSTREAM oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer() {}
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+ : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+ omitEndingLineFeed_(false) {}
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+
+void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+
+void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+
+JSONCPP_STRING FastWriter::write(const Value& root) {
+ document_.clear();
+ writeValue(root);
+ if (!omitEndingLineFeed_)
+ document_ += "\n";
+ return document_;
+}
+
+void FastWriter::writeValue(const Value& value) {
+ switch (value.type()) {
+ case nullValue:
+ if (!dropNullPlaceholders_)
+ document_ += "null";
+ break;
+ case intValue:
+ document_ += valueToString(value.asLargestInt());
+ break;
+ case uintValue:
+ document_ += valueToString(value.asLargestUInt());
+ break;
+ case realValue:
+ document_ += valueToString(value.asDouble());
+ break;
+ case stringValue:
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
+ break;
+ }
+ case booleanValue:
+ document_ += valueToString(value.asBool());
+ break;
+ case arrayValue: {
+ document_ += '[';
+ ArrayIndex size = value.size();
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ',';
+ writeValue(value[index]);
+ }
+ document_ += ']';
+ } break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ document_ += '{';
+ for (Value::Members::iterator it = members.begin(); it != members.end();
+ ++it) {
+ const JSONCPP_STRING& name = *it;
+ if (it != members.begin())
+ document_ += ',';
+ document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
+ document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ writeValue(value[name]);
+ }
+ document_ += '}';
+ } break;
+ }
+}
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+ : rightMargin_(74), indentSize_(3), addChildValues_() {}
+
+JSONCPP_STRING StyledWriter::write(const Value& root) {
+ document_.clear();
+ addChildValues_ = false;
+ indentString_.clear();
+ writeCommentBeforeValue(root);
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ document_ += "\n";
+ return document_;
+}
+
+void StyledWriter::writeValue(const Value& value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue:
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ const JSONCPP_STRING& name = *it;
+ const Value& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ document_ += " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ document_ += ',';
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
+ }
+}
+
+void StyledWriter::writeArrayValue(const Value& value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isArrayMultiLine = isMultineArray(value);
+ if (isArrayMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ for (;;) {
+ const Value& childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ writeIndent();
+ writeValue(childValue);
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ document_ += ',';
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ document_ += "[ ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ", ";
+ document_ += childValues_[index];
+ }
+ document_ += " ]";
+ }
+ }
+}
+
+bool StyledWriter::isMultineArray(const Value& value) {
+ ArrayIndex const size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+ const Value& childValue = value[index];
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0);
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (hasCommentForValue(value[index])) {
+ isMultiLine = true;
+ }
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void StyledWriter::pushValue(const JSONCPP_STRING& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ document_ += value;
+}
+
+void StyledWriter::writeIndent() {
+ if (!document_.empty()) {
+ char last = document_[document_.length() - 1];
+ if (last == ' ') // already indented
+ return;
+ if (last != '\n') // Comments may add new-line
+ document_ += '\n';
+ }
+ document_ += indentString_;
+}
+
+void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
+ writeIndent();
+ document_ += value;
+}
+
+void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
+
+void StyledWriter::unindent() {
+ assert(indentString_.size() >= indentSize_);
+ indentString_.resize(indentString_.size() - indentSize_);
+}
+
+void StyledWriter::writeCommentBeforeValue(const Value& root) {
+ if (!root.hasComment(commentBefore))
+ return;
+
+ document_ += "\n";
+ writeIndent();
+ const JSONCPP_STRING& comment = root.getComment(commentBefore);
+ JSONCPP_STRING::const_iterator iter = comment.begin();
+ while (iter != comment.end()) {
+ document_ += *iter;
+ if (*iter == '\n' &&
+ (iter != comment.end() && *(iter + 1) == '/'))
+ writeIndent();
+ ++iter;
+ }
+
+ // Comments are stripped of trailing newlines, so add one here
+ document_ += "\n";
+}
+
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+ if (root.hasComment(commentAfterOnSameLine))
+ document_ += " " + root.getComment(commentAfterOnSameLine);
+
+ if (root.hasComment(commentAfter)) {
+ document_ += "\n";
+ document_ += root.getComment(commentAfter);
+ document_ += "\n";
+ }
+}
+
+bool StyledWriter::hasCommentForValue(const Value& value) {
+ return value.hasComment(commentBefore) ||
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
+}
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
+ : document_(NULL), rightMargin_(74), indentation_(indentation),
+ addChildValues_() {}
+
+void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
+ document_ = &out;
+ addChildValues_ = false;
+ indentString_.clear();
+ indented_ = true;
+ writeCommentBeforeValue(root);
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *document_ << "\n";
+ document_ = NULL; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value& value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue:
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ const JSONCPP_STRING& name = *it;
+ const Value& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ *document_ << " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
+ }
+}
+
+void StyledStreamWriter::writeArrayValue(const Value& value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isArrayMultiLine = isMultineArray(value);
+ if (isArrayMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ for (;;) {
+ const Value& childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(childValue);
+ indented_ = false;
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ *document_ << "[ ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ *document_ << ", ";
+ *document_ << childValues_[index];
+ }
+ *document_ << " ]";
+ }
+ }
+}
+
+bool StyledStreamWriter::isMultineArray(const Value& value) {
+ ArrayIndex const size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+ const Value& childValue = value[index];
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0);
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (hasCommentForValue(value[index])) {
+ isMultiLine = true;
+ }
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ *document_ << value;
+}
+
+void StyledStreamWriter::writeIndent() {
+ // blep intended this to look at the so-far-written string
+ // to determine whether we are already indented, but
+ // with a stream we cannot do that. So we rely on some saved state.
+ // The caller checks indented_.
+ *document_ << '\n' << indentString_;
+}
+
+void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
+ if (!indented_) writeIndent();
+ *document_ << value;
+ indented_ = false;
+}
+
+void StyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void StyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
+ if (!root.hasComment(commentBefore))
+ return;
+
+ if (!indented_) writeIndent();
+ const JSONCPP_STRING& comment = root.getComment(commentBefore);
+ JSONCPP_STRING::const_iterator iter = comment.begin();
+ while (iter != comment.end()) {
+ *document_ << *iter;
+ if (*iter == '\n' &&
+ (iter != comment.end() && *(iter + 1) == '/'))
+ // writeIndent(); // would include newline
+ *document_ << indentString_;
+ ++iter;
+ }
+ indented_ = false;
+}
+
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+ if (root.hasComment(commentAfterOnSameLine))
+ *document_ << ' ' << root.getComment(commentAfterOnSameLine);
+
+ if (root.hasComment(commentAfter)) {
+ writeIndent();
+ *document_ << root.getComment(commentAfter);
+ }
+ indented_ = false;
+}
+
+bool StyledStreamWriter::hasCommentForValue(const Value& value) {
+ return value.hasComment(commentBefore) ||
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
+}
+
+//////////////////////////
+// BuiltStyledStreamWriter
+
+/// Scoped enums are not available until C++11.
+struct CommentStyle {
+ /// Decide whether to write comments.
+ enum Enum {
+ None, ///< Drop all comments.
+ Most, ///< Recover odd behavior of previous versions (not implemented yet).
+ All ///< Keep all comments.
+ };
+};
+
+struct BuiltStyledStreamWriter : public StreamWriter
+{
+ BuiltStyledStreamWriter(
+ JSONCPP_STRING const& indentation,
+ CommentStyle::Enum cs,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
+ bool useSpecialFloats,
+ unsigned int precision);
+ int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
+private:
+ void writeValue(Value const& value);
+ void writeArrayValue(Value const& value);
+ bool isMultineArray(Value const& value);
+ void pushValue(JSONCPP_STRING const& value);
+ void writeIndent();
+ void writeWithIndent(JSONCPP_STRING const& value);
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue(Value const& root);
+ void writeCommentAfterValueOnSameLine(Value const& root);
+ static bool hasCommentForValue(const Value& value);
+
+ typedef std::vector<JSONCPP_STRING> ChildValues;
+
+ ChildValues childValues_;
+ JSONCPP_STRING indentString_;
+ unsigned int rightMargin_;
+ JSONCPP_STRING indentation_;
+ CommentStyle::Enum cs_;
+ JSONCPP_STRING colonSymbol_;
+ JSONCPP_STRING nullSymbol_;
+ JSONCPP_STRING endingLineFeedSymbol_;
+ bool addChildValues_ : 1;
+ bool indented_ : 1;
+ bool useSpecialFloats_ : 1;
+ unsigned int precision_;
+};
+BuiltStyledStreamWriter::BuiltStyledStreamWriter(
+ JSONCPP_STRING const& indentation,
+ CommentStyle::Enum cs,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
+ bool useSpecialFloats,
+ unsigned int precision)
+ : rightMargin_(74)
+ , indentation_(indentation)
+ , cs_(cs)
+ , colonSymbol_(colonSymbol)
+ , nullSymbol_(nullSymbol)
+ , endingLineFeedSymbol_(endingLineFeedSymbol)
+ , addChildValues_(false)
+ , indented_(false)
+ , useSpecialFloats_(useSpecialFloats)
+ , precision_(precision)
+{
+}
+int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
+{
+ sout_ = sout;
+ addChildValues_ = false;
+ indented_ = true;
+ indentString_.clear();
+ writeCommentBeforeValue(root);
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *sout_ << endingLineFeedSymbol_;
+ sout_ = NULL;
+ return 0;
+}
+void BuiltStyledStreamWriter::writeValue(Value const& value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue(nullSymbol_);
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+ break;
+ case stringValue:
+ {
+ // Is NULL is possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ JSONCPP_STRING const& name = *it;
+ Value const& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+ *sout_ << colonSymbol_;
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *sout_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
+ }
+}
+
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+ if (isMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ for (;;) {
+ Value const& childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ if (!indented_) writeIndent();
+ indented_ = true;
+ writeValue(childValue);
+ indented_ = false;
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *sout_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ *sout_ << "[";
+ if (!indentation_.empty()) *sout_ << " ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ *sout_ << ((!indentation_.empty()) ? ", " : ",");
+ *sout_ << childValues_[index];
+ }
+ if (!indentation_.empty()) *sout_ << " ";
+ *sout_ << "]";
+ }
+ }
+}
+
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+ ArrayIndex const size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+ Value const& childValue = value[index];
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0);
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (hasCommentForValue(value[index])) {
+ isMultiLine = true;
+ }
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ *sout_ << value;
+}
+
+void BuiltStyledStreamWriter::writeIndent() {
+ // blep intended this to look at the so-far-written string
+ // to determine whether we are already indented, but
+ // with a stream we cannot do that. So we rely on some saved state.
+ // The caller checks indented_.
+
+ if (!indentation_.empty()) {
+ // In this case, drop newlines too.
+ *sout_ << '\n' << indentString_;
+ }
+}
+
+void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
+ if (!indented_) writeIndent();
+ *sout_ << value;
+ indented_ = false;
+}
+
+void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void BuiltStyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
+ if (cs_ == CommentStyle::None) return;
+ if (!root.hasComment(commentBefore))
+ return;
+
+ if (!indented_) writeIndent();
+ const JSONCPP_STRING& comment = root.getComment(commentBefore);
+ JSONCPP_STRING::const_iterator iter = comment.begin();
+ while (iter != comment.end()) {
+ *sout_ << *iter;
+ if (*iter == '\n' &&
+ (iter != comment.end() && *(iter + 1) == '/'))
+ // writeIndent(); // would write extra newline
+ *sout_ << indentString_;
+ ++iter;
+ }
+ indented_ = false;
+}
+
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
+ if (cs_ == CommentStyle::None) return;
+ if (root.hasComment(commentAfterOnSameLine))
+ *sout_ << " " + root.getComment(commentAfterOnSameLine);
+
+ if (root.hasComment(commentAfter)) {
+ writeIndent();
+ *sout_ << root.getComment(commentAfter);
+ }
+}
+
+// static
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
+ return value.hasComment(commentBefore) ||
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
+}
+
+///////////////
+// StreamWriter
+
+StreamWriter::StreamWriter()
+ : sout_(NULL)
+{
+}
+StreamWriter::~StreamWriter()
+{
+}
+StreamWriter::Factory::~Factory()
+{}
+StreamWriterBuilder::StreamWriterBuilder()
+{
+ setDefaults(&settings_);
+}
+StreamWriterBuilder::~StreamWriterBuilder()
+{}
+StreamWriter* StreamWriterBuilder::newStreamWriter() const
+{
+ JSONCPP_STRING indentation = settings_["indentation"].asString();
+ JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
+ bool eyc = settings_["enableYAMLCompatibility"].asBool();
+ bool dnp = settings_["dropNullPlaceholders"].asBool();
+ bool usf = settings_["useSpecialFloats"].asBool();
+ unsigned int pre = settings_["precision"].asUInt();
+ CommentStyle::Enum cs = CommentStyle::All;
+ if (cs_str == "All") {
+ cs = CommentStyle::All;
+ } else if (cs_str == "None") {
+ cs = CommentStyle::None;
+ } else {
+ throwRuntimeError("commentStyle must be 'All' or 'None'");
+ }
+ JSONCPP_STRING colonSymbol = " : ";
+ if (eyc) {
+ colonSymbol = ": ";
+ } else if (indentation.empty()) {
+ colonSymbol = ":";
+ }
+ JSONCPP_STRING nullSymbol = "null";
+ if (dnp) {
+ nullSymbol.clear();
+ }
+ if (pre > 17) pre = 17;
+ JSONCPP_STRING endingLineFeedSymbol;
+ return new BuiltStyledStreamWriter(
+ indentation, cs,
+ colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+}
+static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
+{
+ valid_keys->clear();
+ valid_keys->insert("indentation");
+ valid_keys->insert("commentStyle");
+ valid_keys->insert("enableYAMLCompatibility");
+ valid_keys->insert("dropNullPlaceholders");
+ valid_keys->insert("useSpecialFloats");
+ valid_keys->insert("precision");
+}
+bool StreamWriterBuilder::validate(Json::Value* invalid) const
+{
+ Json::Value my_invalid;
+ if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
+ Json::Value& inv = *invalid;
+ std::set<JSONCPP_STRING> valid_keys;
+ getValidWriterKeys(&valid_keys);
+ Value::Members keys = settings_.getMemberNames();
+ size_t n = keys.size();
+ for (size_t i = 0; i < n; ++i) {
+ JSONCPP_STRING const& key = keys[i];
+ if (valid_keys.find(key) == valid_keys.end()) {
+ inv[key] = settings_[key];
+ }
+ }
+ return 0u == inv.size();
+}
+Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
+{
+ return settings_[key];
+}
+// static
+void StreamWriterBuilder::setDefaults(Json::Value* settings)
+{
+ //! [StreamWriterBuilderDefaults]
+ (*settings)["commentStyle"] = "All";
+ (*settings)["indentation"] = "\t";
+ (*settings)["enableYAMLCompatibility"] = false;
+ (*settings)["dropNullPlaceholders"] = false;
+ (*settings)["useSpecialFloats"] = false;
+ (*settings)["precision"] = 17;
+ //! [StreamWriterBuilderDefaults]
+}
+
+JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
+ JSONCPP_OSTRINGSTREAM sout;
+ StreamWriterPtr const writer(builder.newStreamWriter());
+ writer->write(root, &sout);
+ return sout.str();
+}
+
+JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
+ StreamWriterBuilder builder;
+ StreamWriterPtr const writer(builder.newStreamWriter());
+ writer->write(root, &sout);
+ return sout;
+}
+
+} // namespace Json
diff --git a/extern/jsoncpp/src/sconscript b/extern/jsoncpp/src/sconscript
new file mode 100644
index 00000000000..6e7c6c8a076
--- /dev/null
+++ b/extern/jsoncpp/src/sconscript
@@ -0,0 +1,8 @@
+Import( 'env buildLibrary' )
+
+buildLibrary( env, Split( """
+ json_reader.cpp
+ json_value.cpp
+ json_writer.cpp
+ """ ),
+ 'json' )
diff --git a/extern/jsoncpp/src/version.h.in b/extern/jsoncpp/src/version.h.in
new file mode 100644
index 00000000000..47aac69bdd5
--- /dev/null
+++ b/extern/jsoncpp/src/version.h.in
@@ -0,0 +1,20 @@
+// DO NOT EDIT. This file (and "version") is generated by CMake.
+// Run CMake configure step to update it.
+#ifndef JSON_VERSION_H_INCLUDED
+# define JSON_VERSION_H_INCLUDED
+
+# define JSONCPP_VERSION_STRING "@JSONCPP_VERSION@"
+# define JSONCPP_VERSION_MAJOR @JSONCPP_VERSION_MAJOR@
+# define JSONCPP_VERSION_MINOR @JSONCPP_VERSION_MINOR@
+# define JSONCPP_VERSION_PATCH @JSONCPP_VERSION_PATCH@
+# define JSONCPP_VERSION_QUALIFIER
+# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY @JSONCPP_USE_SECURE_MEMORY@
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
diff --git a/extern/openxr/CMakeLists.txt b/extern/openxr/CMakeLists.txt
new file mode 100644
index 00000000000..313ad11b380
--- /dev/null
+++ b/extern/openxr/CMakeLists.txt
@@ -0,0 +1,71 @@
+# Copyright (c) 2017-2019 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author:
+#
+
+# Note: This is the top-level CMake file for the OpenXR project.
+# It should contain only definitions that are applicable to the
+# entire project and includes for the sub-directories.
+
+cmake_minimum_required(VERSION 3.0)
+project(OPENXR)
+
+#find_package(PythonInterp 3)
+
+# Enable IDE GUI folders. "Helper targets" that don't have interesting source code should set their FOLDER property to this
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake predefined targets")
+set(LOADER_FOLDER "Loader")
+set(HELPER_FOLDER "Helpers")
+set(CODEGEN_FOLDER "Generated")
+set(TESTS_FOLDER "Tests")
+set(API_LAYERS_FOLDER "Layers")
+set(SAMPLES_FOLDER "Samples")
+
+option(BUILD_FORCE_GENERATION "Force re-generation of files even in the presence of pre-generated copies, replacing those copies." OFF)
+
+if(BUILD_FORCE_GENERATION AND NOT PYTHON_EXECUTABLE)
+ message(FATAL_ERROR "BUILD_FORCE_GENERATION requires Python")
+endif()
+
+set(OPENXR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+add_subdirectory(include)
+add_subdirectory(src)
+
+# uninstall target
+if(NOT TARGET uninstall)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/cmake/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE
+ @ONLY)
+ add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
+ set_target_properties(uninstall PROPERTIES FOLDER ${HELPER_FOLDER})
+endif()
+
+find_program(BASH_COMMAND NAMES bash)
+if(BASH_COMMAND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/specification/Makefile")
+ option(BUILD_SPECIFICATION "Run './makeAllExts all' in the specification directory as part of the build - intended for one-step checking of spec changes" OFF)
+ if(BUILD_SPECIFICATION)
+ add_custom_target(spec-all ALL
+ ${BASH_COMMAND} ./makeAllExts all
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/specification"
+ VERBATIM
+ COMMENT "Running './makeAllExts all' in the specification directory"
+ USES_TERMINAL)
+ endif()
+endif()
+
+install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION share/doc/openxr)
diff --git a/extern/openxr/LICENSE b/extern/openxr/LICENSE
new file mode 100644
index 00000000000..d6456956733
--- /dev/null
+++ b/extern/openxr/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/extern/openxr/include/CMakeLists.txt b/extern/openxr/include/CMakeLists.txt
new file mode 100644
index 00000000000..b43bb19792a
--- /dev/null
+++ b/extern/openxr/include/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Copyright (c) 2017 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author:
+#
+
+add_subdirectory(openxr) \ No newline at end of file
diff --git a/extern/openxr/include/openxr/CMakeLists.txt b/extern/openxr/include/openxr/CMakeLists.txt
new file mode 100644
index 00000000000..0b5a74ddcdf
--- /dev/null
+++ b/extern/openxr/include/openxr/CMakeLists.txt
@@ -0,0 +1,94 @@
+# Copyright (c) 2017-2019 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author:
+#
+
+# Copy the openxr_platform_defines.h file and place it in the binary (build) directory.
+configure_file(openxr_platform_defines.h ${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h COPYONLY)
+
+# Generate OpenXR header files.
+
+
+set(HEADERS
+ openxr.h
+ openxr_platform.h
+ openxr_reflection.h)
+set(HAVE_PREGENERATED TRUE)
+set(SOURCE_HEADERS)
+foreach(output ${HEADERS})
+ list(APPEND SOURCE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/${output})
+ if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${output})
+ set(HAVE_PREGENERATED FALSE)
+ endif()
+endforeach()
+
+set(XR_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
+if(HAVE_PREGENERATED AND NOT BUILD_FORCE_GENERATION)
+ add_custom_target(generate_openxr_header
+ COMMENT "Using found pre-generated OpenXR headers.")
+
+ set(INSTALL_HEADERS ${SOURCE_HEADERS})
+else()
+
+ set(GENERATED_HEADERS)
+ set(OUTPUT_STAMPS)
+ # Copy the openxr_platform_defines.h file and place it in the binary (build) directory.
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/openxr_platform_defines.h
+ ${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h
+ COPYONLY)
+
+ # Generate the header files and place it in the binary (build) directory.
+ foreach(output ${HEADERS})
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output}
+ COMMAND ${PYTHON_EXECUTABLE} ${XR_ROOT}/specification/scripts/genxr.py
+ -registry ${XR_ROOT}/specification/registry/xr.xml
+ -o ${CMAKE_CURRENT_BINARY_DIR} ${output}
+ DEPENDS
+ ${XR_ROOT}/specification/scripts/genxr.py
+ ${XR_ROOT}/specification/scripts/cgenerator.py
+ ${XR_ROOT}/specification/scripts/creflectiongenerator.py
+ ${XR_ROOT}/specification/scripts/generator.py
+ ${XR_ROOT}/specification/scripts/reg.py
+ ${XR_ROOT}/specification/registry/xr.xml
+ COMMENT "Generating ${CMAKE_CURRENT_BINARY_DIR}/${output}"
+ )
+ list(APPEND GENERATED_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/${output}")
+ endforeach()
+
+ set_source_files_properties(
+ ${GENERATED_HEADERS}
+ PROPERTIES GENERATED TRUE
+ )
+
+ set(INSTALL_HEADERS
+ ${CMAKE_CURRENT_BINARY_DIR}/openxr_platform_defines.h
+ ${CMAKE_CURRENT_BINARY_DIR}/openxr.h
+ ${CMAKE_CURRENT_BINARY_DIR}/openxr_platform.h)
+
+
+ # Define generate_openxr_header target to generate the OpenXR header files.
+ # Other targets that need the OpenXR headers should use generate_openxr_header as a dependency.
+ add_custom_target(generate_openxr_header
+ SOURCES ${XR_ROOT}/specification/registry/xr.xml
+ DEPENDS
+ ${GENERATED_HEADERS}
+ ${OUTPUT_STAMPS}
+ )
+endif()
+set_target_properties(generate_openxr_header PROPERTIES FOLDER ${CODEGEN_FOLDER})
+
+INSTALL(FILES ${INSTALL_HEADERS}
+ DESTINATION include/openxr
+)
diff --git a/extern/openxr/include/openxr/openxr.h b/extern/openxr/include/openxr/openxr.h
new file mode 100644
index 00000000000..b776babdc87
--- /dev/null
+++ b/extern/openxr/include/openxr/openxr.h
@@ -0,0 +1,1538 @@
+#ifndef OPENXR_H_
+#define OPENXR_H_ 1
+
+/*
+** Copyright (c) 2017-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define XR_VERSION_1_0 1
+#include "openxr_platform_defines.h"
+#define XR_MAKE_VERSION(major, minor, patch) \
+ ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))
+
+// OpenXR current version number.
+#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 0)
+
+#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)
+
+#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
+
+
+
+#define XR_NULL_SYSTEM_ID 0
+
+
+#define XR_NULL_PATH 0
+
+
+#define XR_SUCCEEDED(result) ((result) >= 0)
+
+
+#define XR_FAILED(result) ((result) < 0)
+
+
+#define XR_UNQUALIFIED_SUCCESS(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)
+
+
+#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_DEFINE_ATOM)
+ #define XR_DEFINE_ATOM(object) typedef uint64_t object;
+#endif
+
+
+typedef uint64_t XrVersion;
+typedef uint64_t XrFlags64;
+XR_DEFINE_ATOM(XrSystemId)
+typedef uint32_t XrBool32;
+XR_DEFINE_ATOM(XrPath)
+typedef int64_t XrTime;
+typedef int64_t XrDuration;
+XR_DEFINE_HANDLE(XrInstance)
+XR_DEFINE_HANDLE(XrSession)
+XR_DEFINE_HANDLE(XrSpace)
+XR_DEFINE_HANDLE(XrAction)
+XR_DEFINE_HANDLE(XrSwapchain)
+XR_DEFINE_HANDLE(XrActionSet)
+#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_MIN_COMPOSITION_LAYERS_SUPPORTED 16
+#define XR_MAX_ACTION_SET_NAME_SIZE 64
+#define XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE 128
+#define XR_MAX_ACTION_NAME_SIZE 64
+#define XR_MAX_LOCALIZED_ACTION_NAME_SIZE 128
+
+typedef enum XrResult {
+ 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_ERROR_VALIDATION_FAILURE = -1,
+ XR_ERROR_RUNTIME_FAILURE = -2,
+ XR_ERROR_OUT_OF_MEMORY = -3,
+ XR_ERROR_API_VERSION_UNSUPPORTED = -4,
+ XR_ERROR_INITIALIZATION_FAILED = -6,
+ XR_ERROR_FUNCTION_UNSUPPORTED = -7,
+ XR_ERROR_FEATURE_UNSUPPORTED = -8,
+ XR_ERROR_EXTENSION_NOT_PRESENT = -9,
+ XR_ERROR_LIMIT_REACHED = -10,
+ XR_ERROR_SIZE_INSUFFICIENT = -11,
+ XR_ERROR_HANDLE_INVALID = -12,
+ XR_ERROR_INSTANCE_LOST = -13,
+ XR_ERROR_SESSION_RUNNING = -14,
+ XR_ERROR_SESSION_NOT_RUNNING = -16,
+ XR_ERROR_SESSION_LOST = -17,
+ XR_ERROR_SYSTEM_INVALID = -18,
+ XR_ERROR_PATH_INVALID = -19,
+ XR_ERROR_PATH_COUNT_EXCEEDED = -20,
+ XR_ERROR_PATH_FORMAT_INVALID = -21,
+ XR_ERROR_PATH_UNSUPPORTED = -22,
+ XR_ERROR_LAYER_INVALID = -23,
+ XR_ERROR_LAYER_LIMIT_EXCEEDED = -24,
+ XR_ERROR_SWAPCHAIN_RECT_INVALID = -25,
+ XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26,
+ XR_ERROR_ACTION_TYPE_MISMATCH = -27,
+ XR_ERROR_SESSION_NOT_READY = -28,
+ XR_ERROR_SESSION_NOT_STOPPING = -29,
+ XR_ERROR_TIME_INVALID = -30,
+ XR_ERROR_REFERENCE_SPACE_UNSUPPORTED = -31,
+ XR_ERROR_FILE_ACCESS_ERROR = -32,
+ XR_ERROR_FILE_CONTENTS_INVALID = -33,
+ XR_ERROR_FORM_FACTOR_UNSUPPORTED = -34,
+ XR_ERROR_FORM_FACTOR_UNAVAILABLE = -35,
+ XR_ERROR_API_LAYER_NOT_PRESENT = -36,
+ XR_ERROR_CALL_ORDER_INVALID = -37,
+ XR_ERROR_GRAPHICS_DEVICE_INVALID = -38,
+ XR_ERROR_POSE_INVALID = -39,
+ XR_ERROR_INDEX_OUT_OF_RANGE = -40,
+ XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED = -41,
+ XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED = -42,
+ XR_ERROR_NAME_DUPLICATED = -44,
+ XR_ERROR_NAME_INVALID = -45,
+ XR_ERROR_ACTIONSET_NOT_ATTACHED = -46,
+ XR_ERROR_ACTIONSETS_ALREADY_ATTACHED = -47,
+ XR_ERROR_LOCALIZED_NAME_DUPLICATED = -48,
+ XR_ERROR_LOCALIZED_NAME_INVALID = -49,
+ XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR = -1000003000,
+ XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR = -1000003001,
+ XR_RESULT_MAX_ENUM = 0x7FFFFFFF
+} XrResult;
+
+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_INSTANCE_CREATE_INFO_ANDROID_KHR = 1000008000,
+ 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_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000019000,
+ XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000019001,
+ XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000019002,
+ XR_TYPE_DEBUG_UTILS_LABEL_EXT = 1000019003,
+ 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_OPENGL_ES_ANDROID_KHR = 1000024001,
+ XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR = 1000024002,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR = 1000024003,
+ 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_VISIBILITY_MASK_KHR = 1000031000,
+ XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001,
+ XR_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrStructureType;
+
+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 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_MAX_ENUM = 0x7FFFFFFF
+} XrViewConfigurationType;
+
+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 XrReferenceSpaceType {
+ XR_REFERENCE_SPACE_TYPE_VIEW = 1,
+ XR_REFERENCE_SPACE_TYPE_LOCAL = 2,
+ XR_REFERENCE_SPACE_TYPE_STAGE = 3,
+ XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrReferenceSpaceType;
+
+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 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 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 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_DEBUG_UTILS_MESSENGER_EXT = 1000019000,
+ XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrObjectType;
+typedef XrFlags64 XrInstanceCreateFlags;
+
+// Flag bits for XrInstanceCreateFlags
+
+typedef XrFlags64 XrSessionCreateFlags;
+
+// Flag bits for XrSessionCreateFlags
+
+typedef XrFlags64 XrSpaceVelocityFlags;
+
+// Flag bits for XrSpaceVelocityFlags
+static const XrSpaceVelocityFlags XR_SPACE_VELOCITY_LINEAR_VALID_BIT = 0x00000001;
+static const XrSpaceVelocityFlags XR_SPACE_VELOCITY_ANGULAR_VALID_BIT = 0x00000002;
+
+typedef XrFlags64 XrSpaceLocationFlags;
+
+// Flag bits for XrSpaceLocationFlags
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_VALID_BIT = 0x00000001;
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_VALID_BIT = 0x00000002;
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT = 0x00000004;
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_TRACKED_BIT = 0x00000008;
+
+typedef XrFlags64 XrSwapchainCreateFlags;
+
+// Flag bits for XrSwapchainCreateFlags
+static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT = 0x00000001;
+static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT = 0x00000002;
+
+typedef XrFlags64 XrSwapchainUsageFlags;
+
+// Flag bits for XrSwapchainUsageFlags
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT = 0x00000001;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000002;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT = 0x00000004;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT = 0x00000008;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT = 0x00000010;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_SAMPLED_BIT = 0x00000020;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT = 0x00000040;
+
+typedef XrFlags64 XrCompositionLayerFlags;
+
+// Flag bits for XrCompositionLayerFlags
+static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001;
+static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002;
+static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT = 0x00000004;
+
+typedef XrFlags64 XrViewStateFlags;
+
+// Flag bits for XrViewStateFlags
+static const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_VALID_BIT = 0x00000001;
+static const XrViewStateFlags XR_VIEW_STATE_POSITION_VALID_BIT = 0x00000002;
+static const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_TRACKED_BIT = 0x00000004;
+static const XrViewStateFlags XR_VIEW_STATE_POSITION_TRACKED_BIT = 0x00000008;
+
+typedef XrFlags64 XrInputSourceLocalizedNameFlags;
+
+// Flag bits for XrInputSourceLocalizedNameFlags
+static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT = 0x00000001;
+static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT = 0x00000002;
+static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT = 0x00000004;
+
+typedef void (XRAPI_PTR *PFN_xrVoidFunction)(void);
+typedef struct XrApiLayerProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ char layerName[XR_MAX_API_LAYER_NAME_SIZE];
+ XrVersion specVersion;
+ uint32_t layerVersion;
+ char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];
+} XrApiLayerProperties;
+
+typedef struct XrExtensionProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ char extensionName[XR_MAX_EXTENSION_NAME_SIZE];
+ uint32_t extensionVersion;
+} XrExtensionProperties;
+
+typedef struct XrApplicationInfo {
+ char applicationName[XR_MAX_APPLICATION_NAME_SIZE];
+ uint32_t applicationVersion;
+ char engineName[XR_MAX_ENGINE_NAME_SIZE];
+ uint32_t engineVersion;
+ XrVersion apiVersion;
+} XrApplicationInfo;
+
+typedef struct XrInstanceCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrInstanceCreateFlags createFlags;
+ XrApplicationInfo applicationInfo;
+ uint32_t enabledApiLayerCount;
+ const char* const* enabledApiLayerNames;
+ uint32_t enabledExtensionCount;
+ const char* const* enabledExtensionNames;
+} XrInstanceCreateInfo;
+
+typedef struct XrInstanceProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion runtimeVersion;
+ char runtimeName[XR_MAX_RUNTIME_NAME_SIZE];
+} XrInstanceProperties;
+
+typedef struct XrEventDataBuffer {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint8_t varying[4000];
+} XrEventDataBuffer;
+
+typedef struct XrSystemGetInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrFormFactor formFactor;
+} XrSystemGetInfo;
+
+typedef struct XrSystemGraphicsProperties {
+ uint32_t maxSwapchainImageHeight;
+ uint32_t maxSwapchainImageWidth;
+ uint32_t maxLayerCount;
+} XrSystemGraphicsProperties;
+
+typedef struct XrSystemTrackingProperties {
+ XrBool32 orientationTracking;
+ XrBool32 positionTracking;
+} XrSystemTrackingProperties;
+
+typedef struct XrSystemProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSystemId systemId;
+ uint32_t vendorId;
+ char systemName[XR_MAX_SYSTEM_NAME_SIZE];
+ XrSystemGraphicsProperties graphicsProperties;
+ XrSystemTrackingProperties trackingProperties;
+} XrSystemProperties;
+
+typedef struct XrSessionCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSessionCreateFlags createFlags;
+ XrSystemId systemId;
+} XrSessionCreateInfo;
+
+typedef struct XrVector3f {
+ float x;
+ float y;
+ float z;
+} XrVector3f;
+
+typedef struct XrSpaceVelocity {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSpaceVelocityFlags velocityFlags;
+ XrVector3f linearVelocity;
+ XrVector3f angularVelocity;
+} XrSpaceVelocity;
+
+typedef struct XrQuaternionf {
+ float x;
+ float y;
+ float z;
+ float w;
+} XrQuaternionf;
+
+typedef struct XrPosef {
+ XrQuaternionf orientation;
+ XrVector3f position;
+} XrPosef;
+
+typedef struct XrReferenceSpaceCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrReferenceSpaceType referenceSpaceType;
+ XrPosef poseInReferenceSpace;
+} XrReferenceSpaceCreateInfo;
+
+typedef struct XrExtent2Df {
+ float width;
+ float height;
+} XrExtent2Df;
+
+typedef struct XrActionSpaceCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath subactionPath;
+ XrPosef poseInActionSpace;
+} XrActionSpaceCreateInfo;
+
+typedef struct XrSpaceLocation {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSpaceLocationFlags locationFlags;
+ XrPosef pose;
+} XrSpaceLocation;
+
+typedef struct XrViewConfigurationProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+ XrBool32 fovMutable;
+} XrViewConfigurationProperties;
+
+typedef struct XrViewConfigurationView {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t recommendedImageRectWidth;
+ uint32_t maxImageRectWidth;
+ uint32_t recommendedImageRectHeight;
+ uint32_t maxImageRectHeight;
+ uint32_t recommendedSwapchainSampleCount;
+ uint32_t maxSwapchainSampleCount;
+} XrViewConfigurationView;
+
+typedef struct XrSwapchainCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS 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;
+} XrSwapchainCreateInfo;
+
+typedef struct XR_MAY_ALIAS XrSwapchainImageBaseHeader {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+} XrSwapchainImageBaseHeader;
+
+typedef struct XrSwapchainImageAcquireInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSwapchainImageAcquireInfo;
+
+typedef struct XrSwapchainImageWaitInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDuration timeout;
+} XrSwapchainImageWaitInfo;
+
+typedef struct XrSwapchainImageReleaseInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSwapchainImageReleaseInfo;
+
+typedef struct XrSessionBeginInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViewConfigurationType primaryViewConfigurationType;
+} XrSessionBeginInfo;
+
+typedef struct XrFrameWaitInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrFrameWaitInfo;
+
+typedef struct XrFrameState {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrTime predictedDisplayTime;
+ XrDuration predictedDisplayPeriod;
+ XrBool32 shouldRender;
+} XrFrameState;
+
+typedef struct XrFrameBeginInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrFrameBeginInfo;
+
+typedef struct XR_MAY_ALIAS XrCompositionLayerBaseHeader {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+} XrCompositionLayerBaseHeader;
+
+typedef struct XrFrameEndInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrTime displayTime;
+ XrEnvironmentBlendMode environmentBlendMode;
+ uint32_t layerCount;
+ const XrCompositionLayerBaseHeader* const* layers;
+} XrFrameEndInfo;
+
+typedef struct XrViewLocateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+ XrTime displayTime;
+ XrSpace space;
+} XrViewLocateInfo;
+
+typedef struct XrViewState {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrViewStateFlags viewStateFlags;
+} XrViewState;
+
+typedef struct XrFovf {
+ float angleLeft;
+ float angleRight;
+ float angleUp;
+ float angleDown;
+} XrFovf;
+
+typedef struct XrView {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPosef pose;
+ XrFovf fov;
+} XrView;
+
+typedef struct XrActionSetCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE];
+ char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE];
+ uint32_t priority;
+} XrActionSetCreateInfo;
+
+typedef struct XrActionCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ char actionName[XR_MAX_ACTION_NAME_SIZE];
+ XrActionType actionType;
+ uint32_t countSubactionPaths;
+ const XrPath* subactionPaths;
+ char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE];
+} XrActionCreateInfo;
+
+typedef struct XrActionSuggestedBinding {
+ XrAction action;
+ XrPath binding;
+} XrActionSuggestedBinding;
+
+typedef struct XrInteractionProfileSuggestedBinding {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPath interactionProfile;
+ uint32_t countSuggestedBindings;
+ const XrActionSuggestedBinding* suggestedBindings;
+} XrInteractionProfileSuggestedBinding;
+
+typedef struct XrSessionActionSetsAttachInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t countActionSets;
+ const XrActionSet* actionSets;
+} XrSessionActionSetsAttachInfo;
+
+typedef struct XrInteractionProfileState {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPath interactionProfile;
+} XrInteractionProfileState;
+
+typedef struct XrActionStateGetInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath subactionPath;
+} XrActionStateGetInfo;
+
+typedef struct XrActionStateBoolean {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+} XrActionStateBoolean;
+
+typedef struct XrActionStateFloat {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ float currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+} XrActionStateFloat;
+
+typedef struct XrVector2f {
+ float x;
+ float y;
+} XrVector2f;
+
+typedef struct XrActionStateVector2f {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVector2f currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+} XrActionStateVector2f;
+
+typedef struct XrActionStatePose {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 isActive;
+} XrActionStatePose;
+
+typedef struct XrActiveActionSet {
+ XrActionSet actionSet;
+ XrPath subactionPath;
+} XrActiveActionSet;
+
+typedef struct XrActionsSyncInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t countActiveActionSets;
+ const XrActiveActionSet* activeActionSets;
+} XrActionsSyncInfo;
+
+typedef struct XrBoundSourcesForActionEnumerateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+} XrBoundSourcesForActionEnumerateInfo;
+
+typedef struct XrInputSourceLocalizedNameGetInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPath sourcePath;
+ XrInputSourceLocalizedNameFlags whichComponents;
+} XrInputSourceLocalizedNameGetInfo;
+
+typedef struct XrHapticActionInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath subactionPath;
+} XrHapticActionInfo;
+
+typedef struct XR_MAY_ALIAS XrHapticBaseHeader {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrHapticBaseHeader;
+
+typedef struct XR_MAY_ALIAS XrBaseInStructure {
+ XrStructureType type;
+ const struct XrBaseInStructure* next;
+} XrBaseInStructure;
+
+typedef struct XR_MAY_ALIAS XrBaseOutStructure {
+ XrStructureType type;
+ struct XrBaseOutStructure* next;
+} XrBaseOutStructure;
+
+typedef struct XrOffset2Di {
+ int32_t x;
+ int32_t y;
+} XrOffset2Di;
+
+typedef struct XrExtent2Di {
+ int32_t width;
+ int32_t height;
+} XrExtent2Di;
+
+typedef struct XrRect2Di {
+ XrOffset2Di offset;
+ XrExtent2Di extent;
+} XrRect2Di;
+
+typedef struct XrSwapchainSubImage {
+ XrSwapchain swapchain;
+ XrRect2Di imageRect;
+ uint32_t imageArrayIndex;
+} XrSwapchainSubImage;
+
+typedef struct XrCompositionLayerProjectionView {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPosef pose;
+ XrFovf fov;
+ XrSwapchainSubImage subImage;
+} XrCompositionLayerProjectionView;
+
+typedef struct XrCompositionLayerProjection {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ uint32_t viewCount;
+ const XrCompositionLayerProjectionView* views;
+} XrCompositionLayerProjection;
+
+typedef struct XrCompositionLayerQuad {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ XrExtent2Df size;
+} XrCompositionLayerQuad;
+
+typedef struct XR_MAY_ALIAS XrEventDataBaseHeader {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrEventDataBaseHeader;
+
+typedef struct XrEventDataEventsLost {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t lostEventCount;
+} XrEventDataEventsLost;
+
+typedef struct XrEventDataInstanceLossPending {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrTime lossTime;
+} XrEventDataInstanceLossPending;
+
+typedef struct XrEventDataSessionStateChanged {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+ XrSessionState state;
+ XrTime time;
+} XrEventDataSessionStateChanged;
+
+typedef struct XrEventDataReferenceSpaceChangePending {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+ XrReferenceSpaceType referenceSpaceType;
+ XrTime changeTime;
+ XrBool32 poseValid;
+ XrPosef poseInPreviousSpace;
+} XrEventDataReferenceSpaceChangePending;
+
+typedef struct XrEventDataInteractionProfileChanged {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+} XrEventDataInteractionProfileChanged;
+
+typedef struct XrHapticVibration {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDuration duration;
+ float frequency;
+ float amplitude;
+} XrHapticVibration;
+
+typedef struct XrOffset2Df {
+ float x;
+ float y;
+} XrOffset2Df;
+
+typedef struct XrRect2Df {
+ XrOffset2Df offset;
+ XrExtent2Df extent;
+} XrRect2Df;
+
+typedef struct XrVector4f {
+ float x;
+ float y;
+ float z;
+ float w;
+} XrVector4f;
+
+typedef struct XrColor4f {
+ float r;
+ float g;
+ float b;
+ float a;
+} XrColor4f;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateApiLayerProperties)(uint32_t propertyCapacityInput, uint32_t* propertyCountOutput, XrApiLayerProperties* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateInstanceExtensionProperties)(const char* layerName, uint32_t propertyCapacityInput, uint32_t* propertyCountOutput, XrExtensionProperties* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateInstance)(const XrInstanceCreateInfo* createInfo, XrInstance* instance);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyInstance)(XrInstance instance);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProperties)(XrInstance instance, XrInstanceProperties* instanceProperties);
+typedef XrResult (XRAPI_PTR *PFN_xrPollEvent)(XrInstance instance, XrEventDataBuffer* eventData);
+typedef XrResult (XRAPI_PTR *PFN_xrResultToString)(XrInstance instance, XrResult value, char buffer[XR_MAX_RESULT_STRING_SIZE]);
+typedef XrResult (XRAPI_PTR *PFN_xrStructureTypeToString)(XrInstance instance, XrStructureType value, char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSystem)(XrInstance instance, const XrSystemGetInfo* getInfo, XrSystemId* systemId);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSystemProperties)(XrInstance instance, XrSystemId systemId, XrSystemProperties* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateEnvironmentBlendModes)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t* environmentBlendModeCountOutput, XrEnvironmentBlendMode* environmentBlendModes);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSession)(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySession)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateReferenceSpaces)(XrSession session, uint32_t spaceCapacityInput, uint32_t* spaceCountOutput, XrReferenceSpaceType* spaces);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession session, const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrGetReferenceSpaceBoundsRect)(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df* bounds);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession session, const XrActionSpaceCreateInfo* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation* location);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpace)(XrSpace space);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurations)(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t* viewConfigurationTypeCountOutput, XrViewConfigurationType* viewConfigurationTypes);
+typedef XrResult (XRAPI_PTR *PFN_xrGetViewConfigurationProperties)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties* configurationProperties);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurationViews)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrViewConfigurationView* views);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainFormats)(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchain)(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySwapchain)(XrSwapchain swapchain);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainImages)(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images);
+typedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index);
+typedef XrResult (XRAPI_PTR *PFN_xrWaitSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageWaitInfo* waitInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrBeginSession)(XrSession session, const XrSessionBeginInfo* beginInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEndSession)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrRequestExitSession)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrWaitFrame)(XrSession session, const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState);
+typedef XrResult (XRAPI_PTR *PFN_xrBeginFrame)(XrSession session, const XrFrameBeginInfo* frameBeginInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEndFrame)(XrSession session, const XrFrameEndInfo* frameEndInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateViews)(XrSession session, const XrViewLocateInfo* viewLocateInfo, XrViewState* viewState, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrView* views);
+typedef XrResult (XRAPI_PTR *PFN_xrStringToPath)(XrInstance instance, const char* pathString, XrPath* path);
+typedef XrResult (XRAPI_PTR *PFN_xrPathToString)(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSet)(XrInstance instance, const XrActionSetCreateInfo* createInfo, XrActionSet* actionSet);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyActionSet)(XrActionSet actionSet);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateAction)(XrActionSet actionSet, const XrActionCreateInfo* createInfo, XrAction* action);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyAction)(XrAction action);
+typedef XrResult (XRAPI_PTR *PFN_xrSuggestInteractionProfileBindings)(XrInstance instance, const XrInteractionProfileSuggestedBinding* suggestedBindings);
+typedef XrResult (XRAPI_PTR *PFN_xrAttachSessionActionSets)(XrSession session, const XrSessionActionSetsAttachInfo* attachInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrGetCurrentInteractionProfile)(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState* interactionProfile);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateBoolean)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateBoolean* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateFloat)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateFloat* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateVector2f)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateVector2f* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStatePose)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStatePose* state);
+typedef XrResult (XRAPI_PTR *PFN_xrSyncActions)(XrSession session, const XrActionsSyncInfo* syncInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateBoundSourcesForAction)(XrSession session, const XrBoundSourcesForActionEnumerateInfo* enumerateInfo, uint32_t sourceCapacityInput, uint32_t* sourceCountOutput, XrPath* sources);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInputSourceLocalizedName)(XrSession session, const XrInputSourceLocalizedNameGetInfo* getInfo, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrApplyHapticFeedback)(XrSession session, const XrHapticActionInfo* hapticActionInfo, const XrHapticBaseHeader* hapticFeedback);
+typedef XrResult (XRAPI_PTR *PFN_xrStopHapticFeedback)(XrSession session, const XrHapticActionInfo* hapticActionInfo);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(
+ XrInstance instance,
+ const char* name,
+ PFN_xrVoidFunction* function);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(
+ uint32_t propertyCapacityInput,
+ uint32_t* propertyCountOutput,
+ XrApiLayerProperties* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(
+ const char* layerName,
+ uint32_t propertyCapacityInput,
+ uint32_t* propertyCountOutput,
+ XrExtensionProperties* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(
+ const XrInstanceCreateInfo* createInfo,
+ XrInstance* instance);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(
+ XrInstance instance);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
+ XrSpace space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
+ XrSwapchain swapchain);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
+ XrActionSet actionSet);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
+ XrAction action);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo);
+#endif
+
+
+#define XR_KHR_composition_layer_cube 1
+#define XR_KHR_composition_layer_cube_SPEC_VERSION 8
+#define XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME "XR_KHR_composition_layer_cube"
+typedef struct XrCompositionLayerCubeKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchain swapchain;
+ uint32_t imageArrayIndex;
+ XrQuaternionf orientation;
+} XrCompositionLayerCubeKHR;
+
+
+
+#define XR_KHR_composition_layer_depth 1
+#define XR_KHR_composition_layer_depth_SPEC_VERSION 5
+#define XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME "XR_KHR_composition_layer_depth"
+typedef struct XrCompositionLayerDepthInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSwapchainSubImage subImage;
+ float minDepth;
+ float maxDepth;
+ float nearZ;
+ float farZ;
+} XrCompositionLayerDepthInfoKHR;
+
+
+
+#define XR_KHR_composition_layer_cylinder 1
+#define XR_KHR_composition_layer_cylinder_SPEC_VERSION 4
+#define XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME "XR_KHR_composition_layer_cylinder"
+typedef struct XrCompositionLayerCylinderKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ float centralAngle;
+ float aspectRatio;
+} XrCompositionLayerCylinderKHR;
+
+
+
+#define XR_KHR_composition_layer_equirect 1
+#define XR_KHR_composition_layer_equirect_SPEC_VERSION 3
+#define XR_KHR_COMPOSITION_LAYER_EQUIRECT_EXTENSION_NAME "XR_KHR_composition_layer_equirect"
+typedef struct XrCompositionLayerEquirectKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ XrVector2f scale;
+ XrVector2f bias;
+} XrCompositionLayerEquirectKHR;
+
+
+
+#define XR_KHR_visibility_mask 1
+#define XR_KHR_visibility_mask_SPEC_VERSION 2
+#define XR_KHR_VISIBILITY_MASK_EXTENSION_NAME "XR_KHR_visibility_mask"
+
+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_MAX_ENUM_KHR = 0x7FFFFFFF
+} XrVisibilityMaskTypeKHR;
+typedef struct XrVisibilityMaskKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrVector2f* vertices;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint32_t* indices;
+} XrVisibilityMaskKHR;
+
+typedef struct XrEventDataVisibilityMaskChangedKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+ XrViewConfigurationType viewConfigurationType;
+ uint32_t viewIndex;
+} XrEventDataVisibilityMaskChangedKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetVisibilityMaskKHR)(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR* visibilityMask);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVisibilityMaskKHR(
+ XrSession session,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewIndex,
+ XrVisibilityMaskTypeKHR visibilityMaskType,
+ XrVisibilityMaskKHR* visibilityMask);
+#endif
+
+
+#define XR_EXT_performance_settings 1
+#define XR_EXT_performance_settings_SPEC_VERSION 1
+#define XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME "XR_EXT_performance_settings"
+
+typedef enum XrPerfSettingsDomainEXT {
+ XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
+ XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
+ XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsDomainEXT;
+
+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_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsSubDomainEXT;
+
+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_MAX_ENUM_EXT = 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_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsNotificationLevelEXT;
+typedef struct XrEventDataPerfSettingsEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPerfSettingsDomainEXT domain;
+ XrPerfSettingsSubDomainEXT subDomain;
+ XrPerfSettingsNotificationLevelEXT fromLevel;
+ XrPerfSettingsNotificationLevelEXT toLevel;
+} XrEventDataPerfSettingsEXT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrPerfSettingsSetPerformanceLevelEXT)(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrPerfSettingsSetPerformanceLevelEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsLevelEXT level);
+#endif
+
+
+#define XR_EXT_thermal_query 1
+#define XR_EXT_thermal_query_SPEC_VERSION 1
+#define XR_EXT_THERMAL_QUERY_EXTENSION_NAME "XR_EXT_thermal_query"
+typedef XrResult (XRAPI_PTR *PFN_xrThermalGetTemperatureTrendEXT)(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsNotificationLevelEXT* notificationLevel, float* tempHeadroom, float* tempSlope);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrThermalGetTemperatureTrendEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsNotificationLevelEXT* notificationLevel,
+ float* tempHeadroom,
+ float* tempSlope);
+#endif
+
+
+#define XR_EXT_debug_utils 1
+XR_DEFINE_HANDLE(XrDebugUtilsMessengerEXT)
+#define XR_EXT_debug_utils_SPEC_VERSION 3
+#define XR_EXT_DEBUG_UTILS_EXTENSION_NAME "XR_EXT_debug_utils"
+typedef XrFlags64 XrDebugUtilsMessageSeverityFlagsEXT;
+
+// Flag bits for XrDebugUtilsMessageSeverityFlagsEXT
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001;
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010;
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100;
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000;
+
+typedef XrFlags64 XrDebugUtilsMessageTypeFlagsEXT;
+
+// Flag bits for XrDebugUtilsMessageTypeFlagsEXT
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001;
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002;
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004;
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT = 0x00000008;
+
+typedef struct XrDebugUtilsObjectNameInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrObjectType objectType;
+ uint64_t objectHandle;
+ const char* objectName;
+} XrDebugUtilsObjectNameInfoEXT;
+
+typedef struct XrDebugUtilsLabelEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ const char* labelName;
+} XrDebugUtilsLabelEXT;
+
+typedef struct XrDebugUtilsMessengerCallbackDataEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ const char* messageId;
+ const char* functionName;
+ const char* message;
+ uint32_t objectCount;
+ XrDebugUtilsObjectNameInfoEXT* objects;
+ uint32_t sessionLabelCount;
+ XrDebugUtilsLabelEXT* sessionLabels;
+} XrDebugUtilsMessengerCallbackDataEXT;
+
+typedef XrBool32 (XRAPI_PTR *PFN_xrDebugUtilsMessengerCallbackEXT)(
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData,
+ void* userData);
+
+
+typedef struct XrDebugUtilsMessengerCreateInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverities;
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes;
+ PFN_xrDebugUtilsMessengerCallbackEXT userCallback;
+ void* XR_MAY_ALIAS userData;
+} XrDebugUtilsMessengerCreateInfoEXT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrSetDebugUtilsObjectNameEXT)(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateDebugUtilsMessengerEXT)(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT* createInfo, XrDebugUtilsMessengerEXT* messenger);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyDebugUtilsMessengerEXT)(XrDebugUtilsMessengerEXT messenger);
+typedef XrResult (XRAPI_PTR *PFN_xrSubmitDebugUtilsMessageEXT)(XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
+typedef XrResult (XRAPI_PTR *PFN_xrSessionBeginDebugUtilsLabelRegionEXT)(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrSessionEndDebugUtilsLabelRegionEXT)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrSessionInsertDebugUtilsLabelEXT)(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+#endif
+
+
+#define XR_VARJO_quad_views 1
+#define XR_VARJO_quad_views_SPEC_VERSION 1
+#define XR_VARJO_QUAD_VIEWS_EXTENSION_NAME "XR_VARJO_quad_views"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/openxr/include/openxr/openxr_platform.h b/extern/openxr/include/openxr/openxr_platform.h
new file mode 100644
index 00000000000..f84dd8d20a6
--- /dev/null
+++ b/extern/openxr/include/openxr/openxr_platform.h
@@ -0,0 +1,383 @@
+#ifndef OPENXR_PLATFORM_H_
+#define OPENXR_PLATFORM_H_ 1
+
+/*
+** Copyright (c) 2017-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+#include "openxr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_android_thread_settings 1
+#define XR_KHR_android_thread_settings_SPEC_VERSION 5
+#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings"
+
+typedef enum XrAndroidThreadTypeKHR {
+ XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
+ XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
+ XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
+ XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
+ XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} XrAndroidThreadTypeKHR;
+typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
+ XrSession session,
+ XrAndroidThreadTypeKHR threadType,
+ uint32_t threadId);
+#endif
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_android_surface_swapchain 1
+#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4
+#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain"
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
+ XrSession session,
+ const XrSwapchainCreateInfo* info,
+ XrSwapchain* swapchain,
+ jobject* surface);
+#endif
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_android_create_instance 1
+#define XR_KHR_android_create_instance_SPEC_VERSION 3
+#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance"
+typedef struct XrInstanceCreateInfoAndroidKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ void* XR_MAY_ALIAS applicationVM;
+ void* XR_MAY_ALIAS applicationActivity;
+} XrInstanceCreateInfoAndroidKHR;
+
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_KHR_vulkan_swapchain_format_list 1
+#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"
+typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t viewFormatCount;
+ const VkFormat* viewFormats;
+} XrVulkanSwapchainFormatListCreateInfoKHR;
+
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL
+
+#define XR_KHR_opengl_enable 1
+#define XR_KHR_opengl_enable_SPEC_VERSION 7
+#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
+#ifdef XR_USE_PLATFORM_WIN32
+typedef struct XrGraphicsBindingOpenGLWin32KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ HDC hDC;
+ HGLRC hGLRC;
+} XrGraphicsBindingOpenGLWin32KHR;
+#endif // XR_USE_PLATFORM_WIN32
+
+#ifdef XR_USE_PLATFORM_XLIB
+typedef struct XrGraphicsBindingOpenGLXlibKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ Display* xDisplay;
+ uint32_t visualid;
+ GLXFBConfig glxFBConfig;
+ GLXDrawable glxDrawable;
+ GLXContext glxContext;
+} XrGraphicsBindingOpenGLXlibKHR;
+#endif // XR_USE_PLATFORM_XLIB
+
+#ifdef XR_USE_PLATFORM_XCB
+typedef struct XrGraphicsBindingOpenGLXcbKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ xcb_connection_t* connection;
+ uint32_t screenNumber;
+ xcb_glx_fbconfig_t fbconfigid;
+ xcb_visualid_t visualid;
+ xcb_glx_drawable_t glxDrawable;
+ xcb_glx_context_t glxContext;
+} XrGraphicsBindingOpenGLXcbKHR;
+#endif // XR_USE_PLATFORM_XCB
+
+#ifdef XR_USE_PLATFORM_WAYLAND
+typedef struct XrGraphicsBindingOpenGLWaylandKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ struct wl_display* display;
+} XrGraphicsBindingOpenGLWaylandKHR;
+#endif // XR_USE_PLATFORM_WAYLAND
+
+typedef struct XrSwapchainImageOpenGLKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t image;
+} XrSwapchainImageOpenGLKHR;
+
+typedef struct XrGraphicsRequirementsOpenGLKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+} XrGraphicsRequirementsOpenGLKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
+#endif
+#endif /* XR_USE_GRAPHICS_API_OPENGL */
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
+
+#define XR_KHR_opengl_es_enable 1
+#define XR_KHR_opengl_es_enable_SPEC_VERSION 6
+#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable"
+#ifdef XR_USE_PLATFORM_ANDROID
+typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ EGLDisplay display;
+ EGLConfig config;
+ EGLContext context;
+} XrGraphicsBindingOpenGLESAndroidKHR;
+#endif // XR_USE_PLATFORM_ANDROID
+
+typedef struct XrSwapchainImageOpenGLESKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t image;
+} XrSwapchainImageOpenGLESKHR;
+
+typedef struct XrGraphicsRequirementsOpenGLESKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+} XrGraphicsRequirementsOpenGLESKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
+#endif
+#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_KHR_vulkan_enable 1
+#define XR_KHR_vulkan_enable_SPEC_VERSION 6
+#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
+typedef struct XrGraphicsBindingVulkanKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ VkInstance instance;
+ VkPhysicalDevice physicalDevice;
+ VkDevice device;
+ uint32_t queueFamilyIndex;
+ uint32_t queueIndex;
+} XrGraphicsBindingVulkanKHR;
+
+typedef struct XrSwapchainImageVulkanKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ VkImage image;
+} XrSwapchainImageVulkanKHR;
+
+typedef struct XrGraphicsRequirementsVulkanKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+} XrGraphicsRequirementsVulkanKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ VkInstance vkInstance,
+ VkPhysicalDevice* vkPhysicalDevice);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+#endif
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_GRAPHICS_API_D3D11
+
+#define XR_KHR_D3D11_enable 1
+#define XR_KHR_D3D11_enable_SPEC_VERSION 4
+#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
+typedef struct XrGraphicsBindingD3D11KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ ID3D11Device* device;
+} XrGraphicsBindingD3D11KHR;
+
+typedef struct XrSwapchainImageD3D11KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ ID3D11Texture2D* texture;
+} XrSwapchainImageD3D11KHR;
+
+typedef struct XrGraphicsRequirementsD3D11KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ LUID adapterLuid;
+ D3D_FEATURE_LEVEL minFeatureLevel;
+} XrGraphicsRequirementsD3D11KHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
+#endif
+#endif /* XR_USE_GRAPHICS_API_D3D11 */
+
+#ifdef XR_USE_GRAPHICS_API_D3D12
+
+#define XR_KHR_D3D12_enable 1
+#define XR_KHR_D3D12_enable_SPEC_VERSION 5
+#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
+typedef struct XrGraphicsBindingD3D12KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ ID3D12Device* device;
+ ID3D12CommandQueue* queue;
+} XrGraphicsBindingD3D12KHR;
+
+typedef struct XrSwapchainImageD3D12KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ ID3D12Resource* texture;
+} XrSwapchainImageD3D12KHR;
+
+typedef struct XrGraphicsRequirementsD3D12KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ LUID adapterLuid;
+ D3D_FEATURE_LEVEL minFeatureLevel;
+} XrGraphicsRequirementsD3D12KHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
+#endif
+#endif /* XR_USE_GRAPHICS_API_D3D12 */
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#define XR_KHR_win32_convert_performance_counter_time 1
+#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1
+#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time"
+typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
+ XrInstance instance,
+ const LARGE_INTEGER* performanceCounter,
+ XrTime* time);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
+ XrInstance instance,
+ XrTime time,
+ LARGE_INTEGER* performanceCounter);
+#endif
+#endif /* XR_USE_PLATFORM_WIN32 */
+
+#ifdef XR_USE_TIMESPEC
+
+#define XR_KHR_convert_timespec_time 1
+#define XR_KHR_convert_timespec_time_SPEC_VERSION 1
+#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time"
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
+ XrInstance instance,
+ const struct timespec* timespecTime,
+ XrTime* time);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
+ XrInstance instance,
+ XrTime time,
+ struct timespec* timespecTime);
+#endif
+#endif /* XR_USE_TIMESPEC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/openxr/include/openxr/openxr_platform_defines.h b/extern/openxr/include/openxr/openxr_platform_defines.h
new file mode 100644
index 00000000000..1642f54d0e9
--- /dev/null
+++ b/extern/openxr/include/openxr/openxr_platform_defines.h
@@ -0,0 +1,124 @@
+/*
+** Copyright (c) 2017-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef OPENXR_PLATFORM_DEFINES_H_
+#define OPENXR_PLATFORM_DEFINES_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Platform-specific calling convention macros.
+ *
+ * Platforms should define these so that OpenXR clients call OpenXR functions
+ * with the same calling conventions that the OpenXR implementation expects.
+ *
+ * XRAPI_ATTR - Placed before the return type in function declarations.
+ * Useful for C++11 and GCC/Clang-style function attribute syntax.
+ * XRAPI_CALL - Placed after the return type in function declarations.
+ * Useful for MSVC-style calling convention syntax.
+ * XRAPI_PTR - Placed between the '(' and '*' in function pointer types.
+ *
+ * Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void);
+ * Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
+ */
+#if defined(_WIN32)
+#ifdef XRAPI_DLL_EXPORT
+#define XRAPI_ATTR __declspec(dllexport)
+#else
+#define XRAPI_ATTR
+#endif
+// On Windows, functions use the stdcall convention
+#define XRAPI_CALL __stdcall
+#define XRAPI_PTR XRAPI_CALL
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
+#error "API not supported for the 'armeabi' NDK ABI"
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
+// On Android 32-bit ARM targets, functions use the "hardfloat"
+// calling convention, i.e. float parameters are passed in registers. This
+// is true even if the rest of the application passes floats on the stack,
+// as it does by default when compiling for the armeabi-v7a NDK ABI.
+#define XRAPI_ATTR __attribute__((pcs("aapcs-vfp")))
+#define XRAPI_CALL
+#define XRAPI_PTR XRAPI_ATTR
+#else
+// On other platforms, use the default calling convention
+#define XRAPI_ATTR
+#define XRAPI_CALL
+#define XRAPI_PTR
+#endif
+
+#include <stddef.h>
+
+#if !defined(XR_NO_STDINT_H)
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <stdint.h>
+#endif
+#endif // !defined( XR_NO_STDINT_H )
+
+// XR_PTR_SIZE (in bytes)
+#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))
+#define XR_PTR_SIZE 8
+#else
+#define XR_PTR_SIZE 4
+#endif
+
+// Needed so we can use clang __has_feature portably.
+#if !defined(XR_COMPILER_HAS_FEATURE)
+#if defined(__clang__)
+#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)
+#else
+#define XR_COMPILER_HAS_FEATURE(x) 0
+#endif
+#endif
+
+// Identifies if the current compiler has C++11 support enabled.
+// Does not by itself identify if any given C++11 feature is present.
+#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)
+#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define XR_CPP11_ENABLED 1
+#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
+#define XR_CPP11_ENABLED 1
+#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.
+#define XR_CPP11_ENABLED 1
+#endif
+#endif
+
+// Identifies if the current compiler supports C++11 nullptr.
+#if !defined(XR_CPP_NULLPTR_SUPPORTED)
+#if defined(XR_CPP11_ENABLED) && \
+ ((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \
+ (defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
+ (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))
+#define XR_CPP_NULLPTR_SUPPORTED 1
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/extern/openxr/include/openxr/openxr_reflection.h b/extern/openxr/include/openxr/openxr_reflection.h
new file mode 100644
index 00000000000..0589daae4e3
--- /dev/null
+++ b/extern/openxr/include/openxr/openxr_reflection.h
@@ -0,0 +1,1004 @@
+#ifndef OPENXR_REFLECTION_H_
+#define OPENXR_REFLECTION_H_ 1
+
+/*
+** Copyright (c) 2017-2019 The Khronos Group Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+#include "openxr.h"
+
+/*
+This file contains expansion macros (X Macros) for OpenXR enumerations and structures.
+Example of how to use expansion macros to make an enum-to-string function:
+
+#define XR_ENUM_CASE_STR(name, val) case name: return #name;
+#define XR_ENUM_STR(enumType) \
+ constexpr const char* XrEnumStr(enumType e) { \
+ switch (e) { \
+ XR_LIST_ENUM_##enumType(XR_ENUM_CASE_STR) \
+ default: return "Unknown"; \
+ } \
+ } \
+
+XR_ENUM_STR(XrResult);
+*/
+
+#define XR_LIST_ENUM_XrResult(_) \
+ _(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_ERROR_VALIDATION_FAILURE, -1) \
+ _(XR_ERROR_RUNTIME_FAILURE, -2) \
+ _(XR_ERROR_OUT_OF_MEMORY, -3) \
+ _(XR_ERROR_API_VERSION_UNSUPPORTED, -4) \
+ _(XR_ERROR_INITIALIZATION_FAILED, -6) \
+ _(XR_ERROR_FUNCTION_UNSUPPORTED, -7) \
+ _(XR_ERROR_FEATURE_UNSUPPORTED, -8) \
+ _(XR_ERROR_EXTENSION_NOT_PRESENT, -9) \
+ _(XR_ERROR_LIMIT_REACHED, -10) \
+ _(XR_ERROR_SIZE_INSUFFICIENT, -11) \
+ _(XR_ERROR_HANDLE_INVALID, -12) \
+ _(XR_ERROR_INSTANCE_LOST, -13) \
+ _(XR_ERROR_SESSION_RUNNING, -14) \
+ _(XR_ERROR_SESSION_NOT_RUNNING, -16) \
+ _(XR_ERROR_SESSION_LOST, -17) \
+ _(XR_ERROR_SYSTEM_INVALID, -18) \
+ _(XR_ERROR_PATH_INVALID, -19) \
+ _(XR_ERROR_PATH_COUNT_EXCEEDED, -20) \
+ _(XR_ERROR_PATH_FORMAT_INVALID, -21) \
+ _(XR_ERROR_PATH_UNSUPPORTED, -22) \
+ _(XR_ERROR_LAYER_INVALID, -23) \
+ _(XR_ERROR_LAYER_LIMIT_EXCEEDED, -24) \
+ _(XR_ERROR_SWAPCHAIN_RECT_INVALID, -25) \
+ _(XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED, -26) \
+ _(XR_ERROR_ACTION_TYPE_MISMATCH, -27) \
+ _(XR_ERROR_SESSION_NOT_READY, -28) \
+ _(XR_ERROR_SESSION_NOT_STOPPING, -29) \
+ _(XR_ERROR_TIME_INVALID, -30) \
+ _(XR_ERROR_REFERENCE_SPACE_UNSUPPORTED, -31) \
+ _(XR_ERROR_FILE_ACCESS_ERROR, -32) \
+ _(XR_ERROR_FILE_CONTENTS_INVALID, -33) \
+ _(XR_ERROR_FORM_FACTOR_UNSUPPORTED, -34) \
+ _(XR_ERROR_FORM_FACTOR_UNAVAILABLE, -35) \
+ _(XR_ERROR_API_LAYER_NOT_PRESENT, -36) \
+ _(XR_ERROR_CALL_ORDER_INVALID, -37) \
+ _(XR_ERROR_GRAPHICS_DEVICE_INVALID, -38) \
+ _(XR_ERROR_POSE_INVALID, -39) \
+ _(XR_ERROR_INDEX_OUT_OF_RANGE, -40) \
+ _(XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, -41) \
+ _(XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED, -42) \
+ _(XR_ERROR_NAME_DUPLICATED, -44) \
+ _(XR_ERROR_NAME_INVALID, -45) \
+ _(XR_ERROR_ACTIONSET_NOT_ATTACHED, -46) \
+ _(XR_ERROR_ACTIONSETS_ALREADY_ATTACHED, -47) \
+ _(XR_ERROR_LOCALIZED_NAME_DUPLICATED, -48) \
+ _(XR_ERROR_LOCALIZED_NAME_INVALID, -49) \
+ _(XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR, -1000003000) \
+ _(XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR, -1000003001) \
+ _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_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_INSTANCE_CREATE_INFO_ANDROID_KHR, 1000008000) \
+ _(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_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 1000019000) \
+ _(XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 1000019001) \
+ _(XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, 1000019002) \
+ _(XR_TYPE_DEBUG_UTILS_LABEL_EXT, 1000019003) \
+ _(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_OPENGL_ES_ANDROID_KHR, 1000024001) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR, 1000024002) \
+ _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, 1000024003) \
+ _(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_VISIBILITY_MASK_KHR, 1000031000) \
+ _(XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, 1000031001) \
+ _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFormFactor(_) \
+ _(XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, 1) \
+ _(XR_FORM_FACTOR_HANDHELD_DISPLAY, 2) \
+ _(XR_FORM_FACTOR_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_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_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_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)
+
+#define XR_LIST_ENUM_XrReferenceSpaceType(_) \
+ _(XR_REFERENCE_SPACE_TYPE_VIEW, 1) \
+ _(XR_REFERENCE_SPACE_TYPE_LOCAL, 2) \
+ _(XR_REFERENCE_SPACE_TYPE_STAGE, 3) \
+ _(XR_REFERENCE_SPACE_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_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)
+
+#define XR_LIST_ENUM_XrEyeVisibility(_) \
+ _(XR_EYE_VISIBILITY_BOTH, 0) \
+ _(XR_EYE_VISIBILITY_LEFT, 1) \
+ _(XR_EYE_VISIBILITY_RIGHT, 2) \
+ _(XR_EYE_VISIBILITY_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_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)
+
+#define XR_LIST_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_DEBUG_UTILS_MESSENGER_EXT, 1000019000) \
+ _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrAndroidThreadTypeKHR(_) \
+ _(XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, 1) \
+ _(XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR, 2) \
+ _(XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, 3) \
+ _(XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR, 4) \
+ _(XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF)
+
+#define XR_LIST_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_MAX_ENUM_KHR, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPerfSettingsDomainEXT(_) \
+ _(XR_PERF_SETTINGS_DOMAIN_CPU_EXT, 1) \
+ _(XR_PERF_SETTINGS_DOMAIN_GPU_EXT, 2) \
+ _(XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_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_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_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_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_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_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_BITS_XrInstanceCreateFlags(_)
+
+#define XR_LIST_BITS_XrSessionCreateFlags(_)
+
+#define XR_LIST_BITS_XrSpaceVelocityFlags(_) \
+ _(XR_SPACE_VELOCITY_LINEAR_VALID_BIT, 0x00000001) \
+ _(XR_SPACE_VELOCITY_ANGULAR_VALID_BIT, 0x00000002)
+
+#define XR_LIST_BITS_XrSpaceLocationFlags(_) \
+ _(XR_SPACE_LOCATION_ORIENTATION_VALID_BIT, 0x00000001) \
+ _(XR_SPACE_LOCATION_POSITION_VALID_BIT, 0x00000002) \
+ _(XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT, 0x00000004) \
+ _(XR_SPACE_LOCATION_POSITION_TRACKED_BIT, 0x00000008)
+
+#define XR_LIST_BITS_XrSwapchainCreateFlags(_) \
+ _(XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT, 0x00000001) \
+ _(XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT, 0x00000002)
+
+#define XR_LIST_BITS_XrSwapchainUsageFlags(_) \
+ _(XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, 0x00000001) \
+ _(XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0x00000002) \
+ _(XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT, 0x00000004) \
+ _(XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT, 0x00000008) \
+ _(XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT, 0x00000010) \
+ _(XR_SWAPCHAIN_USAGE_SAMPLED_BIT, 0x00000020) \
+ _(XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, 0x00000040)
+
+#define XR_LIST_BITS_XrCompositionLayerFlags(_) \
+ _(XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, 0x00000001) \
+ _(XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT, 0x00000002) \
+ _(XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT, 0x00000004)
+
+#define XR_LIST_BITS_XrViewStateFlags(_) \
+ _(XR_VIEW_STATE_ORIENTATION_VALID_BIT, 0x00000001) \
+ _(XR_VIEW_STATE_POSITION_VALID_BIT, 0x00000002) \
+ _(XR_VIEW_STATE_ORIENTATION_TRACKED_BIT, 0x00000004) \
+ _(XR_VIEW_STATE_POSITION_TRACKED_BIT, 0x00000008)
+
+#define XR_LIST_BITS_XrInputSourceLocalizedNameFlags(_) \
+ _(XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT, 0x00000001) \
+ _(XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT, 0x00000002) \
+ _(XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT, 0x00000004)
+
+#define XR_LIST_BITS_XrDebugUtilsMessageSeverityFlagsEXT(_) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, 0x00000001) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, 0x00000010) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, 0x00000100) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 0x00001000)
+
+#define XR_LIST_BITS_XrDebugUtilsMessageTypeFlagsEXT(_) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 0x00000001) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, 0x00000002) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, 0x00000004) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT, 0x00000008)
+
+#define XR_LIST_STRUCT_XrApiLayerProperties(_) \
+ _(type) \
+ _(next) \
+ _(layerName) \
+ _(specVersion) \
+ _(layerVersion) \
+ _(description)
+
+#define XR_LIST_STRUCT_XrExtensionProperties(_) \
+ _(type) \
+ _(next) \
+ _(extensionName) \
+ _(extensionVersion)
+
+#define XR_LIST_STRUCT_XrApplicationInfo(_) \
+ _(applicationName) \
+ _(applicationVersion) \
+ _(engineName) \
+ _(engineVersion) \
+ _(apiVersion)
+
+#define XR_LIST_STRUCT_XrInstanceCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(applicationInfo) \
+ _(enabledApiLayerCount) \
+ _(enabledApiLayerNames) \
+ _(enabledExtensionCount) \
+ _(enabledExtensionNames)
+
+#define XR_LIST_STRUCT_XrInstanceProperties(_) \
+ _(type) \
+ _(next) \
+ _(runtimeVersion) \
+ _(runtimeName)
+
+#define XR_LIST_STRUCT_XrEventDataBuffer(_) \
+ _(type) \
+ _(next) \
+ _(varying)
+
+#define XR_LIST_STRUCT_XrSystemGetInfo(_) \
+ _(type) \
+ _(next) \
+ _(formFactor)
+
+#define XR_LIST_STRUCT_XrSystemGraphicsProperties(_) \
+ _(maxSwapchainImageHeight) \
+ _(maxSwapchainImageWidth) \
+ _(maxLayerCount)
+
+#define XR_LIST_STRUCT_XrSystemTrackingProperties(_) \
+ _(orientationTracking) \
+ _(positionTracking)
+
+#define XR_LIST_STRUCT_XrSystemProperties(_) \
+ _(type) \
+ _(next) \
+ _(systemId) \
+ _(vendorId) \
+ _(systemName) \
+ _(graphicsProperties) \
+ _(trackingProperties)
+
+#define XR_LIST_STRUCT_XrSessionCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(systemId)
+
+#define XR_LIST_STRUCT_XrVector3f(_) \
+ _(x) \
+ _(y) \
+ _(z)
+
+#define XR_LIST_STRUCT_XrSpaceVelocity(_) \
+ _(type) \
+ _(next) \
+ _(velocityFlags) \
+ _(linearVelocity) \
+ _(angularVelocity)
+
+#define XR_LIST_STRUCT_XrQuaternionf(_) \
+ _(x) \
+ _(y) \
+ _(z) \
+ _(w)
+
+#define XR_LIST_STRUCT_XrPosef(_) \
+ _(orientation) \
+ _(position)
+
+#define XR_LIST_STRUCT_XrReferenceSpaceCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(referenceSpaceType) \
+ _(poseInReferenceSpace)
+
+#define XR_LIST_STRUCT_XrExtent2Df(_) \
+ _(width) \
+ _(height)
+
+#define XR_LIST_STRUCT_XrActionSpaceCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(subactionPath) \
+ _(poseInActionSpace)
+
+#define XR_LIST_STRUCT_XrSpaceLocation(_) \
+ _(type) \
+ _(next) \
+ _(locationFlags) \
+ _(pose)
+
+#define XR_LIST_STRUCT_XrViewConfigurationProperties(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+ _(fovMutable)
+
+#define XR_LIST_STRUCT_XrViewConfigurationView(_) \
+ _(type) \
+ _(next) \
+ _(recommendedImageRectWidth) \
+ _(maxImageRectWidth) \
+ _(recommendedImageRectHeight) \
+ _(maxImageRectHeight) \
+ _(recommendedSwapchainSampleCount) \
+ _(maxSwapchainSampleCount)
+
+#define XR_LIST_STRUCT_XrSwapchainCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(usageFlags) \
+ _(format) \
+ _(sampleCount) \
+ _(width) \
+ _(height) \
+ _(faceCount) \
+ _(arraySize) \
+ _(mipCount)
+
+#define XR_LIST_STRUCT_XrSwapchainImageBaseHeader(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrSwapchainImageAcquireInfo(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrSwapchainImageWaitInfo(_) \
+ _(type) \
+ _(next) \
+ _(timeout)
+
+#define XR_LIST_STRUCT_XrSwapchainImageReleaseInfo(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrSessionBeginInfo(_) \
+ _(type) \
+ _(next) \
+ _(primaryViewConfigurationType)
+
+#define XR_LIST_STRUCT_XrFrameWaitInfo(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrFrameState(_) \
+ _(type) \
+ _(next) \
+ _(predictedDisplayTime) \
+ _(predictedDisplayPeriod) \
+ _(shouldRender)
+
+#define XR_LIST_STRUCT_XrFrameBeginInfo(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrCompositionLayerBaseHeader(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space)
+
+#define XR_LIST_STRUCT_XrFrameEndInfo(_) \
+ _(type) \
+ _(next) \
+ _(displayTime) \
+ _(environmentBlendMode) \
+ _(layerCount) \
+ _(layers)
+
+#define XR_LIST_STRUCT_XrViewLocateInfo(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+ _(displayTime) \
+ _(space)
+
+#define XR_LIST_STRUCT_XrViewState(_) \
+ _(type) \
+ _(next) \
+ _(viewStateFlags)
+
+#define XR_LIST_STRUCT_XrFovf(_) \
+ _(angleLeft) \
+ _(angleRight) \
+ _(angleUp) \
+ _(angleDown)
+
+#define XR_LIST_STRUCT_XrView(_) \
+ _(type) \
+ _(next) \
+ _(pose) \
+ _(fov)
+
+#define XR_LIST_STRUCT_XrActionSetCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(actionSetName) \
+ _(localizedActionSetName) \
+ _(priority)
+
+#define XR_LIST_STRUCT_XrActionCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(actionName) \
+ _(actionType) \
+ _(countSubactionPaths) \
+ _(subactionPaths) \
+ _(localizedActionName)
+
+#define XR_LIST_STRUCT_XrActionSuggestedBinding(_) \
+ _(action) \
+ _(binding)
+
+#define XR_LIST_STRUCT_XrInteractionProfileSuggestedBinding(_) \
+ _(type) \
+ _(next) \
+ _(interactionProfile) \
+ _(countSuggestedBindings) \
+ _(suggestedBindings)
+
+#define XR_LIST_STRUCT_XrSessionActionSetsAttachInfo(_) \
+ _(type) \
+ _(next) \
+ _(countActionSets) \
+ _(actionSets)
+
+#define XR_LIST_STRUCT_XrInteractionProfileState(_) \
+ _(type) \
+ _(next) \
+ _(interactionProfile)
+
+#define XR_LIST_STRUCT_XrActionStateGetInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(subactionPath)
+
+#define XR_LIST_STRUCT_XrActionStateBoolean(_) \
+ _(type) \
+ _(next) \
+ _(currentState) \
+ _(changedSinceLastSync) \
+ _(lastChangeTime) \
+ _(isActive)
+
+#define XR_LIST_STRUCT_XrActionStateFloat(_) \
+ _(type) \
+ _(next) \
+ _(currentState) \
+ _(changedSinceLastSync) \
+ _(lastChangeTime) \
+ _(isActive)
+
+#define XR_LIST_STRUCT_XrVector2f(_) \
+ _(x) \
+ _(y)
+
+#define XR_LIST_STRUCT_XrActionStateVector2f(_) \
+ _(type) \
+ _(next) \
+ _(currentState) \
+ _(changedSinceLastSync) \
+ _(lastChangeTime) \
+ _(isActive)
+
+#define XR_LIST_STRUCT_XrActionStatePose(_) \
+ _(type) \
+ _(next) \
+ _(isActive)
+
+#define XR_LIST_STRUCT_XrActiveActionSet(_) \
+ _(actionSet) \
+ _(subactionPath)
+
+#define XR_LIST_STRUCT_XrActionsSyncInfo(_) \
+ _(type) \
+ _(next) \
+ _(countActiveActionSets) \
+ _(activeActionSets)
+
+#define XR_LIST_STRUCT_XrBoundSourcesForActionEnumerateInfo(_) \
+ _(type) \
+ _(next) \
+ _(action)
+
+#define XR_LIST_STRUCT_XrInputSourceLocalizedNameGetInfo(_) \
+ _(type) \
+ _(next) \
+ _(sourcePath) \
+ _(whichComponents)
+
+#define XR_LIST_STRUCT_XrHapticActionInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(subactionPath)
+
+#define XR_LIST_STRUCT_XrHapticBaseHeader(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrBaseInStructure(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrBaseOutStructure(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrOffset2Di(_) \
+ _(x) \
+ _(y)
+
+#define XR_LIST_STRUCT_XrExtent2Di(_) \
+ _(width) \
+ _(height)
+
+#define XR_LIST_STRUCT_XrRect2Di(_) \
+ _(offset) \
+ _(extent)
+
+#define XR_LIST_STRUCT_XrSwapchainSubImage(_) \
+ _(swapchain) \
+ _(imageRect) \
+ _(imageArrayIndex)
+
+#define XR_LIST_STRUCT_XrCompositionLayerProjectionView(_) \
+ _(type) \
+ _(next) \
+ _(pose) \
+ _(fov) \
+ _(subImage)
+
+#define XR_LIST_STRUCT_XrCompositionLayerProjection(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(viewCount) \
+ _(views)
+
+#define XR_LIST_STRUCT_XrCompositionLayerQuad(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(size)
+
+#define XR_LIST_STRUCT_XrEventDataBaseHeader(_) \
+ _(type) \
+ _(next)
+
+#define XR_LIST_STRUCT_XrEventDataEventsLost(_) \
+ _(type) \
+ _(next) \
+ _(lostEventCount)
+
+#define XR_LIST_STRUCT_XrEventDataInstanceLossPending(_) \
+ _(type) \
+ _(next) \
+ _(lossTime)
+
+#define XR_LIST_STRUCT_XrEventDataSessionStateChanged(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+ _(state) \
+ _(time)
+
+#define XR_LIST_STRUCT_XrEventDataReferenceSpaceChangePending(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+ _(referenceSpaceType) \
+ _(changeTime) \
+ _(poseValid) \
+ _(poseInPreviousSpace)
+
+#define XR_LIST_STRUCT_XrEventDataInteractionProfileChanged(_) \
+ _(type) \
+ _(next) \
+ _(session)
+
+#define XR_LIST_STRUCT_XrHapticVibration(_) \
+ _(type) \
+ _(next) \
+ _(duration) \
+ _(frequency) \
+ _(amplitude)
+
+#define XR_LIST_STRUCT_XrOffset2Df(_) \
+ _(x) \
+ _(y)
+
+#define XR_LIST_STRUCT_XrRect2Df(_) \
+ _(offset) \
+ _(extent)
+
+#define XR_LIST_STRUCT_XrVector4f(_) \
+ _(x) \
+ _(y) \
+ _(z) \
+ _(w)
+
+#define XR_LIST_STRUCT_XrColor4f(_) \
+ _(r) \
+ _(g) \
+ _(b) \
+ _(a)
+
+#define XR_LIST_STRUCT_XrCompositionLayerCubeKHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(swapchain) \
+ _(imageArrayIndex) \
+ _(orientation)
+
+#define XR_LIST_STRUCT_XrInstanceCreateInfoAndroidKHR(_) \
+ _(type) \
+ _(next) \
+ _(applicationVM) \
+ _(applicationActivity)
+
+#define XR_LIST_STRUCT_XrCompositionLayerDepthInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(subImage) \
+ _(minDepth) \
+ _(maxDepth) \
+ _(nearZ) \
+ _(farZ)
+
+#define XR_LIST_STRUCT_XrVulkanSwapchainFormatListCreateInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(viewFormatCount) \
+ _(viewFormats)
+
+#define XR_LIST_STRUCT_XrCompositionLayerCylinderKHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(radius) \
+ _(centralAngle) \
+ _(aspectRatio)
+
+#define XR_LIST_STRUCT_XrCompositionLayerEquirectKHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(radius) \
+ _(scale) \
+ _(bias)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWin32KHR(_) \
+ _(type) \
+ _(next) \
+ _(hDC) \
+ _(hGLRC)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXlibKHR(_) \
+ _(type) \
+ _(next) \
+ _(xDisplay) \
+ _(visualid) \
+ _(glxFBConfig) \
+ _(glxDrawable) \
+ _(glxContext)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXcbKHR(_) \
+ _(type) \
+ _(next) \
+ _(connection) \
+ _(screenNumber) \
+ _(fbconfigid) \
+ _(visualid) \
+ _(glxDrawable) \
+ _(glxContext)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWaylandKHR(_) \
+ _(type) \
+ _(next) \
+ _(display)
+
+#define XR_LIST_STRUCT_XrSwapchainImageOpenGLKHR(_) \
+ _(type) \
+ _(next) \
+ _(image)
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLKHR(_) \
+ _(type) \
+ _(next) \
+ _(minApiVersionSupported) \
+ _(maxApiVersionSupported)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLESAndroidKHR(_) \
+ _(type) \
+ _(next) \
+ _(display) \
+ _(config) \
+ _(context)
+
+#define XR_LIST_STRUCT_XrSwapchainImageOpenGLESKHR(_) \
+ _(type) \
+ _(next) \
+ _(image)
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLESKHR(_) \
+ _(type) \
+ _(next) \
+ _(minApiVersionSupported) \
+ _(maxApiVersionSupported)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingVulkanKHR(_) \
+ _(type) \
+ _(next) \
+ _(instance) \
+ _(physicalDevice) \
+ _(device) \
+ _(queueFamilyIndex) \
+ _(queueIndex)
+
+#define XR_LIST_STRUCT_XrSwapchainImageVulkanKHR(_) \
+ _(type) \
+ _(next) \
+ _(image)
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsVulkanKHR(_) \
+ _(type) \
+ _(next) \
+ _(minApiVersionSupported) \
+ _(maxApiVersionSupported)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingD3D11KHR(_) \
+ _(type) \
+ _(next) \
+ _(device)
+
+#define XR_LIST_STRUCT_XrSwapchainImageD3D11KHR(_) \
+ _(type) \
+ _(next) \
+ _(texture)
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D11KHR(_) \
+ _(type) \
+ _(next) \
+ _(adapterLuid) \
+ _(minFeatureLevel)
+
+#define XR_LIST_STRUCT_XrGraphicsBindingD3D12KHR(_) \
+ _(type) \
+ _(next) \
+ _(device) \
+ _(queue)
+
+#define XR_LIST_STRUCT_XrSwapchainImageD3D12KHR(_) \
+ _(type) \
+ _(next) \
+ _(texture)
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D12KHR(_) \
+ _(type) \
+ _(next) \
+ _(adapterLuid) \
+ _(minFeatureLevel)
+
+#define XR_LIST_STRUCT_XrVisibilityMaskKHR(_) \
+ _(type) \
+ _(next) \
+ _(vertexCapacityInput) \
+ _(vertexCountOutput) \
+ _(vertices) \
+ _(indexCapacityInput) \
+ _(indexCountOutput) \
+ _(indices)
+
+#define XR_LIST_STRUCT_XrEventDataVisibilityMaskChangedKHR(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+ _(viewConfigurationType) \
+ _(viewIndex)
+
+#define XR_LIST_STRUCT_XrEventDataPerfSettingsEXT(_) \
+ _(type) \
+ _(next) \
+ _(domain) \
+ _(subDomain) \
+ _(fromLevel) \
+ _(toLevel)
+
+#define XR_LIST_STRUCT_XrDebugUtilsObjectNameInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(objectType) \
+ _(objectHandle) \
+ _(objectName)
+
+#define XR_LIST_STRUCT_XrDebugUtilsLabelEXT(_) \
+ _(type) \
+ _(next) \
+ _(labelName)
+
+#define XR_LIST_STRUCT_XrDebugUtilsMessengerCallbackDataEXT(_) \
+ _(type) \
+ _(next) \
+ _(messageId) \
+ _(functionName) \
+ _(message) \
+ _(objectCount) \
+ _(objects) \
+ _(sessionLabelCount) \
+ _(sessionLabels)
+
+#define XR_LIST_STRUCT_XrDebugUtilsMessengerCreateInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(messageSeverities) \
+ _(messageTypes) \
+ _(userCallback) \
+ _(userData)
+
+
+
+
+#endif
+
diff --git a/extern/openxr/src/CMakeLists.txt b/extern/openxr/src/CMakeLists.txt
new file mode 100644
index 00000000000..877d5b9562d
--- /dev/null
+++ b/extern/openxr/src/CMakeLists.txt
@@ -0,0 +1,194 @@
+# Copyright (c) 2017 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author:
+#
+
+# Entire project uses C++11
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+# All options defined here
+option(BUILD_LOADER "Build loader" ON)
+option(BUILD_LOADER_WITH_EXCEPTION_HANDLING "Enable exception handling in the loader. Leave this on unless your standard library is built to not throw." ON)
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ option(DYNAMIC_LOADER "Build the loader as a .dll library" OFF)
+else()
+ option(DYNAMIC_LOADER "Build the loader as a .dll library" ON)
+endif()
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/api_layers")
+ option(BUILD_API_LAYERS "Build API layers" ON)
+endif()
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
+ option(BUILD_TESTS "Build tests" ON)
+endif()
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/conformance")
+ option(BUILD_CONFORMANCE_TESTS "Build conformance tests" ON)
+endif()
+
+# Several files use these compile-time OS switches
+if(WIN32)
+ add_definitions(-DXR_OS_WINDOWS)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ add_definitions(-DXR_OS_LINUX)
+endif()
+
+# Determine the presentation backend for Linux systems.
+# Use an include because the code is pretty big.
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ include(presentation)
+endif()
+
+# Several files use these compile-time platform switches
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_definitions( -DXR_USE_PLATFORM_WIN32 )
+elseif( PRESENTATION_BACKEND MATCHES "xlib" )
+ add_definitions( -DXR_USE_PLATFORM_XLIB )
+elseif( PRESENTATION_BACKEND MATCHES "xcb" )
+ add_definitions( -DXR_USE_PLATFORM_XCB )
+
+ # TODO remove once conformance supports XCB
+ set(BUILD_CONFORMANCE_TESTS OFF)
+elseif( PRESENTATION_BACKEND MATCHES "wayland" )
+ add_definitions( -DXR_USE_PLATFORM_WAYLAND )
+
+ # TODO remove once conformance supports Wayland
+ set(BUILD_CONFORMANCE_TESTS OFF)
+endif()
+
+# Enable graphics API available to the build.
+if (NOT CMAKE_VERSION VERSION_LESS 3.7.0)
+ # Find the Vulkan headers
+ find_package(VulkanHeaders)
+ if (VulkanHeaders_FOUND)
+ add_definitions(-DXR_USE_GRAPHICS_API_VULKAN)
+ endif()
+ # Find the Vulkan loader.
+ find_package(Vulkan)
+ # To use simply include ${Vulkan_LIBRARY} in your target_link_library or
+ # wherever you normally link your library files to your target.
+endif()
+
+find_package(OpenGL)
+if (OPENGL_FOUND)
+ add_definitions(-DXR_USE_GRAPHICS_API_OPENGL)
+endif()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D)
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D11)
+ add_definitions(-DXR_USE_GRAPHICS_API_D3D12)
+endif()
+
+if(BUILD_LOADER_WITH_EXCEPTION_HANDLING)
+ set(XRLOADER_ENABLE_EXCEPTION_HANDLING TRUE)
+endif()
+# Check for the existence of the secure_getenv or __secure_getenv commands
+include(CheckFunctionExists)
+CHECK_FUNCTION_EXISTS(secure_getenv HAVE_SECURE_GETENV)
+CHECK_FUNCTION_EXISTS(__secure_getenv HAVE___SECURE_GETENV)
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/common_cmake_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/common_cmake_config.h)
+
+# Be able to find pre-generated files, if used.
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include
+ ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
+
+add_definitions(-DXR_USE_TIMESPEC)
+
+# Set up the OpenXR version variables, used by several targets in this project.
+include(${CMAKE_CURRENT_SOURCE_DIR}/version.cmake)
+
+# Path separators ( : or ; ) are not handled well in CMake.
+# This seems like a reasonable approach.
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(CODEGEN_PYTHON_PATH "${CMAKE_SOURCE_DIR}/specification/scripts;${CMAKE_SOURCE_DIR}/src/scripts;$ENV{PYTHONPATH}")
+else()
+ set(CODEGEN_PYTHON_PATH "${CMAKE_SOURCE_DIR}/specification/scripts:${CMAKE_SOURCE_DIR}/src/scripts:$ENV{PYTHONPATH}")
+endif()
+
+# General code generation macro used by several targets.
+macro(run_xr_xml_generate dependency output)
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${output}" AND NOT BUILD_FORCE_GENERATION)
+ # pre-generated found
+ message(STATUS "Found and will use pre-generated ${output} in source tree")
+ list(APPEND GENERATED_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${output}")
+ else()
+ if(NOT PYTHON_EXECUTABLE)
+ message(FATAL_ERROR "Python 3 not found, but pre-generated ${CMAKE_CURRENT_SOURCE_DIR}/${output} not found")
+ endif()
+ add_custom_command(OUTPUT ${output}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CODEGEN_PYTHON_PATH}"
+ ${PYTHON_EXECUTABLE}
+ ${CMAKE_SOURCE_DIR}/src/scripts/src_genxr.py
+ -registry ${CMAKE_SOURCE_DIR}/specification/registry/xr.xml
+ ${output}
+ DEPENDS
+ "${CMAKE_SOURCE_DIR}/specification/registry/xr.xml"
+ "${CMAKE_SOURCE_DIR}/specification/scripts/generator.py"
+ "${CMAKE_SOURCE_DIR}/specification/scripts/reg.py"
+ "${CMAKE_SOURCE_DIR}/src/scripts/${dependency}"
+ "${CMAKE_SOURCE_DIR}/src/scripts/src_genxr.py"
+ ${ARGN}
+ COMMENT "Generating ${output} using ${PYTHON_EXECUTABLE} on ${dependency}"
+ )
+ set_source_files_properties(${output} PROPERTIES GENERATED TRUE)
+ list(APPEND GENERATED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${output}")
+ list(APPEND GENERATED_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${output}")
+ endif()
+endmacro()
+
+# Layer JSON generation macro used by several targets.
+macro(gen_xr_layer_json filename layername libfile version desc genbad)
+ add_custom_command(OUTPUT ${filename}
+ COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${CODEGEN_PYTHON_PATH}"
+ ${PYTHON_EXECUTABLE}
+ ${CMAKE_SOURCE_DIR}/src/scripts/generate_api_layer_manifest.py
+ -f ${filename} -n ${layername} -l ${libfile} -a ${MAJOR}.${MINOR} -v ${version} ${genbad} -d ${desc}
+ DEPENDS ${CMAKE_SOURCE_DIR}/src/scripts/generate_api_layer_manifest.py
+ COMMENT "Generating API Layer JSON ${filename} using -f ${filename} -n ${layername} -l ${libfile} -a ${MAJOR}.${MINOR} -v ${version} ${genbad} -d ${desc}"
+ )
+endmacro()
+
+# Custom target for generated dispatch table sources, used by several targets.
+set(GENERATED_OUTPUT)
+run_xr_xml_generate(utility_source_generator.py xr_generated_dispatch_table.h)
+run_xr_xml_generate(utility_source_generator.py xr_generated_dispatch_table.c)
+run_xr_xml_generate(utility_source_generator.py xr_generated_utilities.h)
+run_xr_xml_generate(utility_source_generator.py xr_generated_utilities.c)
+add_custom_target(xr_global_generated_files DEPENDS
+ ${GENERATED_DEPENDS}
+)
+set_target_properties(xr_global_generated_files PROPERTIES FOLDER ${CODEGEN_FOLDER})
+
+set(COMMON_GENERATED_OUTPUT ${GENERATED_OUTPUT})
+
+if(BUILD_LOADER)
+ add_subdirectory(loader)
+endif()
+
+if(BUILD_API_LAYERS)
+ add_subdirectory(api_layers)
+endif()
+
+if(BUILD_TESTS)
+ add_subdirectory(tests)
+endif()
+
+if(BUILD_CONFORMANCE_TESTS)
+ add_subdirectory(conformance)
+endif()
+
+
+
diff --git a/extern/openxr/src/api_layers/CMakeLists.txt b/extern/openxr/src/api_layers/CMakeLists.txt
new file mode 100644
index 00000000000..0a73a5c1206
--- /dev/null
+++ b/extern/openxr/src/api_layers/CMakeLists.txt
@@ -0,0 +1,103 @@
+# Copyright (c) 2017-2019 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author:
+#
+
+# Force all compilers to output to binary folder without additional output (like Windows adds "Debug" and "Release" folders)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
+ string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_CURRENT_BINARY_DIR})
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_CURRENT_BINARY_DIR})
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_CURRENT_BINARY_DIR})
+endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
+
+# Copy the api_layer_platform_defines.h file and place it in the binary (build) directory.
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/api_layer_platform_defines.h ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
+
+# Basics for core_validation API Layer
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/XrApiLayer_core_validation.json ${CMAKE_CURRENT_BINARY_DIR}/XrApiLayer_core_validation.json COPYONLY)
+
+add_library(XrApiLayer_core_validation SHARED
+ core_validation.cpp
+ ${OPENXR_ROOT_DIR}/src/common/hex_and_handles.cpp
+ ${OPENXR_ROOT_DIR}/src/common/hex_and_handles.h
+ ${OPENXR_ROOT_DIR}/src/xr_generated_dispatch_table.c
+ ${OPENXR_ROOT_DIR}/src/api_layers/xr_generated_core_validation.cpp
+ ${OPENXR_ROOT_DIR}/src/api_layers/xr_generated_core_validation.hpp
+ # Included in this list to force generation
+ ${CMAKE_CURRENT_BINARY_DIR}/XrApiLayer_core_validation.json
+)
+set_target_properties(XrApiLayer_core_validation PROPERTIES FOLDER ${API_LAYERS_FOLDER})
+
+add_dependencies(XrApiLayer_core_validation
+ generate_openxr_header
+ xr_global_generated_files
+)
+target_include_directories(XrApiLayer_core_validation
+ PRIVATE ${OPENXR_ROOT_DIR}/src/common
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_BINARY_DIR}/include
+ PRIVATE ${CMAKE_BINARY_DIR}/src
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
+)
+if(VulkanHeaders_FOUND)
+ target_include_directories(XrApiLayer_core_validation
+ PRIVATE ${Vulkan_INCLUDE_DIRS}
+ )
+endif()
+
+# Flag generated files
+set_source_files_properties(
+ ${CMAKE_BINARY_DIR}/src/xr_generated_dispatch_table.c
+ PROPERTIES GENERATED TRUE
+)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ # Windows core_validation-specific information
+ target_compile_definitions(XrApiLayer_core_validation PRIVATE _CRT_SECURE_NO_WARNINGS)
+ # Turn off transitional "changed behavior" warning message for Visual Studio versions prior to 2015.
+ # The changed behavior is that constructor initializers are now fixed to clear the struct members.
+ target_compile_options(XrApiLayer_core_validation PRIVATE "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,19>>:/wd4351>")
+
+ FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/XrApiLayer_core_validation.def DEF_FILE)
+ add_custom_target(copy-core_validation-def-file ALL
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEF_FILE} ${CMAKE_CURRENT_BINARY_DIR}/XrApiLayer_core_validation.def
+ VERBATIM
+ )
+ set_target_properties(copy-core_validation-def-file PROPERTIES FOLDER ${HELPER_FOLDER})
+elseif(APPLE)
+ # Apple core_validation-specific information
+ target_compile_options(XrApiLayer_core_validation PRIVATE -Wpointer-arith -Wno-unused-function -Wno-sign-compare)
+ set_target_properties(XrApiLayer_core_validation PROPERTIES LINK_FLAGS "-Wl")
+
+else()
+ # Linux core_validation-specific information
+ target_compile_options(XrApiLayer_core_validation PRIVATE -Wpointer-arith -Wno-unused-function -Wno-sign-compare)
+ set_target_properties(XrApiLayer_core_validation PROPERTIES LINK_FLAGS "-Wl,-Bsymbolic,--exclude-libs,ALL")
+endif()
+
+# Install explicit layers on Linux
+set(TARGET_NAMES
+ XrApiLayer_core_validation)
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ foreach(TARGET_NAME ${TARGET_NAMES})
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.json DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openxr/${MAJOR}/api_layers/explicit.d)
+ install(TARGETS ${TARGET_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ endforeach()
+endif()
diff --git a/extern/openxr/src/api_layers/XrApiLayer_core_validation.def b/extern/openxr/src/api_layers/XrApiLayer_core_validation.def
new file mode 100644
index 00000000000..668aafcc7a2
--- /dev/null
+++ b/extern/openxr/src/api_layers/XrApiLayer_core_validation.def
@@ -0,0 +1,27 @@
+
+;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Copyright (c) 2017-2019 The Khronos Group Inc.
+; Copyright (c) 2017-2019 Valve Corporation
+; Copyright (c) 2017-2019 LunarG, Inc.
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+; Author: Mark Young <marky@lunarg.com>
+;
+;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+LIBRARY XrApiLayer_core_validation
+EXPORTS
+xrNegotiateLoaderApiLayerInterface
+
diff --git a/extern/openxr/src/api_layers/XrApiLayer_core_validation.json b/extern/openxr/src/api_layers/XrApiLayer_core_validation.json
new file mode 100644
index 00000000000..f0d7a6974a1
--- /dev/null
+++ b/extern/openxr/src/api_layers/XrApiLayer_core_validation.json
@@ -0,0 +1,10 @@
+{
+ "file_format_version": "1.0.0",
+ "api_layer": {
+ "name": "XR_APILAYER_LUNARG_core_validation",
+ "library_path": "libXrApiLayer_core_validation.dll",
+ "api_version": "1.0",
+ "implementation_version": "1",
+ "description": "API Layer to perform validation of api calls and parameters as they occur"
+ }
+}
diff --git a/extern/openxr/src/api_layers/api_layer_platform_defines.h b/extern/openxr/src/api_layers/api_layer_platform_defines.h
new file mode 100644
index 00000000000..fc247d16f9a
--- /dev/null
+++ b/extern/openxr/src/api_layers/api_layer_platform_defines.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2018-2019 The Khronos Group Inc.
+// Copyright (c) 2018-2019 Valve Corporation
+// Copyright (c) 2018-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#ifndef API_LAYER_PLATFORM_DEFINES_H_
+#define API_LAYER_PLATFORM_DEFINES_H_ 1
+
+#ifdef _WIN32
+#define XR_USE_PLATFORM_WIN32 1 // Win32 platform
+#endif // _WIN32
+#if defined(OS_LINUX_XLIB)
+#define XR_USE_PLATFORM_XLIB 1 // Xlib platform
+#endif // OS_LINUX_XLIB
+#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX)
+#define XR_USE_PLATFORM_XCB 1 // Xcb platform
+#endif // OS_LINUX_XCB || OS_LINUX_XCB_GLX
+#if defined(OS_LINUX_WAYLAND)
+#define XR_USE_PLATFORM_WAYLAND 1 // Wayland platform
+#endif // OS_LINUX_WAYLAND
+#if defined(XR_OS_APPLE_IOS)
+#define XR_USE_PLATFORM_IOS 1 // iOS platform
+#define XR_USE_GRAPHICS_API_OPENGL_ES 1 // OpenGLES exists
+#define XR_USE_GRAPHICS_API_METAL 1 // Metal exists
+#endif // XR_OS_APPLE_IOS
+#if defined(XR_OS_APPLE_MACOS)
+#define XR_USE_PLATFORM_MACOS 1 // MacOS platform
+#define XR_USE_GRAPHICS_API_OPENGL 1 // OpenGL exists
+#define XR_USE_GRAPHICS_API_METAL 1 // Metal exists
+#endif // XR_OS_APPLE_MACOS
+
+#include "xr_dependencies.h" // IWYU pragma: export
+
+#endif // API_LAYER_PLATFORM_DEFINES_H_
diff --git a/extern/openxr/src/api_layers/core_validation.cpp b/extern/openxr/src/api_layers/core_validation.cpp
new file mode 100644
index 00000000000..388359a83e6
--- /dev/null
+++ b/extern/openxr/src/api_layers/core_validation.cpp
@@ -0,0 +1,932 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "api_layer_platform_defines.h"
+#include "extra_algorithms.h"
+#include "hex_and_handles.h"
+#include "loader_interfaces.h"
+#include "platform_utils.hpp"
+#include "validation_utils.h"
+#include "xr_generated_core_validation.hpp"
+#include "xr_generated_dispatch_table.h"
+
+#include <openxr/openxr.h>
+
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LAYER_EXPORT __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define LAYER_EXPORT __attribute__((visibility("default")))
+#else
+#define LAYER_EXPORT
+#endif
+
+// Log recording information
+enum CoreValidationRecordType {
+ RECORD_NONE = 0,
+ RECORD_TEXT_COUT,
+ RECORD_TEXT_FILE,
+ RECORD_HTML_FILE,
+};
+
+struct CoreValidationRecordInfo {
+ bool initialized;
+ CoreValidationRecordType type;
+ std::string file_name;
+};
+
+static CoreValidationRecordInfo g_record_info = {};
+static std::mutex g_record_mutex = {};
+
+// HTML utilities
+bool CoreValidationWriteHtmlHeader() {
+ try {
+ std::unique_lock<std::mutex> mlock(g_record_mutex);
+ std::ofstream html_file;
+ html_file.open(g_record_info.file_name, std::ios::out);
+ html_file
+ << "<!doctype html>\n"
+ "<html>\n"
+ " <head>\n"
+ " <title>OpenXR Core Validation</title>\n"
+ " <style type='text/css'>\n"
+ " html {\n"
+ " background-color: #0b1e48;\n"
+ " background-image: url('https://vulkan.lunarg.com/img/bg-starfield.jpg');\n"
+ " background-position: center;\n"
+ " -webkit-background-size: cover;\n"
+ " -moz-background-size: cover;\n"
+ " -o-background-size: cover;\n"
+ " background-size: cover;\n"
+ " background-attachment: fixed;\n"
+ " background-repeat: no-repeat;\n"
+ " height: 100%;\n"
+ " }\n"
+ " #header {\n"
+ " z-index: -1;\n"
+ " }\n"
+ " #header>img {\n"
+ " position: absolute;\n"
+ " width: 160px;\n"
+ " margin-left: -280px;\n"
+ " top: -10px;\n"
+ " left: 50%;\n"
+ " }\n"
+ " #header>h1 {\n"
+ " font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;\n"
+ " font-size: 48px;\n"
+ " font-weight: 200;\n"
+ " text-shadow: 4px 4px 5px #000;\n"
+ " color: #eee;\n"
+ " position: absolute;\n"
+ " width: 600px;\n"
+ " margin-left: -80px;\n"
+ " top: 8px;\n"
+ " left: 50%;\n"
+ " }\n"
+ " body {\n"
+ " font-family: Consolas, monaco, monospace;\n"
+ " font-size: 14px;\n"
+ " line-height: 20px;\n"
+ " color: #eee;\n"
+ " height: 100%;\n"
+ " margin: 0;\n"
+ " overflow: hidden;\n"
+ " }\n"
+ " #wrapper {\n"
+ " background-color: rgba(0, 0, 0, 0.7);\n"
+ " border: 1px solid #446;\n"
+ " box-shadow: 0px 0px 10px #000;\n"
+ " padding: 8px 12px;\n"
+ " display: inline-block;\n"
+ " position: absolute;\n"
+ " top: 80px;\n"
+ " bottom: 25px;\n"
+ " left: 50px;\n"
+ " right: 50px;\n"
+ " overflow: auto;\n"
+ " }\n"
+ " details>*:not(summary) {\n"
+ " margin-left: 22px;\n"
+ " }\n"
+ " summary:only-child {\n"
+ " display: block;\n"
+ " padding-left: 15px;\n"
+ " }\n"
+ " details>summary:only-child::-webkit-details-marker {\n"
+ " display: none;\n"
+ " padding-left: 15px;\n"
+ " }\n"
+ " .headervar, .generalheadertype, .warningheadertype, .errorheadertype, .debugheadertype, .headerval {\n"
+ " display: inline;\n"
+ " margin: 0 9px;\n"
+ " }\n"
+ " .var, .type, .val {\n"
+ " display: inline;\n"
+ " margin: 0 6px;\n"
+ " }\n"
+ " .warningheadertype, .type {\n"
+ " color: #dce22f;\n"
+ " }\n"
+ " .errorheadertype, .type {\n"
+ " color: #ff1616;\n"
+ " }\n"
+ " .debugheadertype, .type {\n"
+ " color: #888;\n"
+ " }\n"
+ " .generalheadertype, .type {\n"
+ " color: #acf;\n"
+ " }\n"
+ " .headerval, .val {\n"
+ " color: #afa;\n"
+ " text-align: right;\n"
+ " }\n"
+ " .thd {\n"
+ " color: #888;\n"
+ " }\n"
+ " </style>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div id='header'>\n"
+ " <img src='https://lunarg.com/wp-content/uploads/2016/02/LunarG-wReg-150.png' />\n"
+ " <h1>OpenXR Core Validation</h1>\n"
+ " </div>\n"
+ " <div id='wrapper'>\n";
+ return true;
+ } catch (...) {
+ return false;
+ }
+}
+
+bool CoreValidationWriteHtmlFooter() {
+ try {
+ std::unique_lock<std::mutex> mlock(g_record_mutex);
+ std::ofstream html_file;
+ html_file.open(g_record_info.file_name, std::ios::out | std::ios::app);
+ html_file << " </div>\n"
+ " </body>\n"
+ "</html>";
+
+ // Writing the footer means we're done.
+ if (g_record_info.initialized) {
+ g_record_info.initialized = false;
+ g_record_info.type = RECORD_NONE;
+ }
+ return true;
+ } catch (...) {
+ return false;
+ }
+}
+
+// Function to record all the core validation information
+void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,
+ GenValidUsageDebugSeverity message_severity, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message) {
+ if (g_record_info.initialized) {
+ std::unique_lock<std::mutex> mlock(g_record_mutex);
+
+ // Debug Utils items (in case we need them)
+ XrDebugUtilsMessageSeverityFlagsEXT debug_utils_severity = 0;
+ std::vector<XrDebugUtilsObjectNameInfoEXT> debug_utils_objects;
+ std::vector<XrDebugUtilsLabelEXT> session_labels;
+
+ std::string severity_string;
+ switch (message_severity) {
+ case VALID_USAGE_DEBUG_SEVERITY_DEBUG:
+ severity_string = "VALID_DEBUG";
+ debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ break;
+ case VALID_USAGE_DEBUG_SEVERITY_INFO:
+ severity_string = "VALID_INFO";
+ debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ break;
+ case VALID_USAGE_DEBUG_SEVERITY_WARNING:
+ severity_string = "VALID_WARNING";
+ debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ break;
+ case VALID_USAGE_DEBUG_SEVERITY_ERROR:
+ severity_string = "VALID_ERROR";
+ debug_utils_severity = XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ break;
+ default:
+ severity_string = "VALID_UNKNOWN";
+ break;
+ }
+
+ // If we have instance information, see if we need to log this information out to a debug messenger
+ // callback.
+ if (nullptr != instance_info) {
+ if (!objects_info.empty()) {
+ for (auto &obj : objects_info) {
+ XrDebugUtilsObjectNameInfoEXT obj_name_info = {};
+ obj_name_info.next = nullptr;
+ obj_name_info.objectType = obj.type;
+ obj_name_info.objectHandle = obj.handle;
+ // If there's a session in the list, see if it has labels
+ if (XR_OBJECT_TYPE_SESSION == obj.type) {
+ XrSession session = TreatIntegerAsHandle<XrSession>(obj.handle);
+ auto session_label_iterator = g_xr_session_labels.find(session);
+ if (session_label_iterator != g_xr_session_labels.end()) {
+ auto rev_iter = session_label_iterator->second->rbegin();
+ for (; rev_iter != session_label_iterator->second->rend(); ++rev_iter) {
+ session_labels.push_back((*rev_iter)->debug_utils_label);
+ }
+ }
+ }
+ // Loop through all object names and see if any match
+ for (auto &object_name : instance_info->object_names) {
+ if (object_name->objectType == obj.type && object_name->objectHandle == obj.handle) {
+ obj_name_info.objectName = object_name->objectName;
+ break;
+ }
+ }
+ debug_utils_objects.push_back(obj_name_info);
+ }
+ }
+ if (!instance_info->debug_messengers.empty()) {
+ // Setup our callback data once
+ XrDebugUtilsMessengerCallbackDataEXT callback_data = {};
+ callback_data.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.messageId = message_id.c_str();
+ callback_data.functionName = command_name.c_str();
+ callback_data.message = message.c_str();
+ callback_data.objectCount = static_cast<uint8_t>(debug_utils_objects.size());
+ if (debug_utils_objects.empty()) {
+ callback_data.objects = nullptr;
+ } else {
+ callback_data.objects = debug_utils_objects.data();
+ }
+ callback_data.sessionLabelCount = static_cast<uint8_t>(session_labels.size());
+ if (session_labels.empty()) {
+ callback_data.sessionLabels = nullptr;
+ } else {
+ callback_data.sessionLabels = session_labels.data();
+ }
+
+ // Loop through all active messengers and give each a chance to output information
+ for (auto &debug_messenger : instance_info->debug_messengers) {
+ CoreValidationMessengerInfo *validation_messenger_info = debug_messenger.get();
+ XrDebugUtilsMessengerCreateInfoEXT *messenger_create_info = validation_messenger_info->create_info;
+ // If a callback exists, and the message is of a type this callback cares about, call it.
+ if (nullptr != messenger_create_info->userCallback &&
+ 0 != (messenger_create_info->messageSeverities & debug_utils_severity) &&
+ 0 != (messenger_create_info->messageTypes & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) {
+ XrBool32 ret_val = messenger_create_info->userCallback(debug_utils_severity,
+ XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+ &callback_data, messenger_create_info->userData);
+ }
+ }
+ }
+ }
+
+ switch (g_record_info.type) {
+ case RECORD_TEXT_COUT: {
+ std::cout << "[" << severity_string << " | " << message_id << " | " << command_name << "]: " << message
+ << std::endl;
+ if (!objects_info.empty()) {
+ std::cout << " Objects:" << std::endl;
+ uint32_t count = 0;
+ for (auto object_info : objects_info) {
+ std::string object_type = GenValidUsageXrObjectTypeToString(object_info.type);
+ std::ostringstream oss_object_handle;
+ std::cout << " [" << std::to_string(count++) << "] - " << object_type << " ("
+ << Uint64ToHexString(object_info.handle) << ")";
+ std::cout << std::endl;
+ }
+ }
+ if (!session_labels.empty()) {
+ std::cout << " Session Labels:" << std::endl;
+ uint32_t count = 0;
+ for (auto session_label : session_labels) {
+ std::cout << " [" << std::to_string(count++) << "] - " << session_label.labelName << std::endl;
+ }
+ }
+ std::cout << std::flush;
+ break;
+ }
+ case RECORD_TEXT_FILE: {
+ std::ofstream text_file;
+ text_file.open(g_record_info.file_name, std::ios::out | std::ios::app);
+ text_file << "[" << severity_string << " | " << message_id << " | " << command_name << "]: " << message
+ << std::endl;
+ if (!objects_info.empty()) {
+ text_file << " Objects:" << std::endl;
+ uint32_t count = 0;
+ for (auto object_info : objects_info) {
+ std::string object_type = GenValidUsageXrObjectTypeToString(object_info.type);
+ text_file << " [" << std::to_string(count++) << "] - " << object_type << " ("
+ << Uint64ToHexString(object_info.handle) << ")";
+ text_file << std::endl;
+ }
+ }
+ if (!session_labels.empty()) {
+ text_file << " Session Labels:" << std::endl;
+ uint32_t count = 0;
+ for (auto session_label : session_labels) {
+ text_file << " [" << std::to_string(count++) << "] - " << session_label.labelName << std::endl;
+ }
+ }
+ text_file << std::flush;
+ text_file.close();
+ break;
+ }
+ case RECORD_HTML_FILE: {
+ std::ofstream text_file;
+ text_file.open(g_record_info.file_name, std::ios::out | std::ios::app);
+ text_file << "<details class='data'>\n";
+ std::string header_type = "generalheadertype";
+ switch (message_severity) {
+ case VALID_USAGE_DEBUG_SEVERITY_DEBUG:
+ header_type = "debugheadertype";
+ severity_string = "Debug Message";
+ break;
+ case VALID_USAGE_DEBUG_SEVERITY_INFO:
+ severity_string = "Info Message";
+ break;
+ case VALID_USAGE_DEBUG_SEVERITY_WARNING:
+ header_type = "warningheadertype";
+ severity_string = "Warning Message";
+ break;
+ case VALID_USAGE_DEBUG_SEVERITY_ERROR:
+ header_type = "errorheadertype";
+ severity_string = "Error Message";
+ break;
+ default:
+ severity_string = "Unknown Message";
+ break;
+ }
+ text_file << " <summary>\n"
+ << " <div class='" << header_type << "'>" << severity_string << "</div>\n"
+ << " <div class='headerval'>" << command_name << "</div>\n"
+ << " <div class='headervar'>" << message_id << "</div>\n"
+ << " </summary>\n";
+ text_file << " <div class='data'>\n";
+ text_file << " <div class='val'>" << message << "</div>\n";
+ if (!objects_info.empty()) {
+ text_file << " <details class='data'>\n";
+ text_file << " <summary>\n";
+ text_file << " <div class='type'>Relevant OpenXR Objects</div>\n";
+ text_file << " </summary>\n";
+ uint32_t count = 0;
+ for (auto object_info : objects_info) {
+ std::string object_type = GenValidUsageXrObjectTypeToString(object_info.type);
+ text_file << " <div class='data'>\n";
+ text_file << " <div class='var'>[" << count++ << "]</div>\n";
+ text_file << " <div class='type'>" << object_type << "</div>\n";
+ text_file << " <div class='val'>" << Uint64ToHexString(object_info.handle) << "</div>\n";
+ text_file << " </div>\n";
+ }
+ text_file << " </details>\n";
+ text_file << std::flush;
+ }
+ if (!session_labels.empty()) {
+ text_file << " <details class='data'>\n";
+ text_file << " <summary>\n";
+ text_file << " <div class='type'>Relevant Session Labels</div>\n";
+ text_file << " </summary>\n";
+ uint32_t count = 0;
+ for (auto session_label : session_labels) {
+ text_file << " <div class='data'>\n";
+ text_file << " <div class='var'>[" << count++ << "]</div>\n";
+ text_file << " <div class='type'>" << session_label.labelName << "</div>\n";
+ text_file << " </div>\n";
+ }
+ text_file << " </details>\n";
+ }
+ text_file << " </div>\n";
+ text_file << "</details>\n";
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void reportInternalError(std::string const &message) {
+ std::cerr << "INTERNAL VALIDATION LAYER ERROR: " << message << std::endl;
+ throw std::runtime_error("Internal validation layer error: " + message);
+}
+
+void InvalidStructureType(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo> &objects_info, const char *structure_name, XrStructureType type,
+ const char *vuid, XrStructureType expected, const char *expected_name) {
+ std::ostringstream oss_type;
+ oss_type << structure_name << " has an invalid XrStructureType ";
+ oss_type << Uint32ToHexString(static_cast<uint32_t>(type));
+ if (expected != 0) {
+ oss_type << ", expected " << Uint32ToHexString(static_cast<uint32_t>(type));
+ oss_type << " (" << expected_name << ")";
+ }
+ if (vuid != nullptr) {
+ CoreValidLogMessage(instance_info, vuid, VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info, oss_type.str());
+ } else {
+ CoreValidLogMessage(instance_info, "VUID-" + std::string(structure_name) + "-type-type", VALID_USAGE_DEBUG_SEVERITY_ERROR,
+ command_name, objects_info, oss_type.str());
+ }
+}
+
+// NOTE: Can't validate the following VUIDs since the command never enters a layer:
+// Command: xrEnumerateApiLayerProperties
+// VUIDs: "VUID-xrEnumerateApiLayerProperties-propertyCountOutput-parameter"
+// "VUID-xrEnumerateApiLayerProperties-properties-parameter"
+// Command: xrEnumerateInstanceExtensionProperties
+// VUIDs: "VUID-xrEnumerateInstanceExtensionProperties-layerName-parameter"
+// "VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter"
+// "VUID-xrEnumerateInstanceExtensionProperties-properties-parameter"
+
+XrResult CoreValidationXrCreateInstance(const XrInstanceCreateInfo * /*info*/, XrInstance * /*instance*/) {
+ // Shouldn't be called, coreValidationXrCreateApiLayerInstance should called instead
+ return XR_SUCCESS;
+}
+
+GenValidUsageXrInstanceInfo::GenValidUsageXrInstanceInfo(XrInstance inst, PFN_xrGetInstanceProcAddr next_get_instance_proc_addr)
+ : instance(inst), dispatch_table(new XrGeneratedDispatchTable()) {
+ /// @todo smart pointer here!
+
+ // Create the dispatch table to the next levels
+ GeneratedXrPopulateDispatchTable(dispatch_table, instance, next_get_instance_proc_addr);
+}
+
+GenValidUsageXrInstanceInfo::~GenValidUsageXrInstanceInfo() { delete dispatch_table; }
+
+// See if there is a debug utils create structure in the "next" chain
+
+XrResult CoreValidationXrCreateApiLayerInstance(const XrInstanceCreateInfo *info, const struct XrApiLayerCreateInfo *apiLayerInfo,
+ XrInstance *instance) {
+ try {
+ XrApiLayerCreateInfo new_api_layer_info = {};
+ XrResult validation_result = XR_SUCCESS;
+ bool user_defined_output = false;
+ bool first_time = !g_record_info.initialized;
+
+ if (!g_record_info.initialized) {
+ g_record_info.initialized = true;
+ g_record_info.type = RECORD_NONE;
+ }
+
+ char *export_type = PlatformUtilsGetEnv("XR_CORE_VALIDATION_EXPORT_TYPE");
+ char *file_name = PlatformUtilsGetEnv("XR_CORE_VALIDATION_FILE_NAME");
+ if (nullptr != file_name) {
+ g_record_info.file_name = file_name;
+ PlatformUtilsFreeEnv(file_name);
+ }
+
+ if (nullptr != export_type) {
+ std::string string_export_type = export_type;
+ PlatformUtilsFreeEnv(export_type);
+ std::transform(string_export_type.begin(), string_export_type.end(), string_export_type.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+
+ std::cerr << "Core Validation output type: " << string_export_type << ", first time = " << std::to_string(first_time)
+ << std::endl;
+ if (string_export_type == "text") {
+ if (!g_record_info.file_name.empty()) {
+ g_record_info.type = RECORD_TEXT_FILE;
+ } else {
+ g_record_info.type = RECORD_TEXT_COUT;
+ }
+ user_defined_output = true;
+ } else if (string_export_type == "html" && first_time) {
+ g_record_info.type = RECORD_HTML_FILE;
+ if (!CoreValidationWriteHtmlHeader()) {
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+ }
+ }
+
+ // Call the generated pre valid usage check.
+ validation_result = GenValidUsageInputsXrCreateInstance(info, instance);
+
+ // Copy the contents of the layer info struct, but then move the next info up by
+ // one slot so that the next layer gets information.
+ memcpy(&new_api_layer_info, apiLayerInfo, sizeof(XrApiLayerCreateInfo));
+ new_api_layer_info.nextInfo = apiLayerInfo->nextInfo->next;
+
+ // Get the function pointers we need
+ PFN_xrGetInstanceProcAddr next_get_instance_proc_addr = apiLayerInfo->nextInfo->nextGetInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance next_create_api_layer_instance = apiLayerInfo->nextInfo->nextCreateApiLayerInstance;
+
+ // Create the instance using the layer create instance command for the next layer
+ XrInstance returned_instance = *instance;
+ XrResult next_result = next_create_api_layer_instance(info, &new_api_layer_info, &returned_instance);
+ *instance = returned_instance;
+
+ // Create the instance information
+ std::unique_ptr<GenValidUsageXrInstanceInfo> instance_info(
+ new GenValidUsageXrInstanceInfo(returned_instance, next_get_instance_proc_addr));
+
+ // Save the enabled extensions.
+ for (uint32_t extension = 0; extension < info->enabledExtensionCount; ++extension) {
+ instance_info->enabled_extensions.emplace_back(info->enabledExtensionNames[extension]);
+ }
+
+ g_instance_info.insert(returned_instance, std::move(instance_info));
+
+ // See if a debug utils messenger is supposed to be created as part of the instance
+ // NOTE: We have to wait until after the instance info is added to the map for this
+ // to work properly.
+ const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
+ const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
+ while (next_header != nullptr) {
+ if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
+ // Create the debug messenger. We don't have to keep track of it because it will be tracked as part
+ // of the instance info from here on out.
+ XrDebugUtilsMessengerEXT messenger;
+ validation_result = CoreValidationXrCreateDebugUtilsMessengerEXT(*instance, dbg_utils_create_info, &messenger);
+ // If we created a debug messenger, turn off the text output unless a user indicates they wanted it
+ if (XR_SUCCESS == validation_result && !user_defined_output) {
+ g_record_info.type = RECORD_NONE;
+ }
+ break;
+ }
+ next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
+ }
+
+ if (XR_SUCCESS == validation_result) {
+ return next_result;
+ }
+ return validation_result;
+
+ } catch (std::bad_alloc &) {
+ return XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+}
+
+void EraseAllInstanceTableMapElements(GenValidUsageXrInstanceInfo *search_value) {
+ typedef typename InstanceHandleInfo::value_t value_t;
+ auto map_with_lock = g_instance_info.lockMap();
+ auto &map = map_with_lock.second;
+
+ map_erase_if(map, [=](value_t const &data) { return data.second.get() == search_value; });
+}
+
+XrResult CoreValidationXrDestroyInstance(XrInstance instance) {
+ GenValidUsageInputsXrDestroyInstance(instance);
+ if (XR_NULL_HANDLE != instance) {
+ auto info_with_lock = g_instance_info.getWithLock(instance);
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_lock.second;
+ if (nullptr != gen_instance_info) {
+ gen_instance_info->object_names.clear();
+ gen_instance_info->debug_messengers.clear();
+ }
+ }
+ XrResult result = GenValidUsageNextXrDestroyInstance(instance);
+ if (!g_instance_info.empty() && g_record_info.type == RECORD_HTML_FILE) {
+ CoreValidationWriteHtmlFooter();
+ }
+ return result;
+ return XR_SUCCESS;
+}
+
+XrResult CoreValidationXrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session) {
+ try {
+ XrResult test_result = GenValidUsageInputsXrCreateSession(instance, createInfo, session);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+
+ // Check the next chain for a graphics binding structure, we need at least one.
+ uint32_t num_graphics_bindings_found = 0;
+ const auto *cur_ptr = reinterpret_cast<const XrBaseInStructure *>(createInfo->next);
+ while (nullptr != cur_ptr) {
+ switch (cur_ptr->type) {
+ default:
+ continue;
+#ifdef XR_USE_PLATFORM_WIN32
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR:
+ num_graphics_bindings_found++;
+ break;
+#endif
+#ifdef XR_USE_PLATFORM_XLIB
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR:
+ num_graphics_bindings_found++;
+ break;
+#endif
+#ifdef XR_USE_PLATFORM_XCB
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR:
+ num_graphics_bindings_found++;
+ break;
+#endif
+#ifdef XR_USE_PLATFORM_WAYLAND
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR:
+ num_graphics_bindings_found++;
+ break;
+#endif
+ }
+ cur_ptr = reinterpret_cast<const XrBaseInStructure *>(cur_ptr->next);
+ }
+ auto const &enabled_extensions = gen_instance_info->enabled_extensions;
+#ifdef XR_KHR_headless
+ bool has_headless = (enabled_extensions.end() !=
+ std::find(enabled_extensions.begin(), enabled_extensions.end(), XR_KHR_HEADLESS_EXTENSION_NAME));
+#else
+ bool has_headless = false;
+#endif // XR_KHR_headless
+ bool got_right_graphics_binding_count = (num_graphics_bindings_found == 1);
+ if (!got_right_graphics_binding_count && has_headless) {
+ // This permits 0 as well.
+ got_right_graphics_binding_count = (num_graphics_bindings_found == 0);
+ }
+ if (!got_right_graphics_binding_count) {
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+ std::ostringstream error_stream;
+ error_stream << "Invalid number of graphics binding structures provided. ";
+ error_stream << "Expected ";
+ if (has_headless) {
+ error_stream << "0 or 1";
+ } else {
+ error_stream << "1";
+ }
+ error_stream << ", but received ";
+ error_stream << num_graphics_bindings_found;
+ error_stream << ".";
+ // TODO: This needs to be updated with the actual VUID once we generate it.
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSession-next-parameter", VALID_USAGE_DEBUG_SEVERITY_ERROR,
+ "xrCreateSession", objects_info, error_stream.str());
+ return XR_ERROR_GRAPHICS_DEVICE_INVALID;
+ }
+ return GenValidUsageNextXrCreateSession(instance, createInfo, session);
+ } catch (...) {
+ return XR_SUCCESS;
+ }
+}
+
+// ---- XR_EXT_debug_utils extension commands
+XrResult CoreValidationXrSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) {
+ try {
+ XrResult result = GenValidUsageInputsXrSetDebugUtilsObjectNameEXT(instance, nameInfo);
+ if (!XR_UNQUALIFIED_SUCCESS(result)) {
+ return result;
+ }
+ result = GenValidUsageNextXrSetDebugUtilsObjectNameEXT(instance, nameInfo);
+ if (!XR_UNQUALIFIED_SUCCESS(result)) {
+ return result;
+ }
+ auto info_with_lock = g_instance_info.getWithLock(instance);
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_lock.second;
+ if (nullptr != gen_instance_info) {
+ // Create a copy of the base object name info (no next items)
+ auto len = strlen(nameInfo->objectName);
+ char *name_string = new char[len + 1];
+ strncpy(name_string, nameInfo->objectName, len);
+ bool found = false;
+ for (auto &object_name : gen_instance_info->object_names) {
+ if (object_name->objectHandle == nameInfo->objectHandle && object_name->objectType == nameInfo->objectType) {
+ delete[] object_name->objectName;
+ object_name->objectName = name_string;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ UniqueXrDebugUtilsObjectNameInfoEXT new_object_name(new XrDebugUtilsObjectNameInfoEXT(*nameInfo));
+ new_object_name->next = nullptr;
+ new_object_name->objectName = name_string;
+ gen_instance_info->object_names.push_back(std::move(new_object_name));
+ }
+ }
+ return result;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult CoreValidationXrCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
+ XrDebugUtilsMessengerEXT *messenger) {
+ try {
+ XrResult result = GenValidUsageInputsXrCreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ if (!XR_UNQUALIFIED_SUCCESS(result)) {
+ return result;
+ }
+ result = GenValidUsageNextXrCreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ if (!XR_UNQUALIFIED_SUCCESS(result)) {
+ return result;
+ }
+ auto info_with_lock = g_instance_info.getWithLock(instance);
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_lock.second;
+ if (nullptr != gen_instance_info) {
+ auto *new_create_info = new XrDebugUtilsMessengerCreateInfoEXT(*createInfo);
+ new_create_info->next = nullptr;
+ UniqueCoreValidationMessengerInfo new_messenger_info(new CoreValidationMessengerInfo);
+ new_messenger_info->messenger = *messenger;
+ new_messenger_info->create_info = new_create_info;
+ gen_instance_info->debug_messengers.push_back(std::move(new_messenger_info));
+ }
+ return result;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult CoreValidationXrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) {
+ try {
+ XrResult result = GenValidUsageInputsXrDestroyDebugUtilsMessengerEXT(messenger);
+ if (!XR_UNQUALIFIED_SUCCESS(result)) {
+ return result;
+ }
+ result = GenValidUsageNextXrDestroyDebugUtilsMessengerEXT(messenger);
+ if (!XR_UNQUALIFIED_SUCCESS(result)) {
+ return result;
+ }
+ if (XR_NULL_HANDLE == messenger) {
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ auto info_with_lock = g_debugutilsmessengerext_info.getWithLock(messenger);
+ GenValidUsageXrHandleInfo *gen_handle_info = info_with_lock.second;
+ if (nullptr != gen_handle_info) {
+ auto &debug_messengers = gen_handle_info->instance_info->debug_messengers;
+ vector_remove_if_and_erase(debug_messengers,
+ [=](UniqueCoreValidationMessengerInfo const &msg) { return msg->messenger == messenger; });
+ }
+ return result;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+// We always want to remove the old individual label before we do anything else.
+// So, do that in it's own method
+void CoreValidationRemoveIndividualLabel(std::vector<GenValidUsageXrInternalSessionLabel *> *label_vec) {
+ if (!label_vec->empty()) {
+ GenValidUsageXrInternalSessionLabel *cur_label = label_vec->back();
+ if (cur_label->is_individual_label) {
+ label_vec->pop_back();
+ delete cur_label;
+ }
+ }
+}
+
+void CoreValidationBeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT *label_info) {
+ std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = nullptr;
+ auto session_label_iterator = g_xr_session_labels.find(session);
+ if (session_label_iterator == g_xr_session_labels.end()) {
+ vec_ptr = new std::vector<GenValidUsageXrInternalSessionLabel *>;
+ g_xr_session_labels[session] = vec_ptr;
+ } else {
+ vec_ptr = session_label_iterator->second;
+ }
+
+ // Individual labels do not stay around in the transition into a new label region
+ CoreValidationRemoveIndividualLabel(vec_ptr);
+
+ // Start the new label region
+ auto *new_session_label = new GenValidUsageXrInternalSessionLabel;
+ new_session_label->label_name = label_info->labelName;
+ new_session_label->debug_utils_label = *label_info;
+ new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
+ new_session_label->is_individual_label = false;
+ vec_ptr->push_back(new_session_label);
+}
+
+void CoreValidationEndLabelRegion(XrSession session) {
+ auto session_label_iterator = g_xr_session_labels.find(session);
+ if (session_label_iterator == g_xr_session_labels.end()) {
+ return;
+ }
+
+ std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = session_label_iterator->second;
+
+ // Individual labels do not stay around in the transition out of label region
+ CoreValidationRemoveIndividualLabel(vec_ptr);
+
+ // Remove the last label region
+ if (!vec_ptr->empty()) {
+ GenValidUsageXrInternalSessionLabel *cur_label = vec_ptr->back();
+ vec_ptr->pop_back();
+ delete cur_label;
+ }
+}
+
+void CoreValidationInsertLabel(XrSession session, const XrDebugUtilsLabelEXT *label_info) {
+ std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = nullptr;
+ auto session_label_iterator = g_xr_session_labels.find(session);
+ if (session_label_iterator == g_xr_session_labels.end()) {
+ vec_ptr = new std::vector<GenValidUsageXrInternalSessionLabel *>;
+ g_xr_session_labels[session] = vec_ptr;
+ } else {
+ vec_ptr = session_label_iterator->second;
+ }
+
+ // Remove any individual layer that might already be there
+ CoreValidationRemoveIndividualLabel(vec_ptr);
+
+ // Insert a new individual label
+ auto *new_session_label = new GenValidUsageXrInternalSessionLabel;
+ new_session_label->label_name = label_info->labelName;
+ new_session_label->debug_utils_label = *label_info;
+ new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
+ new_session_label->is_individual_label = true;
+ vec_ptr->push_back(new_session_label);
+}
+
+// Called during xrDestroySession. We need to delete all session related labels.
+void CoreValidationDeleteSessionLabels(XrSession session) {
+ std::vector<GenValidUsageXrInternalSessionLabel *> *vec_ptr = nullptr;
+ auto session_label_iterator = g_xr_session_labels.find(session);
+ if (session_label_iterator == g_xr_session_labels.end()) {
+ return;
+ }
+ vec_ptr = session_label_iterator->second;
+ while (!vec_ptr->empty()) {
+ delete vec_ptr->back();
+ vec_ptr->pop_back();
+ }
+ delete vec_ptr;
+ g_xr_session_labels.erase(session);
+}
+
+XrResult CoreValidationXrSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) {
+ XrResult test_result = GenValidUsageInputsXrSessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ CoreValidationBeginLabelRegion(session, labelInfo);
+ return GenValidUsageNextXrSessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
+}
+
+XrResult CoreValidationXrSessionEndDebugUtilsLabelRegionEXT(XrSession session) {
+ XrResult test_result = GenValidUsageInputsXrSessionEndDebugUtilsLabelRegionEXT(session);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ CoreValidationEndLabelRegion(session);
+ return GenValidUsageNextXrSessionEndDebugUtilsLabelRegionEXT(session);
+}
+
+XrResult CoreValidationXrSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) {
+ XrResult test_result = GenValidUsageInputsXrSessionInsertDebugUtilsLabelEXT(session, labelInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ CoreValidationInsertLabel(session, labelInfo);
+ return GenValidUsageNextXrSessionInsertDebugUtilsLabelEXT(session, labelInfo);
+}
+
+// ############################################################
+// NOTE: Add new validation checking above this comment block
+// ############################################################
+
+extern "C" {
+
+// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or
+// more API layers needs to expose at least this function.
+LAYER_EXPORT XrResult xrNegotiateLoaderApiLayerInterface(const XrNegotiateLoaderInfo *loaderInfo, const char * /*apiLayerName*/,
+ XrNegotiateApiLayerRequest *apiLayerRequest) {
+ if (nullptr == loaderInfo || nullptr == apiLayerRequest || loaderInfo->structType != XR_LOADER_INTERFACE_STRUCT_LOADER_INFO ||
+ loaderInfo->structVersion != XR_LOADER_INFO_STRUCT_VERSION || loaderInfo->structSize != sizeof(XrNegotiateLoaderInfo) ||
+ apiLayerRequest->structType != XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST ||
+ apiLayerRequest->structVersion != XR_API_LAYER_INFO_STRUCT_VERSION ||
+ apiLayerRequest->structSize != sizeof(XrNegotiateApiLayerRequest) ||
+ loaderInfo->minInterfaceVersion > XR_CURRENT_LOADER_API_LAYER_VERSION ||
+ loaderInfo->maxInterfaceVersion < XR_CURRENT_LOADER_API_LAYER_VERSION ||
+ loaderInfo->maxInterfaceVersion > XR_CURRENT_LOADER_API_LAYER_VERSION ||
+ loaderInfo->maxApiVersion < XR_CORE_VALIDATION_API_VERSION || loaderInfo->minApiVersion > XR_CORE_VALIDATION_API_VERSION) {
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+
+ apiLayerRequest->layerInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
+ apiLayerRequest->layerApiVersion = XR_CORE_VALIDATION_API_VERSION;
+ apiLayerRequest->getInstanceProcAddr = reinterpret_cast<PFN_xrGetInstanceProcAddr>(GenValidUsageXrGetInstanceProcAddr);
+ apiLayerRequest->createApiLayerInstance =
+ reinterpret_cast<PFN_xrCreateApiLayerInstance>(CoreValidationXrCreateApiLayerInstance);
+
+ return XR_SUCCESS;
+}
+
+} // extern "C"
diff --git a/extern/openxr/src/api_layers/validation_utils.h b/extern/openxr/src/api_layers/validation_utils.h
new file mode 100644
index 00000000000..71d119ec83b
--- /dev/null
+++ b/extern/openxr/src/api_layers/validation_utils.h
@@ -0,0 +1,324 @@
+// Copyright (c) 2018-2019 The Khronos Group Inc.
+// Copyright (c) 2018-2019 Valve Corporation
+// Copyright (c) 2018-2019 LunarG, Inc.
+// Copyright (c) 2019, Collabora, Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+// Mark Young <marky@lunarg.com>
+//
+
+#ifndef VALIDATION_UTILS_H_
+#define VALIDATION_UTILS_H_ 1
+
+#include "api_layer_platform_defines.h"
+#include "hex_and_handles.h"
+#include "extra_algorithms.h"
+
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#include <vector>
+#include <unordered_map>
+#include <string>
+#include <mutex>
+#include <memory>
+
+/// Prints a message to stderr then throws an exception.
+///
+/// The printing of the message is because the exception will probably be caught and silently turned into a validation error.
+[[noreturn]] void reportInternalError(std::string const &message);
+
+// Structure used for storing the instance information we need for validating
+// various aspects of the OpenXR API.
+
+// Debug Utils items
+struct CoreValidationMessengerInfo {
+ XrDebugUtilsMessengerEXT messenger;
+ XrDebugUtilsMessengerCreateInfoEXT *create_info;
+};
+
+struct XrGeneratedDispatchTable;
+
+struct CoreValidationMessengerInfoDeleter {
+ void operator()(CoreValidationMessengerInfo *ptr) const {
+ delete ptr->create_info;
+ delete ptr;
+ }
+};
+
+struct XrDebugUtilsObjectNameInfoEXTDeleter {
+ void operator()(XrDebugUtilsObjectNameInfoEXT *ptr) const {
+ delete ptr->objectName;
+ delete ptr;
+ }
+};
+
+typedef std::unique_ptr<XrDebugUtilsObjectNameInfoEXT, XrDebugUtilsObjectNameInfoEXTDeleter> UniqueXrDebugUtilsObjectNameInfoEXT;
+
+typedef std::unique_ptr<CoreValidationMessengerInfo, CoreValidationMessengerInfoDeleter> UniqueCoreValidationMessengerInfo;
+
+// Define the instance struct used for passing information around.
+// This information includes things like the dispatch table as well as the
+// enabled extensions.
+struct GenValidUsageXrInstanceInfo {
+ GenValidUsageXrInstanceInfo(XrInstance inst, PFN_xrGetInstanceProcAddr next_get_instance_proc_addr);
+ ~GenValidUsageXrInstanceInfo();
+ const XrInstance instance;
+ XrGeneratedDispatchTable *dispatch_table;
+ std::vector<std::string> enabled_extensions;
+ std::vector<UniqueCoreValidationMessengerInfo> debug_messengers;
+ std::vector<UniqueXrDebugUtilsObjectNameInfoEXT> object_names;
+};
+
+// Structure used for storing information for other handles
+struct GenValidUsageXrHandleInfo {
+ GenValidUsageXrInstanceInfo *instance_info;
+ XrObjectType direct_parent_type;
+ uint64_t direct_parent_handle;
+};
+
+// Structure used for storing session label information
+struct GenValidUsageXrInternalSessionLabel {
+ XrDebugUtilsLabelEXT debug_utils_label;
+ std::string label_name;
+ bool is_individual_label;
+};
+
+// Enum used for indicating handle validation status.
+enum ValidateXrHandleResult {
+ VALIDATE_XR_HANDLE_NULL,
+ VALIDATE_XR_HANDLE_INVALID,
+ VALIDATE_XR_HANDLE_SUCCESS,
+};
+
+// Unordered Map associating pointer to a vector of session label information to a session's handle
+extern std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel *> *> g_xr_session_labels;
+
+// This function is used to delete session labels when a session is destroyed
+extern void CoreValidationDeleteSessionLabels(XrSession session);
+
+// Object information used for logging.
+struct GenValidUsageXrObjectInfo {
+ uint64_t handle;
+ XrObjectType type;
+ GenValidUsageXrObjectInfo() = default;
+ template <typename T>
+ GenValidUsageXrObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
+};
+
+// Debug message severity levels for logging.
+enum GenValidUsageDebugSeverity {
+ VALID_USAGE_DEBUG_SEVERITY_DEBUG = 0,
+ VALID_USAGE_DEBUG_SEVERITY_INFO = 7,
+ VALID_USAGE_DEBUG_SEVERITY_WARNING = 14,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR = 21,
+};
+
+// in core_validation.cpp
+void EraseAllInstanceTableMapElements(GenValidUsageXrInstanceInfo *search_value);
+
+typedef std::unique_lock<std::mutex> UniqueLock;
+template <typename HandleType, typename InfoType>
+class HandleInfoBase {
+ public:
+ typedef InfoType info_t;
+ typedef HandleType handle_t;
+ typedef std::unordered_map<HandleType, std::unique_ptr<InfoType>> map_t;
+ typedef typename map_t::value_type value_t;
+
+ /// Validate a handle.
+ ///
+ /// Returns an enum indicating null, invalid (not found), or success.
+ ValidateXrHandleResult verifyHandle(HandleType const *handle_to_check);
+
+ /// Lookup a handle.
+ /// Throws if not found.
+ InfoType *get(HandleType handle);
+
+ /// Lookup a handle, returning a pointer (if found) as well as a lock for this object's dispatch mutex.
+ std::pair<UniqueLock, InfoType *> getWithLock(HandleType handle);
+
+ bool empty() const { return info_map_.empty(); }
+
+ /// Insert an info for the supplied handle.
+ /// Throws if it's already there.
+ void insert(HandleType handle, std::unique_ptr<InfoType> &&info);
+
+ /// Remove the info associated with the supplied handle.
+ /// Throws if not found.
+ void erase(HandleType handle);
+
+ /// Get a constant reference to the whole map as well as a lock for this object's dispatch mutex.
+ std::pair<UniqueLock, map_t const &> lockMapConst();
+
+ /// Get a reference to the whole map as well as a lock for this object's dispatch mutex.
+ std::pair<UniqueLock, map_t &> lockMap();
+
+ protected:
+ map_t info_map_;
+ std::mutex dispatch_mutex_;
+};
+
+/// Subclass used exclusively for instances.
+class InstanceHandleInfo : public HandleInfoBase<XrInstance, GenValidUsageXrInstanceInfo> {
+ public:
+ typedef HandleInfoBase<XrInstance, GenValidUsageXrInstanceInfo> base_t;
+ typedef typename base_t::info_t info_t;
+ typedef typename base_t::handle_t handle_t;
+};
+
+/// Generic handle info for everything-except-instance handles.
+template <typename HandleType>
+class HandleInfo : public HandleInfoBase<HandleType, GenValidUsageXrHandleInfo> {
+ public:
+ typedef HandleInfoBase<HandleType, GenValidUsageXrHandleInfo> base_t;
+ typedef typename base_t::info_t info_t;
+ typedef typename base_t::handle_t handle_t;
+
+ /// Lookup a handle and its instance info
+ /// Throws if not found.
+ std::pair<GenValidUsageXrHandleInfo *, GenValidUsageXrInstanceInfo *> getWithInstanceInfo(HandleType handle);
+
+ /// Removes handles associated with an instance.
+ void removeHandlesForInstance(GenValidUsageXrInstanceInfo *search_value);
+};
+
+/// Function to record all the core validation information
+void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,
+ GenValidUsageDebugSeverity message_severity, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message);
+
+void InvalidStructureType(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo> &objects_info, const char *structure_name, XrStructureType type,
+ const char *vuid = nullptr, XrStructureType expected = XrStructureType(0),
+ const char *expected_name = "");
+
+// -- Only implementations of templates follow --//
+
+template <typename HT, typename IT>
+inline std::pair<UniqueLock, typename HandleInfoBase<HT, IT>::map_t const &> HandleInfoBase<HT, IT>::lockMapConst() {
+ return {UniqueLock(dispatch_mutex_), info_map_};
+}
+
+template <typename HT, typename IT>
+inline std::pair<UniqueLock, typename HandleInfoBase<HT, IT>::map_t &> HandleInfoBase<HT, IT>::lockMap() {
+ return {UniqueLock(dispatch_mutex_), info_map_};
+}
+
+template <typename HandleType, typename InfoType>
+inline ValidateXrHandleResult HandleInfoBase<HandleType, InfoType>::verifyHandle(HandleType const *handle_to_check) {
+ try {
+ if (nullptr == handle_to_check) {
+ return VALIDATE_XR_HANDLE_INVALID;
+ }
+ // XR_NULL_HANDLE is valid in some cases, so we want to return that we found that value
+ // and let the calling function decide what to do with it.
+ if (*handle_to_check == XR_NULL_HANDLE) {
+ return VALIDATE_XR_HANDLE_NULL;
+ }
+
+ // Try to find the handle in the appropriate map
+ UniqueLock lock(dispatch_mutex_);
+ auto entry_returned = info_map_.find(*handle_to_check);
+ // If it is not a valid handle, it should return the end of the map.
+ if (info_map_.end() == entry_returned) {
+ return VALIDATE_XR_HANDLE_INVALID;
+ }
+ return VALIDATE_XR_HANDLE_SUCCESS;
+ } catch (...) {
+ return VALIDATE_XR_HANDLE_INVALID;
+ }
+}
+
+template <typename HandleType, typename InfoType>
+inline InfoType *HandleInfoBase<HandleType, InfoType>::get(HandleType handle) {
+ if (handle == XR_NULL_HANDLE) {
+ reportInternalError("Null handle passed to HandleInfoBase::get()");
+ }
+ // Try to find the handle in the appropriate map
+ UniqueLock lock(dispatch_mutex_);
+ auto entry_returned = info_map_.find(handle);
+ if (entry_returned == info_map_.end()) {
+ reportInternalError("Handle passed to HandleInfoBase::insert() not inserted");
+ }
+ return entry_returned->second.get();
+}
+
+template <typename HandleType, typename InfoType>
+inline std::pair<UniqueLock, InfoType *> HandleInfoBase<HandleType, InfoType>::getWithLock(HandleType handle) {
+ if (handle == XR_NULL_HANDLE) {
+ reportInternalError("Null handle passed to HandleInfoBase::getWithLock()");
+ }
+ // Try to find the handle in the appropriate map
+ UniqueLock lock(dispatch_mutex_);
+ auto it = info_map_.find(handle);
+ // If it is not a valid handle, it should return the end of the map.
+ if (info_map_.end() == it) {
+ return {std::move(lock), nullptr};
+ }
+ return {std::move(lock), it->second.get()};
+}
+
+template <typename HandleType, typename InfoType>
+inline void HandleInfoBase<HandleType, InfoType>::insert(HandleType handle, std::unique_ptr<InfoType> &&info) {
+ if (handle == XR_NULL_HANDLE) {
+ reportInternalError("Null handle passed to HandleInfoBase::insert()");
+ }
+ UniqueLock lock(dispatch_mutex_);
+ auto entry_returned = info_map_.find(handle);
+ if (entry_returned != info_map_.end()) {
+ reportInternalError("Handle passed to HandleInfoBase::insert() already inserted");
+ }
+ info_map_[handle] = std::move(info);
+}
+
+template <typename HandleType, typename InfoType>
+inline void HandleInfoBase<HandleType, InfoType>::erase(HandleType handle) {
+ if (handle == XR_NULL_HANDLE) {
+ reportInternalError("Null handle passed to HandleInfoBase::erase()");
+ }
+ UniqueLock lock(dispatch_mutex_);
+ auto entry_returned = info_map_.find(handle);
+ if (entry_returned == info_map_.end()) {
+ reportInternalError("Handle passed to HandleInfoBase::insert() not inserted");
+ }
+ info_map_.erase(handle);
+}
+
+template <typename HandleType>
+inline std::pair<GenValidUsageXrHandleInfo *, GenValidUsageXrInstanceInfo *> HandleInfo<HandleType>::getWithInstanceInfo(
+ HandleType handle) {
+ if (handle == XR_NULL_HANDLE) {
+ reportInternalError("Null handle passed to HandleInfoBase::getWithInstanceInfo()");
+ }
+ // Try to find the handle in the appropriate map
+ UniqueLock lock(this->dispatch_mutex_);
+ auto entry_returned = this->info_map_.find(handle);
+ if (entry_returned == this->info_map_.end()) {
+ reportInternalError("Handle passed to HandleInfoBase::getWithInstanceInfo() not inserted");
+ }
+ GenValidUsageXrHandleInfo *info = entry_returned->second.get();
+ GenValidUsageXrInstanceInfo *instance_info = info->instance_info;
+ return {info, instance_info};
+}
+
+template <typename HandleType>
+inline void HandleInfo<HandleType>::removeHandlesForInstance(GenValidUsageXrInstanceInfo *search_value) {
+ typedef typename base_t::value_t value_t;
+ UniqueLock lock(this->dispatch_mutex_);
+ map_erase_if(this->info_map_, [=](value_t const &data) { return data.second && data.second->instance_info == search_value; });
+}
+
+#endif // VALIDATION_UTILS_H_
diff --git a/extern/openxr/src/api_layers/xr_generated_core_validation.cpp b/extern/openxr/src/api_layers/xr_generated_core_validation.cpp
new file mode 100644
index 00000000000..2de26d028b4
--- /dev/null
+++ b/extern/openxr/src/api_layers/xr_generated_core_validation.cpp
@@ -0,0 +1,15407 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See validation_layer_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "xr_generated_core_validation.hpp"
+
+#include "api_layer_platform_defines.h"
+#include "hex_and_handles.h"
+#include "validation_utils.h"
+#include "xr_dependencies.h"
+#include "xr_generated_dispatch_table.h"
+
+#include "api_layer_platform_defines.h"
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#include <algorithm>
+#include <cstring>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+
+// Structure used for indicating status of 'flags' test.
+enum ValidateXrFlagsResult {
+ VALIDATE_XR_FLAGS_ZERO,
+ VALIDATE_XR_FLAGS_INVALID,
+ VALIDATE_XR_FLAGS_SUCCESS,
+};
+
+// Unordered Map associating pointer to a vector of session label information to a session's handle
+std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel*>*> g_xr_session_labels;
+
+InstanceHandleInfo g_instance_info;
+HandleInfo<XrSession> g_session_info;
+HandleInfo<XrSpace> g_space_info;
+HandleInfo<XrAction> g_action_info;
+HandleInfo<XrSwapchain> g_swapchain_info;
+HandleInfo<XrActionSet> g_actionset_info;
+HandleInfo<XrDebugUtilsMessengerEXT> g_debugutilsmessengerext_info;
+ValidateXrHandleResult VerifyXrInstanceHandle(const XrInstance* handle_to_check);
+ValidateXrHandleResult VerifyXrSessionHandle(const XrSession* handle_to_check);
+ValidateXrHandleResult VerifyXrSpaceHandle(const XrSpace* handle_to_check);
+ValidateXrHandleResult VerifyXrActionHandle(const XrAction* handle_to_check);
+ValidateXrHandleResult VerifyXrSwapchainHandle(const XrSwapchain* handle_to_check);
+ValidateXrHandleResult VerifyXrActionSetHandle(const XrActionSet* handle_to_check);
+ValidateXrHandleResult VerifyXrDebugUtilsMessengerEXTHandle(const XrDebugUtilsMessengerEXT* handle_to_check);
+
+// Write out prototypes for handle parent verification functions
+bool VerifyXrParent(XrObjectType handle1_type, const uint64_t handle1,
+ XrObjectType handle2_type, const uint64_t handle2,
+ bool check_this);
+
+// Function to check if an extension has been enabled
+bool ExtensionEnabled(std::vector<std::string> &extensions, const char* const check_extension_name);
+
+// Functions to validate structures
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrApiLayerProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrExtensionProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrApplicationInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInstanceCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInstanceProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataBuffer* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemGetInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemGraphicsProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemTrackingProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSessionCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVector3f* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSpaceVelocity* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrQuaternionf* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrPosef* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrReferenceSpaceCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrExtent2Df* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionSpaceCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSpaceLocation* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewConfigurationProperties* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewConfigurationView* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageBaseHeader* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageAcquireInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageWaitInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageReleaseInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSessionBeginInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameWaitInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameState* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameBeginInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerBaseHeader* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameEndInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewLocateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewState* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFovf* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrView* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionSetCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionCreateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionSuggestedBinding* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInteractionProfileSuggestedBinding* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSessionActionSetsAttachInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInteractionProfileState* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateGetInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateBoolean* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateFloat* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVector2f* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateVector2f* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStatePose* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActiveActionSet* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionsSyncInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrBoundSourcesForActionEnumerateInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInputSourceLocalizedNameGetInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrHapticActionInfo* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrHapticBaseHeader* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrBaseInStructure* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrBaseOutStructure* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrOffset2Di* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrExtent2Di* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrRect2Di* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainSubImage* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerProjectionView* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerProjection* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerQuad* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataBaseHeader* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataEventsLost* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataInstanceLossPending* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataSessionStateChanged* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataReferenceSpaceChangePending* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataInteractionProfileChanged* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrHapticVibration* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrOffset2Df* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrRect2Df* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVector4f* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrColor4f* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerCubeKHR* value);
+#if defined(XR_USE_PLATFORM_ANDROID)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInstanceCreateInfoAndroidKHR* value);
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerDepthInfoKHR* value);
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVulkanSwapchainFormatListCreateInfoKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerCylinderKHR* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerEquirectKHR* value);
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLWin32KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLXlibKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLXcbKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLWaylandKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageOpenGLKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsOpenGLKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLESAndroidKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageOpenGLESKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsOpenGLESKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingVulkanKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageVulkanKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsVulkanKHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingD3D11KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageD3D11KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsD3D11KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingD3D12KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageD3D12KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsD3D12KHR* value);
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVisibilityMaskKHR* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataVisibilityMaskChangedKHR* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataPerfSettingsEXT* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsObjectNameInfoEXT* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsLabelEXT* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsMessengerCallbackDataEXT* value);
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsMessengerCreateInfoEXT* value);
+// Function used to clean up any residual map values that point to an instance prior to that
+// instance being deleted.
+void GenValidUsageCleanUpMaps(GenValidUsageXrInstanceInfo *instance_info) {
+ EraseAllInstanceTableMapElements(instance_info);
+ g_session_info.removeHandlesForInstance(instance_info);
+ g_space_info.removeHandlesForInstance(instance_info);
+ g_action_info.removeHandlesForInstance(instance_info);
+ g_swapchain_info.removeHandlesForInstance(instance_info);
+ g_actionset_info.removeHandlesForInstance(instance_info);
+ g_debugutilsmessengerext_info.removeHandlesForInstance(instance_info);
+}
+
+// Function to convert XrObjectType to string
+std::string GenValidUsageXrObjectTypeToString(const XrObjectType& type) {
+ std::string object_string;
+ if (type == XR_OBJECT_TYPE_UNKNOWN) {
+ object_string = "Unknown XR Object";
+ } else if (type == XR_OBJECT_TYPE_INSTANCE) {
+ object_string = "XrInstance";
+ } else if (type == XR_OBJECT_TYPE_SESSION) {
+ object_string = "XrSession";
+ } else if (type == XR_OBJECT_TYPE_SWAPCHAIN) {
+ object_string = "XrSwapchain";
+ } else if (type == XR_OBJECT_TYPE_SPACE) {
+ object_string = "XrSpace";
+ } else if (type == XR_OBJECT_TYPE_ACTION_SET) {
+ object_string = "XrActionSet";
+ } else if (type == XR_OBJECT_TYPE_ACTION) {
+ object_string = "XrAction";
+ } else if (type == XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT) {
+ object_string = "XrDebugUtilsMessengerEXT";
+ }
+ return object_string;
+}
+
+// Structure used for state validation.
+
+// Result return value for next chain validation
+enum NextChainResult {
+ NEXT_CHAIN_RESULT_VALID = 0,
+ NEXT_CHAIN_RESULT_ERROR = -1,
+ NEXT_CHAIN_RESULT_DUPLICATE_STRUCT = -2,
+};
+
+// Prototype for validateNextChain command (it uses the validate structure commands so add it after
+NextChainResult ValidateNextChain(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const void* next,
+ std::vector<XrStructureType>& valid_ext_structs,
+ std::vector<XrStructureType>& encountered_structs,
+ std::vector<XrStructureType>& duplicate_structs);
+
+// Function to validate XrInstanceCreateFlags flags
+ValidateXrFlagsResult ValidateXrInstanceCreateFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrSessionCreateFlags flags
+ValidateXrFlagsResult ValidateXrSessionCreateFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrSpaceVelocityFlags flags
+ValidateXrFlagsResult ValidateXrSpaceVelocityFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_SPACE_VELOCITY_LINEAR_VALID_BIT) != 0) {
+ // Clear the value XR_SPACE_VELOCITY_LINEAR_VALID_BIT since it is valid
+ int_value &= ~XR_SPACE_VELOCITY_LINEAR_VALID_BIT;
+ }
+ if ((int_value & XR_SPACE_VELOCITY_ANGULAR_VALID_BIT) != 0) {
+ // Clear the value XR_SPACE_VELOCITY_ANGULAR_VALID_BIT since it is valid
+ int_value &= ~XR_SPACE_VELOCITY_ANGULAR_VALID_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrSpaceLocationFlags flags
+ValidateXrFlagsResult ValidateXrSpaceLocationFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0) {
+ // Clear the value XR_SPACE_LOCATION_ORIENTATION_VALID_BIT since it is valid
+ int_value &= ~XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
+ }
+ if ((int_value & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0) {
+ // Clear the value XR_SPACE_LOCATION_POSITION_VALID_BIT since it is valid
+ int_value &= ~XR_SPACE_LOCATION_POSITION_VALID_BIT;
+ }
+ if ((int_value & XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT) != 0) {
+ // Clear the value XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT since it is valid
+ int_value &= ~XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT;
+ }
+ if ((int_value & XR_SPACE_LOCATION_POSITION_TRACKED_BIT) != 0) {
+ // Clear the value XR_SPACE_LOCATION_POSITION_TRACKED_BIT since it is valid
+ int_value &= ~XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrSwapchainCreateFlags flags
+ValidateXrFlagsResult ValidateXrSwapchainCreateFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrSwapchainUsageFlags flags
+ValidateXrFlagsResult ValidateXrSwapchainUsageFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_USAGE_SAMPLED_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_SAMPLED_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_SAMPLED_BIT;
+ }
+ if ((int_value & XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT) != 0) {
+ // Clear the value XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT since it is valid
+ int_value &= ~XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrCompositionLayerFlags flags
+ValidateXrFlagsResult ValidateXrCompositionLayerFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT) != 0) {
+ // Clear the value XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT since it is valid
+ int_value &= ~XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
+ }
+ if ((int_value & XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT) != 0) {
+ // Clear the value XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT since it is valid
+ int_value &= ~XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
+ }
+ if ((int_value & XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT) != 0) {
+ // Clear the value XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT since it is valid
+ int_value &= ~XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrViewStateFlags flags
+ValidateXrFlagsResult ValidateXrViewStateFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_VIEW_STATE_ORIENTATION_VALID_BIT) != 0) {
+ // Clear the value XR_VIEW_STATE_ORIENTATION_VALID_BIT since it is valid
+ int_value &= ~XR_VIEW_STATE_ORIENTATION_VALID_BIT;
+ }
+ if ((int_value & XR_VIEW_STATE_POSITION_VALID_BIT) != 0) {
+ // Clear the value XR_VIEW_STATE_POSITION_VALID_BIT since it is valid
+ int_value &= ~XR_VIEW_STATE_POSITION_VALID_BIT;
+ }
+ if ((int_value & XR_VIEW_STATE_ORIENTATION_TRACKED_BIT) != 0) {
+ // Clear the value XR_VIEW_STATE_ORIENTATION_TRACKED_BIT since it is valid
+ int_value &= ~XR_VIEW_STATE_ORIENTATION_TRACKED_BIT;
+ }
+ if ((int_value & XR_VIEW_STATE_POSITION_TRACKED_BIT) != 0) {
+ // Clear the value XR_VIEW_STATE_POSITION_TRACKED_BIT since it is valid
+ int_value &= ~XR_VIEW_STATE_POSITION_TRACKED_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrInputSourceLocalizedNameFlags flags
+ValidateXrFlagsResult ValidateXrInputSourceLocalizedNameFlags(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT) != 0) {
+ // Clear the value XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT since it is valid
+ int_value &= ~XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT;
+ }
+ if ((int_value & XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT) != 0) {
+ // Clear the value XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT since it is valid
+ int_value &= ~XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT;
+ }
+ if ((int_value & XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT) != 0) {
+ // Clear the value XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT since it is valid
+ int_value &= ~XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrDebugUtilsMessageSeverityFlagsEXT flags
+ValidateXrFlagsResult ValidateXrDebugUtilsMessageSeverityFlagsEXT(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ }
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ }
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ }
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrDebugUtilsMessageTypeFlagsEXT flags
+ValidateXrFlagsResult ValidateXrDebugUtilsMessageTypeFlagsEXT(const XrFlags64 value) {
+ if (0 == value) {
+ return VALIDATE_XR_FLAGS_ZERO;
+ }
+ XrFlags64 int_value = value;
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ }
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ }
+ if ((int_value & XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT) != 0) {
+ // Clear the value XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT since it is valid
+ int_value &= ~XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT;
+ }
+ if (int_value != 0) {
+ // Something is left, it must be invalid
+ return VALIDATE_XR_FLAGS_INVALID;
+ }
+ return VALIDATE_XR_FLAGS_SUCCESS;
+}
+
+// Function to validate XrResult enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrResult value) {
+ switch (value) {
+ case XR_SUCCESS:
+ return true;
+ case XR_TIMEOUT_EXPIRED:
+ return true;
+ case XR_SESSION_LOSS_PENDING:
+ return true;
+ case XR_EVENT_UNAVAILABLE:
+ return true;
+ case XR_SPACE_BOUNDS_UNAVAILABLE:
+ return true;
+ case XR_SESSION_NOT_FOCUSED:
+ return true;
+ case XR_FRAME_DISCARDED:
+ return true;
+ case XR_ERROR_VALIDATION_FAILURE:
+ return true;
+ case XR_ERROR_RUNTIME_FAILURE:
+ return true;
+ case XR_ERROR_OUT_OF_MEMORY:
+ return true;
+ case XR_ERROR_API_VERSION_UNSUPPORTED:
+ return true;
+ case XR_ERROR_INITIALIZATION_FAILED:
+ return true;
+ case XR_ERROR_FUNCTION_UNSUPPORTED:
+ return true;
+ case XR_ERROR_FEATURE_UNSUPPORTED:
+ return true;
+ case XR_ERROR_EXTENSION_NOT_PRESENT:
+ return true;
+ case XR_ERROR_LIMIT_REACHED:
+ return true;
+ case XR_ERROR_SIZE_INSUFFICIENT:
+ return true;
+ case XR_ERROR_HANDLE_INVALID:
+ return true;
+ case XR_ERROR_INSTANCE_LOST:
+ return true;
+ case XR_ERROR_SESSION_RUNNING:
+ return true;
+ case XR_ERROR_SESSION_NOT_RUNNING:
+ return true;
+ case XR_ERROR_SESSION_LOST:
+ return true;
+ case XR_ERROR_SYSTEM_INVALID:
+ return true;
+ case XR_ERROR_PATH_INVALID:
+ return true;
+ case XR_ERROR_PATH_COUNT_EXCEEDED:
+ return true;
+ case XR_ERROR_PATH_FORMAT_INVALID:
+ return true;
+ case XR_ERROR_PATH_UNSUPPORTED:
+ return true;
+ case XR_ERROR_LAYER_INVALID:
+ return true;
+ case XR_ERROR_LAYER_LIMIT_EXCEEDED:
+ return true;
+ case XR_ERROR_SWAPCHAIN_RECT_INVALID:
+ return true;
+ case XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED:
+ return true;
+ case XR_ERROR_ACTION_TYPE_MISMATCH:
+ return true;
+ case XR_ERROR_SESSION_NOT_READY:
+ return true;
+ case XR_ERROR_SESSION_NOT_STOPPING:
+ return true;
+ case XR_ERROR_TIME_INVALID:
+ return true;
+ case XR_ERROR_REFERENCE_SPACE_UNSUPPORTED:
+ return true;
+ case XR_ERROR_FILE_ACCESS_ERROR:
+ return true;
+ case XR_ERROR_FILE_CONTENTS_INVALID:
+ return true;
+ case XR_ERROR_FORM_FACTOR_UNSUPPORTED:
+ return true;
+ case XR_ERROR_FORM_FACTOR_UNAVAILABLE:
+ return true;
+ case XR_ERROR_API_LAYER_NOT_PRESENT:
+ return true;
+ case XR_ERROR_CALL_ORDER_INVALID:
+ return true;
+ case XR_ERROR_GRAPHICS_DEVICE_INVALID:
+ return true;
+ case XR_ERROR_POSE_INVALID:
+ return true;
+ case XR_ERROR_INDEX_OUT_OF_RANGE:
+ return true;
+ case XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED:
+ return true;
+ case XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED:
+ return true;
+ case XR_ERROR_NAME_DUPLICATED:
+ return true;
+ case XR_ERROR_NAME_INVALID:
+ return true;
+ case XR_ERROR_ACTIONSET_NOT_ATTACHED:
+ return true;
+ case XR_ERROR_ACTIONSETS_ALREADY_ATTACHED:
+ return true;
+ case XR_ERROR_LOCALIZED_NAME_DUPLICATED:
+ return true;
+ case XR_ERROR_LOCALIZED_NAME_INVALID:
+ return true;
+ case XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR:
+ // Enum value XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR requires extension XR_KHR_android_thread_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_android_thread_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrResult value \"XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_android_thread_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR:
+ // Enum value XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR requires extension XR_KHR_android_thread_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_android_thread_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrResult value \"XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_android_thread_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrStructureType enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrStructureType value) {
+ switch (value) {
+ case XR_TYPE_UNKNOWN:
+ return false; // Invalid XrStructureType
+ case XR_TYPE_API_LAYER_PROPERTIES:
+ return true;
+ case XR_TYPE_EXTENSION_PROPERTIES:
+ return true;
+ case XR_TYPE_INSTANCE_CREATE_INFO:
+ return true;
+ case XR_TYPE_SYSTEM_GET_INFO:
+ return true;
+ case XR_TYPE_SYSTEM_PROPERTIES:
+ return true;
+ case XR_TYPE_VIEW_LOCATE_INFO:
+ return true;
+ case XR_TYPE_VIEW:
+ return true;
+ case XR_TYPE_SESSION_CREATE_INFO:
+ return true;
+ case XR_TYPE_SWAPCHAIN_CREATE_INFO:
+ return true;
+ case XR_TYPE_SESSION_BEGIN_INFO:
+ return true;
+ case XR_TYPE_VIEW_STATE:
+ return true;
+ case XR_TYPE_FRAME_END_INFO:
+ return true;
+ case XR_TYPE_HAPTIC_VIBRATION:
+ return true;
+ case XR_TYPE_EVENT_DATA_BUFFER:
+ return true;
+ case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
+ return true;
+ case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
+ return true;
+ case XR_TYPE_ACTION_STATE_BOOLEAN:
+ return true;
+ case XR_TYPE_ACTION_STATE_FLOAT:
+ return true;
+ case XR_TYPE_ACTION_STATE_VECTOR2F:
+ return true;
+ case XR_TYPE_ACTION_STATE_POSE:
+ return true;
+ case XR_TYPE_ACTION_SET_CREATE_INFO:
+ return true;
+ case XR_TYPE_ACTION_CREATE_INFO:
+ return true;
+ case XR_TYPE_INSTANCE_PROPERTIES:
+ return true;
+ case XR_TYPE_FRAME_WAIT_INFO:
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION:
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_QUAD:
+ return true;
+ case XR_TYPE_REFERENCE_SPACE_CREATE_INFO:
+ return true;
+ case XR_TYPE_ACTION_SPACE_CREATE_INFO:
+ return true;
+ case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
+ return true;
+ case XR_TYPE_VIEW_CONFIGURATION_VIEW:
+ return true;
+ case XR_TYPE_SPACE_LOCATION:
+ return true;
+ case XR_TYPE_SPACE_VELOCITY:
+ return true;
+ case XR_TYPE_FRAME_STATE:
+ return true;
+ case XR_TYPE_VIEW_CONFIGURATION_PROPERTIES:
+ return true;
+ case XR_TYPE_FRAME_BEGIN_INFO:
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW:
+ return true;
+ case XR_TYPE_EVENT_DATA_EVENTS_LOST:
+ return true;
+ case XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING:
+ return true;
+ case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
+ return true;
+ case XR_TYPE_INTERACTION_PROFILE_STATE:
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO:
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO:
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO:
+ return true;
+ case XR_TYPE_ACTION_STATE_GET_INFO:
+ return true;
+ case XR_TYPE_HAPTIC_ACTION_INFO:
+ return true;
+ case XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO:
+ return true;
+ case XR_TYPE_ACTIONS_SYNC_INFO:
+ return true;
+ case XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO:
+ return true;
+ case XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO:
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_CUBE_KHR:
+ // Enum value XR_TYPE_COMPOSITION_LAYER_CUBE_KHR requires extension XR_KHR_composition_layer_cube, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_cube")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_COMPOSITION_LAYER_CUBE_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_composition_layer_cube\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR:
+ // Enum value XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR requires extension XR_KHR_android_create_instance, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_android_create_instance")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_android_create_instance\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR:
+ // Enum value XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR requires extension XR_KHR_composition_layer_depth, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_depth")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_composition_layer_depth\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR:
+ // Enum value XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR requires extension XR_KHR_vulkan_swapchain_format_list, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_vulkan_swapchain_format_list")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_vulkan_swapchain_format_list\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT:
+ // Enum value XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT requires extension XR_EXT_performance_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_performance_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_EXT_performance_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR:
+ // Enum value XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR requires extension XR_KHR_composition_layer_cylinder, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_cylinder")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_composition_layer_cylinder\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR:
+ // Enum value XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR requires extension XR_KHR_composition_layer_equirect, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_equirect")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_composition_layer_equirect\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT:
+ // Enum value XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT requires extension XR_EXT_debug_utils, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_debug_utils")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_EXT_debug_utils\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT:
+ // Enum value XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT requires extension XR_EXT_debug_utils, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_debug_utils")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_EXT_debug_utils\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:
+ // Enum value XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT requires extension XR_EXT_debug_utils, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_debug_utils")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_EXT_debug_utils\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_DEBUG_UTILS_LABEL_EXT:
+ // Enum value XR_TYPE_DEBUG_UTILS_LABEL_EXT requires extension XR_EXT_debug_utils, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_debug_utils")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_DEBUG_UTILS_LABEL_EXT\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_EXT_debug_utils\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR requires extension XR_KHR_opengl_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR requires extension XR_KHR_opengl_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR requires extension XR_KHR_opengl_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR requires extension XR_KHR_opengl_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR:
+ // Enum value XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR requires extension XR_KHR_opengl_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR:
+ // Enum value XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR requires extension XR_KHR_opengl_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR requires extension XR_KHR_opengl_es_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_es_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_es_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR:
+ // Enum value XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR requires extension XR_KHR_opengl_es_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_es_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_es_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR:
+ // Enum value XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR requires extension XR_KHR_opengl_es_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_es_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_opengl_es_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR requires extension XR_KHR_vulkan_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_vulkan_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_vulkan_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR:
+ // Enum value XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR requires extension XR_KHR_vulkan_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_vulkan_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_vulkan_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR:
+ // Enum value XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR requires extension XR_KHR_vulkan_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_vulkan_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_vulkan_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_D3D11_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_D3D11_KHR requires extension XR_KHR_D3D11_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D11_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_D3D11_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_D3D11_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR:
+ // Enum value XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR requires extension XR_KHR_D3D11_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D11_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_D3D11_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR:
+ // Enum value XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR requires extension XR_KHR_D3D11_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D11_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_D3D11_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_BINDING_D3D12_KHR:
+ // Enum value XR_TYPE_GRAPHICS_BINDING_D3D12_KHR requires extension XR_KHR_D3D12_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D12_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_BINDING_D3D12_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_D3D12_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR:
+ // Enum value XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR requires extension XR_KHR_D3D12_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D12_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_D3D12_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR:
+ // Enum value XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR requires extension XR_KHR_D3D12_enable, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D12_enable")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_D3D12_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_VISIBILITY_MASK_KHR:
+ // Enum value XR_TYPE_VISIBILITY_MASK_KHR requires extension XR_KHR_visibility_mask, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_visibility_mask")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_VISIBILITY_MASK_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_visibility_mask\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR:
+ // Enum value XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR requires extension XR_KHR_visibility_mask, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_visibility_mask")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrStructureType value \"XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_KHR_visibility_mask\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrFormFactor enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrFormFactor value) {
+ switch (value) {
+ case XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY:
+ return true;
+ case XR_FORM_FACTOR_HANDHELD_DISPLAY:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrViewConfigurationType enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrViewConfigurationType value) {
+ switch (value) {
+ case XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO:
+ return true;
+ case XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO:
+ return true;
+ case XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO:
+ // Enum value XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO requires extension XR_VARJO_quad_views, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_VARJO_quad_views")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrViewConfigurationType value \"XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_VARJO_quad_views\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrEnvironmentBlendMode enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrEnvironmentBlendMode value) {
+ switch (value) {
+ case XR_ENVIRONMENT_BLEND_MODE_OPAQUE:
+ return true;
+ case XR_ENVIRONMENT_BLEND_MODE_ADDITIVE:
+ return true;
+ case XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrReferenceSpaceType enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrReferenceSpaceType value) {
+ switch (value) {
+ case XR_REFERENCE_SPACE_TYPE_VIEW:
+ return true;
+ case XR_REFERENCE_SPACE_TYPE_LOCAL:
+ return true;
+ case XR_REFERENCE_SPACE_TYPE_STAGE:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrActionType enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrActionType value) {
+ switch (value) {
+ case XR_ACTION_TYPE_BOOLEAN_INPUT:
+ return true;
+ case XR_ACTION_TYPE_FLOAT_INPUT:
+ return true;
+ case XR_ACTION_TYPE_VECTOR2F_INPUT:
+ return true;
+ case XR_ACTION_TYPE_POSE_INPUT:
+ return true;
+ case XR_ACTION_TYPE_VIBRATION_OUTPUT:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrEyeVisibility enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrEyeVisibility value) {
+ switch (value) {
+ case XR_EYE_VISIBILITY_BOTH:
+ return true;
+ case XR_EYE_VISIBILITY_LEFT:
+ return true;
+ case XR_EYE_VISIBILITY_RIGHT:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrSessionState enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrSessionState value) {
+ switch (value) {
+ case XR_SESSION_STATE_UNKNOWN:
+ return true;
+ case XR_SESSION_STATE_IDLE:
+ return true;
+ case XR_SESSION_STATE_READY:
+ return true;
+ case XR_SESSION_STATE_SYNCHRONIZED:
+ return true;
+ case XR_SESSION_STATE_VISIBLE:
+ return true;
+ case XR_SESSION_STATE_FOCUSED:
+ return true;
+ case XR_SESSION_STATE_STOPPING:
+ return true;
+ case XR_SESSION_STATE_LOSS_PENDING:
+ return true;
+ case XR_SESSION_STATE_EXITING:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrObjectType enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrObjectType value) {
+ switch (value) {
+ case XR_OBJECT_TYPE_UNKNOWN:
+ return true;
+ case XR_OBJECT_TYPE_INSTANCE:
+ return true;
+ case XR_OBJECT_TYPE_SESSION:
+ return true;
+ case XR_OBJECT_TYPE_SWAPCHAIN:
+ return true;
+ case XR_OBJECT_TYPE_SPACE:
+ return true;
+ case XR_OBJECT_TYPE_ACTION_SET:
+ return true;
+ case XR_OBJECT_TYPE_ACTION:
+ return true;
+ case XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
+ // Enum value XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT requires extension XR_EXT_debug_utils, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_debug_utils")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrObjectType value \"XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT\"";
+ error_str += " being used, which requires extension ";
+ error_str += " \"XR_EXT_debug_utils\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ return true;
+ default:
+ return false;
+}
+}
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+// Function to validate XrAndroidThreadTypeKHR enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrAndroidThreadTypeKHR value) {
+ // Enum requires extension XR_KHR_android_thread_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_android_thread_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrAndroidThreadTypeKHR requires extension ";
+ error_str += " \"XR_KHR_android_thread_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ switch (value) {
+ case XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR:
+ return true;
+ case XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR:
+ return true;
+ case XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR:
+ return true;
+ case XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR:
+ return true;
+ default:
+ return false;
+}
+}
+
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+// Function to validate XrVisibilityMaskTypeKHR enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrVisibilityMaskTypeKHR value) {
+ // Enum requires extension XR_KHR_visibility_mask, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_visibility_mask")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrVisibilityMaskTypeKHR requires extension ";
+ error_str += " \"XR_KHR_visibility_mask\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ switch (value) {
+ case XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR:
+ return true;
+ case XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR:
+ return true;
+ case XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrPerfSettingsDomainEXT enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrPerfSettingsDomainEXT value) {
+ // Enum requires extension XR_EXT_performance_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_performance_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrPerfSettingsDomainEXT requires extension ";
+ error_str += " \"XR_EXT_performance_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ switch (value) {
+ case XR_PERF_SETTINGS_DOMAIN_CPU_EXT:
+ return true;
+ case XR_PERF_SETTINGS_DOMAIN_GPU_EXT:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrPerfSettingsSubDomainEXT enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrPerfSettingsSubDomainEXT value) {
+ // Enum requires extension XR_EXT_performance_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_performance_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrPerfSettingsSubDomainEXT requires extension ";
+ error_str += " \"XR_EXT_performance_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ switch (value) {
+ case XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT:
+ return true;
+ case XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT:
+ return true;
+ case XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrPerfSettingsLevelEXT enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrPerfSettingsLevelEXT value) {
+ // Enum requires extension XR_EXT_performance_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_performance_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrPerfSettingsLevelEXT requires extension ";
+ error_str += " \"XR_EXT_performance_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ switch (value) {
+ case XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT:
+ return true;
+ case XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT:
+ return true;
+ case XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT:
+ return true;
+ case XR_PERF_SETTINGS_LEVEL_BOOST_EXT:
+ return true;
+ default:
+ return false;
+}
+}
+
+// Function to validate XrPerfSettingsNotificationLevelEXT enum
+bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ const std::string &validation_name,
+ const std::string &item_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const XrPerfSettingsNotificationLevelEXT value) {
+ // Enum requires extension XR_EXT_performance_settings, so check that it is enabled
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_performance_settings")) {
+ std::string vuid = "VUID-";
+ vuid += validation_name;
+ vuid += "-";
+ vuid += item_name;
+ vuid += "-parameter";
+ std::string error_str = "XrPerfSettingsNotificationLevelEXT requires extension ";
+ error_str += " \"XR_EXT_performance_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, vuid,
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return false;
+ }
+ switch (value) {
+ case XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT:
+ return true;
+ case XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT:
+ return true;
+ case XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT:
+ return true;
+ default:
+ return false;
+}
+}
+
+bool ExtensionEnabled(std::vector<std::string> &extensions, const char* const check_extension_name) {
+ for (auto enabled_extension: extensions) {
+ if (enabled_extension == check_extension_name) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ValidateInstanceExtensionDependencies(GenValidUsageXrInstanceInfo *gen_instance_info,
+ const std::string &command,
+ const std::string &struct_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ std::vector<std::string> &extensions) {
+ for (uint32_t cur_index = 0; cur_index < extensions.size(); ++cur_index) {
+ if (extensions[cur_index] == "XR_KHR_vulkan_swapchain_format_list") {
+ for (uint32_t check_index = 0; check_index < extensions.size(); ++check_index) {
+ if (cur_index == check_index) {
+ continue;
+ }
+ if (!ExtensionEnabled(extensions, "XR_KHR_vulkan_enable")) {
+ if (nullptr != gen_instance_info) {
+ std::string vuid = "VUID-";
+ vuid += command;
+ vuid += "-";
+ vuid += struct_name;
+ vuid += "-parameter";
+ CoreValidLogMessage(gen_instance_info, vuid, VALID_USAGE_DEBUG_SEVERITY_ERROR,
+ command, objects_info,
+ "Missing extension dependency \"XR_KHR_vulkan_enable\" (required by extension" \
+ "\"XR_KHR_vulkan_swapchain_format_list\") from enabled extension list");
+ }
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool ValidateSystemExtensionDependencies(GenValidUsageXrInstanceInfo *gen_instance_info,
+ const std::string &command,
+ const std::string &struct_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ std::vector<std::string> &extensions) {
+ // No system extensions to check dependencies for
+ return true;
+}
+
+ValidateXrHandleResult VerifyXrInstanceHandle(const XrInstance* handle_to_check) {
+ return g_instance_info.verifyHandle(handle_to_check);
+}
+
+ValidateXrHandleResult VerifyXrSessionHandle(const XrSession* handle_to_check) {
+ return g_session_info.verifyHandle(handle_to_check);
+}
+
+ValidateXrHandleResult VerifyXrSpaceHandle(const XrSpace* handle_to_check) {
+ return g_space_info.verifyHandle(handle_to_check);
+}
+
+ValidateXrHandleResult VerifyXrActionHandle(const XrAction* handle_to_check) {
+ return g_action_info.verifyHandle(handle_to_check);
+}
+
+ValidateXrHandleResult VerifyXrSwapchainHandle(const XrSwapchain* handle_to_check) {
+ return g_swapchain_info.verifyHandle(handle_to_check);
+}
+
+ValidateXrHandleResult VerifyXrActionSetHandle(const XrActionSet* handle_to_check) {
+ return g_actionset_info.verifyHandle(handle_to_check);
+}
+
+ValidateXrHandleResult VerifyXrDebugUtilsMessengerEXTHandle(const XrDebugUtilsMessengerEXT* handle_to_check) {
+ return g_debugutilsmessengerext_info.verifyHandle(handle_to_check);
+}
+
+// Implementation function to get parent handle information
+bool GetXrParent(const XrObjectType inhandle_type, const uint64_t inhandle,
+ XrObjectType& outhandle_type, uint64_t& outhandle) {
+ if (inhandle_type == XR_OBJECT_TYPE_INSTANCE) {
+ return false;
+ }
+ if (inhandle_type == XR_OBJECT_TYPE_SESSION) {
+ // Get the object and parent of the handle
+ GenValidUsageXrHandleInfo *handle_info = g_session_info.get(TreatIntegerAsHandle<XrSession>(inhandle));
+ outhandle_type = handle_info->direct_parent_type;
+ outhandle = handle_info->direct_parent_handle;
+ return true;
+ }
+ if (inhandle_type == XR_OBJECT_TYPE_SPACE) {
+ // Get the object and parent of the handle
+ GenValidUsageXrHandleInfo *handle_info = g_space_info.get(TreatIntegerAsHandle<XrSpace>(inhandle));
+ outhandle_type = handle_info->direct_parent_type;
+ outhandle = handle_info->direct_parent_handle;
+ return true;
+ }
+ if (inhandle_type == XR_OBJECT_TYPE_ACTION) {
+ // Get the object and parent of the handle
+ GenValidUsageXrHandleInfo *handle_info = g_action_info.get(TreatIntegerAsHandle<XrAction>(inhandle));
+ outhandle_type = handle_info->direct_parent_type;
+ outhandle = handle_info->direct_parent_handle;
+ return true;
+ }
+ if (inhandle_type == XR_OBJECT_TYPE_SWAPCHAIN) {
+ // Get the object and parent of the handle
+ GenValidUsageXrHandleInfo *handle_info = g_swapchain_info.get(TreatIntegerAsHandle<XrSwapchain>(inhandle));
+ outhandle_type = handle_info->direct_parent_type;
+ outhandle = handle_info->direct_parent_handle;
+ return true;
+ }
+ if (inhandle_type == XR_OBJECT_TYPE_ACTION_SET) {
+ // Get the object and parent of the handle
+ GenValidUsageXrHandleInfo *handle_info = g_actionset_info.get(TreatIntegerAsHandle<XrActionSet>(inhandle));
+ outhandle_type = handle_info->direct_parent_type;
+ outhandle = handle_info->direct_parent_handle;
+ return true;
+ }
+ if (inhandle_type == XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT) {
+ // Get the object and parent of the handle
+ GenValidUsageXrHandleInfo *handle_info = g_debugutilsmessengerext_info.get(TreatIntegerAsHandle<XrDebugUtilsMessengerEXT>(inhandle));
+ outhandle_type = handle_info->direct_parent_type;
+ outhandle = handle_info->direct_parent_handle;
+ return true;
+ }
+ return false;
+}
+
+// Implementation of VerifyXrParent function
+bool VerifyXrParent(XrObjectType handle1_type, const uint64_t handle1,
+ XrObjectType handle2_type, const uint64_t handle2,
+ bool check_this) {
+ if (IsIntegerNullHandle(handle1) || IsIntegerNullHandle(handle2)) {
+ return false;
+ } else if (check_this && handle1_type == handle2_type) {
+ return (handle1 == handle2);
+ }
+ if (handle1_type == XR_OBJECT_TYPE_INSTANCE && handle2_type != XR_OBJECT_TYPE_INSTANCE) {
+ XrObjectType parent_type;
+ uint64_t parent_handle;
+ if (!GetXrParent(handle2_type, handle2, parent_type, parent_handle)) {
+ return false;
+ }
+ return VerifyXrParent(handle1_type, handle1, parent_type, parent_handle, true);
+ } else if (handle2_type == XR_OBJECT_TYPE_INSTANCE && handle1_type != XR_OBJECT_TYPE_INSTANCE) {
+ XrObjectType parent_type;
+ uint64_t parent_handle;
+ if (!GetXrParent(handle1_type, handle1, parent_type, parent_handle)) {
+ return false;
+ }
+ return VerifyXrParent(parent_type, parent_handle, handle2_type, handle2, true);
+ } else {
+ XrObjectType parent1_type;
+ uint64_t parent1_handle;
+ XrObjectType parent2_type;
+ uint64_t parent2_handle;
+ if (!GetXrParent(handle1_type, handle1, parent1_type, parent1_handle)) {
+ return false;
+ }
+ if (!GetXrParent(handle2_type, handle2, parent2_type, parent2_handle)) {
+ return false;
+ }
+ if (parent1_type == handle2_type) {
+ return (parent1_handle == handle2);
+ } else if (handle1_type == parent2_type) {
+ return (handle1 == parent2_handle);
+ } else {
+ return VerifyXrParent(parent1_type, parent1_handle, parent2_type, parent2_handle, true);
+ }
+ }
+ return false;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrApiLayerProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_API_LAYER_PROPERTIES) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrApiLayerProperties",
+ value->type, "VUID-XrApiLayerProperties-type-type", XR_TYPE_API_LAYER_PROPERTIES, "XR_TYPE_API_LAYER_PROPERTIES");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrApiLayerProperties-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrApiLayerProperties struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrApiLayerProperties : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrApiLayerProperties-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrApiLayerProperties struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_API_LAYER_NAME_SIZE < std::strlen(value->layerName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrApiLayerProperties-layerName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrApiLayerProperties member layerName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (XR_MAX_API_LAYER_DESCRIPTION_SIZE < std::strlen(value->description)) {
+ CoreValidLogMessage(instance_info, "VUID-XrApiLayerProperties-description-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrApiLayerProperties member description length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrExtensionProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EXTENSION_PROPERTIES) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrExtensionProperties",
+ value->type, "VUID-XrExtensionProperties-type-type", XR_TYPE_EXTENSION_PROPERTIES, "XR_TYPE_EXTENSION_PROPERTIES");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrExtensionProperties-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrExtensionProperties struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrExtensionProperties : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrExtensionProperties-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrExtensionProperties struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_EXTENSION_NAME_SIZE < std::strlen(value->extensionName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrExtensionProperties-extensionName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrExtensionProperties member extensionName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrApplicationInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_APPLICATION_NAME_SIZE < std::strlen(value->applicationName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrApplicationInfo-applicationName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrApplicationInfo member applicationName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (XR_MAX_ENGINE_NAME_SIZE < std::strlen(value->engineName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrApplicationInfo-engineName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrApplicationInfo member engineName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInstanceCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_INSTANCE_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrInstanceCreateInfo",
+ value->type, "VUID-XrInstanceCreateInfo-type-type", XR_TYPE_INSTANCE_CREATE_INFO, "XR_TYPE_INSTANCE_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ valid_ext_structs.push_back(XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
+ valid_ext_structs.push_back(XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR);
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrInstanceCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrInstanceCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrInstanceCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult instance_create_flags_result = ValidateXrInstanceCreateFlags(value->createFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == instance_create_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrInstanceCreateInfo invalid member XrInstanceCreateFlags \"createFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->createFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-createFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrApplicationInfo is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->applicationInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-applicationInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrInstanceCreateInfo member applicationInfo is invalid");
+ return xr_result;
+ }
+ // Pointer/array variable with a length variable. Make sure that
+ // if length variable is non-zero that the pointer is not NULL
+ if (nullptr == value->enabledApiLayerNames && 0 != value->enabledApiLayerCount) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrInstanceCreateInfo contains invalid NULL for char \"enabledApiLayerNames\" is which not "
+ "optional since \"enabledApiLayerCount\" is set and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter" null-termination
+ // Optional array must be non-NULL when value->enabledExtensionCount is non-zero
+ if (0 != value->enabledExtensionCount && nullptr == value->enabledExtensionNames) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrInstanceCreateInfo member enabledExtensionCount is NULL, but value->enabledExtensionCount is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Pointer/array variable with a length variable. Make sure that
+ // if length variable is non-zero that the pointer is not NULL
+ if (nullptr == value->enabledExtensionNames && 0 != value->enabledExtensionCount) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrInstanceCreateInfo contains invalid NULL for char \"enabledExtensionNames\" is which not "
+ "optional since \"enabledExtensionCount\" is set and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter" null-termination
+ std::vector<std::string> enabled_extension_vec;
+ for (uint32_t extension = 0; extension < value->enabledExtensionCount; ++extension) {
+ enabled_extension_vec.push_back(value->enabledExtensionNames[extension]);
+ }
+ if (!ValidateInstanceExtensionDependencies(nullptr, command_name, "XrInstanceCreateInfo",
+ objects_info, enabled_extension_vec)) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInstanceProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_INSTANCE_PROPERTIES) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrInstanceProperties",
+ value->type, "VUID-XrInstanceProperties-type-type", XR_TYPE_INSTANCE_PROPERTIES, "XR_TYPE_INSTANCE_PROPERTIES");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceProperties-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrInstanceProperties struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrInstanceProperties : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceProperties-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrInstanceProperties struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_RUNTIME_NAME_SIZE < std::strlen(value->runtimeName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceProperties-runtimeName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrInstanceProperties member runtimeName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataBuffer* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_BUFFER) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataBuffer",
+ value->type, "VUID-XrEventDataBuffer-type-type", XR_TYPE_EVENT_DATA_BUFFER, "XR_TYPE_EVENT_DATA_BUFFER");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataBuffer-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataBuffer struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataBuffer : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataBuffer-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataBuffer struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemGetInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SYSTEM_GET_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSystemGetInfo",
+ value->type, "VUID-XrSystemGetInfo-type-type", XR_TYPE_SYSTEM_GET_INFO, "XR_TYPE_SYSTEM_GET_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSystemGetInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSystemGetInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSystemGetInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSystemGetInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSystemGetInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrFormFactor value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrSystemGetInfo", "formFactor", objects_info, value->formFactor)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrSystemGetInfo contains invalid XrFormFactor \"formFactor\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->formFactor));
+ CoreValidLogMessage(instance_info, "VUID-XrSystemGetInfo-formFactor-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemGraphicsProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemTrackingProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSystemProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SYSTEM_PROPERTIES) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSystemProperties",
+ value->type, "VUID-XrSystemProperties-type-type", XR_TYPE_SYSTEM_PROPERTIES, "XR_TYPE_SYSTEM_PROPERTIES");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSystemProperties-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSystemProperties struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSystemProperties : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSystemProperties-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSystemProperties struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_SYSTEM_NAME_SIZE < std::strlen(value->systemName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrSystemProperties-systemName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrSystemProperties member systemName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSystemTrackingProperties is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->trackingProperties);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSystemProperties-trackingProperties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrSystemProperties member trackingProperties is invalid");
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSessionCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SESSION_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSessionCreateInfo",
+ value->type, "VUID-XrSessionCreateInfo-type-type", XR_TYPE_SESSION_CREATE_INFO, "XR_TYPE_SESSION_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_D3D11_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_D3D12_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR);
+ valid_ext_structs.push_back(XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR);
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSessionCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSessionCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSessionCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSessionCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSessionCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult session_create_flags_result = ValidateXrSessionCreateFlags(value->createFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == session_create_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrSessionCreateInfo invalid member XrSessionCreateFlags \"createFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->createFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrSessionCreateInfo-createFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVector3f* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSpaceVelocity* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SPACE_VELOCITY) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSpaceVelocity",
+ value->type, "VUID-XrSpaceVelocity-type-type", XR_TYPE_SPACE_VELOCITY, "XR_TYPE_SPACE_VELOCITY");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSpaceVelocity-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSpaceVelocity struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSpaceVelocity : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSpaceVelocity-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSpaceVelocity struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult space_velocity_flags_result = ValidateXrSpaceVelocityFlags(value->velocityFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == space_velocity_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrSpaceVelocity invalid member XrSpaceVelocityFlags \"velocityFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->velocityFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrSpaceVelocity-velocityFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrQuaternionf* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrPosef* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrReferenceSpaceCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_REFERENCE_SPACE_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrReferenceSpaceCreateInfo",
+ value->type, "VUID-XrReferenceSpaceCreateInfo-type-type", XR_TYPE_REFERENCE_SPACE_CREATE_INFO, "XR_TYPE_REFERENCE_SPACE_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrReferenceSpaceCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrReferenceSpaceCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrReferenceSpaceCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrReferenceSpaceCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrReferenceSpaceCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrReferenceSpaceType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrReferenceSpaceCreateInfo", "referenceSpaceType", objects_info, value->referenceSpaceType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrReferenceSpaceCreateInfo contains invalid XrReferenceSpaceType \"referenceSpaceType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->referenceSpaceType));
+ CoreValidLogMessage(instance_info, "VUID-XrReferenceSpaceCreateInfo-referenceSpaceType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrExtent2Df* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionSpaceCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_SPACE_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionSpaceCreateInfo",
+ value->type, "VUID-XrActionSpaceCreateInfo-type-type", XR_TYPE_ACTION_SPACE_CREATE_INFO, "XR_TYPE_ACTION_SPACE_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionSpaceCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionSpaceCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionSpaceCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionSpaceCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionSpaceCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionHandle(&value->action);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrAction handle \"action\" ";
+ oss << HandleToHexString(value->action);
+ CoreValidLogMessage(instance_info, "VUID-XrActionSpaceCreateInfo-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSpaceLocation* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SPACE_LOCATION) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSpaceLocation",
+ value->type, "VUID-XrSpaceLocation-type-type", XR_TYPE_SPACE_LOCATION, "XR_TYPE_SPACE_LOCATION");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ valid_ext_structs.push_back(XR_TYPE_SPACE_VELOCITY);
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSpaceLocation-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSpaceLocation struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSpaceLocation : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSpaceLocation-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSpaceLocation struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult space_location_flags_result = ValidateXrSpaceLocationFlags(value->locationFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == space_location_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrSpaceLocation invalid member XrSpaceLocationFlags \"locationFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->locationFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrSpaceLocation-locationFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewConfigurationProperties* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VIEW_CONFIGURATION_PROPERTIES) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrViewConfigurationProperties",
+ value->type, "VUID-XrViewConfigurationProperties-type-type", XR_TYPE_VIEW_CONFIGURATION_PROPERTIES, "XR_TYPE_VIEW_CONFIGURATION_PROPERTIES");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrViewConfigurationProperties-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrViewConfigurationProperties struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrViewConfigurationProperties : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrViewConfigurationProperties-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrViewConfigurationProperties struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrViewConfigurationProperties", "viewConfigurationType", objects_info, value->viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrViewConfigurationProperties contains invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->viewConfigurationType));
+ CoreValidLogMessage(instance_info, "VUID-XrViewConfigurationProperties-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewConfigurationView* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VIEW_CONFIGURATION_VIEW) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrViewConfigurationView",
+ value->type, "VUID-XrViewConfigurationView-type-type", XR_TYPE_VIEW_CONFIGURATION_VIEW, "XR_TYPE_VIEW_CONFIGURATION_VIEW");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrViewConfigurationView-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrViewConfigurationView struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrViewConfigurationView : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrViewConfigurationView-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrViewConfigurationView struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainCreateInfo",
+ value->type, "VUID-XrSwapchainCreateInfo-type-type", XR_TYPE_SWAPCHAIN_CREATE_INFO, "XR_TYPE_SWAPCHAIN_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult swapchain_create_flags_result = ValidateXrSwapchainCreateFlags(value->createFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == swapchain_create_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrSwapchainCreateInfo invalid member XrSwapchainCreateFlags \"createFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->createFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainCreateInfo-createFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ ValidateXrFlagsResult swapchain_usage_flags_result = ValidateXrSwapchainUsageFlags(value->usageFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == swapchain_usage_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrSwapchainCreateInfo invalid member XrSwapchainUsageFlags \"usageFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->usageFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainCreateInfo-usageFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageBaseHeader* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // NOTE: Can't validate "VUID-XrSwapchainImageBaseHeader-type-parameter" because it is a base structure
+ // NOTE: Can't validate "VUID-XrSwapchainImageBaseHeader-next-next" because it is a base structure
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ if (value->type == XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) {
+ const XrSwapchainImageOpenGLKHR* new_value = reinterpret_cast<const XrSwapchainImageOpenGLKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_enable")) {
+ std::string error_str = "XrSwapchainImageBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR\"";
+ error_str += " which requires extension \"XR_KHR_opengl_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ if (value->type == XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) {
+ const XrSwapchainImageOpenGLESKHR* new_value = reinterpret_cast<const XrSwapchainImageOpenGLESKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_opengl_es_enable")) {
+ std::string error_str = "XrSwapchainImageBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR\"";
+ error_str += " which requires extension \"XR_KHR_opengl_es_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ if (value->type == XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) {
+ const XrSwapchainImageVulkanKHR* new_value = reinterpret_cast<const XrSwapchainImageVulkanKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_vulkan_enable")) {
+ std::string error_str = "XrSwapchainImageBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR\"";
+ error_str += " which requires extension \"XR_KHR_vulkan_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ if (value->type == XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) {
+ const XrSwapchainImageD3D11KHR* new_value = reinterpret_cast<const XrSwapchainImageD3D11KHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D11_enable")) {
+ std::string error_str = "XrSwapchainImageBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR\"";
+ error_str += " which requires extension \"XR_KHR_D3D11_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ if (value->type == XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) {
+ const XrSwapchainImageD3D12KHR* new_value = reinterpret_cast<const XrSwapchainImageD3D12KHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_D3D12_enable")) {
+ std::string error_str = "XrSwapchainImageBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR\"";
+ error_str += " which requires extension \"XR_KHR_D3D12_enable\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageBaseHeader",
+ value->type, "VUID-XrSwapchainImageBaseHeader-type-type");
+ return XR_ERROR_VALIDATION_FAILURE;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageAcquireInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageAcquireInfo",
+ value->type, "VUID-XrSwapchainImageAcquireInfo-type-type", XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, "XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageAcquireInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageAcquireInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageAcquireInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageAcquireInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageAcquireInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageWaitInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageWaitInfo",
+ value->type, "VUID-XrSwapchainImageWaitInfo-type-type", XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, "XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageWaitInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageWaitInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageWaitInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageWaitInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageWaitInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageReleaseInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageReleaseInfo",
+ value->type, "VUID-XrSwapchainImageReleaseInfo-type-type", XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, "XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageReleaseInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageReleaseInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageReleaseInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageReleaseInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageReleaseInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSessionBeginInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SESSION_BEGIN_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSessionBeginInfo",
+ value->type, "VUID-XrSessionBeginInfo-type-type", XR_TYPE_SESSION_BEGIN_INFO, "XR_TYPE_SESSION_BEGIN_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSessionBeginInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSessionBeginInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSessionBeginInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSessionBeginInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSessionBeginInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrSessionBeginInfo", "primaryViewConfigurationType", objects_info, value->primaryViewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrSessionBeginInfo contains invalid XrViewConfigurationType \"primaryViewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->primaryViewConfigurationType));
+ CoreValidLogMessage(instance_info, "VUID-XrSessionBeginInfo-primaryViewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameWaitInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_FRAME_WAIT_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrFrameWaitInfo",
+ value->type, "VUID-XrFrameWaitInfo-type-type", XR_TYPE_FRAME_WAIT_INFO, "XR_TYPE_FRAME_WAIT_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrFrameWaitInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrFrameWaitInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrFrameWaitInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrFrameWaitInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrFrameWaitInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameState* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_FRAME_STATE) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrFrameState",
+ value->type, "VUID-XrFrameState-type-type", XR_TYPE_FRAME_STATE, "XR_TYPE_FRAME_STATE");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrFrameState-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrFrameState struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrFrameState : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrFrameState-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrFrameState struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameBeginInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_FRAME_BEGIN_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrFrameBeginInfo",
+ value->type, "VUID-XrFrameBeginInfo-type-type", XR_TYPE_FRAME_BEGIN_INFO, "XR_TYPE_FRAME_BEGIN_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrFrameBeginInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrFrameBeginInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrFrameBeginInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrFrameBeginInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrFrameBeginInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerBaseHeader* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // NOTE: Can't validate "VUID-XrCompositionLayerBaseHeader-type-parameter" because it is a base structure
+ // NOTE: Can't validate "VUID-XrCompositionLayerBaseHeader-next-next" because it is a base structure
+ // NOTE: Can't validate "VUID-XrCompositionLayerBaseHeader-layerFlags-parameter" because it is a base structure
+ // NOTE: Can't validate "VUID-XrCompositionLayerBaseHeader-space-parameter" because it is a base structure
+ if (value->type == XR_TYPE_COMPOSITION_LAYER_PROJECTION) {
+ const XrCompositionLayerProjection* new_value = reinterpret_cast<const XrCompositionLayerProjection*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_COMPOSITION_LAYER_QUAD) {
+ const XrCompositionLayerQuad* new_value = reinterpret_cast<const XrCompositionLayerQuad*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) {
+ const XrCompositionLayerCubeKHR* new_value = reinterpret_cast<const XrCompositionLayerCubeKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_cube")) {
+ std::string error_str = "XrCompositionLayerBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_COMPOSITION_LAYER_CUBE_KHR\"";
+ error_str += " which requires extension \"XR_KHR_composition_layer_cube\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) {
+ const XrCompositionLayerCylinderKHR* new_value = reinterpret_cast<const XrCompositionLayerCylinderKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_cylinder")) {
+ std::string error_str = "XrCompositionLayerBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR\"";
+ error_str += " which requires extension \"XR_KHR_composition_layer_cylinder\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) {
+ const XrCompositionLayerEquirectKHR* new_value = reinterpret_cast<const XrCompositionLayerEquirectKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_composition_layer_equirect")) {
+ std::string error_str = "XrCompositionLayerBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR\"";
+ error_str += " which requires extension \"XR_KHR_composition_layer_equirect\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerBaseHeader",
+ value->type, "VUID-XrCompositionLayerBaseHeader-type-type");
+ return XR_ERROR_VALIDATION_FAILURE;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFrameEndInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_FRAME_END_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrFrameEndInfo",
+ value->type, "VUID-XrFrameEndInfo-type-type", XR_TYPE_FRAME_END_INFO, "XR_TYPE_FRAME_END_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrFrameEndInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrFrameEndInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrFrameEndInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrEnvironmentBlendMode value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrFrameEndInfo", "environmentBlendMode", objects_info, value->environmentBlendMode)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrFrameEndInfo contains invalid XrEnvironmentBlendMode \"environmentBlendMode\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->environmentBlendMode));
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-environmentBlendMode-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Optional array must be non-NULL when value->layerCount is non-zero
+ if (0 != value->layerCount && nullptr == value->layers) {
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrFrameEndInfo member layerCount is NULL, but value->layerCount is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ for (uint32_t value_layers_inc = 0; value_layers_inc < value->layerCount; ++value_layers_inc) {
+ // Validate if XrCompositionLayerBaseHeader is a child structure of type XrCompositionLayerProjection and it is valid
+ const XrCompositionLayerProjection* const* new_compositionlayerprojection_value = reinterpret_cast<const XrCompositionLayerProjection* const*>(value->layers);
+ if (new_compositionlayerprojection_value[value_layers_inc]->type == XR_TYPE_COMPOSITION_LAYER_PROJECTION) {
+ if (nullptr != new_compositionlayerprojection_value) {
+ xr_result = ValidateXrStruct(instance_info, command_name,
+ objects_info, check_members, new_compositionlayerprojection_value[value_layers_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Structure XrFrameEndInfo member layers";
+ error_message += "[";
+ error_message += std::to_string(value_layers_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+ // Validate if XrCompositionLayerBaseHeader is a child structure of type XrCompositionLayerQuad and it is valid
+ const XrCompositionLayerQuad* const* new_compositionlayerquad_value = reinterpret_cast<const XrCompositionLayerQuad* const*>(value->layers);
+ if (new_compositionlayerquad_value[value_layers_inc]->type == XR_TYPE_COMPOSITION_LAYER_QUAD) {
+ if (nullptr != new_compositionlayerquad_value) {
+ xr_result = ValidateXrStruct(instance_info, command_name,
+ objects_info, check_members, new_compositionlayerquad_value[value_layers_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Structure XrFrameEndInfo member layers";
+ error_message += "[";
+ error_message += std::to_string(value_layers_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+ // Validate if XrCompositionLayerBaseHeader is a child structure of type XrCompositionLayerCubeKHR and it is valid
+ const XrCompositionLayerCubeKHR* const* new_compositionlayercubekhr_value = reinterpret_cast<const XrCompositionLayerCubeKHR* const*>(value->layers);
+ if (new_compositionlayercubekhr_value[value_layers_inc]->type == XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) {
+ if (nullptr != new_compositionlayercubekhr_value) {
+ xr_result = ValidateXrStruct(instance_info, command_name,
+ objects_info, check_members, new_compositionlayercubekhr_value[value_layers_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Structure XrFrameEndInfo member layers";
+ error_message += "[";
+ error_message += std::to_string(value_layers_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+ // Validate if XrCompositionLayerBaseHeader is a child structure of type XrCompositionLayerCylinderKHR and it is valid
+ const XrCompositionLayerCylinderKHR* const* new_compositionlayercylinderkhr_value = reinterpret_cast<const XrCompositionLayerCylinderKHR* const*>(value->layers);
+ if (new_compositionlayercylinderkhr_value[value_layers_inc]->type == XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) {
+ if (nullptr != new_compositionlayercylinderkhr_value) {
+ xr_result = ValidateXrStruct(instance_info, command_name,
+ objects_info, check_members, new_compositionlayercylinderkhr_value[value_layers_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Structure XrFrameEndInfo member layers";
+ error_message += "[";
+ error_message += std::to_string(value_layers_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+ // Validate if XrCompositionLayerBaseHeader is a child structure of type XrCompositionLayerEquirectKHR and it is valid
+ const XrCompositionLayerEquirectKHR* const* new_compositionlayerequirectkhr_value = reinterpret_cast<const XrCompositionLayerEquirectKHR* const*>(value->layers);
+ if (new_compositionlayerequirectkhr_value[value_layers_inc]->type == XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) {
+ if (nullptr != new_compositionlayerequirectkhr_value) {
+ xr_result = ValidateXrStruct(instance_info, command_name,
+ objects_info, check_members, new_compositionlayerequirectkhr_value[value_layers_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Structure XrFrameEndInfo member layers";
+ error_message += "[";
+ error_message += std::to_string(value_layers_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+ // Validate that the base-structure XrCompositionLayerBaseHeader is valid
+ if (nullptr != value->layers[value_layers_inc]) {
+ xr_result = ValidateXrStruct(instance_info, command_name,
+ objects_info, check_members, value->layers[value_layers_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrFrameEndInfo-layers-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrFrameEndInfo member layers is invalid");
+ return xr_result;
+ }
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewLocateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VIEW_LOCATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrViewLocateInfo",
+ value->type, "VUID-XrViewLocateInfo-type-type", XR_TYPE_VIEW_LOCATE_INFO, "XR_TYPE_VIEW_LOCATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrViewLocateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrViewLocateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrViewLocateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrViewLocateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrViewLocateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrViewLocateInfo", "viewConfigurationType", objects_info, value->viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrViewLocateInfo contains invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->viewConfigurationType));
+ CoreValidLogMessage(instance_info, "VUID-XrViewLocateInfo-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&value->space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(value->space);
+ CoreValidLogMessage(instance_info, "VUID-XrViewLocateInfo-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrViewState* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VIEW_STATE) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrViewState",
+ value->type, "VUID-XrViewState-type-type", XR_TYPE_VIEW_STATE, "XR_TYPE_VIEW_STATE");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrViewState-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrViewState struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrViewState : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrViewState-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrViewState struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult view_state_flags_result = ValidateXrViewStateFlags(value->viewStateFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == view_state_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrViewState invalid member XrViewStateFlags \"viewStateFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->viewStateFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrViewState-viewStateFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrFovf* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrView* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VIEW) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrView",
+ value->type, "VUID-XrView-type-type", XR_TYPE_VIEW, "XR_TYPE_VIEW");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrView-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrView struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrView : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrView-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrView struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionSetCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_SET_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionSetCreateInfo",
+ value->type, "VUID-XrActionSetCreateInfo-type-type", XR_TYPE_ACTION_SET_CREATE_INFO, "XR_TYPE_ACTION_SET_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionSetCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionSetCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionSetCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionSetCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionSetCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_ACTION_SET_NAME_SIZE < std::strlen(value->actionSetName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionSetCreateInfo-actionSetName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionSetCreateInfo member actionSetName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE < std::strlen(value->localizedActionSetName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionSetCreateInfo-localizedActionSetName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionSetCreateInfo member localizedActionSetName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionCreateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_CREATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionCreateInfo",
+ value->type, "VUID-XrActionCreateInfo-type-type", XR_TYPE_ACTION_CREATE_INFO, "XR_TYPE_ACTION_CREATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionCreateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionCreateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionCreateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionCreateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionCreateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ if (XR_MAX_ACTION_NAME_SIZE < std::strlen(value->actionName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionCreateInfo-actionName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionCreateInfo member actionName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrActionType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrActionCreateInfo", "actionType", objects_info, value->actionType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrActionCreateInfo contains invalid XrActionType \"actionType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->actionType));
+ CoreValidLogMessage(instance_info, "VUID-XrActionCreateInfo-actionType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Optional array must be non-NULL when value->countSubactionPaths is non-zero
+ if (0 != value->countSubactionPaths && nullptr == value->subactionPaths) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionCreateInfo-subactionPaths-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionCreateInfo member countSubactionPaths is NULL, but value->countSubactionPaths is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrActionCreateInfo-subactionPaths-parameter" type
+ if (XR_MAX_LOCALIZED_ACTION_NAME_SIZE < std::strlen(value->localizedActionName)) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionCreateInfo-localizedActionName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionCreateInfo member localizedActionName length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionSuggestedBinding* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionHandle(&value->action);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrAction handle \"action\" ";
+ oss << HandleToHexString(value->action);
+ CoreValidLogMessage(instance_info, "VUID-XrActionSuggestedBinding-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInteractionProfileSuggestedBinding* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrInteractionProfileSuggestedBinding",
+ value->type, "VUID-XrInteractionProfileSuggestedBinding-type-type", XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, "XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileSuggestedBinding-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrInteractionProfileSuggestedBinding struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrInteractionProfileSuggestedBinding : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileSuggestedBinding-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrInteractionProfileSuggestedBinding struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional array length must be non-zero
+ if (0 >= value->countSuggestedBindings && nullptr != value->suggestedBindings) {
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileSuggestedBinding-countSuggestedBindings-arraylength",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrInteractionProfileSuggestedBinding member countSuggestedBindings is non-optional and must be greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Pointer/array variable with a length variable. Make sure that
+ // if length variable is non-zero that the pointer is not NULL
+ if (nullptr == value->suggestedBindings && 0 != value->countSuggestedBindings) {
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileSuggestedBinding-suggestedBindings-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrInteractionProfileSuggestedBinding contains invalid NULL for XrActionSuggestedBinding \"suggestedBindings\" is which not "
+ "optional since \"countSuggestedBindings\" is set and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ for (uint32_t value_suggestedbindings_inc = 0; value_suggestedbindings_inc < value->countSuggestedBindings; ++value_suggestedbindings_inc) {
+ // Validate that the structure XrActionSuggestedBinding is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->suggestedBindings[value_suggestedbindings_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileSuggestedBinding-suggestedBindings-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrInteractionProfileSuggestedBinding member suggestedBindings is invalid");
+ return xr_result;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSessionActionSetsAttachInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSessionActionSetsAttachInfo",
+ value->type, "VUID-XrSessionActionSetsAttachInfo-type-type", XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO, "XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSessionActionSetsAttachInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSessionActionSetsAttachInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSessionActionSetsAttachInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSessionActionSetsAttachInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSessionActionSetsAttachInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional array length must be non-zero
+ if (0 >= value->countActionSets && nullptr != value->actionSets) {
+ CoreValidLogMessage(instance_info, "VUID-XrSessionActionSetsAttachInfo-countActionSets-arraylength",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrSessionActionSetsAttachInfo member countActionSets is non-optional and must be greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Pointer/array variable with a length variable. Make sure that
+ // if length variable is non-zero that the pointer is not NULL
+ if (nullptr == value->actionSets && 0 != value->countActionSets) {
+ CoreValidLogMessage(instance_info, "VUID-XrSessionActionSetsAttachInfo-actionSets-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrSessionActionSetsAttachInfo contains invalid NULL for XrActionSet \"actionSets\" is which not "
+ "optional since \"countActionSets\" is set and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ for (uint32_t value_actionsets_inc = 0; value_actionsets_inc < value->countActionSets; ++value_actionsets_inc) {
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionSetHandle(&value->actionSets[value_actionsets_inc]);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrActionSet handle \"actionSets\" ";
+ oss << HandleToHexString(value->actionSets[value_actionsets_inc]);
+ CoreValidLogMessage(instance_info, "VUID-XrSessionActionSetsAttachInfo-actionSets-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInteractionProfileState* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_INTERACTION_PROFILE_STATE) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrInteractionProfileState",
+ value->type, "VUID-XrInteractionProfileState-type-type", XR_TYPE_INTERACTION_PROFILE_STATE, "XR_TYPE_INTERACTION_PROFILE_STATE");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileState-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrInteractionProfileState struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrInteractionProfileState : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrInteractionProfileState-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrInteractionProfileState struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateGetInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_STATE_GET_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionStateGetInfo",
+ value->type, "VUID-XrActionStateGetInfo-type-type", XR_TYPE_ACTION_STATE_GET_INFO, "XR_TYPE_ACTION_STATE_GET_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateGetInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionStateGetInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionStateGetInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateGetInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionStateGetInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionHandle(&value->action);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrAction handle \"action\" ";
+ oss << HandleToHexString(value->action);
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateGetInfo-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateBoolean* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_STATE_BOOLEAN) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionStateBoolean",
+ value->type, "VUID-XrActionStateBoolean-type-type", XR_TYPE_ACTION_STATE_BOOLEAN, "XR_TYPE_ACTION_STATE_BOOLEAN");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateBoolean-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionStateBoolean struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionStateBoolean : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateBoolean-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionStateBoolean struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateFloat* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_STATE_FLOAT) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionStateFloat",
+ value->type, "VUID-XrActionStateFloat-type-type", XR_TYPE_ACTION_STATE_FLOAT, "XR_TYPE_ACTION_STATE_FLOAT");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateFloat-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionStateFloat struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionStateFloat : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateFloat-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionStateFloat struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVector2f* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStateVector2f* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_STATE_VECTOR2F) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionStateVector2f",
+ value->type, "VUID-XrActionStateVector2f-type-type", XR_TYPE_ACTION_STATE_VECTOR2F, "XR_TYPE_ACTION_STATE_VECTOR2F");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateVector2f-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionStateVector2f struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionStateVector2f : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionStateVector2f-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionStateVector2f struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionStatePose* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTION_STATE_POSE) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionStatePose",
+ value->type, "VUID-XrActionStatePose-type-type", XR_TYPE_ACTION_STATE_POSE, "XR_TYPE_ACTION_STATE_POSE");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionStatePose-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionStatePose struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionStatePose : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionStatePose-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionStatePose struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActiveActionSet* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionSetHandle(&value->actionSet);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrActionSet handle \"actionSet\" ";
+ oss << HandleToHexString(value->actionSet);
+ CoreValidLogMessage(instance_info, "VUID-XrActiveActionSet-actionSet-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrActionsSyncInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_ACTIONS_SYNC_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrActionsSyncInfo",
+ value->type, "VUID-XrActionsSyncInfo-type-type", XR_TYPE_ACTIONS_SYNC_INFO, "XR_TYPE_ACTIONS_SYNC_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionsSyncInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrActionsSyncInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrActionsSyncInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrActionsSyncInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrActionsSyncInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Optional array must be non-NULL when value->countActiveActionSets is non-zero
+ if (0 != value->countActiveActionSets && nullptr == value->activeActionSets) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionsSyncInfo-activeActionSets-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionsSyncInfo member countActiveActionSets is NULL, but value->countActiveActionSets is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ for (uint32_t value_activeactionsets_inc = 0; value_activeactionsets_inc < value->countActiveActionSets; ++value_activeactionsets_inc) {
+ // Validate that the structure XrActiveActionSet is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->activeActionSets[value_activeactionsets_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrActionsSyncInfo-activeActionSets-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrActionsSyncInfo member activeActionSets is invalid");
+ return xr_result;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrBoundSourcesForActionEnumerateInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrBoundSourcesForActionEnumerateInfo",
+ value->type, "VUID-XrBoundSourcesForActionEnumerateInfo-type-type", XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO, "XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrBoundSourcesForActionEnumerateInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrBoundSourcesForActionEnumerateInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrBoundSourcesForActionEnumerateInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrBoundSourcesForActionEnumerateInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrBoundSourcesForActionEnumerateInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionHandle(&value->action);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrAction handle \"action\" ";
+ oss << HandleToHexString(value->action);
+ CoreValidLogMessage(instance_info, "VUID-XrBoundSourcesForActionEnumerateInfo-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInputSourceLocalizedNameGetInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrInputSourceLocalizedNameGetInfo",
+ value->type, "VUID-XrInputSourceLocalizedNameGetInfo-type-type", XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO, "XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInputSourceLocalizedNameGetInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrInputSourceLocalizedNameGetInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrInputSourceLocalizedNameGetInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrInputSourceLocalizedNameGetInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrInputSourceLocalizedNameGetInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult input_source_localized_name_flags_result = ValidateXrInputSourceLocalizedNameFlags(value->whichComponents);
+ // Flags must be non-zero in this case.
+ if (VALIDATE_XR_FLAGS_ZERO == input_source_localized_name_flags_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInputSourceLocalizedNameGetInfo-whichComponents-requiredbitmask",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "XrInputSourceLocalizedNameFlags \"whichComponents\" flag must be non-zero");
+ return XR_ERROR_VALIDATION_FAILURE;
+ } else if (VALIDATE_XR_FLAGS_SUCCESS != input_source_localized_name_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrInputSourceLocalizedNameGetInfo invalid member XrInputSourceLocalizedNameFlags \"whichComponents\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->whichComponents));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrInputSourceLocalizedNameGetInfo-whichComponents-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrHapticActionInfo* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_HAPTIC_ACTION_INFO) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrHapticActionInfo",
+ value->type, "VUID-XrHapticActionInfo-type-type", XR_TYPE_HAPTIC_ACTION_INFO, "XR_TYPE_HAPTIC_ACTION_INFO");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrHapticActionInfo-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrHapticActionInfo struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrHapticActionInfo : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrHapticActionInfo-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrHapticActionInfo struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionHandle(&value->action);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrAction handle \"action\" ";
+ oss << HandleToHexString(value->action);
+ CoreValidLogMessage(instance_info, "VUID-XrHapticActionInfo-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrHapticBaseHeader* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // NOTE: Can't validate "VUID-XrHapticBaseHeader-type-parameter" because it is a base structure
+ // NOTE: Can't validate "VUID-XrHapticBaseHeader-next-next" because it is a base structure
+ if (value->type == XR_TYPE_HAPTIC_VIBRATION) {
+ const XrHapticVibration* new_value = reinterpret_cast<const XrHapticVibration*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ InvalidStructureType(instance_info, command_name, objects_info, "XrHapticBaseHeader",
+ value->type, "VUID-XrHapticBaseHeader-type-type");
+ return XR_ERROR_VALIDATION_FAILURE;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrOffset2Di* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrExtent2Di* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrRect2Di* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainSubImage* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&value->swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(value->swapchain);
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainSubImage-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerProjectionView* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerProjectionView",
+ value->type, "VUID-XrCompositionLayerProjectionView-type-type", XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW, "XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ valid_ext_structs.push_back(XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR);
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjectionView-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerProjectionView struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerProjectionView : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjectionView-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerProjectionView struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Validate that the structure XrSwapchainSubImage is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->subImage);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjectionView-subImage-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerProjectionView member subImage is invalid");
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerProjection* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_PROJECTION) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerProjection",
+ value->type, "VUID-XrCompositionLayerProjection-type-type", XR_TYPE_COMPOSITION_LAYER_PROJECTION, "XR_TYPE_COMPOSITION_LAYER_PROJECTION");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerProjection struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerProjection : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerProjection struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult composition_layer_flags_result = ValidateXrCompositionLayerFlags(value->layerFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == composition_layer_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerProjection invalid member XrCompositionLayerFlags \"layerFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->layerFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-layerFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&value->space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(value->space);
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Non-optional array length must be non-zero
+ if (0 >= value->viewCount && nullptr != value->views) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-viewCount-arraylength",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerProjection member viewCount is non-optional and must be greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Pointer/array variable with a length variable. Make sure that
+ // if length variable is non-zero that the pointer is not NULL
+ if (nullptr == value->views && 0 != value->viewCount) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-views-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrCompositionLayerProjection contains invalid NULL for XrCompositionLayerProjectionView \"views\" is which not "
+ "optional since \"viewCount\" is set and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ for (uint32_t value_views_inc = 0; value_views_inc < value->viewCount; ++value_views_inc) {
+ // Validate that the structure XrCompositionLayerProjectionView is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->views[value_views_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerProjection-views-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerProjection member views is invalid");
+ return xr_result;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerQuad* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_QUAD) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerQuad",
+ value->type, "VUID-XrCompositionLayerQuad-type-type", XR_TYPE_COMPOSITION_LAYER_QUAD, "XR_TYPE_COMPOSITION_LAYER_QUAD");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerQuad-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerQuad struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerQuad : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerQuad-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerQuad struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult composition_layer_flags_result = ValidateXrCompositionLayerFlags(value->layerFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == composition_layer_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerQuad invalid member XrCompositionLayerFlags \"layerFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->layerFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerQuad-layerFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&value->space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(value->space);
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerQuad-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrEyeVisibility value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrCompositionLayerQuad", "eyeVisibility", objects_info, value->eyeVisibility)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerQuad contains invalid XrEyeVisibility \"eyeVisibility\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->eyeVisibility));
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerQuad-eyeVisibility-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSwapchainSubImage is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->subImage);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerQuad-subImage-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerQuad member subImage is invalid");
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataBaseHeader* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // NOTE: Can't validate "VUID-XrEventDataBaseHeader-type-parameter" because it is a base structure
+ // NOTE: Can't validate "VUID-XrEventDataBaseHeader-next-next" because it is a base structure
+ if (value->type == XR_TYPE_EVENT_DATA_EVENTS_LOST) {
+ const XrEventDataEventsLost* new_value = reinterpret_cast<const XrEventDataEventsLost*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) {
+ const XrEventDataInstanceLossPending* new_value = reinterpret_cast<const XrEventDataInstanceLossPending*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
+ const XrEventDataSessionStateChanged* new_value = reinterpret_cast<const XrEventDataSessionStateChanged*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) {
+ const XrEventDataReferenceSpaceChangePending* new_value = reinterpret_cast<const XrEventDataReferenceSpaceChangePending*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) {
+ const XrEventDataInteractionProfileChanged* new_value = reinterpret_cast<const XrEventDataInteractionProfileChanged*>(value);
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) {
+ const XrEventDataVisibilityMaskChangedKHR* new_value = reinterpret_cast<const XrEventDataVisibilityMaskChangedKHR*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_KHR_visibility_mask")) {
+ std::string error_str = "XrEventDataBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR\"";
+ error_str += " which requires extension \"XR_KHR_visibility_mask\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ if (value->type == XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) {
+ const XrEventDataPerfSettingsEXT* new_value = reinterpret_cast<const XrEventDataPerfSettingsEXT*>(value);
+ if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "XR_EXT_performance_settings")) {
+ std::string error_str = "XrEventDataBaseHeader being used with child struct type ";
+ error_str += "\"XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT\"";
+ error_str += " which requires extension \"XR_EXT_performance_settings\" to be enabled, but it is not enabled";
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataBaseHeader-type-type",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, error_str);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);
+ }
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataBaseHeader",
+ value->type, "VUID-XrEventDataBaseHeader-type-type");
+ return XR_ERROR_VALIDATION_FAILURE;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataEventsLost* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_EVENTS_LOST) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataEventsLost",
+ value->type, "VUID-XrEventDataEventsLost-type-type", XR_TYPE_EVENT_DATA_EVENTS_LOST, "XR_TYPE_EVENT_DATA_EVENTS_LOST");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataEventsLost-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataEventsLost struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataEventsLost : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataEventsLost-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataEventsLost struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataInstanceLossPending* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataInstanceLossPending",
+ value->type, "VUID-XrEventDataInstanceLossPending-type-type", XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING, "XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataInstanceLossPending-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataInstanceLossPending struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataInstanceLossPending : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataInstanceLossPending-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataInstanceLossPending struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataSessionStateChanged* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataSessionStateChanged",
+ value->type, "VUID-XrEventDataSessionStateChanged-type-type", XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED, "XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataSessionStateChanged-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataSessionStateChanged struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataSessionStateChanged : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataSessionStateChanged-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataSessionStateChanged struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&value->session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(value->session);
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataSessionStateChanged-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrSessionState value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataSessionStateChanged", "state", objects_info, value->state)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataSessionStateChanged contains invalid XrSessionState \"state\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->state));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataSessionStateChanged-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataReferenceSpaceChangePending* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataReferenceSpaceChangePending",
+ value->type, "VUID-XrEventDataReferenceSpaceChangePending-type-type", XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING, "XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataReferenceSpaceChangePending-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataReferenceSpaceChangePending struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataReferenceSpaceChangePending : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataReferenceSpaceChangePending-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataReferenceSpaceChangePending struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&value->session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(value->session);
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataReferenceSpaceChangePending-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrReferenceSpaceType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataReferenceSpaceChangePending", "referenceSpaceType", objects_info, value->referenceSpaceType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataReferenceSpaceChangePending contains invalid XrReferenceSpaceType \"referenceSpaceType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->referenceSpaceType));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataReferenceSpaceChangePending-referenceSpaceType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataInteractionProfileChanged* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataInteractionProfileChanged",
+ value->type, "VUID-XrEventDataInteractionProfileChanged-type-type", XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED, "XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataInteractionProfileChanged-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataInteractionProfileChanged struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataInteractionProfileChanged : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataInteractionProfileChanged-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataInteractionProfileChanged struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&value->session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(value->session);
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataInteractionProfileChanged-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrHapticVibration* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_HAPTIC_VIBRATION) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrHapticVibration",
+ value->type, "VUID-XrHapticVibration-type-type", XR_TYPE_HAPTIC_VIBRATION, "XR_TYPE_HAPTIC_VIBRATION");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrHapticVibration-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrHapticVibration struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrHapticVibration : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrHapticVibration-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrHapticVibration struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrOffset2Df* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrRect2Df* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVector4f* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrColor4f* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerCubeKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerCubeKHR",
+ value->type, "VUID-XrCompositionLayerCubeKHR-type-type", XR_TYPE_COMPOSITION_LAYER_CUBE_KHR, "XR_TYPE_COMPOSITION_LAYER_CUBE_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCubeKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerCubeKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerCubeKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCubeKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerCubeKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult composition_layer_flags_result = ValidateXrCompositionLayerFlags(value->layerFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == composition_layer_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerCubeKHR invalid member XrCompositionLayerFlags \"layerFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->layerFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCubeKHR-layerFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&value->space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(value->space);
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCubeKHR-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrEyeVisibility value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrCompositionLayerCubeKHR", "eyeVisibility", objects_info, value->eyeVisibility)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerCubeKHR contains invalid XrEyeVisibility \"eyeVisibility\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->eyeVisibility));
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCubeKHR-eyeVisibility-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&value->swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(value->swapchain);
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCubeKHR-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrInstanceCreateInfoAndroidKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrInstanceCreateInfoAndroidKHR",
+ value->type, "VUID-XrInstanceCreateInfoAndroidKHR-type-type", XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, "XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfoAndroidKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrInstanceCreateInfoAndroidKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrInstanceCreateInfoAndroidKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfoAndroidKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrInstanceCreateInfoAndroidKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->applicationVM) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfoAndroidKHR-applicationVM-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrInstanceCreateInfoAndroidKHR contains invalid NULL for void \"applicationVM\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->applicationActivity) {
+ CoreValidLogMessage(instance_info, "VUID-XrInstanceCreateInfoAndroidKHR-applicationActivity-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrInstanceCreateInfoAndroidKHR contains invalid NULL for void \"applicationActivity\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerDepthInfoKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerDepthInfoKHR",
+ value->type, "VUID-XrCompositionLayerDepthInfoKHR-type-type", XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR, "XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerDepthInfoKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerDepthInfoKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerDepthInfoKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerDepthInfoKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerDepthInfoKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Validate that the structure XrSwapchainSubImage is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->subImage);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerDepthInfoKHR-subImage-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerDepthInfoKHR member subImage is invalid");
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVulkanSwapchainFormatListCreateInfoKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrVulkanSwapchainFormatListCreateInfoKHR",
+ value->type, "VUID-XrVulkanSwapchainFormatListCreateInfoKHR-type-type", XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR, "XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrVulkanSwapchainFormatListCreateInfoKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrVulkanSwapchainFormatListCreateInfoKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrVulkanSwapchainFormatListCreateInfoKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrVulkanSwapchainFormatListCreateInfoKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrVulkanSwapchainFormatListCreateInfoKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Optional array must be non-NULL when value->viewFormatCount is non-zero
+ if (0 != value->viewFormatCount && nullptr == value->viewFormats) {
+ CoreValidLogMessage(instance_info, "VUID-XrVulkanSwapchainFormatListCreateInfoKHR-viewFormats-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrVulkanSwapchainFormatListCreateInfoKHR member viewFormatCount is NULL, but value->viewFormatCount is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Pointer/array variable with a length variable. Make sure that
+ // if length variable is non-zero that the pointer is not NULL
+ if (nullptr == value->viewFormats && 0 != value->viewFormatCount) {
+ CoreValidLogMessage(instance_info, "VUID-XrVulkanSwapchainFormatListCreateInfoKHR-viewFormats-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrVulkanSwapchainFormatListCreateInfoKHR contains invalid NULL for VkFormat \"viewFormats\" is which not "
+ "optional since \"viewFormatCount\" is set and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrVulkanSwapchainFormatListCreateInfoKHR-viewFormats-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerCylinderKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerCylinderKHR",
+ value->type, "VUID-XrCompositionLayerCylinderKHR-type-type", XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR, "XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCylinderKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerCylinderKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerCylinderKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCylinderKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerCylinderKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult composition_layer_flags_result = ValidateXrCompositionLayerFlags(value->layerFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == composition_layer_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerCylinderKHR invalid member XrCompositionLayerFlags \"layerFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->layerFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCylinderKHR-layerFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&value->space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(value->space);
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCylinderKHR-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrEyeVisibility value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrCompositionLayerCylinderKHR", "eyeVisibility", objects_info, value->eyeVisibility)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerCylinderKHR contains invalid XrEyeVisibility \"eyeVisibility\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->eyeVisibility));
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCylinderKHR-eyeVisibility-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSwapchainSubImage is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->subImage);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerCylinderKHR-subImage-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerCylinderKHR member subImage is invalid");
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrCompositionLayerEquirectKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrCompositionLayerEquirectKHR",
+ value->type, "VUID-XrCompositionLayerEquirectKHR-type-type", XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR, "XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerEquirectKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrCompositionLayerEquirectKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrCompositionLayerEquirectKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerEquirectKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrCompositionLayerEquirectKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult composition_layer_flags_result = ValidateXrCompositionLayerFlags(value->layerFlags);
+ // Valid flags available, so it must be invalid to fail.
+ if (VALIDATE_XR_FLAGS_INVALID == composition_layer_flags_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerEquirectKHR invalid member XrCompositionLayerFlags \"layerFlags\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->layerFlags));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerEquirectKHR-layerFlags-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&value->space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(value->space);
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerEquirectKHR-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrEyeVisibility value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrCompositionLayerEquirectKHR", "eyeVisibility", objects_info, value->eyeVisibility)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrCompositionLayerEquirectKHR contains invalid XrEyeVisibility \"eyeVisibility\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->eyeVisibility));
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerEquirectKHR-eyeVisibility-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSwapchainSubImage is valid
+ xr_result = ValidateXrStruct(instance_info, command_name, objects_info,
+ check_members, &value->subImage);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrCompositionLayerEquirectKHR-subImage-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrCompositionLayerEquirectKHR member subImage is invalid");
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLWin32KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingOpenGLWin32KHR",
+ value->type, "VUID-XrGraphicsBindingOpenGLWin32KHR-type-type", XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, "XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLWin32KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingOpenGLWin32KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingOpenGLWin32KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLWin32KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingOpenGLWin32KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLXlibKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingOpenGLXlibKHR",
+ value->type, "VUID-XrGraphicsBindingOpenGLXlibKHR-type-type", XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, "XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLXlibKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingOpenGLXlibKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingOpenGLXlibKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLXlibKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingOpenGLXlibKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->xDisplay) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLXlibKHR-xDisplay-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrGraphicsBindingOpenGLXlibKHR contains invalid NULL for Display \"xDisplay\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrGraphicsBindingOpenGLXlibKHR-xDisplay-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLXcbKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingOpenGLXcbKHR",
+ value->type, "VUID-XrGraphicsBindingOpenGLXcbKHR-type-type", XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR, "XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLXcbKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingOpenGLXcbKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingOpenGLXcbKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLXcbKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingOpenGLXcbKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLWaylandKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingOpenGLWaylandKHR",
+ value->type, "VUID-XrGraphicsBindingOpenGLWaylandKHR-type-type", XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR, "XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLWaylandKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingOpenGLWaylandKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingOpenGLWaylandKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLWaylandKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingOpenGLWaylandKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageOpenGLKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageOpenGLKHR",
+ value->type, "VUID-XrSwapchainImageOpenGLKHR-type-type", XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR, "XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageOpenGLKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageOpenGLKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageOpenGLKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageOpenGLKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageOpenGLKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsOpenGLKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsRequirementsOpenGLKHR",
+ value->type, "VUID-XrGraphicsRequirementsOpenGLKHR-type-type", XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR, "XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsOpenGLKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsRequirementsOpenGLKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsRequirementsOpenGLKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsOpenGLKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsRequirementsOpenGLKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingOpenGLESAndroidKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingOpenGLESAndroidKHR",
+ value->type, "VUID-XrGraphicsBindingOpenGLESAndroidKHR-type-type", XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, "XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLESAndroidKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingOpenGLESAndroidKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingOpenGLESAndroidKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingOpenGLESAndroidKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingOpenGLESAndroidKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageOpenGLESKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageOpenGLESKHR",
+ value->type, "VUID-XrSwapchainImageOpenGLESKHR-type-type", XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR, "XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageOpenGLESKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageOpenGLESKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageOpenGLESKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageOpenGLESKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageOpenGLESKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsOpenGLESKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsRequirementsOpenGLESKHR",
+ value->type, "VUID-XrGraphicsRequirementsOpenGLESKHR-type-type", XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, "XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsOpenGLESKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsRequirementsOpenGLESKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsRequirementsOpenGLESKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsOpenGLESKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsRequirementsOpenGLESKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingVulkanKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingVulkanKHR",
+ value->type, "VUID-XrGraphicsBindingVulkanKHR-type-type", XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, "XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingVulkanKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingVulkanKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingVulkanKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingVulkanKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingVulkanKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageVulkanKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageVulkanKHR",
+ value->type, "VUID-XrSwapchainImageVulkanKHR-type-type", XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR, "XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageVulkanKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageVulkanKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageVulkanKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageVulkanKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageVulkanKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsVulkanKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsRequirementsVulkanKHR",
+ value->type, "VUID-XrGraphicsRequirementsVulkanKHR-type-type", XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, "XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsVulkanKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsRequirementsVulkanKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsRequirementsVulkanKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsVulkanKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsRequirementsVulkanKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingD3D11KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingD3D11KHR",
+ value->type, "VUID-XrGraphicsBindingD3D11KHR-type-type", XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, "XR_TYPE_GRAPHICS_BINDING_D3D11_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D11KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingD3D11KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingD3D11KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D11KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingD3D11KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->device) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D11KHR-device-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrGraphicsBindingD3D11KHR contains invalid NULL for ID3D11Device \"device\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrGraphicsBindingD3D11KHR-device-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageD3D11KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageD3D11KHR",
+ value->type, "VUID-XrSwapchainImageD3D11KHR-type-type", XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR, "XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageD3D11KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageD3D11KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageD3D11KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageD3D11KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageD3D11KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->texture) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageD3D11KHR-texture-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrSwapchainImageD3D11KHR contains invalid NULL for ID3D11Texture2D \"texture\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrSwapchainImageD3D11KHR-texture-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsD3D11KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsRequirementsD3D11KHR",
+ value->type, "VUID-XrGraphicsRequirementsD3D11KHR-type-type", XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR, "XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsD3D11KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsRequirementsD3D11KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsRequirementsD3D11KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsD3D11KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsRequirementsD3D11KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsBindingD3D12KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsBindingD3D12KHR",
+ value->type, "VUID-XrGraphicsBindingD3D12KHR-type-type", XR_TYPE_GRAPHICS_BINDING_D3D12_KHR, "XR_TYPE_GRAPHICS_BINDING_D3D12_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D12KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsBindingD3D12KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsBindingD3D12KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D12KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsBindingD3D12KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->device) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D12KHR-device-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrGraphicsBindingD3D12KHR contains invalid NULL for ID3D12Device \"device\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrGraphicsBindingD3D12KHR-device-parameter" type
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->queue) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsBindingD3D12KHR-queue-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrGraphicsBindingD3D12KHR contains invalid NULL for ID3D12CommandQueue \"queue\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrGraphicsBindingD3D12KHR-queue-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrSwapchainImageD3D12KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrSwapchainImageD3D12KHR",
+ value->type, "VUID-XrSwapchainImageD3D12KHR-type-type", XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR, "XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageD3D12KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrSwapchainImageD3D12KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrSwapchainImageD3D12KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageD3D12KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrSwapchainImageD3D12KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->texture) {
+ CoreValidLogMessage(instance_info, "VUID-XrSwapchainImageD3D12KHR-texture-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrSwapchainImageD3D12KHR contains invalid NULL for ID3D12Resource \"texture\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrSwapchainImageD3D12KHR-texture-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrGraphicsRequirementsD3D12KHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrGraphicsRequirementsD3D12KHR",
+ value->type, "VUID-XrGraphicsRequirementsD3D12KHR-type-type", XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR, "XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsD3D12KHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrGraphicsRequirementsD3D12KHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrGraphicsRequirementsD3D12KHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrGraphicsRequirementsD3D12KHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrGraphicsRequirementsD3D12KHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrVisibilityMaskKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_VISIBILITY_MASK_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrVisibilityMaskKHR",
+ value->type, "VUID-XrVisibilityMaskKHR-type-type", XR_TYPE_VISIBILITY_MASK_KHR, "XR_TYPE_VISIBILITY_MASK_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrVisibilityMaskKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrVisibilityMaskKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrVisibilityMaskKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrVisibilityMaskKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrVisibilityMaskKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // NOTE: Can't validate "VUID-XrVisibilityMaskKHR-vertices-parameter" type
+ // Optional array must be non-NULL when value->indexCapacityInput is non-zero
+ if (0 != value->indexCapacityInput && nullptr == value->indices) {
+ CoreValidLogMessage(instance_info, "VUID-XrVisibilityMaskKHR-indices-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrVisibilityMaskKHR member indexCapacityInput is NULL, but value->indexCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrVisibilityMaskKHR-indices-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataVisibilityMaskChangedKHR* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataVisibilityMaskChangedKHR",
+ value->type, "VUID-XrEventDataVisibilityMaskChangedKHR-type-type", XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, "XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataVisibilityMaskChangedKHR-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataVisibilityMaskChangedKHR struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataVisibilityMaskChangedKHR : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataVisibilityMaskChangedKHR-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataVisibilityMaskChangedKHR struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&value->session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(value->session);
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataVisibilityMaskChangedKHR-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataVisibilityMaskChangedKHR", "viewConfigurationType", objects_info, value->viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataVisibilityMaskChangedKHR contains invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->viewConfigurationType));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataVisibilityMaskChangedKHR-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrEventDataPerfSettingsEXT* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrEventDataPerfSettingsEXT",
+ value->type, "VUID-XrEventDataPerfSettingsEXT-type-type", XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT, "XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataPerfSettingsEXT-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrEventDataPerfSettingsEXT struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrEventDataPerfSettingsEXT : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataPerfSettingsEXT-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrEventDataPerfSettingsEXT struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrPerfSettingsDomainEXT value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataPerfSettingsEXT", "domain", objects_info, value->domain)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataPerfSettingsEXT contains invalid XrPerfSettingsDomainEXT \"domain\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->domain));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataPerfSettingsEXT-domain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrPerfSettingsSubDomainEXT value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataPerfSettingsEXT", "subDomain", objects_info, value->subDomain)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataPerfSettingsEXT contains invalid XrPerfSettingsSubDomainEXT \"subDomain\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->subDomain));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataPerfSettingsEXT-subDomain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrPerfSettingsNotificationLevelEXT value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataPerfSettingsEXT", "fromLevel", objects_info, value->fromLevel)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataPerfSettingsEXT contains invalid XrPerfSettingsNotificationLevelEXT \"fromLevel\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->fromLevel));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataPerfSettingsEXT-fromLevel-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrPerfSettingsNotificationLevelEXT value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrEventDataPerfSettingsEXT", "toLevel", objects_info, value->toLevel)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrEventDataPerfSettingsEXT contains invalid XrPerfSettingsNotificationLevelEXT \"toLevel\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->toLevel));
+ CoreValidLogMessage(instance_info, "VUID-XrEventDataPerfSettingsEXT-toLevel-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsObjectNameInfoEXT* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrDebugUtilsObjectNameInfoEXT",
+ value->type, "VUID-XrDebugUtilsObjectNameInfoEXT-type-type", XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, "XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsObjectNameInfoEXT-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrDebugUtilsObjectNameInfoEXT struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrDebugUtilsObjectNameInfoEXT : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsObjectNameInfoEXT-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrDebugUtilsObjectNameInfoEXT struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Make sure the enum type XrObjectType value is valid
+ if (!ValidateXrEnum(instance_info, command_name, "XrDebugUtilsObjectNameInfoEXT", "objectType", objects_info, value->objectType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "XrDebugUtilsObjectNameInfoEXT contains invalid XrObjectType \"objectType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->objectType));
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsObjectNameInfoEXT-objectType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrDebugUtilsObjectNameInfoEXT-objectName-parameter" null-termination
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsLabelEXT* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_DEBUG_UTILS_LABEL_EXT) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrDebugUtilsLabelEXT",
+ value->type, "VUID-XrDebugUtilsLabelEXT-type-type", XR_TYPE_DEBUG_UTILS_LABEL_EXT, "XR_TYPE_DEBUG_UTILS_LABEL_EXT");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsLabelEXT-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrDebugUtilsLabelEXT struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrDebugUtilsLabelEXT : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsLabelEXT-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrDebugUtilsLabelEXT struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->labelName) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsLabelEXT-labelName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrDebugUtilsLabelEXT contains invalid NULL for char \"labelName\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrDebugUtilsLabelEXT-labelName-parameter" null-termination
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsMessengerCallbackDataEXT* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrDebugUtilsMessengerCallbackDataEXT",
+ value->type, "VUID-XrDebugUtilsMessengerCallbackDataEXT-type-type", XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, "XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCallbackDataEXT-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrDebugUtilsMessengerCallbackDataEXT struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrDebugUtilsMessengerCallbackDataEXT : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCallbackDataEXT-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrDebugUtilsMessengerCallbackDataEXT struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->messageId) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCallbackDataEXT-messageId-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrDebugUtilsMessengerCallbackDataEXT contains invalid NULL for char \"messageId\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrDebugUtilsMessengerCallbackDataEXT-messageId-parameter" null-termination
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->functionName) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCallbackDataEXT-functionName-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrDebugUtilsMessengerCallbackDataEXT contains invalid NULL for char \"functionName\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrDebugUtilsMessengerCallbackDataEXT-functionName-parameter" null-termination
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->message) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCallbackDataEXT-message-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrDebugUtilsMessengerCallbackDataEXT contains invalid NULL for char \"message\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrDebugUtilsMessengerCallbackDataEXT-message-parameter" null-termination
+ // Optional array must be non-NULL when value->sessionLabelCount is non-zero
+ if (0 != value->sessionLabelCount && nullptr == value->sessionLabels) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCallbackDataEXT-sessionLabels-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Structure XrDebugUtilsMessengerCallbackDataEXT member sessionLabelCount is NULL, but value->sessionLabelCount is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Everything checked out properly
+ return xr_result;
+}
+
+XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,
+ const XrDebugUtilsMessengerCreateInfoEXT* value) {
+ XrResult xr_result = XR_SUCCESS;
+ // Make sure the structure type is correct
+ if (value->type != XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ InvalidStructureType(instance_info, command_name, objects_info, "XrDebugUtilsMessengerCreateInfoEXT",
+ value->type, "VUID-XrDebugUtilsMessengerCreateInfoEXT-type-type", XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, "XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ std::vector<XrStructureType> valid_ext_structs;
+ std::vector<XrStructureType> duplicate_ext_structs;
+ std::vector<XrStructureType> encountered_structs;
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,
+ value->next, valid_ext_structs,
+ encountered_structs,
+ duplicate_ext_structs);
+ // No valid extension structs for this 'next'. Therefore, must be NULL
+ // or only contain a list of valid extension structures.
+ if (NEXT_CHAIN_RESULT_ERROR == next_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-next-next",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "Invalid structure(s) in \"next\" chain for XrDebugUtilsMessengerCreateInfoEXT struct \"next\"");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ } else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {
+ char struct_type_buffer[XR_MAX_STRUCTURE_NAME_SIZE];
+ std::string error_message = "Multiple structures of the same type(s) in \"next\" chain for ";
+ error_message += "XrDebugUtilsMessengerCreateInfoEXT : ";
+ if (nullptr != instance_info) {
+ bool wrote_struct = false;
+ for (uint32_t dup = 0; dup < duplicate_ext_structs.size(); ++dup) {
+ if (XR_SUCCESS == instance_info->dispatch_table->StructureTypeToString(instance_info->instance,
+ duplicate_ext_structs[dup],
+ struct_type_buffer)) {
+ if (wrote_struct) {
+ error_message += ", ";
+ } else {
+ wrote_struct = true;
+ }
+ error_message += struct_type_buffer;
+ }
+ }
+ }
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-next-unique",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info,
+ "Multiple structures of the same type(s) in \"next\" chain for XrDebugUtilsMessengerCreateInfoEXT struct");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If we are not to check the rest of the members, just return here.
+ if (!check_members || XR_SUCCESS != xr_result) {
+ return xr_result;
+ }
+ ValidateXrFlagsResult debug_utils_message_severity_flags_ext_result = ValidateXrDebugUtilsMessageSeverityFlagsEXT(value->messageSeverities);
+ // Flags must be non-zero in this case.
+ if (VALIDATE_XR_FLAGS_ZERO == debug_utils_message_severity_flags_ext_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-messageSeverities-requiredbitmask",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "XrDebugUtilsMessageSeverityFlagsEXT \"messageSeverities\" flag must be non-zero");
+ return XR_ERROR_VALIDATION_FAILURE;
+ } else if (VALIDATE_XR_FLAGS_SUCCESS != debug_utils_message_severity_flags_ext_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrDebugUtilsMessengerCreateInfoEXT invalid member XrDebugUtilsMessageSeverityFlagsEXT \"messageSeverities\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->messageSeverities));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-messageSeverities-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ ValidateXrFlagsResult debug_utils_message_type_flags_ext_result = ValidateXrDebugUtilsMessageTypeFlagsEXT(value->messageTypes);
+ // Flags must be non-zero in this case.
+ if (VALIDATE_XR_FLAGS_ZERO == debug_utils_message_type_flags_ext_result) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-messageTypes-requiredbitmask",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, "XrDebugUtilsMessageTypeFlagsEXT \"messageTypes\" flag must be non-zero");
+ return XR_ERROR_VALIDATION_FAILURE;
+ } else if (VALIDATE_XR_FLAGS_SUCCESS != debug_utils_message_type_flags_ext_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "XrDebugUtilsMessengerCreateInfoEXT invalid member XrDebugUtilsMessageTypeFlagsEXT \"messageTypes\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value->messageTypes));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-messageTypes-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == value->userCallback) {
+ CoreValidLogMessage(instance_info, "VUID-XrDebugUtilsMessengerCreateInfoEXT-userCallback-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name, objects_info,
+ "XrDebugUtilsMessengerCreateInfoEXT contains invalid NULL for PFN_xrDebugUtilsMessengerCallbackEXT \"userCallback\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-XrDebugUtilsMessengerCreateInfoEXT-userCallback-parameter" type
+ // Everything checked out properly
+ return xr_result;
+}
+
+
+NextChainResult ValidateNextChain(GenValidUsageXrInstanceInfo *instance_info,
+ const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo>& objects_info,
+ const void* next,
+ std::vector<XrStructureType>& valid_ext_structs,
+ std::vector<XrStructureType>& encountered_structs,
+ std::vector<XrStructureType>& duplicate_structs) {
+ NextChainResult return_result = NEXT_CHAIN_RESULT_VALID;
+ // NULL is valid
+ if (nullptr == next) {
+ return return_result;
+ }
+ // Non-NULL is not valid if there is no valid extension structs
+ if (nullptr != next && 0 == valid_ext_structs.size()) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ const XrBaseInStructure* next_header = reinterpret_cast<const XrBaseInStructure*>(next);
+ auto valid_ext = std::find(valid_ext_structs.begin(), valid_ext_structs.end(), next_header->type);
+ if (valid_ext == valid_ext_structs.end()) {
+ // Not a valid extension structure type for this next chain.
+ return NEXT_CHAIN_RESULT_ERROR;
+ } else {
+ // Check to see if we've already encountered this structure.
+ auto already_encountered_ext = std::find(encountered_structs.begin(), encountered_structs.end(), next_header->type);
+ if (already_encountered_ext != encountered_structs.end()) {
+ // Make sure we only put in unique types into our duplicate list.
+ auto already_duplicate = std::find(duplicate_structs.begin(), duplicate_structs.end(), next_header->type);
+ if (already_duplicate == duplicate_structs.end()) {
+ duplicate_structs.push_back(next_header->type);
+ }
+ return_result = NEXT_CHAIN_RESULT_DUPLICATE_STRUCT;
+ }
+ }
+ switch (next_header->type) {
+ case XR_TYPE_API_LAYER_PROPERTIES:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrApiLayerProperties*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EXTENSION_PROPERTIES:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrExtensionProperties*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_INSTANCE_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrInstanceCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SYSTEM_GET_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSystemGetInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SYSTEM_PROPERTIES:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSystemProperties*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_VIEW_LOCATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrViewLocateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_VIEW:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrView*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SESSION_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSessionCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SWAPCHAIN_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SESSION_BEGIN_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSessionBeginInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_VIEW_STATE:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrViewState*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_FRAME_END_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrFrameEndInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_HAPTIC_VIBRATION:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrHapticVibration*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_BUFFER:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataBuffer*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataInstanceLossPending*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataSessionStateChanged*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_STATE_BOOLEAN:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionStateBoolean*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_STATE_FLOAT:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionStateFloat*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_STATE_VECTOR2F:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionStateVector2f*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_STATE_POSE:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionStatePose*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_SET_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionSetCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_INSTANCE_PROPERTIES:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrInstanceProperties*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_FRAME_WAIT_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrFrameWaitInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerProjection*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_QUAD:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerQuad*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_REFERENCE_SPACE_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrReferenceSpaceCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_SPACE_CREATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionSpaceCreateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataReferenceSpaceChangePending*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_VIEW_CONFIGURATION_VIEW:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrViewConfigurationView*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SPACE_LOCATION:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSpaceLocation*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SPACE_VELOCITY:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSpaceVelocity*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_FRAME_STATE:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrFrameState*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_VIEW_CONFIGURATION_PROPERTIES:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrViewConfigurationProperties*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_FRAME_BEGIN_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrFrameBeginInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerProjectionView*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_EVENTS_LOST:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataEventsLost*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrInteractionProfileSuggestedBinding*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataInteractionProfileChanged*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_INTERACTION_PROFILE_STATE:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrInteractionProfileState*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageAcquireInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageWaitInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageReleaseInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTION_STATE_GET_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionStateGetInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_HAPTIC_ACTION_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrHapticActionInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSessionActionSetsAttachInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_ACTIONS_SYNC_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrActionsSyncInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrBoundSourcesForActionEnumerateInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrInputSourceLocalizedNameGetInfo*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_CUBE_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerCubeKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#if defined(XR_USE_PLATFORM_ANDROID)
+ case XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrInstanceCreateInfoAndroidKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+ case XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerDepthInfoKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ case XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrVulkanSwapchainFormatListCreateInfoKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+ case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataPerfSettingsEXT*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerCylinderKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrCompositionLayerEquirectKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrDebugUtilsObjectNameInfoEXT*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrDebugUtilsMessengerCallbackDataEXT*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_DEBUG_UTILS_LABEL_EXT:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrDebugUtilsLabelEXT*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingOpenGLWin32KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingOpenGLXlibKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingOpenGLXcbKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingOpenGLWaylandKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageOpenGLKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsRequirementsOpenGLKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingOpenGLESAndroidKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageOpenGLESKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsRequirementsOpenGLESKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ case XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingVulkanKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ case XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageVulkanKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsRequirementsVulkanKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ case XR_TYPE_GRAPHICS_BINDING_D3D11_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingD3D11KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ case XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageD3D11KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsRequirementsD3D11KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ case XR_TYPE_GRAPHICS_BINDING_D3D12_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsBindingD3D12KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ case XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrSwapchainImageD3D12KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrGraphicsRequirementsD3D12KHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+ case XR_TYPE_VISIBILITY_MASK_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrVisibilityMaskKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR:
+ if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,
+ reinterpret_cast<const XrEventDataVisibilityMaskChangedKHR*>(next))) {
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ break;
+ default:
+ return NEXT_CHAIN_RESULT_ERROR;
+ }
+ NextChainResult next_result = ValidateNextChain(instance_info, command_name,
+ objects_info, next_header->next,
+ valid_ext_structs,
+ encountered_structs,
+ duplicate_structs);
+ if (NEXT_CHAIN_RESULT_VALID == next_result && NEXT_CHAIN_RESULT_VALID != return_result) {
+ return return_result;
+ } else {
+ return next_result;
+ }
+}
+
+
+// ---- Core 1.0 commands
+XrResult GenValidUsageInputsXrCreateInstance(
+const XrInstanceCreateInfo* createInfo,
+XrInstance* instance) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(nullptr, "VUID-xrCreateInstance-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateInstance", objects_info,
+ "Invalid NULL for XrInstanceCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrInstanceCreateInfo is valid
+ xr_result = ValidateXrStruct(nullptr, "xrCreateInstance", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(nullptr, "VUID-xrCreateInstance-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateInstance",
+ objects_info,
+ "Command xrCreateInstance param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == instance) {
+ CoreValidLogMessage(nullptr, "VUID-xrCreateInstance-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateInstance", objects_info,
+ "Invalid NULL for XrInstance \"instance\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageInputsXrDestroyInstance(
+XrInstance instance) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroyInstance-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroyInstance",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroyInstance(
+ XrInstance instance) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->DestroyInstance(instance);
+ if (XR_SUCCEEDED(result)) {
+ g_instance_info.erase(instance);
+ }
+ GenValidUsageCleanUpMaps(gen_instance_info);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrGetInstanceProperties(
+XrInstance instance,
+XrInstanceProperties* instanceProperties) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetInstanceProperties-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProperties",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == instanceProperties) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetInstanceProperties-instanceProperties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProperties", objects_info,
+ "Invalid NULL for XrInstanceProperties \"instanceProperties\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrInstanceProperties is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetInstanceProperties", objects_info,
+ false, instanceProperties);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetInstanceProperties-instanceProperties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProperties",
+ objects_info,
+ "Command xrGetInstanceProperties param instanceProperties is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetInstanceProperties(instance, instanceProperties);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties) {
+ XrResult test_result = GenValidUsageInputsXrGetInstanceProperties(instance, instanceProperties);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetInstanceProperties(instance, instanceProperties);
+}
+
+XrResult GenValidUsageInputsXrPollEvent(
+XrInstance instance,
+XrEventDataBuffer* eventData) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrPollEvent-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPollEvent",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == eventData) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrPollEvent-eventData-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPollEvent", objects_info,
+ "Invalid NULL for XrEventDataBuffer \"eventData\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrEventDataBuffer is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrPollEvent", objects_info,
+ false, eventData);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrPollEvent-eventData-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPollEvent",
+ objects_info,
+ "Command xrPollEvent param eventData is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->PollEvent(instance, eventData);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData) {
+ XrResult test_result = GenValidUsageInputsXrPollEvent(instance, eventData);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrPollEvent(instance, eventData);
+}
+
+XrResult GenValidUsageInputsXrResultToString(
+XrInstance instance,
+XrResult value,
+char buffer[XR_MAX_RESULT_STRING_SIZE]) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrResultToString-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrResultToString",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Make sure the enum type XrResult value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrResultToString", "xrResultToString", "value", objects_info, value)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrResult \"value\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrResultToString-value-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrResultToString",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (XR_MAX_RESULT_STRING_SIZE < std::strlen(buffer)) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrResultToString-buffer-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrResultToString",
+ objects_info,
+ "Command xrResultToString param buffer length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->ResultToString(instance, value, buffer);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]) {
+ XrResult test_result = GenValidUsageInputsXrResultToString(instance, value, buffer);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrResultToString(instance, value, buffer);
+}
+
+XrResult GenValidUsageInputsXrStructureTypeToString(
+XrInstance instance,
+XrStructureType value,
+char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrStructureTypeToString-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStructureTypeToString",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Make sure the enum type XrStructureType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrStructureTypeToString", "xrStructureTypeToString", "value", objects_info, value)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrStructureType \"value\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(value));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrStructureTypeToString-value-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStructureTypeToString",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (XR_MAX_STRUCTURE_NAME_SIZE < std::strlen(buffer)) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrStructureTypeToString-buffer-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStructureTypeToString",
+ objects_info,
+ "Command xrStructureTypeToString param buffer length is too long.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->StructureTypeToString(instance, value, buffer);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) {
+ XrResult test_result = GenValidUsageInputsXrStructureTypeToString(instance, value, buffer);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrStructureTypeToString(instance, value, buffer);
+}
+
+XrResult GenValidUsageInputsXrGetSystem(
+XrInstance instance,
+const XrSystemGetInfo* getInfo,
+XrSystemId* systemId) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetSystem-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystem",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == getInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetSystem-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystem", objects_info,
+ "Invalid NULL for XrSystemGetInfo \"getInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSystemGetInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetSystem", objects_info,
+ true, getInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetSystem-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystem",
+ objects_info,
+ "Command xrGetSystem param getInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == systemId) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetSystem-systemId-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystem", objects_info,
+ "Invalid NULL for XrSystemId \"systemId\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrGetSystem-systemId-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetSystem(instance, getInfo, systemId);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId) {
+ XrResult test_result = GenValidUsageInputsXrGetSystem(instance, getInfo, systemId);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetSystem(instance, getInfo, systemId);
+}
+
+XrResult GenValidUsageInputsXrGetSystemProperties(
+XrInstance instance,
+XrSystemId systemId,
+XrSystemProperties* properties) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetSystemProperties-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystemProperties",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == properties) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetSystemProperties-properties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystemProperties", objects_info,
+ "Invalid NULL for XrSystemProperties \"properties\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSystemProperties is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetSystemProperties", objects_info,
+ false, properties);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetSystemProperties-properties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetSystemProperties",
+ objects_info,
+ "Command xrGetSystemProperties param properties is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetSystemProperties(instance, systemId, properties);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties) {
+ XrResult test_result = GenValidUsageInputsXrGetSystemProperties(instance, systemId, properties);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetSystemProperties(instance, systemId, properties);
+}
+
+XrResult GenValidUsageInputsXrEnumerateEnvironmentBlendModes(
+XrInstance instance,
+XrSystemId systemId,
+XrViewConfigurationType viewConfigurationType,
+uint32_t environmentBlendModeCapacityInput,
+uint32_t* environmentBlendModeCountOutput,
+XrEnvironmentBlendMode* environmentBlendModes) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateEnvironmentBlendModes-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateEnvironmentBlendModes",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrEnumerateEnvironmentBlendModes", "xrEnumerateEnvironmentBlendModes", "viewConfigurationType", objects_info, viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(viewConfigurationType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateEnvironmentBlendModes-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateEnvironmentBlendModes",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Optional array must be non-NULL when environmentBlendModeCapacityInput is non-zero
+ if (0 != environmentBlendModeCapacityInput && nullptr == environmentBlendModes) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateEnvironmentBlendModes-environmentBlendModes-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateEnvironmentBlendModes",
+ objects_info,
+ "Command xrEnumerateEnvironmentBlendModes param environmentBlendModes is NULL, but environmentBlendModeCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == environmentBlendModeCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateEnvironmentBlendModes-environmentBlendModeCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateEnvironmentBlendModes", objects_info,
+ "Invalid NULL for uint32_t \"environmentBlendModeCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateEnvironmentBlendModes-environmentBlendModeCountOutput-parameter" type
+ for (uint32_t value_environmentblendmodes_inc = 0; value_environmentblendmodes_inc < environmentBlendModeCapacityInput; ++value_environmentblendmodes_inc) {
+ // Make sure the enum type XrEnvironmentBlendMode value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrEnumerateEnvironmentBlendModes", "xrEnumerateEnvironmentBlendModes", "environmentBlendModes", objects_info, environmentBlendModes[value_environmentblendmodes_inc])) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrEnvironmentBlendMode \"environmentBlendModes\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(environmentBlendModes[value_environmentblendmodes_inc]));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateEnvironmentBlendModes-environmentBlendModes-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateEnvironmentBlendModes",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->EnumerateEnvironmentBlendModes(instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateEnvironmentBlendModes(instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateEnvironmentBlendModes(instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+}
+
+XrResult GenValidUsageInputsXrCreateSession(
+XrInstance instance,
+const XrSessionCreateInfo* createInfo,
+XrSession* session) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateSession-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSession",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSession-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSession", objects_info,
+ "Invalid NULL for XrSessionCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSessionCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateSession", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSession-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSession",
+ objects_info,
+ "Command xrCreateSession param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == session) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSession-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSession", objects_info,
+ "Invalid NULL for XrSession \"session\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->CreateSession(instance, createInfo, session);
+ if (XR_SUCCESS == result && nullptr != session) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_INSTANCE;
+ handle_info->direct_parent_handle = MakeHandleGeneric(instance);
+ g_session_info.insert(*session, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrDestroySession(
+XrSession session) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroySession-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroySession",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroySession(
+ XrSession session) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->DestroySession(session);
+
+ // Clean up any labels associated with this session
+ CoreValidationDeleteSessionLabels(session);
+
+ if (XR_SUCCEEDED(result)) {
+ g_session_info.erase(session);
+ }
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrDestroySession(
+ XrSession session) {
+ XrResult test_result = GenValidUsageInputsXrDestroySession(session);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrDestroySession(session);
+}
+
+XrResult GenValidUsageInputsXrEnumerateReferenceSpaces(
+XrSession session,
+uint32_t spaceCapacityInput,
+uint32_t* spaceCountOutput,
+XrReferenceSpaceType* spaces) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateReferenceSpaces-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateReferenceSpaces",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Optional array must be non-NULL when spaceCapacityInput is non-zero
+ if (0 != spaceCapacityInput && nullptr == spaces) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateReferenceSpaces-spaces-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateReferenceSpaces",
+ objects_info,
+ "Command xrEnumerateReferenceSpaces param spaces is NULL, but spaceCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == spaceCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateReferenceSpaces-spaceCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateReferenceSpaces", objects_info,
+ "Invalid NULL for uint32_t \"spaceCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateReferenceSpaces-spaceCountOutput-parameter" type
+ for (uint32_t value_spaces_inc = 0; value_spaces_inc < spaceCapacityInput; ++value_spaces_inc) {
+ // Make sure the enum type XrReferenceSpaceType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrEnumerateReferenceSpaces", "xrEnumerateReferenceSpaces", "spaces", objects_info, spaces[value_spaces_inc])) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrReferenceSpaceType \"spaces\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(spaces[value_spaces_inc]));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateReferenceSpaces-spaces-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateReferenceSpaces",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->EnumerateReferenceSpaces(session, spaceCapacityInput, spaceCountOutput, spaces);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateReferenceSpaces(session, spaceCapacityInput, spaceCountOutput, spaces);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateReferenceSpaces(session, spaceCapacityInput, spaceCountOutput, spaces);
+}
+
+XrResult GenValidUsageInputsXrCreateReferenceSpace(
+XrSession session,
+const XrReferenceSpaceCreateInfo* createInfo,
+XrSpace* space) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateReferenceSpace-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateReferenceSpace",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateReferenceSpace-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateReferenceSpace", objects_info,
+ "Invalid NULL for XrReferenceSpaceCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrReferenceSpaceCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateReferenceSpace", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateReferenceSpace-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateReferenceSpace",
+ objects_info,
+ "Command xrCreateReferenceSpace param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == space) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateReferenceSpace-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateReferenceSpace", objects_info,
+ "Invalid NULL for XrSpace \"space\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->CreateReferenceSpace(session, createInfo, space);
+ if (XR_SUCCESS == result && nullptr != space) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_SESSION;
+ handle_info->direct_parent_handle = MakeHandleGeneric(session);
+ g_space_info.insert(*space, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space) {
+ XrResult test_result = GenValidUsageInputsXrCreateReferenceSpace(session, createInfo, space);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrCreateReferenceSpace(session, createInfo, space);
+}
+
+XrResult GenValidUsageInputsXrGetReferenceSpaceBoundsRect(
+XrSession session,
+XrReferenceSpaceType referenceSpaceType,
+XrExtent2Df* bounds) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetReferenceSpaceBoundsRect-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetReferenceSpaceBoundsRect",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Make sure the enum type XrReferenceSpaceType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrGetReferenceSpaceBoundsRect", "xrGetReferenceSpaceBoundsRect", "referenceSpaceType", objects_info, referenceSpaceType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrReferenceSpaceType \"referenceSpaceType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(referenceSpaceType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetReferenceSpaceBoundsRect-referenceSpaceType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetReferenceSpaceBoundsRect",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == bounds) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetReferenceSpaceBoundsRect-bounds-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetReferenceSpaceBoundsRect", objects_info,
+ "Invalid NULL for XrExtent2Df \"bounds\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrGetReferenceSpaceBoundsRect-bounds-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetReferenceSpaceBoundsRect(session, referenceSpaceType, bounds);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds) {
+ XrResult test_result = GenValidUsageInputsXrGetReferenceSpaceBoundsRect(session, referenceSpaceType, bounds);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetReferenceSpaceBoundsRect(session, referenceSpaceType, bounds);
+}
+
+XrResult GenValidUsageInputsXrCreateActionSpace(
+XrSession session,
+const XrActionSpaceCreateInfo* createInfo,
+XrSpace* space) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateActionSpace-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSpace",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateActionSpace-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSpace", objects_info,
+ "Invalid NULL for XrActionSpaceCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionSpaceCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateActionSpace", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateActionSpace-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSpace",
+ objects_info,
+ "Command xrCreateActionSpace param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == space) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateActionSpace-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSpace", objects_info,
+ "Invalid NULL for XrSpace \"space\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->CreateActionSpace(session, createInfo, space);
+ if (XR_SUCCESS == result && nullptr != space) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_SESSION;
+ handle_info->direct_parent_handle = MakeHandleGeneric(session);
+ g_space_info.insert(*space, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space) {
+ XrResult test_result = GenValidUsageInputsXrCreateActionSpace(session, createInfo, space);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrCreateActionSpace(session, createInfo, space);
+}
+
+XrResult GenValidUsageInputsXrLocateSpace(
+XrSpace space,
+XrSpace baseSpace,
+XrTime time,
+XrSpaceLocation* location) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(space, XR_OBJECT_TYPE_SPACE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(space);
+ CoreValidLogMessage(nullptr, "VUID-xrLocateSpace-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateSpace",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_space_info.getWithInstanceInfo(space);
+ GenValidUsageXrHandleInfo *gen_space_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ objects_info.emplace_back(baseSpace, XR_OBJECT_TYPE_SPACE);
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&baseSpace);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"baseSpace\" ";
+ oss << HandleToHexString(baseSpace);
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateSpace-baseSpace-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateSpace",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ // Verify that the handles share a common ancestry
+ if (!VerifyXrParent(XR_OBJECT_TYPE_SPACE, MakeHandleGeneric(space),
+ XR_OBJECT_TYPE_SPACE, MakeHandleGeneric(baseSpace), false)) {
+ std::ostringstream oss_error;
+ oss_error << "XrSpace " << HandleToHexString(space);
+ oss_error << " and XrSpace ";
+ oss_error << HandleToHexString(baseSpace);
+ oss_error << " must share a parent";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateSpace-commonparent",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateSpace",
+ objects_info, oss_error.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == location) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateSpace-location-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateSpace", objects_info,
+ "Invalid NULL for XrSpaceLocation \"location\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSpaceLocation is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrLocateSpace", objects_info,
+ false, location);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateSpace-location-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateSpace",
+ objects_info,
+ "Command xrLocateSpace param location is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_space_info.getWithInstanceInfo(space);
+ GenValidUsageXrHandleInfo *gen_space_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->LocateSpace(space, baseSpace, time, location);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location) {
+ XrResult test_result = GenValidUsageInputsXrLocateSpace(space, baseSpace, time, location);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrLocateSpace(space, baseSpace, time, location);
+}
+
+XrResult GenValidUsageInputsXrDestroySpace(
+XrSpace space) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(space, XR_OBJECT_TYPE_SPACE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSpaceHandle(&space);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSpace handle \"space\" ";
+ oss << HandleToHexString(space);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroySpace-space-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroySpace",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_space_info.getWithInstanceInfo(space);
+ GenValidUsageXrHandleInfo *gen_space_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroySpace(
+ XrSpace space) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_space_info.getWithInstanceInfo(space);
+ GenValidUsageXrHandleInfo *gen_space_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->DestroySpace(space);
+ if (XR_SUCCEEDED(result)) {
+ g_space_info.erase(space);
+ }
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrDestroySpace(
+ XrSpace space) {
+ XrResult test_result = GenValidUsageInputsXrDestroySpace(space);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrDestroySpace(space);
+}
+
+XrResult GenValidUsageInputsXrEnumerateViewConfigurations(
+XrInstance instance,
+XrSystemId systemId,
+uint32_t viewConfigurationTypeCapacityInput,
+uint32_t* viewConfigurationTypeCountOutput,
+XrViewConfigurationType* viewConfigurationTypes) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateViewConfigurations-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurations",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Optional array must be non-NULL when viewConfigurationTypeCapacityInput is non-zero
+ if (0 != viewConfigurationTypeCapacityInput && nullptr == viewConfigurationTypes) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurations-viewConfigurationTypes-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurations",
+ objects_info,
+ "Command xrEnumerateViewConfigurations param viewConfigurationTypes is NULL, but viewConfigurationTypeCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == viewConfigurationTypeCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurations-viewConfigurationTypeCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurations", objects_info,
+ "Invalid NULL for uint32_t \"viewConfigurationTypeCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateViewConfigurations-viewConfigurationTypeCountOutput-parameter" type
+ for (uint32_t value_viewconfigurationtypes_inc = 0; value_viewconfigurationtypes_inc < viewConfigurationTypeCapacityInput; ++value_viewconfigurationtypes_inc) {
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrEnumerateViewConfigurations", "xrEnumerateViewConfigurations", "viewConfigurationTypes", objects_info, viewConfigurationTypes[value_viewconfigurationtypes_inc])) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrViewConfigurationType \"viewConfigurationTypes\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(viewConfigurationTypes[value_viewconfigurationtypes_inc]));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurations-viewConfigurationTypes-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurations",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->EnumerateViewConfigurations(instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateViewConfigurations(instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateViewConfigurations(instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+}
+
+XrResult GenValidUsageInputsXrGetViewConfigurationProperties(
+XrInstance instance,
+XrSystemId systemId,
+XrViewConfigurationType viewConfigurationType,
+XrViewConfigurationProperties* configurationProperties) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetViewConfigurationProperties-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetViewConfigurationProperties",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrGetViewConfigurationProperties", "xrGetViewConfigurationProperties", "viewConfigurationType", objects_info, viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(viewConfigurationType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetViewConfigurationProperties-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetViewConfigurationProperties",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == configurationProperties) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetViewConfigurationProperties-configurationProperties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetViewConfigurationProperties", objects_info,
+ "Invalid NULL for XrViewConfigurationProperties \"configurationProperties\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrViewConfigurationProperties is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetViewConfigurationProperties", objects_info,
+ false, configurationProperties);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetViewConfigurationProperties-configurationProperties-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetViewConfigurationProperties",
+ objects_info,
+ "Command xrGetViewConfigurationProperties param configurationProperties is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetViewConfigurationProperties(instance, systemId, viewConfigurationType, configurationProperties);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties) {
+ XrResult test_result = GenValidUsageInputsXrGetViewConfigurationProperties(instance, systemId, viewConfigurationType, configurationProperties);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetViewConfigurationProperties(instance, systemId, viewConfigurationType, configurationProperties);
+}
+
+XrResult GenValidUsageInputsXrEnumerateViewConfigurationViews(
+XrInstance instance,
+XrSystemId systemId,
+XrViewConfigurationType viewConfigurationType,
+uint32_t viewCapacityInput,
+uint32_t* viewCountOutput,
+XrViewConfigurationView* views) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateViewConfigurationViews-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurationViews",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrEnumerateViewConfigurationViews", "xrEnumerateViewConfigurationViews", "viewConfigurationType", objects_info, viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(viewConfigurationType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurationViews-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurationViews",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Optional array must be non-NULL when viewCapacityInput is non-zero
+ if (0 != viewCapacityInput && nullptr == views) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurationViews-views-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurationViews",
+ objects_info,
+ "Command xrEnumerateViewConfigurationViews param views is NULL, but viewCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == viewCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurationViews-viewCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurationViews", objects_info,
+ "Invalid NULL for uint32_t \"viewCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateViewConfigurationViews-viewCountOutput-parameter" type
+ for (uint32_t value_views_inc = 0; value_views_inc < viewCapacityInput; ++value_views_inc) {
+ // Validate that the structure XrViewConfigurationView is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateViewConfigurationViews", objects_info,
+ true, &views[value_views_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateViewConfigurationViews-views-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateViewConfigurationViews",
+ objects_info,
+ "Command xrEnumerateViewConfigurationViews param views is invalid");
+ return xr_result;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->EnumerateViewConfigurationViews(instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateViewConfigurationViews(instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateViewConfigurationViews(instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+}
+
+XrResult GenValidUsageInputsXrEnumerateSwapchainFormats(
+XrSession session,
+uint32_t formatCapacityInput,
+uint32_t* formatCountOutput,
+int64_t* formats) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateSwapchainFormats-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainFormats",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Optional array must be non-NULL when formatCapacityInput is non-zero
+ if (0 != formatCapacityInput && nullptr == formats) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainFormats-formats-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainFormats",
+ objects_info,
+ "Command xrEnumerateSwapchainFormats param formats is NULL, but formatCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == formatCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainFormats-formatCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainFormats", objects_info,
+ "Invalid NULL for uint32_t \"formatCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateSwapchainFormats-formatCountOutput-parameter" type
+ // NOTE: Can't validate "VUID-xrEnumerateSwapchainFormats-formats-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->EnumerateSwapchainFormats(session, formatCapacityInput, formatCountOutput, formats);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateSwapchainFormats(session, formatCapacityInput, formatCountOutput, formats);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateSwapchainFormats(session, formatCapacityInput, formatCountOutput, formats);
+}
+
+XrResult GenValidUsageInputsXrCreateSwapchain(
+XrSession session,
+const XrSwapchainCreateInfo* createInfo,
+XrSwapchain* swapchain) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateSwapchain-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchain",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchain-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchain", objects_info,
+ "Invalid NULL for XrSwapchainCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSwapchainCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateSwapchain", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchain-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchain",
+ objects_info,
+ "Command xrCreateSwapchain param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == swapchain) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchain-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchain", objects_info,
+ "Invalid NULL for XrSwapchain \"swapchain\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->CreateSwapchain(session, createInfo, swapchain);
+ if (XR_SUCCESS == result && nullptr != swapchain) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_SESSION;
+ handle_info->direct_parent_handle = MakeHandleGeneric(session);
+ g_swapchain_info.insert(*swapchain, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain) {
+ XrResult test_result = GenValidUsageInputsXrCreateSwapchain(session, createInfo, swapchain);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrCreateSwapchain(session, createInfo, swapchain);
+}
+
+XrResult GenValidUsageInputsXrDestroySwapchain(
+XrSwapchain swapchain) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(swapchain, XR_OBJECT_TYPE_SWAPCHAIN);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(swapchain);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroySwapchain-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroySwapchain",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroySwapchain(
+ XrSwapchain swapchain) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->DestroySwapchain(swapchain);
+ if (XR_SUCCEEDED(result)) {
+ g_swapchain_info.erase(swapchain);
+ }
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrDestroySwapchain(
+ XrSwapchain swapchain) {
+ XrResult test_result = GenValidUsageInputsXrDestroySwapchain(swapchain);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrDestroySwapchain(swapchain);
+}
+
+XrResult GenValidUsageInputsXrEnumerateSwapchainImages(
+XrSwapchain swapchain,
+uint32_t imageCapacityInput,
+uint32_t* imageCountOutput,
+XrSwapchainImageBaseHeader* images) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(swapchain, XR_OBJECT_TYPE_SWAPCHAIN);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(swapchain);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateSwapchainImages-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Optional array must be non-NULL when imageCapacityInput is non-zero
+ if (0 != imageCapacityInput && nullptr == images) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ "Command xrEnumerateSwapchainImages param images is NULL, but imageCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == imageCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-imageCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages", objects_info,
+ "Invalid NULL for uint32_t \"imageCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateSwapchainImages-imageCountOutput-parameter" type
+ for (uint32_t value_images_inc = 0; value_images_inc < imageCapacityInput; ++value_images_inc) {
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ // Validate if XrSwapchainImageBaseHeader is a child structure of type XrSwapchainImageOpenGLKHR and it is valid
+ XrSwapchainImageOpenGLKHR* new_swapchainimageopenglkhr_value = reinterpret_cast<XrSwapchainImageOpenGLKHR*>(images);
+ if (new_swapchainimageopenglkhr_value[value_images_inc].type == XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) {
+ if (nullptr != new_swapchainimageopenglkhr_value) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateSwapchainImages",
+ objects_info, false, &new_swapchainimageopenglkhr_value[value_images_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Command xrEnumerateSwapchainImages param images";
+ error_message += "[";
+ error_message += std::to_string(value_images_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ // Validate if XrSwapchainImageBaseHeader is a child structure of type XrSwapchainImageOpenGLESKHR and it is valid
+ XrSwapchainImageOpenGLESKHR* new_swapchainimageopengleskhr_value = reinterpret_cast<XrSwapchainImageOpenGLESKHR*>(images);
+ if (new_swapchainimageopengleskhr_value[value_images_inc].type == XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) {
+ if (nullptr != new_swapchainimageopengleskhr_value) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateSwapchainImages",
+ objects_info, false, &new_swapchainimageopengleskhr_value[value_images_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Command xrEnumerateSwapchainImages param images";
+ error_message += "[";
+ error_message += std::to_string(value_images_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ // Validate if XrSwapchainImageBaseHeader is a child structure of type XrSwapchainImageVulkanKHR and it is valid
+ XrSwapchainImageVulkanKHR* new_swapchainimagevulkankhr_value = reinterpret_cast<XrSwapchainImageVulkanKHR*>(images);
+ if (new_swapchainimagevulkankhr_value[value_images_inc].type == XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) {
+ if (nullptr != new_swapchainimagevulkankhr_value) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateSwapchainImages",
+ objects_info, false, &new_swapchainimagevulkankhr_value[value_images_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Command xrEnumerateSwapchainImages param images";
+ error_message += "[";
+ error_message += std::to_string(value_images_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ // Validate if XrSwapchainImageBaseHeader is a child structure of type XrSwapchainImageD3D11KHR and it is valid
+ XrSwapchainImageD3D11KHR* new_swapchainimaged3d11khr_value = reinterpret_cast<XrSwapchainImageD3D11KHR*>(images);
+ if (new_swapchainimaged3d11khr_value[value_images_inc].type == XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) {
+ if (nullptr != new_swapchainimaged3d11khr_value) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateSwapchainImages",
+ objects_info, false, &new_swapchainimaged3d11khr_value[value_images_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Command xrEnumerateSwapchainImages param images";
+ error_message += "[";
+ error_message += std::to_string(value_images_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ // Validate if XrSwapchainImageBaseHeader is a child structure of type XrSwapchainImageD3D12KHR and it is valid
+ XrSwapchainImageD3D12KHR* new_swapchainimaged3d12khr_value = reinterpret_cast<XrSwapchainImageD3D12KHR*>(images);
+ if (new_swapchainimaged3d12khr_value[value_images_inc].type == XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) {
+ if (nullptr != new_swapchainimaged3d12khr_value) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateSwapchainImages",
+ objects_info, false, &new_swapchainimaged3d12khr_value[value_images_inc]);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Command xrEnumerateSwapchainImages param images";
+ error_message += "[";
+ error_message += std::to_string(value_images_inc);
+ error_message += "]";
+ error_message += " is invalid";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ break;
+ } else {
+ continue;
+ }
+ }
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+ // Validate that the base-structure XrSwapchainImageBaseHeader is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateSwapchainImages", objects_info,
+ true, &images[value_images_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateSwapchainImages-images-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateSwapchainImages",
+ objects_info,
+ "Command xrEnumerateSwapchainImages param images is invalid");
+ return xr_result;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->EnumerateSwapchainImages(swapchain, imageCapacityInput, imageCountOutput, images);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateSwapchainImages(swapchain, imageCapacityInput, imageCountOutput, images);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateSwapchainImages(swapchain, imageCapacityInput, imageCountOutput, images);
+}
+
+XrResult GenValidUsageInputsXrAcquireSwapchainImage(
+XrSwapchain swapchain,
+const XrSwapchainImageAcquireInfo* acquireInfo,
+uint32_t* index) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(swapchain, XR_OBJECT_TYPE_SWAPCHAIN);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(swapchain);
+ CoreValidLogMessage(nullptr, "VUID-xrAcquireSwapchainImage-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrAcquireSwapchainImage",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Validate that the structure XrSwapchainImageAcquireInfo is valid
+ if (nullptr != acquireInfo) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrAcquireSwapchainImage",
+ objects_info, false, acquireInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrAcquireSwapchainImage-acquireInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrAcquireSwapchainImage",
+ objects_info,
+ "Command xrAcquireSwapchainImage param acquireInfo is invalid");
+ return xr_result;
+ }
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == index) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrAcquireSwapchainImage-index-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrAcquireSwapchainImage", objects_info,
+ "Invalid NULL for uint32_t \"index\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrAcquireSwapchainImage-index-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->AcquireSwapchainImage(swapchain, acquireInfo, index);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index) {
+ XrResult test_result = GenValidUsageInputsXrAcquireSwapchainImage(swapchain, acquireInfo, index);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrAcquireSwapchainImage(swapchain, acquireInfo, index);
+}
+
+XrResult GenValidUsageInputsXrWaitSwapchainImage(
+XrSwapchain swapchain,
+const XrSwapchainImageWaitInfo* waitInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(swapchain, XR_OBJECT_TYPE_SWAPCHAIN);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(swapchain);
+ CoreValidLogMessage(nullptr, "VUID-xrWaitSwapchainImage-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitSwapchainImage",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == waitInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrWaitSwapchainImage-waitInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitSwapchainImage", objects_info,
+ "Invalid NULL for XrSwapchainImageWaitInfo \"waitInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSwapchainImageWaitInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrWaitSwapchainImage", objects_info,
+ true, waitInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrWaitSwapchainImage-waitInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitSwapchainImage",
+ objects_info,
+ "Command xrWaitSwapchainImage param waitInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->WaitSwapchainImage(swapchain, waitInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo) {
+ XrResult test_result = GenValidUsageInputsXrWaitSwapchainImage(swapchain, waitInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrWaitSwapchainImage(swapchain, waitInfo);
+}
+
+XrResult GenValidUsageInputsXrReleaseSwapchainImage(
+XrSwapchain swapchain,
+const XrSwapchainImageReleaseInfo* releaseInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(swapchain, XR_OBJECT_TYPE_SWAPCHAIN);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSwapchainHandle(&swapchain);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSwapchain handle \"swapchain\" ";
+ oss << HandleToHexString(swapchain);
+ CoreValidLogMessage(nullptr, "VUID-xrReleaseSwapchainImage-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrReleaseSwapchainImage",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Validate that the structure XrSwapchainImageReleaseInfo is valid
+ if (nullptr != releaseInfo) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrReleaseSwapchainImage",
+ objects_info, false, releaseInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrReleaseSwapchainImage-releaseInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrReleaseSwapchainImage",
+ objects_info,
+ "Command xrReleaseSwapchainImage param releaseInfo is invalid");
+ return xr_result;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_swapchain_info.getWithInstanceInfo(swapchain);
+ GenValidUsageXrHandleInfo *gen_swapchain_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->ReleaseSwapchainImage(swapchain, releaseInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo) {
+ XrResult test_result = GenValidUsageInputsXrReleaseSwapchainImage(swapchain, releaseInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrReleaseSwapchainImage(swapchain, releaseInfo);
+}
+
+XrResult GenValidUsageInputsXrBeginSession(
+XrSession session,
+const XrSessionBeginInfo* beginInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrBeginSession-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrBeginSession",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == beginInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrBeginSession-beginInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrBeginSession", objects_info,
+ "Invalid NULL for XrSessionBeginInfo \"beginInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSessionBeginInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrBeginSession", objects_info,
+ true, beginInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrBeginSession-beginInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrBeginSession",
+ objects_info,
+ "Command xrBeginSession param beginInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->BeginSession(session, beginInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo) {
+ XrResult test_result = GenValidUsageInputsXrBeginSession(session, beginInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrBeginSession(session, beginInfo);
+}
+
+XrResult GenValidUsageInputsXrEndSession(
+XrSession session) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrEndSession-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEndSession",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEndSession(
+ XrSession session) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->EndSession(session);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEndSession(
+ XrSession session) {
+ XrResult test_result = GenValidUsageInputsXrEndSession(session);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEndSession(session);
+}
+
+XrResult GenValidUsageInputsXrRequestExitSession(
+XrSession session) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrRequestExitSession-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrRequestExitSession",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrRequestExitSession(
+ XrSession session) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->RequestExitSession(session);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrRequestExitSession(
+ XrSession session) {
+ XrResult test_result = GenValidUsageInputsXrRequestExitSession(session);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrRequestExitSession(session);
+}
+
+XrResult GenValidUsageInputsXrWaitFrame(
+XrSession session,
+const XrFrameWaitInfo* frameWaitInfo,
+XrFrameState* frameState) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrWaitFrame-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitFrame",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Validate that the structure XrFrameWaitInfo is valid
+ if (nullptr != frameWaitInfo) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrWaitFrame",
+ objects_info, false, frameWaitInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrWaitFrame-frameWaitInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitFrame",
+ objects_info,
+ "Command xrWaitFrame param frameWaitInfo is invalid");
+ return xr_result;
+ }
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == frameState) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrWaitFrame-frameState-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitFrame", objects_info,
+ "Invalid NULL for XrFrameState \"frameState\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrFrameState is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrWaitFrame", objects_info,
+ false, frameState);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrWaitFrame-frameState-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrWaitFrame",
+ objects_info,
+ "Command xrWaitFrame param frameState is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->WaitFrame(session, frameWaitInfo, frameState);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState) {
+ XrResult test_result = GenValidUsageInputsXrWaitFrame(session, frameWaitInfo, frameState);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrWaitFrame(session, frameWaitInfo, frameState);
+}
+
+XrResult GenValidUsageInputsXrBeginFrame(
+XrSession session,
+const XrFrameBeginInfo* frameBeginInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrBeginFrame-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrBeginFrame",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Validate that the structure XrFrameBeginInfo is valid
+ if (nullptr != frameBeginInfo) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrBeginFrame",
+ objects_info, false, frameBeginInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrBeginFrame-frameBeginInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrBeginFrame",
+ objects_info,
+ "Command xrBeginFrame param frameBeginInfo is invalid");
+ return xr_result;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->BeginFrame(session, frameBeginInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo) {
+ XrResult test_result = GenValidUsageInputsXrBeginFrame(session, frameBeginInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrBeginFrame(session, frameBeginInfo);
+}
+
+XrResult GenValidUsageInputsXrEndFrame(
+XrSession session,
+const XrFrameEndInfo* frameEndInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrEndFrame-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEndFrame",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == frameEndInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEndFrame-frameEndInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEndFrame", objects_info,
+ "Invalid NULL for XrFrameEndInfo \"frameEndInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrFrameEndInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEndFrame", objects_info,
+ true, frameEndInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEndFrame-frameEndInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEndFrame",
+ objects_info,
+ "Command xrEndFrame param frameEndInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->EndFrame(session, frameEndInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo) {
+ XrResult test_result = GenValidUsageInputsXrEndFrame(session, frameEndInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEndFrame(session, frameEndInfo);
+}
+
+XrResult GenValidUsageInputsXrLocateViews(
+XrSession session,
+const XrViewLocateInfo* viewLocateInfo,
+XrViewState* viewState,
+uint32_t viewCapacityInput,
+uint32_t* viewCountOutput,
+XrView* views) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrLocateViews-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == viewLocateInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-viewLocateInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews", objects_info,
+ "Invalid NULL for XrViewLocateInfo \"viewLocateInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrViewLocateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrLocateViews", objects_info,
+ true, viewLocateInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-viewLocateInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews",
+ objects_info,
+ "Command xrLocateViews param viewLocateInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == viewState) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-viewState-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews", objects_info,
+ "Invalid NULL for XrViewState \"viewState\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrViewState is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrLocateViews", objects_info,
+ false, viewState);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-viewState-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews",
+ objects_info,
+ "Command xrLocateViews param viewState is invalid");
+ return xr_result;
+ }
+ // Optional array must be non-NULL when viewCapacityInput is non-zero
+ if (0 != viewCapacityInput && nullptr == views) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-views-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews",
+ objects_info,
+ "Command xrLocateViews param views is NULL, but viewCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == viewCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-viewCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews", objects_info,
+ "Invalid NULL for uint32_t \"viewCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrLocateViews-viewCountOutput-parameter" type
+ for (uint32_t value_views_inc = 0; value_views_inc < viewCapacityInput; ++value_views_inc) {
+ // Validate that the structure XrView is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrLocateViews", objects_info,
+ true, &views[value_views_inc]);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrLocateViews-views-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrLocateViews",
+ objects_info,
+ "Command xrLocateViews param views is invalid");
+ return xr_result;
+ }
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->LocateViews(session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views) {
+ XrResult test_result = GenValidUsageInputsXrLocateViews(session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrLocateViews(session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+}
+
+XrResult GenValidUsageInputsXrStringToPath(
+XrInstance instance,
+const char* pathString,
+XrPath* path) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrStringToPath-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStringToPath",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == pathString) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrStringToPath-pathString-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStringToPath", objects_info,
+ "Invalid NULL for char \"pathString\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrStringToPath-pathString-parameter" null-termination
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == path) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrStringToPath-path-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStringToPath", objects_info,
+ "Invalid NULL for XrPath \"path\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrStringToPath-path-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->StringToPath(instance, pathString, path);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path) {
+ XrResult test_result = GenValidUsageInputsXrStringToPath(instance, pathString, path);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrStringToPath(instance, pathString, path);
+}
+
+XrResult GenValidUsageInputsXrPathToString(
+XrInstance instance,
+XrPath path,
+uint32_t bufferCapacityInput,
+uint32_t* bufferCountOutput,
+char* buffer) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrPathToString-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPathToString",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Optional array must be non-NULL when bufferCapacityInput is non-zero
+ if (0 != bufferCapacityInput && nullptr == buffer) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrPathToString-buffer-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPathToString",
+ objects_info,
+ "Command xrPathToString param buffer is NULL, but bufferCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == bufferCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrPathToString-bufferCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPathToString", objects_info,
+ "Invalid NULL for uint32_t \"bufferCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrPathToString-bufferCountOutput-parameter" type
+ // NOTE: Can't validate "VUID-xrPathToString-buffer-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->PathToString(instance, path, bufferCapacityInput, bufferCountOutput, buffer);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult test_result = GenValidUsageInputsXrPathToString(instance, path, bufferCapacityInput, bufferCountOutput, buffer);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrPathToString(instance, path, bufferCapacityInput, bufferCountOutput, buffer);
+}
+
+XrResult GenValidUsageInputsXrCreateActionSet(
+XrInstance instance,
+const XrActionSetCreateInfo* createInfo,
+XrActionSet* actionSet) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateActionSet-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSet",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateActionSet-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSet", objects_info,
+ "Invalid NULL for XrActionSetCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionSetCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateActionSet", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateActionSet-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSet",
+ objects_info,
+ "Command xrCreateActionSet param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == actionSet) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateActionSet-actionSet-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateActionSet", objects_info,
+ "Invalid NULL for XrActionSet \"actionSet\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->CreateActionSet(instance, createInfo, actionSet);
+ if (XR_SUCCESS == result && nullptr != actionSet) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_INSTANCE;
+ handle_info->direct_parent_handle = MakeHandleGeneric(instance);
+ g_actionset_info.insert(*actionSet, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet) {
+ XrResult test_result = GenValidUsageInputsXrCreateActionSet(instance, createInfo, actionSet);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrCreateActionSet(instance, createInfo, actionSet);
+}
+
+XrResult GenValidUsageInputsXrDestroyActionSet(
+XrActionSet actionSet) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(actionSet, XR_OBJECT_TYPE_ACTION_SET);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionSetHandle(&actionSet);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrActionSet handle \"actionSet\" ";
+ oss << HandleToHexString(actionSet);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroyActionSet-actionSet-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroyActionSet",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_actionset_info.getWithInstanceInfo(actionSet);
+ GenValidUsageXrHandleInfo *gen_actionset_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroyActionSet(
+ XrActionSet actionSet) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_actionset_info.getWithInstanceInfo(actionSet);
+ GenValidUsageXrHandleInfo *gen_actionset_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->DestroyActionSet(actionSet);
+ if (XR_SUCCEEDED(result)) {
+ g_actionset_info.erase(actionSet);
+ }
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrDestroyActionSet(
+ XrActionSet actionSet) {
+ XrResult test_result = GenValidUsageInputsXrDestroyActionSet(actionSet);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrDestroyActionSet(actionSet);
+}
+
+XrResult GenValidUsageInputsXrCreateAction(
+XrActionSet actionSet,
+const XrActionCreateInfo* createInfo,
+XrAction* action) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(actionSet, XR_OBJECT_TYPE_ACTION_SET);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionSetHandle(&actionSet);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrActionSet handle \"actionSet\" ";
+ oss << HandleToHexString(actionSet);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateAction-actionSet-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateAction",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_actionset_info.getWithInstanceInfo(actionSet);
+ GenValidUsageXrHandleInfo *gen_actionset_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateAction-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateAction", objects_info,
+ "Invalid NULL for XrActionCreateInfo \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateAction", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateAction-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateAction",
+ objects_info,
+ "Command xrCreateAction param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == action) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateAction-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateAction", objects_info,
+ "Invalid NULL for XrAction \"action\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_actionset_info.getWithInstanceInfo(actionSet);
+ GenValidUsageXrHandleInfo *gen_actionset_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->CreateAction(actionSet, createInfo, action);
+ if (XR_SUCCESS == result && nullptr != action) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_ACTION_SET;
+ handle_info->direct_parent_handle = MakeHandleGeneric(actionSet);
+ g_action_info.insert(*action, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action) {
+ XrResult test_result = GenValidUsageInputsXrCreateAction(actionSet, createInfo, action);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrCreateAction(actionSet, createInfo, action);
+}
+
+XrResult GenValidUsageInputsXrDestroyAction(
+XrAction action) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(action, XR_OBJECT_TYPE_ACTION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrActionHandle(&action);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrAction handle \"action\" ";
+ oss << HandleToHexString(action);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroyAction-action-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroyAction",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_action_info.getWithInstanceInfo(action);
+ GenValidUsageXrHandleInfo *gen_action_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroyAction(
+ XrAction action) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_action_info.getWithInstanceInfo(action);
+ GenValidUsageXrHandleInfo *gen_action_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->DestroyAction(action);
+ if (XR_SUCCEEDED(result)) {
+ g_action_info.erase(action);
+ }
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrDestroyAction(
+ XrAction action) {
+ XrResult test_result = GenValidUsageInputsXrDestroyAction(action);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrDestroyAction(action);
+}
+
+XrResult GenValidUsageInputsXrSuggestInteractionProfileBindings(
+XrInstance instance,
+const XrInteractionProfileSuggestedBinding* suggestedBindings) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrSuggestInteractionProfileBindings-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSuggestInteractionProfileBindings",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == suggestedBindings) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSuggestInteractionProfileBindings-suggestedBindings-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSuggestInteractionProfileBindings", objects_info,
+ "Invalid NULL for XrInteractionProfileSuggestedBinding \"suggestedBindings\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrInteractionProfileSuggestedBinding is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrSuggestInteractionProfileBindings", objects_info,
+ true, suggestedBindings);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSuggestInteractionProfileBindings-suggestedBindings-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSuggestInteractionProfileBindings",
+ objects_info,
+ "Command xrSuggestInteractionProfileBindings param suggestedBindings is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->SuggestInteractionProfileBindings(instance, suggestedBindings);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings) {
+ XrResult test_result = GenValidUsageInputsXrSuggestInteractionProfileBindings(instance, suggestedBindings);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrSuggestInteractionProfileBindings(instance, suggestedBindings);
+}
+
+XrResult GenValidUsageInputsXrAttachSessionActionSets(
+XrSession session,
+const XrSessionActionSetsAttachInfo* attachInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrAttachSessionActionSets-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrAttachSessionActionSets",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == attachInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrAttachSessionActionSets-attachInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrAttachSessionActionSets", objects_info,
+ "Invalid NULL for XrSessionActionSetsAttachInfo \"attachInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSessionActionSetsAttachInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrAttachSessionActionSets", objects_info,
+ true, attachInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrAttachSessionActionSets-attachInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrAttachSessionActionSets",
+ objects_info,
+ "Command xrAttachSessionActionSets param attachInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->AttachSessionActionSets(session, attachInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo) {
+ XrResult test_result = GenValidUsageInputsXrAttachSessionActionSets(session, attachInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrAttachSessionActionSets(session, attachInfo);
+}
+
+XrResult GenValidUsageInputsXrGetCurrentInteractionProfile(
+XrSession session,
+XrPath topLevelUserPath,
+XrInteractionProfileState* interactionProfile) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetCurrentInteractionProfile-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetCurrentInteractionProfile",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == interactionProfile) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetCurrentInteractionProfile-interactionProfile-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetCurrentInteractionProfile", objects_info,
+ "Invalid NULL for XrInteractionProfileState \"interactionProfile\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrInteractionProfileState is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetCurrentInteractionProfile", objects_info,
+ false, interactionProfile);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetCurrentInteractionProfile-interactionProfile-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetCurrentInteractionProfile",
+ objects_info,
+ "Command xrGetCurrentInteractionProfile param interactionProfile is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetCurrentInteractionProfile(session, topLevelUserPath, interactionProfile);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile) {
+ XrResult test_result = GenValidUsageInputsXrGetCurrentInteractionProfile(session, topLevelUserPath, interactionProfile);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetCurrentInteractionProfile(session, topLevelUserPath, interactionProfile);
+}
+
+XrResult GenValidUsageInputsXrGetActionStateBoolean(
+XrSession session,
+const XrActionStateGetInfo* getInfo,
+XrActionStateBoolean* state) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetActionStateBoolean-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateBoolean",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == getInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateBoolean-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateBoolean", objects_info,
+ "Invalid NULL for XrActionStateGetInfo \"getInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateGetInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStateBoolean", objects_info,
+ true, getInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateBoolean-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateBoolean",
+ objects_info,
+ "Command xrGetActionStateBoolean param getInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == state) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateBoolean-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateBoolean", objects_info,
+ "Invalid NULL for XrActionStateBoolean \"state\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateBoolean is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStateBoolean", objects_info,
+ false, state);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateBoolean-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateBoolean",
+ objects_info,
+ "Command xrGetActionStateBoolean param state is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetActionStateBoolean(session, getInfo, state);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state) {
+ XrResult test_result = GenValidUsageInputsXrGetActionStateBoolean(session, getInfo, state);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetActionStateBoolean(session, getInfo, state);
+}
+
+XrResult GenValidUsageInputsXrGetActionStateFloat(
+XrSession session,
+const XrActionStateGetInfo* getInfo,
+XrActionStateFloat* state) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetActionStateFloat-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateFloat",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == getInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateFloat-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateFloat", objects_info,
+ "Invalid NULL for XrActionStateGetInfo \"getInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateGetInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStateFloat", objects_info,
+ true, getInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateFloat-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateFloat",
+ objects_info,
+ "Command xrGetActionStateFloat param getInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == state) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateFloat-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateFloat", objects_info,
+ "Invalid NULL for XrActionStateFloat \"state\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateFloat is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStateFloat", objects_info,
+ false, state);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateFloat-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateFloat",
+ objects_info,
+ "Command xrGetActionStateFloat param state is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetActionStateFloat(session, getInfo, state);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state) {
+ XrResult test_result = GenValidUsageInputsXrGetActionStateFloat(session, getInfo, state);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetActionStateFloat(session, getInfo, state);
+}
+
+XrResult GenValidUsageInputsXrGetActionStateVector2f(
+XrSession session,
+const XrActionStateGetInfo* getInfo,
+XrActionStateVector2f* state) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetActionStateVector2f-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateVector2f",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == getInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateVector2f-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateVector2f", objects_info,
+ "Invalid NULL for XrActionStateGetInfo \"getInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateGetInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStateVector2f", objects_info,
+ true, getInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateVector2f-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateVector2f",
+ objects_info,
+ "Command xrGetActionStateVector2f param getInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == state) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateVector2f-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateVector2f", objects_info,
+ "Invalid NULL for XrActionStateVector2f \"state\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateVector2f is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStateVector2f", objects_info,
+ false, state);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStateVector2f-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStateVector2f",
+ objects_info,
+ "Command xrGetActionStateVector2f param state is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetActionStateVector2f(session, getInfo, state);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state) {
+ XrResult test_result = GenValidUsageInputsXrGetActionStateVector2f(session, getInfo, state);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetActionStateVector2f(session, getInfo, state);
+}
+
+XrResult GenValidUsageInputsXrGetActionStatePose(
+XrSession session,
+const XrActionStateGetInfo* getInfo,
+XrActionStatePose* state) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetActionStatePose-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStatePose",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == getInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStatePose-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStatePose", objects_info,
+ "Invalid NULL for XrActionStateGetInfo \"getInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStateGetInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStatePose", objects_info,
+ true, getInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStatePose-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStatePose",
+ objects_info,
+ "Command xrGetActionStatePose param getInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == state) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStatePose-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStatePose", objects_info,
+ "Invalid NULL for XrActionStatePose \"state\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionStatePose is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetActionStatePose", objects_info,
+ false, state);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetActionStatePose-state-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetActionStatePose",
+ objects_info,
+ "Command xrGetActionStatePose param state is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetActionStatePose(session, getInfo, state);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state) {
+ XrResult test_result = GenValidUsageInputsXrGetActionStatePose(session, getInfo, state);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetActionStatePose(session, getInfo, state);
+}
+
+XrResult GenValidUsageInputsXrSyncActions(
+XrSession session,
+const XrActionsSyncInfo* syncInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrSyncActions-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSyncActions",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == syncInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSyncActions-syncInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSyncActions", objects_info,
+ "Invalid NULL for XrActionsSyncInfo \"syncInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrActionsSyncInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrSyncActions", objects_info,
+ true, syncInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSyncActions-syncInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSyncActions",
+ objects_info,
+ "Command xrSyncActions param syncInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->SyncActions(session, syncInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo) {
+ XrResult test_result = GenValidUsageInputsXrSyncActions(session, syncInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrSyncActions(session, syncInfo);
+}
+
+XrResult GenValidUsageInputsXrEnumerateBoundSourcesForAction(
+XrSession session,
+const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+uint32_t sourceCapacityInput,
+uint32_t* sourceCountOutput,
+XrPath* sources) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrEnumerateBoundSourcesForAction-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateBoundSourcesForAction",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == enumerateInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateBoundSourcesForAction-enumerateInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateBoundSourcesForAction", objects_info,
+ "Invalid NULL for XrBoundSourcesForActionEnumerateInfo \"enumerateInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrBoundSourcesForActionEnumerateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrEnumerateBoundSourcesForAction", objects_info,
+ true, enumerateInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateBoundSourcesForAction-enumerateInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateBoundSourcesForAction",
+ objects_info,
+ "Command xrEnumerateBoundSourcesForAction param enumerateInfo is invalid");
+ return xr_result;
+ }
+ // Optional array must be non-NULL when sourceCapacityInput is non-zero
+ if (0 != sourceCapacityInput && nullptr == sources) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateBoundSourcesForAction-sources-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateBoundSourcesForAction",
+ objects_info,
+ "Command xrEnumerateBoundSourcesForAction param sources is NULL, but sourceCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == sourceCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrEnumerateBoundSourcesForAction-sourceCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrEnumerateBoundSourcesForAction", objects_info,
+ "Invalid NULL for uint32_t \"sourceCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrEnumerateBoundSourcesForAction-sourceCountOutput-parameter" type
+ // NOTE: Can't validate "VUID-xrEnumerateBoundSourcesForAction-sources-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->EnumerateBoundSourcesForAction(session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources) {
+ XrResult test_result = GenValidUsageInputsXrEnumerateBoundSourcesForAction(session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrEnumerateBoundSourcesForAction(session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+}
+
+XrResult GenValidUsageInputsXrGetInputSourceLocalizedName(
+XrSession session,
+const XrInputSourceLocalizedNameGetInfo* getInfo,
+uint32_t bufferCapacityInput,
+uint32_t* bufferCountOutput,
+char* buffer) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetInputSourceLocalizedName-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInputSourceLocalizedName",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == getInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetInputSourceLocalizedName-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInputSourceLocalizedName", objects_info,
+ "Invalid NULL for XrInputSourceLocalizedNameGetInfo \"getInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrInputSourceLocalizedNameGetInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetInputSourceLocalizedName", objects_info,
+ true, getInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetInputSourceLocalizedName-getInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInputSourceLocalizedName",
+ objects_info,
+ "Command xrGetInputSourceLocalizedName param getInfo is invalid");
+ return xr_result;
+ }
+ // Optional array must be non-NULL when bufferCapacityInput is non-zero
+ if (0 != bufferCapacityInput && nullptr == buffer) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetInputSourceLocalizedName-buffer-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInputSourceLocalizedName",
+ objects_info,
+ "Command xrGetInputSourceLocalizedName param buffer is NULL, but bufferCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == bufferCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetInputSourceLocalizedName-bufferCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInputSourceLocalizedName", objects_info,
+ "Invalid NULL for uint32_t \"bufferCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrGetInputSourceLocalizedName-bufferCountOutput-parameter" type
+ // NOTE: Can't validate "VUID-xrGetInputSourceLocalizedName-buffer-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetInputSourceLocalizedName(session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult test_result = GenValidUsageInputsXrGetInputSourceLocalizedName(session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetInputSourceLocalizedName(session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+}
+
+XrResult GenValidUsageInputsXrApplyHapticFeedback(
+XrSession session,
+const XrHapticActionInfo* hapticActionInfo,
+const XrHapticBaseHeader* hapticFeedback) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrApplyHapticFeedback-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrApplyHapticFeedback",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == hapticActionInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrApplyHapticFeedback-hapticActionInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrApplyHapticFeedback", objects_info,
+ "Invalid NULL for XrHapticActionInfo \"hapticActionInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrHapticActionInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrApplyHapticFeedback", objects_info,
+ true, hapticActionInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrApplyHapticFeedback-hapticActionInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrApplyHapticFeedback",
+ objects_info,
+ "Command xrApplyHapticFeedback param hapticActionInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == hapticFeedback) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrApplyHapticFeedback-hapticFeedback-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrApplyHapticFeedback", objects_info,
+ "Invalid NULL for XrHapticBaseHeader \"hapticFeedback\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate if XrHapticBaseHeader is a child structure of type XrHapticVibration and it is valid
+ const XrHapticVibration* new_hapticvibration_value = reinterpret_cast<const XrHapticVibration*>(hapticFeedback);
+ if (new_hapticvibration_value->type == XR_TYPE_HAPTIC_VIBRATION) {
+ xr_result = ValidateXrStruct(gen_instance_info, "xrApplyHapticFeedback",
+ objects_info,false, new_hapticvibration_value);
+ if (XR_SUCCESS != xr_result) {
+ std::string error_message = "Command xrApplyHapticFeedback param hapticFeedback";
+ error_message += " is invalid";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrApplyHapticFeedback-hapticFeedback-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrApplyHapticFeedback",
+ objects_info,
+ error_message);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ }
+ // Validate that the base-structure XrHapticBaseHeader is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrApplyHapticFeedback", objects_info,
+ true, hapticFeedback);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrApplyHapticFeedback-hapticFeedback-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrApplyHapticFeedback",
+ objects_info,
+ "Command xrApplyHapticFeedback param hapticFeedback is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->ApplyHapticFeedback(session, hapticActionInfo, hapticFeedback);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback) {
+ XrResult test_result = GenValidUsageInputsXrApplyHapticFeedback(session, hapticActionInfo, hapticFeedback);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrApplyHapticFeedback(session, hapticActionInfo, hapticFeedback);
+}
+
+XrResult GenValidUsageInputsXrStopHapticFeedback(
+XrSession session,
+const XrHapticActionInfo* hapticActionInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrStopHapticFeedback-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStopHapticFeedback",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == hapticActionInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrStopHapticFeedback-hapticActionInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStopHapticFeedback", objects_info,
+ "Invalid NULL for XrHapticActionInfo \"hapticActionInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrHapticActionInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrStopHapticFeedback", objects_info,
+ true, hapticActionInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrStopHapticFeedback-hapticActionInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrStopHapticFeedback",
+ objects_info,
+ "Command xrStopHapticFeedback param hapticActionInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->StopHapticFeedback(session, hapticActionInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo) {
+ XrResult test_result = GenValidUsageInputsXrStopHapticFeedback(session, hapticActionInfo);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrStopHapticFeedback(session, hapticActionInfo);
+}
+
+
+// ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+
+XrResult GenValidUsageInputsXrSetAndroidApplicationThreadKHR(
+XrSession session,
+XrAndroidThreadTypeKHR threadType,
+uint32_t threadId) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrSetAndroidApplicationThreadKHR-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSetAndroidApplicationThreadKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Make sure the enum type XrAndroidThreadTypeKHR value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrSetAndroidApplicationThreadKHR", "xrSetAndroidApplicationThreadKHR", "threadType", objects_info, threadType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrAndroidThreadTypeKHR \"threadType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(threadType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSetAndroidApplicationThreadKHR-threadType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSetAndroidApplicationThreadKHR",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSetAndroidApplicationThreadKHR(
+ XrSession session,
+ XrAndroidThreadTypeKHR threadType,
+ uint32_t threadId) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->SetAndroidApplicationThreadKHR(session, threadType, threadId);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrSetAndroidApplicationThreadKHR(
+ XrSession session,
+ XrAndroidThreadTypeKHR threadType,
+ uint32_t threadId) {
+ XrResult test_result = GenValidUsageInputsXrSetAndroidApplicationThreadKHR(session, threadType, threadId);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrSetAndroidApplicationThreadKHR(session, threadType, threadId);
+}
+
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+
+// ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+
+XrResult GenValidUsageInputsXrCreateSwapchainAndroidSurfaceKHR(
+XrSession session,
+const XrSwapchainCreateInfo* info,
+XrSwapchain* swapchain,
+jobject* surface) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateSwapchainAndroidSurfaceKHR-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchainAndroidSurfaceKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == info) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchainAndroidSurfaceKHR-info-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchainAndroidSurfaceKHR", objects_info,
+ "Invalid NULL for XrSwapchainCreateInfo \"info\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrSwapchainCreateInfo is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateSwapchainAndroidSurfaceKHR", objects_info,
+ true, info);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchainAndroidSurfaceKHR-info-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchainAndroidSurfaceKHR",
+ objects_info,
+ "Command xrCreateSwapchainAndroidSurfaceKHR param info is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == swapchain) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchainAndroidSurfaceKHR-swapchain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchainAndroidSurfaceKHR", objects_info,
+ "Invalid NULL for XrSwapchain \"swapchain\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == surface) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateSwapchainAndroidSurfaceKHR-surface-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateSwapchainAndroidSurfaceKHR", objects_info,
+ "Invalid NULL for jobject \"surface\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrCreateSwapchainAndroidSurfaceKHR-surface-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateSwapchainAndroidSurfaceKHR(
+ XrSession session,
+ const XrSwapchainCreateInfo* info,
+ XrSwapchain* swapchain,
+ jobject* surface) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->CreateSwapchainAndroidSurfaceKHR(session, info, swapchain, surface);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrCreateSwapchainAndroidSurfaceKHR(
+ XrSession session,
+ const XrSwapchainCreateInfo* info,
+ XrSwapchain* swapchain,
+ jobject* surface) {
+ XrResult test_result = GenValidUsageInputsXrCreateSwapchainAndroidSurfaceKHR(session, info, swapchain, surface);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrCreateSwapchainAndroidSurfaceKHR(session, info, swapchain, surface);
+}
+
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+
+// ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+
+XrResult GenValidUsageInputsXrGetOpenGLGraphicsRequirementsKHR(
+XrInstance instance,
+XrSystemId systemId,
+XrGraphicsRequirementsOpenGLKHR* graphicsRequirements) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetOpenGLGraphicsRequirementsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetOpenGLGraphicsRequirementsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == graphicsRequirements) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetOpenGLGraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetOpenGLGraphicsRequirementsKHR", objects_info,
+ "Invalid NULL for XrGraphicsRequirementsOpenGLKHR \"graphicsRequirements\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrGraphicsRequirementsOpenGLKHR is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetOpenGLGraphicsRequirementsKHR", objects_info,
+ false, graphicsRequirements);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetOpenGLGraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetOpenGLGraphicsRequirementsKHR",
+ objects_info,
+ "Command xrGetOpenGLGraphicsRequirementsKHR param graphicsRequirements is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetOpenGLGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLKHR* graphicsRequirements) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetOpenGLGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetOpenGLGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLKHR* graphicsRequirements) {
+ XrResult test_result = GenValidUsageInputsXrGetOpenGLGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetOpenGLGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+
+// ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+XrResult GenValidUsageInputsXrGetOpenGLESGraphicsRequirementsKHR(
+XrInstance instance,
+XrSystemId systemId,
+XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetOpenGLESGraphicsRequirementsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetOpenGLESGraphicsRequirementsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == graphicsRequirements) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetOpenGLESGraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetOpenGLESGraphicsRequirementsKHR", objects_info,
+ "Invalid NULL for XrGraphicsRequirementsOpenGLESKHR \"graphicsRequirements\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrGraphicsRequirementsOpenGLESKHR is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetOpenGLESGraphicsRequirementsKHR", objects_info,
+ false, graphicsRequirements);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetOpenGLESGraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetOpenGLESGraphicsRequirementsKHR",
+ objects_info,
+ "Command xrGetOpenGLESGraphicsRequirementsKHR param graphicsRequirements is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetOpenGLESGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetOpenGLESGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetOpenGLESGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements) {
+ XrResult test_result = GenValidUsageInputsXrGetOpenGLESGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetOpenGLESGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+
+// ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+
+XrResult GenValidUsageInputsXrGetVulkanInstanceExtensionsKHR(
+XrInstance instance,
+XrSystemId systemId,
+uint32_t bufferCapacityInput,
+uint32_t* bufferCountOutput,
+char* buffer) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetVulkanInstanceExtensionsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanInstanceExtensionsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Optional array must be non-NULL when bufferCapacityInput is non-zero
+ if (0 != bufferCapacityInput && nullptr == buffer) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanInstanceExtensionsKHR-buffer-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanInstanceExtensionsKHR",
+ objects_info,
+ "Command xrGetVulkanInstanceExtensionsKHR param buffer is NULL, but bufferCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == bufferCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanInstanceExtensionsKHR-bufferCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanInstanceExtensionsKHR", objects_info,
+ "Invalid NULL for uint32_t \"bufferCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrGetVulkanInstanceExtensionsKHR-bufferCountOutput-parameter" type
+ // NOTE: Can't validate "VUID-xrGetVulkanInstanceExtensionsKHR-buffer-parameter" null-termination
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetVulkanInstanceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetVulkanInstanceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetVulkanInstanceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult test_result = GenValidUsageInputsXrGetVulkanInstanceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetVulkanInstanceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+
+XrResult GenValidUsageInputsXrGetVulkanDeviceExtensionsKHR(
+XrInstance instance,
+XrSystemId systemId,
+uint32_t bufferCapacityInput,
+uint32_t* bufferCountOutput,
+char* buffer) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetVulkanDeviceExtensionsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanDeviceExtensionsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Optional array must be non-NULL when bufferCapacityInput is non-zero
+ if (0 != bufferCapacityInput && nullptr == buffer) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanDeviceExtensionsKHR-buffer-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanDeviceExtensionsKHR",
+ objects_info,
+ "Command xrGetVulkanDeviceExtensionsKHR param buffer is NULL, but bufferCapacityInput is greater than 0");
+ xr_result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == bufferCountOutput) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanDeviceExtensionsKHR-bufferCountOutput-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanDeviceExtensionsKHR", objects_info,
+ "Invalid NULL for uint32_t \"bufferCountOutput\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrGetVulkanDeviceExtensionsKHR-bufferCountOutput-parameter" type
+ // NOTE: Can't validate "VUID-xrGetVulkanDeviceExtensionsKHR-buffer-parameter" null-termination
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetVulkanDeviceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetVulkanDeviceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetVulkanDeviceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) {
+ XrResult test_result = GenValidUsageInputsXrGetVulkanDeviceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetVulkanDeviceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+
+XrResult GenValidUsageInputsXrGetVulkanGraphicsDeviceKHR(
+XrInstance instance,
+XrSystemId systemId,
+VkInstance vkInstance,
+VkPhysicalDevice* vkPhysicalDevice) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetVulkanGraphicsDeviceKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanGraphicsDeviceKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == vkPhysicalDevice) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanGraphicsDeviceKHR-vkPhysicalDevice-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanGraphicsDeviceKHR", objects_info,
+ "Invalid NULL for VkPhysicalDevice \"vkPhysicalDevice\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrGetVulkanGraphicsDeviceKHR-vkPhysicalDevice-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetVulkanGraphicsDeviceKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ VkInstance vkInstance,
+ VkPhysicalDevice* vkPhysicalDevice) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetVulkanGraphicsDeviceKHR(instance, systemId, vkInstance, vkPhysicalDevice);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetVulkanGraphicsDeviceKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ VkInstance vkInstance,
+ VkPhysicalDevice* vkPhysicalDevice) {
+ XrResult test_result = GenValidUsageInputsXrGetVulkanGraphicsDeviceKHR(instance, systemId, vkInstance, vkPhysicalDevice);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetVulkanGraphicsDeviceKHR(instance, systemId, vkInstance, vkPhysicalDevice);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+
+XrResult GenValidUsageInputsXrGetVulkanGraphicsRequirementsKHR(
+XrInstance instance,
+XrSystemId systemId,
+XrGraphicsRequirementsVulkanKHR* graphicsRequirements) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetVulkanGraphicsRequirementsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanGraphicsRequirementsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == graphicsRequirements) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanGraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanGraphicsRequirementsKHR", objects_info,
+ "Invalid NULL for XrGraphicsRequirementsVulkanKHR \"graphicsRequirements\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrGraphicsRequirementsVulkanKHR is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetVulkanGraphicsRequirementsKHR", objects_info,
+ false, graphicsRequirements);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVulkanGraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVulkanGraphicsRequirementsKHR",
+ objects_info,
+ "Command xrGetVulkanGraphicsRequirementsKHR param graphicsRequirements is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetVulkanGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetVulkanGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetVulkanGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements) {
+ XrResult test_result = GenValidUsageInputsXrGetVulkanGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetVulkanGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+
+// ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+
+XrResult GenValidUsageInputsXrGetD3D11GraphicsRequirementsKHR(
+XrInstance instance,
+XrSystemId systemId,
+XrGraphicsRequirementsD3D11KHR* graphicsRequirements) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetD3D11GraphicsRequirementsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetD3D11GraphicsRequirementsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == graphicsRequirements) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetD3D11GraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetD3D11GraphicsRequirementsKHR", objects_info,
+ "Invalid NULL for XrGraphicsRequirementsD3D11KHR \"graphicsRequirements\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrGraphicsRequirementsD3D11KHR is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetD3D11GraphicsRequirementsKHR", objects_info,
+ false, graphicsRequirements);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetD3D11GraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetD3D11GraphicsRequirementsKHR",
+ objects_info,
+ "Command xrGetD3D11GraphicsRequirementsKHR param graphicsRequirements is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetD3D11GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D11KHR* graphicsRequirements) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetD3D11GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetD3D11GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D11KHR* graphicsRequirements) {
+ XrResult test_result = GenValidUsageInputsXrGetD3D11GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetD3D11GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+
+// ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+
+XrResult GenValidUsageInputsXrGetD3D12GraphicsRequirementsKHR(
+XrInstance instance,
+XrSystemId systemId,
+XrGraphicsRequirementsD3D12KHR* graphicsRequirements) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrGetD3D12GraphicsRequirementsKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetD3D12GraphicsRequirementsKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == graphicsRequirements) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetD3D12GraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetD3D12GraphicsRequirementsKHR", objects_info,
+ "Invalid NULL for XrGraphicsRequirementsD3D12KHR \"graphicsRequirements\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrGraphicsRequirementsD3D12KHR is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetD3D12GraphicsRequirementsKHR", objects_info,
+ false, graphicsRequirements);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetD3D12GraphicsRequirementsKHR-graphicsRequirements-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetD3D12GraphicsRequirementsKHR",
+ objects_info,
+ "Command xrGetD3D12GraphicsRequirementsKHR param graphicsRequirements is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetD3D12GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D12KHR* graphicsRequirements) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->GetD3D12GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetD3D12GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D12KHR* graphicsRequirements) {
+ XrResult test_result = GenValidUsageInputsXrGetD3D12GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetD3D12GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+
+// ---- XR_KHR_visibility_mask extension commands
+XrResult GenValidUsageInputsXrGetVisibilityMaskKHR(
+XrSession session,
+XrViewConfigurationType viewConfigurationType,
+uint32_t viewIndex,
+XrVisibilityMaskTypeKHR visibilityMaskType,
+XrVisibilityMaskKHR* visibilityMask) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrGetVisibilityMaskKHR-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVisibilityMaskKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Make sure the enum type XrViewConfigurationType value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrGetVisibilityMaskKHR", "xrGetVisibilityMaskKHR", "viewConfigurationType", objects_info, viewConfigurationType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrViewConfigurationType \"viewConfigurationType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(viewConfigurationType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVisibilityMaskKHR-viewConfigurationType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVisibilityMaskKHR",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrVisibilityMaskTypeKHR value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrGetVisibilityMaskKHR", "xrGetVisibilityMaskKHR", "visibilityMaskType", objects_info, visibilityMaskType)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrVisibilityMaskTypeKHR \"visibilityMaskType\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(visibilityMaskType));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVisibilityMaskKHR-visibilityMaskType-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVisibilityMaskKHR",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == visibilityMask) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVisibilityMaskKHR-visibilityMask-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVisibilityMaskKHR", objects_info,
+ "Invalid NULL for XrVisibilityMaskKHR \"visibilityMask\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrVisibilityMaskKHR is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrGetVisibilityMaskKHR", objects_info,
+ false, visibilityMask);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrGetVisibilityMaskKHR-visibilityMask-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetVisibilityMaskKHR",
+ objects_info,
+ "Command xrGetVisibilityMaskKHR param visibilityMask is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrGetVisibilityMaskKHR(
+ XrSession session,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewIndex,
+ XrVisibilityMaskTypeKHR visibilityMaskType,
+ XrVisibilityMaskKHR* visibilityMask) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->GetVisibilityMaskKHR(session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrGetVisibilityMaskKHR(
+ XrSession session,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewIndex,
+ XrVisibilityMaskTypeKHR visibilityMaskType,
+ XrVisibilityMaskKHR* visibilityMask) {
+ XrResult test_result = GenValidUsageInputsXrGetVisibilityMaskKHR(session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrGetVisibilityMaskKHR(session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask);
+}
+
+
+// ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+
+XrResult GenValidUsageInputsXrConvertWin32PerformanceCounterToTimeKHR(
+XrInstance instance,
+const LARGE_INTEGER* performanceCounter,
+XrTime* time) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrConvertWin32PerformanceCounterToTimeKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertWin32PerformanceCounterToTimeKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == performanceCounter) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrConvertWin32PerformanceCounterToTimeKHR-performanceCounter-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertWin32PerformanceCounterToTimeKHR", objects_info,
+ "Invalid NULL for LARGE_INTEGER \"performanceCounter\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrConvertWin32PerformanceCounterToTimeKHR-performanceCounter-parameter" type
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == time) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrConvertWin32PerformanceCounterToTimeKHR-time-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertWin32PerformanceCounterToTimeKHR", objects_info,
+ "Invalid NULL for XrTime \"time\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrConvertWin32PerformanceCounterToTimeKHR-time-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrConvertWin32PerformanceCounterToTimeKHR(
+ XrInstance instance,
+ const LARGE_INTEGER* performanceCounter,
+ XrTime* time) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->ConvertWin32PerformanceCounterToTimeKHR(instance, performanceCounter, time);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrConvertWin32PerformanceCounterToTimeKHR(
+ XrInstance instance,
+ const LARGE_INTEGER* performanceCounter,
+ XrTime* time) {
+ XrResult test_result = GenValidUsageInputsXrConvertWin32PerformanceCounterToTimeKHR(instance, performanceCounter, time);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrConvertWin32PerformanceCounterToTimeKHR(instance, performanceCounter, time);
+}
+
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+#if defined(XR_USE_PLATFORM_WIN32)
+
+XrResult GenValidUsageInputsXrConvertTimeToWin32PerformanceCounterKHR(
+XrInstance instance,
+XrTime time,
+LARGE_INTEGER* performanceCounter) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrConvertTimeToWin32PerformanceCounterKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimeToWin32PerformanceCounterKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == performanceCounter) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrConvertTimeToWin32PerformanceCounterKHR-performanceCounter-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimeToWin32PerformanceCounterKHR", objects_info,
+ "Invalid NULL for LARGE_INTEGER \"performanceCounter\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrConvertTimeToWin32PerformanceCounterKHR-performanceCounter-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrConvertTimeToWin32PerformanceCounterKHR(
+ XrInstance instance,
+ XrTime time,
+ LARGE_INTEGER* performanceCounter) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->ConvertTimeToWin32PerformanceCounterKHR(instance, time, performanceCounter);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrConvertTimeToWin32PerformanceCounterKHR(
+ XrInstance instance,
+ XrTime time,
+ LARGE_INTEGER* performanceCounter) {
+ XrResult test_result = GenValidUsageInputsXrConvertTimeToWin32PerformanceCounterKHR(instance, time, performanceCounter);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrConvertTimeToWin32PerformanceCounterKHR(instance, time, performanceCounter);
+}
+
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+
+// ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+
+XrResult GenValidUsageInputsXrConvertTimespecTimeToTimeKHR(
+XrInstance instance,
+const struct timespec* timespecTime,
+XrTime* time) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrConvertTimespecTimeToTimeKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimespecTimeToTimeKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == timespecTime) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrConvertTimespecTimeToTimeKHR-timespecTime-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimespecTimeToTimeKHR", objects_info,
+ "Invalid NULL for timespec \"timespecTime\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrConvertTimespecTimeToTimeKHR-timespecTime-parameter" type
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == time) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrConvertTimespecTimeToTimeKHR-time-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimespecTimeToTimeKHR", objects_info,
+ "Invalid NULL for XrTime \"time\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrConvertTimespecTimeToTimeKHR-time-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrConvertTimespecTimeToTimeKHR(
+ XrInstance instance,
+ const struct timespec* timespecTime,
+ XrTime* time) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->ConvertTimespecTimeToTimeKHR(instance, timespecTime, time);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrConvertTimespecTimeToTimeKHR(
+ XrInstance instance,
+ const struct timespec* timespecTime,
+ XrTime* time) {
+ XrResult test_result = GenValidUsageInputsXrConvertTimespecTimeToTimeKHR(instance, timespecTime, time);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrConvertTimespecTimeToTimeKHR(instance, timespecTime, time);
+}
+
+#endif // defined(XR_USE_TIMESPEC)
+
+#if defined(XR_USE_TIMESPEC)
+
+XrResult GenValidUsageInputsXrConvertTimeToTimespecTimeKHR(
+XrInstance instance,
+XrTime time,
+struct timespec* timespecTime) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrConvertTimeToTimespecTimeKHR-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimeToTimespecTimeKHR",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == timespecTime) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrConvertTimeToTimespecTimeKHR-timespecTime-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrConvertTimeToTimespecTimeKHR", objects_info,
+ "Invalid NULL for timespec \"timespecTime\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrConvertTimeToTimespecTimeKHR-timespecTime-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrConvertTimeToTimespecTimeKHR(
+ XrInstance instance,
+ XrTime time,
+ struct timespec* timespecTime) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->ConvertTimeToTimespecTimeKHR(instance, time, timespecTime);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrConvertTimeToTimespecTimeKHR(
+ XrInstance instance,
+ XrTime time,
+ struct timespec* timespecTime) {
+ XrResult test_result = GenValidUsageInputsXrConvertTimeToTimespecTimeKHR(instance, time, timespecTime);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrConvertTimeToTimespecTimeKHR(instance, time, timespecTime);
+}
+
+#endif // defined(XR_USE_TIMESPEC)
+
+
+// ---- XR_EXT_performance_settings extension commands
+XrResult GenValidUsageInputsXrPerfSettingsSetPerformanceLevelEXT(
+XrSession session,
+XrPerfSettingsDomainEXT domain,
+XrPerfSettingsLevelEXT level) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrPerfSettingsSetPerformanceLevelEXT-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPerfSettingsSetPerformanceLevelEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Make sure the enum type XrPerfSettingsDomainEXT value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrPerfSettingsSetPerformanceLevelEXT", "xrPerfSettingsSetPerformanceLevelEXT", "domain", objects_info, domain)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrPerfSettingsDomainEXT \"domain\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(domain));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrPerfSettingsSetPerformanceLevelEXT-domain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPerfSettingsSetPerformanceLevelEXT",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrPerfSettingsLevelEXT value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrPerfSettingsSetPerformanceLevelEXT", "xrPerfSettingsSetPerformanceLevelEXT", "level", objects_info, level)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrPerfSettingsLevelEXT \"level\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(level));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrPerfSettingsSetPerformanceLevelEXT-level-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrPerfSettingsSetPerformanceLevelEXT",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrPerfSettingsSetPerformanceLevelEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsLevelEXT level) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->PerfSettingsSetPerformanceLevelEXT(session, domain, level);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrPerfSettingsSetPerformanceLevelEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsLevelEXT level) {
+ XrResult test_result = GenValidUsageInputsXrPerfSettingsSetPerformanceLevelEXT(session, domain, level);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrPerfSettingsSetPerformanceLevelEXT(session, domain, level);
+}
+
+
+// ---- XR_EXT_thermal_query extension commands
+XrResult GenValidUsageInputsXrThermalGetTemperatureTrendEXT(
+XrSession session,
+XrPerfSettingsDomainEXT domain,
+XrPerfSettingsNotificationLevelEXT* notificationLevel,
+float* tempHeadroom,
+float* tempSlope) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrThermalGetTemperatureTrendEXT-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrThermalGetTemperatureTrendEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Make sure the enum type XrPerfSettingsDomainEXT value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrThermalGetTemperatureTrendEXT", "xrThermalGetTemperatureTrendEXT", "domain", objects_info, domain)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrPerfSettingsDomainEXT \"domain\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(domain));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrThermalGetTemperatureTrendEXT-domain-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrThermalGetTemperatureTrendEXT",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == notificationLevel) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrThermalGetTemperatureTrendEXT-notificationLevel-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrThermalGetTemperatureTrendEXT", objects_info,
+ "Invalid NULL for XrPerfSettingsNotificationLevelEXT \"notificationLevel\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Make sure the enum type XrPerfSettingsNotificationLevelEXT value is valid
+ if (!ValidateXrEnum(gen_instance_info, "xrThermalGetTemperatureTrendEXT", "xrThermalGetTemperatureTrendEXT", "notificationLevel", objects_info, *notificationLevel)) {
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrPerfSettingsNotificationLevelEXT \"notificationLevel\" enum value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(*notificationLevel));
+ CoreValidLogMessage(gen_instance_info, "VUID-xrThermalGetTemperatureTrendEXT-notificationLevel-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrThermalGetTemperatureTrendEXT",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == tempHeadroom) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrThermalGetTemperatureTrendEXT-tempHeadroom-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrThermalGetTemperatureTrendEXT", objects_info,
+ "Invalid NULL for float \"tempHeadroom\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrThermalGetTemperatureTrendEXT-tempHeadroom-parameter" type
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == tempSlope) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrThermalGetTemperatureTrendEXT-tempSlope-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrThermalGetTemperatureTrendEXT", objects_info,
+ "Invalid NULL for float \"tempSlope\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // NOTE: Can't validate "VUID-xrThermalGetTemperatureTrendEXT-tempSlope-parameter" type
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrThermalGetTemperatureTrendEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsNotificationLevelEXT* notificationLevel,
+ float* tempHeadroom,
+ float* tempSlope) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->ThermalGetTemperatureTrendEXT(session, domain, notificationLevel, tempHeadroom, tempSlope);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrThermalGetTemperatureTrendEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsNotificationLevelEXT* notificationLevel,
+ float* tempHeadroom,
+ float* tempSlope) {
+ XrResult test_result = GenValidUsageInputsXrThermalGetTemperatureTrendEXT(session, domain, notificationLevel, tempHeadroom, tempSlope);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrThermalGetTemperatureTrendEXT(session, domain, notificationLevel, tempHeadroom, tempSlope);
+}
+
+
+// ---- XR_EXT_debug_utils extension commands
+XrResult GenValidUsageInputsXrSetDebugUtilsObjectNameEXT(
+XrInstance instance,
+const XrDebugUtilsObjectNameInfoEXT* nameInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrSetDebugUtilsObjectNameEXT-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSetDebugUtilsObjectNameEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == nameInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSetDebugUtilsObjectNameEXT-nameInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSetDebugUtilsObjectNameEXT", objects_info,
+ "Invalid NULL for XrDebugUtilsObjectNameInfoEXT \"nameInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrDebugUtilsObjectNameInfoEXT is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrSetDebugUtilsObjectNameEXT", objects_info,
+ true, nameInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSetDebugUtilsObjectNameEXT-nameInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSetDebugUtilsObjectNameEXT",
+ objects_info,
+ "Command xrSetDebugUtilsObjectNameEXT param nameInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrCreateDebugUtilsMessengerEXT(
+XrInstance instance,
+const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+XrDebugUtilsMessengerEXT* messenger) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrCreateDebugUtilsMessengerEXT-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateDebugUtilsMessengerEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == createInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateDebugUtilsMessengerEXT-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateDebugUtilsMessengerEXT", objects_info,
+ "Invalid NULL for XrDebugUtilsMessengerCreateInfoEXT \"createInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrDebugUtilsMessengerCreateInfoEXT is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrCreateDebugUtilsMessengerEXT", objects_info,
+ true, createInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateDebugUtilsMessengerEXT-createInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateDebugUtilsMessengerEXT",
+ objects_info,
+ "Command xrCreateDebugUtilsMessengerEXT param createInfo is invalid");
+ return xr_result;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == messenger) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrCreateDebugUtilsMessengerEXT", objects_info,
+ "Invalid NULL for XrDebugUtilsMessengerEXT \"messenger\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ if (XR_SUCCESS == result && nullptr != messenger) {
+ std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());
+ handle_info->instance_info = gen_instance_info;
+ handle_info->direct_parent_type = XR_OBJECT_TYPE_INSTANCE;
+ handle_info->direct_parent_handle = MakeHandleGeneric(instance);
+ g_debugutilsmessengerext_info.insert(*messenger, std::move(handle_info));
+ }
+ } catch (std::bad_alloc&) {
+ result = XR_ERROR_OUT_OF_MEMORY;
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrDestroyDebugUtilsMessengerEXT(
+XrDebugUtilsMessengerEXT messenger) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(messenger, XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrDebugUtilsMessengerEXTHandle(&messenger);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrDebugUtilsMessengerEXT handle \"messenger\" ";
+ oss << HandleToHexString(messenger);
+ CoreValidLogMessage(nullptr, "VUID-xrDestroyDebugUtilsMessengerEXT-messenger-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrDestroyDebugUtilsMessengerEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_debugutilsmessengerext_info.getWithInstanceInfo(messenger);
+ GenValidUsageXrHandleInfo *gen_debugutilsmessengerext_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_debugutilsmessengerext_info.getWithInstanceInfo(messenger);
+ GenValidUsageXrHandleInfo *gen_debugutilsmessengerext_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
+ if (XR_SUCCEEDED(result)) {
+ g_debugutilsmessengerext_info.erase(messenger);
+ }
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrSubmitDebugUtilsMessageEXT(
+XrInstance instance,
+XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+const XrDebugUtilsMessengerCallbackDataEXT* callbackData) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(instance, XR_OBJECT_TYPE_INSTANCE);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrInstanceHandle(&instance);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrInstance handle \"instance\" ";
+ oss << HandleToHexString(instance);
+ CoreValidLogMessage(nullptr, "VUID-xrSubmitDebugUtilsMessageEXT-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ ValidateXrFlagsResult debug_utils_message_severity_flags_ext_result = ValidateXrDebugUtilsMessageSeverityFlagsEXT(messageSeverity);
+ // Flags must be non-zero in this case.
+ if (VALIDATE_XR_FLAGS_ZERO == debug_utils_message_severity_flags_ext_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSubmitDebugUtilsMessageEXT-messageSeverity-requiredbitmask",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT",
+ objects_info, "XrDebugUtilsMessageSeverityFlagsEXT \"messageSeverity\" flag must be non-zero");
+ return XR_ERROR_VALIDATION_FAILURE;
+ } else if (VALIDATE_XR_FLAGS_SUCCESS != debug_utils_message_severity_flags_ext_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrDebugUtilsMessageSeverityFlagsEXT \"messageSeverity\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(messageSeverity));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSubmitDebugUtilsMessageEXT-messageSeverity-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ ValidateXrFlagsResult debug_utils_message_type_flags_ext_result = ValidateXrDebugUtilsMessageTypeFlagsEXT(messageTypes);
+ // Flags must be non-zero in this case.
+ if (VALIDATE_XR_FLAGS_ZERO == debug_utils_message_type_flags_ext_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSubmitDebugUtilsMessageEXT-messageTypes-requiredbitmask",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT",
+ objects_info, "XrDebugUtilsMessageTypeFlagsEXT \"messageTypes\" flag must be non-zero");
+ return XR_ERROR_VALIDATION_FAILURE;
+ } else if (VALIDATE_XR_FLAGS_SUCCESS != debug_utils_message_type_flags_ext_result) {
+ // Otherwise, flags must be valid.
+ std::ostringstream oss_enum;
+ oss_enum << "Invalid XrDebugUtilsMessageTypeFlagsEXT \"messageTypes\" flag value ";
+ oss_enum << Uint32ToHexString(static_cast<uint32_t>(messageTypes));
+ oss_enum <<" contains illegal bit";
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSubmitDebugUtilsMessageEXT-messageTypes-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT",
+ objects_info, oss_enum.str());
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == callbackData) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSubmitDebugUtilsMessageEXT-callbackData-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT", objects_info,
+ "Invalid NULL for XrDebugUtilsMessengerCallbackDataEXT \"callbackData\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrDebugUtilsMessengerCallbackDataEXT is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrSubmitDebugUtilsMessageEXT", objects_info,
+ true, callbackData);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSubmitDebugUtilsMessageEXT-callbackData-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSubmitDebugUtilsMessageEXT",
+ objects_info,
+ "Command xrSubmitDebugUtilsMessageEXT param callbackData is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData) {
+ XrResult result = XR_SUCCESS;
+ try {
+ GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(instance);
+ result = gen_instance_info->dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageXrSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData) {
+ XrResult test_result = GenValidUsageInputsXrSubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+ if (XR_SUCCESS != test_result) {
+ return test_result;
+ }
+ return GenValidUsageNextXrSubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+}
+
+XrResult GenValidUsageInputsXrSessionBeginDebugUtilsLabelRegionEXT(
+XrSession session,
+const XrDebugUtilsLabelEXT* labelInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrSessionBeginDebugUtilsLabelRegionEXT-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionBeginDebugUtilsLabelRegionEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == labelInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionBeginDebugUtilsLabelRegionEXT", objects_info,
+ "Invalid NULL for XrDebugUtilsLabelEXT \"labelInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrDebugUtilsLabelEXT is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrSessionBeginDebugUtilsLabelRegionEXT", objects_info,
+ true, labelInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionBeginDebugUtilsLabelRegionEXT",
+ objects_info,
+ "Command xrSessionBeginDebugUtilsLabelRegionEXT param labelInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSessionBeginDebugUtilsLabelRegionEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrSessionEndDebugUtilsLabelRegionEXT(
+XrSession session) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrSessionEndDebugUtilsLabelRegionEXT-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionEndDebugUtilsLabelRegionEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSessionEndDebugUtilsLabelRegionEXT(
+ XrSession session) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+XrResult GenValidUsageInputsXrSessionInsertDebugUtilsLabelEXT(
+XrSession session,
+const XrDebugUtilsLabelEXT* labelInfo) {
+ try {
+ XrResult xr_result = XR_SUCCESS;
+ std::vector<GenValidUsageXrObjectInfo> objects_info;
+ objects_info.emplace_back(session, XR_OBJECT_TYPE_SESSION);
+
+ {
+ // writeValidateInlineHandleValidation
+ ValidateXrHandleResult handle_result = VerifyXrSessionHandle(&session);
+ if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {
+ // Not a valid handle or NULL (which is not valid in this case)
+ std::ostringstream oss;
+ oss << "Invalid XrSession handle \"session\" ";
+ oss << HandleToHexString(session);
+ CoreValidLogMessage(nullptr, "VUID-xrSessionInsertDebugUtilsLabelEXT-session-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionInsertDebugUtilsLabelEXT",
+ objects_info, oss.str());
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ // Non-optional pointer/array variable that needs to not be NULL
+ if (nullptr == labelInfo) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionInsertDebugUtilsLabelEXT", objects_info,
+ "Invalid NULL for XrDebugUtilsLabelEXT \"labelInfo\" which is not "
+ "optional and must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Validate that the structure XrDebugUtilsLabelEXT is valid
+ xr_result = ValidateXrStruct(gen_instance_info, "xrSessionInsertDebugUtilsLabelEXT", objects_info,
+ true, labelInfo);
+ if (XR_SUCCESS != xr_result) {
+ CoreValidLogMessage(gen_instance_info, "VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrSessionInsertDebugUtilsLabelEXT",
+ objects_info,
+ "Command xrSessionInsertDebugUtilsLabelEXT param labelInfo is invalid");
+ return xr_result;
+ }
+ return XR_SUCCESS;
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
+XrResult GenValidUsageNextXrSessionInsertDebugUtilsLabelEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo) {
+ XrResult result = XR_SUCCESS;
+ try {
+ auto info_with_instance = g_session_info.getWithInstanceInfo(session);
+ GenValidUsageXrHandleInfo *gen_session_info = info_with_instance.first;
+ GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;
+ result = gen_instance_info->dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo);
+ } catch (...) {
+ result = XR_ERROR_VALIDATION_FAILURE;
+ }
+ return result;
+}
+
+
+// API Layer's xrGetInstanceProcAddr
+XrResult GenValidUsageXrGetInstanceProcAddr(
+ XrInstance instance,
+ const char* name,
+ PFN_xrVoidFunction* function) {
+ try {
+ std::string func_name = name;
+ std::vector<GenValidUsageXrObjectInfo> objects;
+ if (g_instance_info.verifyHandle(&instance) == VALIDATE_XR_HANDLE_INVALID) {
+ // Make sure the instance is valid if it is not XR_NULL_HANDLE
+ std::vector<GenValidUsageXrObjectInfo> objects;
+ objects.resize(1);
+ objects[0].handle = MakeHandleGeneric(instance);
+ objects[0].type = XR_OBJECT_TYPE_INSTANCE;
+ CoreValidLogMessage(nullptr, "VUID-xrGetInstanceProcAddr-instance-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProcAddr", objects,
+ "Invalid instance handle provided.");
+ }
+ // NOTE: Can't validate "VUID-xrGetInstanceProcAddr-name-parameter" null-termination
+ // If we setup the function, just return
+ if (function == nullptr) {
+ CoreValidLogMessage(nullptr, "VUID-xrGetInstanceProcAddr-function-parameter",
+ VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProcAddr", objects,
+ "function is NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ // ---- Core 1.0 commands
+ if (func_name == "xrGetInstanceProcAddr") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetInstanceProcAddr);
+ } else if (func_name == "xrCreateInstance") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrCreateInstance);
+ } else if (func_name == "xrDestroyInstance") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrDestroyInstance);
+ } else if (func_name == "xrGetInstanceProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetInstanceProperties);
+ } else if (func_name == "xrPollEvent") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrPollEvent);
+ } else if (func_name == "xrResultToString") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrResultToString);
+ } else if (func_name == "xrStructureTypeToString") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrStructureTypeToString);
+ } else if (func_name == "xrGetSystem") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetSystem);
+ } else if (func_name == "xrGetSystemProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetSystemProperties);
+ } else if (func_name == "xrEnumerateEnvironmentBlendModes") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateEnvironmentBlendModes);
+ } else if (func_name == "xrCreateSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrCreateSession);
+ } else if (func_name == "xrDestroySession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrDestroySession);
+ } else if (func_name == "xrEnumerateReferenceSpaces") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateReferenceSpaces);
+ } else if (func_name == "xrCreateReferenceSpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrCreateReferenceSpace);
+ } else if (func_name == "xrGetReferenceSpaceBoundsRect") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetReferenceSpaceBoundsRect);
+ } else if (func_name == "xrCreateActionSpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrCreateActionSpace);
+ } else if (func_name == "xrLocateSpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrLocateSpace);
+ } else if (func_name == "xrDestroySpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrDestroySpace);
+ } else if (func_name == "xrEnumerateViewConfigurations") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateViewConfigurations);
+ } else if (func_name == "xrGetViewConfigurationProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetViewConfigurationProperties);
+ } else if (func_name == "xrEnumerateViewConfigurationViews") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateViewConfigurationViews);
+ } else if (func_name == "xrEnumerateSwapchainFormats") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateSwapchainFormats);
+ } else if (func_name == "xrCreateSwapchain") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrCreateSwapchain);
+ } else if (func_name == "xrDestroySwapchain") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrDestroySwapchain);
+ } else if (func_name == "xrEnumerateSwapchainImages") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateSwapchainImages);
+ } else if (func_name == "xrAcquireSwapchainImage") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrAcquireSwapchainImage);
+ } else if (func_name == "xrWaitSwapchainImage") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrWaitSwapchainImage);
+ } else if (func_name == "xrReleaseSwapchainImage") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrReleaseSwapchainImage);
+ } else if (func_name == "xrBeginSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrBeginSession);
+ } else if (func_name == "xrEndSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEndSession);
+ } else if (func_name == "xrRequestExitSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrRequestExitSession);
+ } else if (func_name == "xrWaitFrame") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrWaitFrame);
+ } else if (func_name == "xrBeginFrame") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrBeginFrame);
+ } else if (func_name == "xrEndFrame") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEndFrame);
+ } else if (func_name == "xrLocateViews") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrLocateViews);
+ } else if (func_name == "xrStringToPath") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrStringToPath);
+ } else if (func_name == "xrPathToString") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrPathToString);
+ } else if (func_name == "xrCreateActionSet") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrCreateActionSet);
+ } else if (func_name == "xrDestroyActionSet") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrDestroyActionSet);
+ } else if (func_name == "xrCreateAction") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrCreateAction);
+ } else if (func_name == "xrDestroyAction") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrDestroyAction);
+ } else if (func_name == "xrSuggestInteractionProfileBindings") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrSuggestInteractionProfileBindings);
+ } else if (func_name == "xrAttachSessionActionSets") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrAttachSessionActionSets);
+ } else if (func_name == "xrGetCurrentInteractionProfile") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetCurrentInteractionProfile);
+ } else if (func_name == "xrGetActionStateBoolean") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetActionStateBoolean);
+ } else if (func_name == "xrGetActionStateFloat") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetActionStateFloat);
+ } else if (func_name == "xrGetActionStateVector2f") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetActionStateVector2f);
+ } else if (func_name == "xrGetActionStatePose") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetActionStatePose);
+ } else if (func_name == "xrSyncActions") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrSyncActions);
+ } else if (func_name == "xrEnumerateBoundSourcesForAction") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrEnumerateBoundSourcesForAction);
+ } else if (func_name == "xrGetInputSourceLocalizedName") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetInputSourceLocalizedName);
+ } else if (func_name == "xrApplyHapticFeedback") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrApplyHapticFeedback);
+ } else if (func_name == "xrStopHapticFeedback") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrStopHapticFeedback);
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ } else if (func_name == "xrSetAndroidApplicationThreadKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrSetAndroidApplicationThreadKHR);
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ } else if (func_name == "xrCreateSwapchainAndroidSurfaceKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrCreateSwapchainAndroidSurfaceKHR);
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ } else if (func_name == "xrGetOpenGLGraphicsRequirementsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetOpenGLGraphicsRequirementsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ } else if (func_name == "xrGetOpenGLESGraphicsRequirementsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetOpenGLESGraphicsRequirementsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "xrGetVulkanInstanceExtensionsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetVulkanInstanceExtensionsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "xrGetVulkanDeviceExtensionsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetVulkanDeviceExtensionsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "xrGetVulkanGraphicsDeviceKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetVulkanGraphicsDeviceKHR);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "xrGetVulkanGraphicsRequirementsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetVulkanGraphicsRequirementsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ } else if (func_name == "xrGetD3D11GraphicsRequirementsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetD3D11GraphicsRequirementsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ } else if (func_name == "xrGetD3D12GraphicsRequirementsKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetD3D12GraphicsRequirementsKHR);
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ } else if (func_name == "xrGetVisibilityMaskKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrGetVisibilityMaskKHR);
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ } else if (func_name == "xrConvertWin32PerformanceCounterToTimeKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrConvertWin32PerformanceCounterToTimeKHR);
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ } else if (func_name == "xrConvertTimeToWin32PerformanceCounterKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrConvertTimeToWin32PerformanceCounterKHR);
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ } else if (func_name == "xrConvertTimespecTimeToTimeKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrConvertTimespecTimeToTimeKHR);
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ } else if (func_name == "xrConvertTimeToTimespecTimeKHR") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrConvertTimeToTimespecTimeKHR);
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_EXT_performance_settings extension commands
+ } else if (func_name == "xrPerfSettingsSetPerformanceLevelEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrPerfSettingsSetPerformanceLevelEXT);
+
+ // ---- XR_EXT_thermal_query extension commands
+ } else if (func_name == "xrThermalGetTemperatureTrendEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrThermalGetTemperatureTrendEXT);
+
+ // ---- XR_EXT_debug_utils extension commands
+ } else if (func_name == "xrSetDebugUtilsObjectNameEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrSetDebugUtilsObjectNameEXT);
+ } else if (func_name == "xrCreateDebugUtilsMessengerEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrCreateDebugUtilsMessengerEXT);
+ } else if (func_name == "xrDestroyDebugUtilsMessengerEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrDestroyDebugUtilsMessengerEXT);
+ } else if (func_name == "xrSubmitDebugUtilsMessageEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(GenValidUsageXrSubmitDebugUtilsMessageEXT);
+ } else if (func_name == "xrSessionBeginDebugUtilsLabelRegionEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrSessionBeginDebugUtilsLabelRegionEXT);
+ } else if (func_name == "xrSessionEndDebugUtilsLabelRegionEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrSessionEndDebugUtilsLabelRegionEXT);
+ } else if (func_name == "xrSessionInsertDebugUtilsLabelEXT") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(CoreValidationXrSessionInsertDebugUtilsLabelEXT);
+ }
+ // If we setup the function, just return
+ if (*function != nullptr) {
+ return XR_SUCCESS;
+ }
+ // We have not found it, so pass it down to the next layer/runtime
+ GenValidUsageXrInstanceInfo* instance_valid_usage_info = g_instance_info.get(instance);
+ if (nullptr == instance_valid_usage_info) {
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ return instance_valid_usage_info->dispatch_table->GetInstanceProcAddr(instance, name, function);
+ } catch (...) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+}
+
diff --git a/extern/openxr/src/api_layers/xr_generated_core_validation.hpp b/extern/openxr/src/api_layers/xr_generated_core_validation.hpp
new file mode 100644
index 00000000000..abd89c66f2d
--- /dev/null
+++ b/extern/openxr/src/api_layers/xr_generated_core_validation.hpp
@@ -0,0 +1,156 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See validation_layer_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+#include "xr_generated_dispatch_table.h"
+#include "validation_utils.h"
+#include "api_layer_platform_defines.h"
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#include <vector>
+#include <string>
+#include <unordered_map>
+#include <thread>
+#include <mutex>
+
+
+// Unordered Map associating pointer to a vector of session label information to a session's handle
+extern std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel*>*> g_xr_session_labels;
+
+
+// ---- Core 1.0 commands
+XrResult GenValidUsageXrGetInstanceProcAddr(
+ XrInstance instance,
+ const char* name,
+ PFN_xrVoidFunction* function);
+XrResult CoreValidationXrCreateInstance(
+ const XrInstanceCreateInfo* createInfo,
+ XrInstance* instance);
+XrResult GenValidUsageInputsXrCreateInstance(const XrInstanceCreateInfo* createInfo, XrInstance* instance);
+XrResult GenValidUsageNextXrCreateInstance(
+ const XrInstanceCreateInfo* createInfo,
+ XrInstance* instance);
+XrResult CoreValidationXrDestroyInstance(
+ XrInstance instance);
+XrResult GenValidUsageInputsXrDestroyInstance(XrInstance instance);
+XrResult GenValidUsageNextXrDestroyInstance(
+ XrInstance instance);
+XrResult CoreValidationXrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session);
+XrResult GenValidUsageInputsXrCreateSession(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
+XrResult GenValidUsageNextXrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session);
+
+// ---- XR_KHR_android_thread_settings extension commands
+
+// ---- XR_KHR_android_surface_swapchain extension commands
+
+// ---- XR_KHR_opengl_enable extension commands
+
+// ---- XR_KHR_opengl_es_enable extension commands
+
+// ---- XR_KHR_vulkan_enable extension commands
+
+// ---- XR_KHR_D3D11_enable extension commands
+
+// ---- XR_KHR_D3D12_enable extension commands
+
+// ---- XR_KHR_visibility_mask extension commands
+
+// ---- XR_KHR_win32_convert_performance_counter_time extension commands
+
+// ---- XR_KHR_convert_timespec_time extension commands
+
+// ---- XR_EXT_performance_settings extension commands
+
+// ---- XR_EXT_thermal_query extension commands
+
+// ---- XR_EXT_debug_utils extension commands
+XrResult CoreValidationXrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+XrResult GenValidUsageInputsXrSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+XrResult GenValidUsageNextXrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+XrResult CoreValidationXrCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger);
+XrResult GenValidUsageInputsXrCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT* createInfo, XrDebugUtilsMessengerEXT* messenger);
+XrResult GenValidUsageNextXrCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger);
+XrResult CoreValidationXrDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger);
+XrResult GenValidUsageInputsXrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger);
+XrResult GenValidUsageNextXrDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger);
+XrResult CoreValidationXrSessionBeginDebugUtilsLabelRegionEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+XrResult GenValidUsageInputsXrSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
+XrResult GenValidUsageNextXrSessionBeginDebugUtilsLabelRegionEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+XrResult CoreValidationXrSessionEndDebugUtilsLabelRegionEXT(
+ XrSession session);
+XrResult GenValidUsageInputsXrSessionEndDebugUtilsLabelRegionEXT(XrSession session);
+XrResult GenValidUsageNextXrSessionEndDebugUtilsLabelRegionEXT(
+ XrSession session);
+XrResult CoreValidationXrSessionInsertDebugUtilsLabelEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+XrResult GenValidUsageInputsXrSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
+XrResult GenValidUsageNextXrSessionInsertDebugUtilsLabelEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+
+// Current API version of the Core Validation API Layer
+#define XR_CORE_VALIDATION_API_VERSION XR_CURRENT_API_VERSION
+
+// Externs for Core Validation
+extern InstanceHandleInfo g_instance_info;
+extern HandleInfo<XrSession> g_session_info;
+extern HandleInfo<XrSpace> g_space_info;
+extern HandleInfo<XrAction> g_action_info;
+extern HandleInfo<XrSwapchain> g_swapchain_info;
+extern HandleInfo<XrActionSet> g_actionset_info;
+extern HandleInfo<XrDebugUtilsMessengerEXT> g_debugutilsmessengerext_info;void GenValidUsageCleanUpMaps(GenValidUsageXrInstanceInfo *instance_info);
+
+
+// Function to convert XrObjectType to string
+std::string GenValidUsageXrObjectTypeToString(const XrObjectType& type);
+
+// Function to record all the core validation information
+extern void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,
+ GenValidUsageDebugSeverity message_severity, const std::string &command_name,
+ std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message);
+
diff --git a/extern/openxr/src/cmake/FindVulkanHeaders.cmake b/extern/openxr/src/cmake/FindVulkanHeaders.cmake
new file mode 100644
index 00000000000..9fc5dab7ea9
--- /dev/null
+++ b/extern/openxr/src/cmake/FindVulkanHeaders.cmake
@@ -0,0 +1,86 @@
+# ~~~
+# Copyright (c) 2018-2019 Valve Corporation
+# Copyright (c) 2018-2019 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ~~~
+
+#.rst:
+# FindVulkanHeaders
+# -----------------
+#
+# Try to find Vulkan Headers and Registry.
+#
+# This module is intended to be used by projects that build Vulkan
+# "system" components such as the loader and layers.
+# Vulkan applications should instead use the FindVulkan (or similar)
+# find module that locates the headers and the loader library.
+#
+# When using this find module to locate the headers and registry
+# in a Vulkan-Headers repository, the Vulkan-Headers repository
+# should be built with 'install' target and the following environment
+# or CMake variable set to the location of the install directory.
+#
+# VULKAN_HEADERS_INSTALL_DIR
+#
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines no IMPORTED targets
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines the following variables::
+#
+# VulkanHeaders_FOUND - True if VulkanHeaders was found
+# VulkanHeaders_INCLUDE_DIRS - include directories for VulkanHeaders
+#
+# VulkanRegistry_FOUND - True if VulkanRegistry was found
+# VulkanRegistry_DIRS - directories for VulkanRegistry
+#
+# The module will also define two cache variables::
+#
+# VulkanHeaders_INCLUDE_DIR - the VulkanHeaders include directory
+# VulkanRegistry_DIR - the VulkanRegistry directory
+#
+
+# Use HINTS instead of PATH to search these locations before
+# searching system environment variables like $PATH that may
+# contain SDK directories.
+find_path(VulkanHeaders_INCLUDE_DIR
+ NAMES vulkan/vulkan.h
+ HINTS
+ ${VULKAN_HEADERS_INSTALL_DIR}/include
+ "$ENV{VULKAN_HEADERS_INSTALL_DIR}/include"
+ "$ENV{VULKAN_SDK}/include")
+
+if(VulkanHeaders_INCLUDE_DIR)
+ get_filename_component(VULKAN_REGISTRY_PATH_HINT ${VulkanHeaders_INCLUDE_DIR} DIRECTORY)
+ find_path(VulkanRegistry_DIR
+ NAMES vk.xml
+ HINTS "${VULKAN_REGISTRY_PATH_HINT}/share/vulkan/registry")
+endif()
+
+set(VulkanHeaders_INCLUDE_DIRS ${VulkanHeaders_INCLUDE_DIR})
+set(VulkanRegistry_DIRS ${VulkanRegistry_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(VulkanHeaders
+ DEFAULT_MSG
+ VulkanHeaders_INCLUDE_DIR)
+find_package_handle_standard_args(VulkanRegistry
+ DEFAULT_MSG
+ VulkanRegistry_DIR)
+
+mark_as_advanced(VulkanHeaders_INCLUDE_DIR VulkanRegistry_DIR)
diff --git a/extern/openxr/src/cmake/cmake_uninstall.cmake.in b/extern/openxr/src/cmake/cmake_uninstall.cmake.in
new file mode 100644
index 00000000000..2037e365393
--- /dev/null
+++ b/extern/openxr/src/cmake/cmake_uninstall.cmake.in
@@ -0,0 +1,21 @@
+if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+string(REGEX REPLACE "\n" ";" files "${files}")
+foreach(file ${files})
+ message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
+ if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ exec_program(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ if(NOT "${rm_retval}" STREQUAL 0)
+ message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
+ endif(NOT "${rm_retval}" STREQUAL 0)
+ else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
+ endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+endforeach(file)
diff --git a/extern/openxr/src/cmake/presentation.cmake b/extern/openxr/src/cmake/presentation.cmake
new file mode 100644
index 00000000000..1abcc0e66f7
--- /dev/null
+++ b/extern/openxr/src/cmake/presentation.cmake
@@ -0,0 +1,101 @@
+set(PRESENTATION_BACKENDS xlib xcb wayland)
+set(PRESENTATION_BACKEND xlib CACHE STRING
+ "Presentation backend chosen at configure time")
+set_property(CACHE PRESENTATION_BACKEND PROPERTY STRINGS
+ ${PRESENTATION_BACKENDS})
+
+list(FIND PRESENTATION_BACKENDS ${PRESENTATION_BACKEND} index)
+if(index EQUAL -1)
+ message(FATAL_ERROR "Presentation backend must be one of
+ ${PRESENTATION_BACKENDS}")
+endif()
+
+message(STATUS "Using presentation backend: ${PRESENTATION_BACKEND}")
+
+
+if( PRESENTATION_BACKEND MATCHES "xlib" )
+ find_package(X11 REQUIRED)
+ if ((NOT X11_Xxf86vm_LIB) OR (NOT X11_Xrandr_LIB))
+ message(FATAL_ERROR "OpenXR xlib backend requires Xxf86vm and Xrandr")
+ endif()
+
+ add_definitions( -DSUPPORT_X )
+ add_definitions( -DOS_LINUX_XLIB )
+ set( XLIB_LIBRARIES
+ ${X11_LIBRARIES}
+ ${X11_Xxf86vm_LIB}
+ ${X11_Xrandr_LIB} )
+
+elseif( PRESENTATION_BACKEND MATCHES "xcb" )
+ find_package(PkgConfig REQUIRED)
+ # XCB + XCB GLX is limited to OpenGL 2.1
+ # add_definitions( -DOS_LINUX_XCB )
+ # XCB + Xlib GLX 1.3
+ add_definitions( -DOS_LINUX_XCB_GLX )
+
+ pkg_search_module(X11 REQUIRED x11)
+ pkg_search_module(XCB REQUIRED xcb)
+ pkg_search_module(XCB_RANDR REQUIRED xcb-randr)
+ pkg_search_module(XCB_KEYSYMS REQUIRED xcb-keysyms)
+ pkg_search_module(XCB_GLX REQUIRED xcb-glx)
+ pkg_search_module(XCB_DRI2 REQUIRED xcb-dri2)
+ pkg_search_module(XCB_ICCCM REQUIRED xcb-icccm)
+
+ set( XCB_LIBRARIES
+ ${XCB_LIBRARIES}
+ ${XCB_KEYSYMS_LIBRARIES}
+ ${XCB_RANDR_LIBRARIES}
+ ${XCB_GLX_LIBRARIES}
+ ${XCB_DRI2_LIBRARIES}
+ ${X11_LIBRARIES} )
+
+elseif( PRESENTATION_BACKEND MATCHES "wayland" )
+ find_package(PkgConfig REQUIRED)
+ pkg_search_module(WAYLAND_CLIENT REQUIRED wayland-client)
+ pkg_search_module(WAYLAND_EGL REQUIRED wayland-egl)
+ pkg_search_module(WAYLAND_SCANNER REQUIRED wayland-scanner)
+ pkg_search_module(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.7)
+ pkg_search_module(EGL REQUIRED egl)
+
+ add_definitions( -DOS_LINUX_WAYLAND )
+ set( WAYLAND_LIBRARIES
+ ${EGL_LIBRARIES}
+ ${WAYLAND_CLIENT_LIBRARIES}
+ ${WAYLAND_EGL_LIBRARIES} )
+
+ # generate wayland protocols
+ set(WAYLAND_PROTOCOLS_DIR ${CMAKE_SOURCE_DIR}/wayland-protocols/)
+ file(MAKE_DIRECTORY ${WAYLAND_PROTOCOLS_DIR})
+
+ pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir)
+ pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
+
+ set(PROTOCOL xdg-shell-unstable-v6)
+ set(PROTOCOL_XML
+ ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/${PROTOCOL}.xml)
+
+ if( EXISTS ${PROTOCOL_XML} )
+ execute_process(COMMAND
+ ${WAYLAND_SCANNER}
+ code
+ ${PROTOCOL_XML}
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c)
+ execute_process(COMMAND
+ ${WAYLAND_SCANNER}
+ client-header
+ ${PROTOCOL_XML}
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h)
+
+ set( WAYLAND_PROTOCOL_SRC
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c
+ ${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h )
+
+ include_directories(${WAYLAND_PROTOCOLS_DIR})
+ else()
+ message(FATAL_ERROR
+ "xdg-shell-unstable-v6.xml not found in "
+ ${WAYLAND_PROTOCOLS_DATADIR}
+ "\nYour wayland-protocols package does not "
+ "contain xdg-shell-unstable-v6.")
+ endif()
+endif()
diff --git a/extern/openxr/src/common/extra_algorithms.h b/extern/openxr/src/common/extra_algorithms.h
new file mode 100644
index 00000000000..f181a90d174
--- /dev/null
+++ b/extern/openxr/src/common/extra_algorithms.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+/*!
+ * @file
+ *
+ * Additional functions along the lines of the standard library algorithms.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <vector>
+
+/// Like std::remove_if, except it works on associative containers and it actually removes this.
+///
+/// The iterator stuff in here is subtle - .erase() invalidates only that iterator, but it returns a non-invalidated iterator to the
+/// next valid element which we can use instead of incrementing.
+template <typename T, typename Pred>
+static inline void map_erase_if(T &container, Pred &&predicate) {
+ for (auto it = container.begin(); it != container.end();) {
+ if (predicate(*it)) {
+ it = container.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+/*!
+ * Moves all elements matching the predicate to the end of the vector then erases them.
+ *
+ * Combines the two parts of the erase-remove idiom to simplify things and avoid accidentally using the wrong erase overload.
+ */
+template <typename T, typename Alloc, typename Pred>
+static inline void vector_remove_if_and_erase(std::vector<T, Alloc> &vec, Pred &&predicate) {
+ auto b = vec.begin();
+ auto e = vec.end();
+ vec.erase(std::remove_if(b, e, std::forward<Pred>(predicate)), e);
+}
diff --git a/extern/openxr/src/common/filesystem_utils.cpp b/extern/openxr/src/common/filesystem_utils.cpp
new file mode 100644
index 00000000000..63671504b17
--- /dev/null
+++ b/extern/openxr/src/common/filesystem_utils.cpp
@@ -0,0 +1,330 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Authors: Mark Young <marky@lunarg.com>
+// Nat Brown <natb@valvesoftware.com>
+//
+
+#include "filesystem_utils.hpp"
+
+#include "platform_utils.hpp"
+
+#ifdef _WIN32
+#include "xr_dependencies.h"
+#endif
+
+#include <cstring>
+
+#if defined DISABLE_STD_FILESYSTEM
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 0
+
+#else
+// If the C++ macro is set to the version containing C++17, it must support
+// the final C++17 package
+#if __cplusplus >= 201703L
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 1
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1900
+
+#if defined(_HAS_CXX17) && _HAS_CXX17
+// When MSC supports c++17 use <filesystem> package.
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 1
+#endif // !_HAS_CXX17
+
+// Right now, GCC still only supports the experimental filesystem items starting in GCC 6
+#elif (__GNUC__ >= 6)
+#define USE_EXPERIMENTAL_FS 1
+#define USE_FINAL_FS 0
+
+// If Clang, check for feature support
+#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
+#if __cpp_lib_filesystem
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 1
+#else
+#define USE_EXPERIMENTAL_FS 1
+#define USE_FINAL_FS 0
+#endif
+
+// If all above fails, fall back to standard C++ and OS-specific items
+#else
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 0
+#endif
+#endif
+
+#if USE_FINAL_FS == 1
+#include <filesystem>
+#define FS_PREFIX std::filesystem
+#elif USE_EXPERIMENTAL_FS == 1
+#include <experimental/filesystem>
+#define FS_PREFIX std::experimental::filesystem
+#elif defined(XR_USE_PLATFORM_WIN32)
+// Windows fallback includes
+#include <stdint.h>
+#include <direct.h>
+#else
+// Linux/Apple fallback includes
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+#endif
+
+#if defined(XR_USE_PLATFORM_WIN32)
+#define PATH_SEPARATOR ';'
+#define DIRECTORY_SYMBOL '\\'
+#else
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+#endif
+
+#if (USE_FINAL_FS == 1) || (USE_EXPERIMENTAL_FS == 1)
+// We can use one of the C++ filesystem packages
+
+bool FileSysUtilsIsRegularFile(const std::string& path) { return FS_PREFIX::is_regular_file(path); }
+
+bool FileSysUtilsIsDirectory(const std::string& path) { return FS_PREFIX::is_directory(path); }
+
+bool FileSysUtilsPathExists(const std::string& path) { return FS_PREFIX::exists(path); }
+
+bool FileSysUtilsIsAbsolutePath(const std::string& path) {
+ FS_PREFIX::path file_path(path);
+ return file_path.is_absolute();
+}
+
+bool FileSysUtilsGetCurrentPath(std::string& path) {
+ FS_PREFIX::path cur_path = FS_PREFIX::current_path();
+ path = cur_path.string();
+ return true;
+}
+
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
+ FS_PREFIX::path path_var(file_path);
+ parent_path = path_var.parent_path().string();
+ return true;
+}
+
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
+ absolute = FS_PREFIX::absolute(path).string();
+ return true;
+}
+
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
+ FS_PREFIX::path parent_path(parent);
+ FS_PREFIX::path child_path(child);
+ FS_PREFIX::path full_path = parent_path / child_path;
+ combined = full_path.string();
+ return true;
+}
+
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
+ std::string::size_type start = 0;
+ std::string::size_type location = path_list.find(PATH_SEPARATOR);
+ while (location != std::string::npos) {
+ paths.push_back(path_list.substr(start, location));
+ start = location + 1;
+ location = path_list.find(PATH_SEPARATOR, start);
+ }
+ paths.push_back(path_list.substr(start, location));
+ return true;
+}
+
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
+ for (auto& dir_iter : FS_PREFIX::directory_iterator(path)) {
+ files.push_back(dir_iter.path().filename().string());
+ }
+ return true;
+}
+
+#elif defined(XR_OS_WINDOWS)
+
+// For pre C++17 compiler that doesn't support experimental filesystem
+#include <shlwapi.h>
+
+bool FileSysUtilsIsRegularFile(const std::string& path) { return (1 != PathIsDirectoryW(utf8_to_wide(path).c_str())); }
+
+bool FileSysUtilsIsDirectory(const std::string& path) { return (1 == PathIsDirectoryW(utf8_to_wide(path).c_str())); }
+
+bool FileSysUtilsPathExists(const std::string& path) { return (1 == PathFileExistsW(utf8_to_wide(path).c_str())); }
+
+bool FileSysUtilsIsAbsolutePath(const std::string& path) {
+ if ((path[0] == '\\') || (path[1] == ':' && (path[2] == '\\' || path[2] == '/'))) {
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetCurrentPath(std::string& path) {
+ wchar_t tmp_path[MAX_PATH];
+ if (nullptr != _wgetcwd(tmp_path, MAX_PATH - 1)) {
+ path = wide_to_utf8(tmp_path);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
+ std::string full_path;
+ if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
+ std::string::size_type lastSeperator = full_path.find_last_of(DIRECTORY_SYMBOL);
+ parent_path = (lastSeperator == 0) ? full_path : full_path.substr(0, lastSeperator);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
+ wchar_t tmp_path[MAX_PATH];
+ if (0 != GetFullPathNameW(utf8_to_wide(path).c_str(), MAX_PATH, tmp_path, NULL)) {
+ absolute = wide_to_utf8(tmp_path);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
+ std::string::size_type parent_len = parent.length();
+ if (0 == parent_len || "." == parent || ".\\" == parent || "./" == parent) {
+ combined = child;
+ return true;
+ }
+ char last_char = parent[parent_len - 1];
+ if (last_char == DIRECTORY_SYMBOL) {
+ parent_len--;
+ }
+ combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
+ return true;
+}
+
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
+ std::string::size_type start = 0;
+ std::string::size_type location = path_list.find(PATH_SEPARATOR);
+ while (location != std::string::npos) {
+ paths.push_back(path_list.substr(start, location));
+ start = location + 1;
+ location = path_list.find(PATH_SEPARATOR, start);
+ }
+ paths.push_back(path_list.substr(start, location));
+ return true;
+}
+
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
+ WIN32_FIND_DATAW file_data;
+ HANDLE file_handle = FindFirstFileW(utf8_to_wide(path).c_str(), &file_data);
+ if (file_handle != INVALID_HANDLE_VALUE) {
+ do {
+ if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ files.push_back(wide_to_utf8(file_data.cFileName));
+ }
+ } while (FindNextFileW(file_handle, &file_data));
+ return true;
+ }
+ return false;
+}
+
+#else // XR_OS_LINUX/XR_OS_APPLE fallback
+
+// simple POSIX-compatible implementation of the <filesystem> pieces used by OpenXR
+
+bool FileSysUtilsIsRegularFile(const std::string& path) {
+ struct stat path_stat;
+ stat(path.c_str(), &path_stat);
+ return S_ISREG(path_stat.st_mode);
+}
+
+bool FileSysUtilsIsDirectory(const std::string& path) {
+ struct stat path_stat;
+ stat(path.c_str(), &path_stat);
+ return S_ISDIR(path_stat.st_mode);
+}
+
+bool FileSysUtilsPathExists(const std::string& path) { return (access(path.c_str(), F_OK) != -1); }
+
+bool FileSysUtilsIsAbsolutePath(const std::string& path) { return (path[0] == DIRECTORY_SYMBOL); }
+
+bool FileSysUtilsGetCurrentPath(std::string& path) {
+ char tmp_path[PATH_MAX];
+ if (nullptr != getcwd(tmp_path, PATH_MAX - 1)) {
+ path = tmp_path;
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
+ std::string full_path;
+ if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
+ std::string::size_type lastSeperator = full_path.find_last_of(DIRECTORY_SYMBOL);
+ parent_path = (lastSeperator == 0) ? full_path : full_path.substr(0, lastSeperator);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
+ char buf[PATH_MAX];
+ if (nullptr != realpath(path.c_str(), buf)) {
+ absolute = buf;
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
+ std::string::size_type parent_len = parent.length();
+ if (0 == parent_len || "." == parent || "./" == parent) {
+ combined = child;
+ return true;
+ }
+ char last_char = parent[parent_len - 1];
+ if (last_char == DIRECTORY_SYMBOL) {
+ parent_len--;
+ }
+ combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
+ return true;
+}
+
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
+ std::string::size_type start = 0;
+ std::string::size_type location = path_list.find(PATH_SEPARATOR);
+ while (location != std::string::npos) {
+ paths.push_back(path_list.substr(start, location));
+ start = location + 1;
+ location = path_list.find(PATH_SEPARATOR, start);
+ }
+ paths.push_back(path_list.substr(start, location));
+ return true;
+}
+
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
+ DIR* dir = opendir(path.c_str());
+ if (dir == nullptr) {
+ return false;
+ }
+ struct dirent* entry;
+ while ((entry = readdir(dir)) != nullptr) {
+ files.emplace_back(entry->d_name);
+ }
+ closedir(dir);
+ return true;
+}
+
+#endif
diff --git a/extern/openxr/src/common/filesystem_utils.hpp b/extern/openxr/src/common/filesystem_utils.hpp
new file mode 100644
index 00000000000..477e2d35cc0
--- /dev/null
+++ b/extern/openxr/src/common/filesystem_utils.hpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+// Determine if the path indicates a regular file (not a directory or symbolic link)
+bool FileSysUtilsIsRegularFile(const std::string& path);
+
+// Determine if the path indicates a directory
+bool FileSysUtilsIsDirectory(const std::string& path);
+
+// Determine if the provided path exists on the filesystem
+bool FileSysUtilsPathExists(const std::string& path);
+
+// Get the current directory of the executable
+bool FileSysUtilsGetCurrentPath(std::string& path);
+
+// Get the parent path of a file
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path);
+
+// Determine if the provided path is an absolute path
+bool FileSysUtilsIsAbsolutePath(const std::string& path);
+
+// Get the absolute path for a provided file
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute);
+
+// Combine a parent and child directory
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined);
+
+// Parse out individual paths in a path list
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths);
+
+// Record all the filenames for files found in the provided path.
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files);
diff --git a/extern/openxr/src/common/hex_and_handles.cpp b/extern/openxr/src/common/hex_and_handles.cpp
new file mode 100644
index 00000000000..df691de6922
--- /dev/null
+++ b/extern/openxr/src/common/hex_and_handles.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+/*!
+ * @file
+ *
+ * Implementations of the include-requiring hex conversion functions.
+ */
+
+#include "hex_and_handles.h"
+
+#include <sstream>
+#include <iomanip>
+
+std::string Uint64ToHexString(uint64_t val) {
+ std::ostringstream oss;
+ oss << "0x";
+ oss << std::hex << std::setw(16) << std::setfill('0') << val;
+ return oss.str();
+}
+
+std::string Uint32ToHexString(uint32_t val) {
+ std::ostringstream oss;
+ oss << "0x";
+ oss << std::hex << std::setw(8) << std::setfill('0') << val;
+ return oss.str();
+}
diff --git a/extern/openxr/src/common/hex_and_handles.h b/extern/openxr/src/common/hex_and_handles.h
new file mode 100644
index 00000000000..41af39adf8b
--- /dev/null
+++ b/extern/openxr/src/common/hex_and_handles.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+/*!
+ * @file
+ *
+ * Some utilities, primarily for working with OpenXR handles in a generic way.
+ *
+ * Most are trivial and inlined by default, but a few involve some non-trivial standard headers:
+ * the various `...ToHexString`functions.
+ * If you want those, make sure your build includes the corresponding hex_and_handles.cpp file.
+ */
+
+#pragma once
+
+#include <openxr/openxr.h>
+
+#include <string>
+#include <stdint.h>
+
+#if XR_PTR_SIZE == 8
+/// Convert a handle into a same-sized integer.
+template <typename T>
+static inline uint64_t MakeHandleGeneric(T handle) {
+ return reinterpret_cast<uint64_t>(handle);
+}
+
+/// Treat an integer as a handle
+template <typename T>
+static inline T& TreatIntegerAsHandle(uint64_t& handle) {
+ return reinterpret_cast<T&>(handle);
+}
+
+/// @overload
+template <typename T>
+static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
+ return reinterpret_cast<T const&>(handle);
+}
+
+/// Does a correctly-sized integer represent a null handle?
+static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == reinterpret_cast<void*>(handle); }
+
+#else
+
+/// Convert a handle into a same-sized integer: no-op on 32-bit systems
+static inline uint64_t MakeHandleGeneric(uint64_t handle) { return handle; }
+
+/// Treat an integer as a handle: no-op on 32-bit systems
+template <typename T>
+static inline T& TreatIntegerAsHandle(uint64_t& handle) {
+ return handle;
+}
+
+/// @overload
+template <typename T>
+static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
+ return handle;
+}
+
+/// Does a correctly-sized integer represent a null handle?
+static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == handle; }
+
+#endif
+
+/// Turns a uint64_t into a string formatted as hex.
+///
+/// The core of the HandleToHexString implementation is in here.
+std::string Uint64ToHexString(uint64_t val);
+
+/// Turns a uint32_t into a string formatted as hex.
+std::string Uint32ToHexString(uint32_t val);
+
+/// Turns an OpenXR handle into a string formatted as hex.
+template <typename T>
+static inline std::string HandleToHexString(T handle) {
+ return Uint64ToHexString(MakeHandleGeneric(handle));
+}
+
+#if XR_PTR_SIZE == 8
+/// Turns a pointer-sized integer into a string formatted as hex.
+static inline std::string UintptrToHexString(uintptr_t val) { return Uint64ToHexString(val); }
+#else
+/// Turns a pointer-sized integer into a string formatted as hex.
+static inline std::string UintptrToHexString(uintptr_t val) { return Uint32ToHexString(val); }
+#endif
+
+/// Convert a pointer to a string formatted as hex.
+template <typename T>
+static inline std::string PointerToHexString(T const* ptr) {
+ return UintptrToHexString(reinterpret_cast<uintptr_t>(ptr));
+}
diff --git a/extern/openxr/src/common/loader_interfaces.h b/extern/openxr/src/common/loader_interfaces.h
new file mode 100644
index 00000000000..23500d8976b
--- /dev/null
+++ b/extern/openxr/src/common/loader_interfaces.h
@@ -0,0 +1,122 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Forward declare.
+typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo;
+
+// Function pointer prototype for the xrCreateApiLayerInstance function used in place of xrCreateInstance.
+// This function allows us to pass special API layer information to each layer during the process of creating an Instance.
+typedef XrResult(XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info,
+ const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance);
+
+// Loader/API Layer Interface versions
+// 1 - First version, introduces negotiation structure and functions
+#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
+
+// Loader/Runtime Interface versions
+// 1 - First version, introduces negotiation structure and functions
+#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
+
+// Version negotiation values
+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;
+
+#define XR_LOADER_INFO_STRUCT_VERSION 1
+typedef struct 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;
+} XrNegotiateLoaderInfo;
+
+#define XR_API_LAYER_INFO_STRUCT_VERSION 1
+typedef struct XrNegotiateApiLayerRequest {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST
+ uint32_t structVersion; // XR_API_LAYER_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrNegotiateApiLayerRequest)
+ uint32_t layerInterfaceVersion; // CURRENT_LOADER_API_LAYER_VERSION
+ XrVersion layerApiVersion;
+ PFN_xrGetInstanceProcAddr getInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance createApiLayerInstance;
+} XrNegotiateApiLayerRequest;
+
+#define XR_RUNTIME_INFO_STRUCT_VERSION 1
+typedef struct 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;
+} XrNegotiateRuntimeRequest;
+
+// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or
+// more API layers needs to expose at least this function.
+typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo *loaderInfo,
+ const char *apiLayerName,
+ XrNegotiateApiLayerRequest *apiLayerRequest);
+
+// Function used to negotiate an interface betewen the loader and a runtime. Each runtime should expose
+// at least this function.
+typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo *loaderInfo,
+ XrNegotiateRuntimeRequest *runtimeRequest);
+
+// Forward declare.
+typedef struct XrApiLayerNextInfo XrApiLayerNextInfo;
+
+#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
+struct XrApiLayerNextInfo {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO
+ uint32_t structVersion; // XR_API_LAYER_NEXT_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrApiLayerNextInfo)
+ char layerName[XR_MAX_API_LAYER_NAME_SIZE]; // Name of API layer which should receive this info
+ PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; // Pointer to next API layer's xrGetInstanceProcAddr
+ PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; // Pointer to next API layer's xrCreateApiLayerInstance
+ XrApiLayerNextInfo *next; // Pointer to the next API layer info in the sequence
+};
+
+#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
+#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
+typedef struct XrApiLayerCreateInfo {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO
+ uint32_t structVersion; // XR_API_LAYER_CREATE_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrApiLayerCreateInfo)
+ void *loaderInstance; // Pointer to the LoaderInstance class
+ char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; // Location to the found settings file (or empty '\0')
+ XrApiLayerNextInfo *nextInfo; // Pointer to the next API layer's Info
+} XrApiLayerCreateInfo;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/extern/openxr/src/common/platform_utils.hpp b/extern/openxr/src/common/platform_utils.hpp
new file mode 100644
index 00000000000..f7b7e8d6ebb
--- /dev/null
+++ b/extern/openxr/src/common/platform_utils.hpp
@@ -0,0 +1,221 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include "xr_dependencies.h"
+#include <string>
+
+#if defined(XR_OS_LINUX)
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+#endif
+
+// This is a CMake generated file with #defines for any functions/includes
+// that it found present. This is currently necessary to properly determine
+// if secure_getenv or __secure_getenv are present
+#if !defined(OPENXR_NON_CMAKE_BUILD)
+#include "common_cmake_config.h"
+#endif // !defined(OPENXR_NON_CMAKE_BUILD)
+
+// Environment variables
+#if defined(XR_OS_LINUX)
+
+static inline char* PlatformUtilsGetEnv(const char* name) { return getenv(name); }
+
+static inline char* PlatformUtilsGetSecureEnv(const char* name) {
+#ifdef HAVE_SECURE_GETENV
+ return secure_getenv(name);
+#elif defined(HAVE___SECURE_GETENV)
+ return __secure_getenv(name);
+#else
+#pragma message( \
+ "Warning: Falling back to non-secure getenv for environmental" \
+ "lookups! Consider updating to a different libc.")
+
+ return PlatformUtilsGetEnv(name);
+#endif
+}
+
+static inline void PlatformUtilsFreeEnv(const char* val) {
+ // No freeing of memory necessary for Linux, but we should at least touch
+ // the val and inst pointers to get rid of compiler warnings.
+ (void)val;
+}
+
+#elif defined(XR_OS_APPLE)
+
+static inline char *PlatformUtilsGetEnv(const char *name) { return getenv(name); }
+
+static inline char *PlatformUtilsGetSecureEnv(const char *name) {
+#ifdef HAVE_SECURE_GETENV
+ return secure_getenv(name);
+#elif defined(HAVE___SECURE_GETENV)
+ return __secure_getenv(name);
+#else
+#pragma message( \
+ "Warning: Falling back to non-secure getenv for environmental" \
+ "lookups! Consider updating to a different libc.")
+
+ return PlatformUtilsGetEnv(name);
+#endif
+}
+
+static inline void PlatformUtilsFreeEnv(char *val) {
+ // No freeing of memory necessary for Linux, but we should at least touch
+ // the val and inst pointers to get rid of compiler warnings.
+ (void)val;
+}
+
+// Prefix for the Apple global runtime JSON file name
+static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
+static const std::string rt_filename = "/active_runtime.json";
+
+static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
+ file_name = rt_dir_prefix;
+ file_name += std::to_string(major_version);
+ file_name += rt_filename;
+ return true;
+}
+
+#elif defined(XR_OS_WINDOWS)
+
+#if defined(_DEBUG)
+inline void LogError(const std::string& error) { OutputDebugStringA(error.c_str()); }
+#else
+#define LogError(x)
+#endif
+
+inline std::wstring utf8_to_wide(const std::string& utf8Text) {
+ if (utf8Text.empty()) {
+ return {};
+ }
+
+ std::wstring wideText;
+ const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0);
+ if (wideLength == 0) {
+ LogError("utf8_to_wide get size error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ // MultiByteToWideChar returns number of chars of the input buffer, regardless of null terminitor
+ wideText.resize(wideLength, 0);
+ wchar_t* wideString = const_cast<wchar_t*>(wideText.data()); // mutable data() only exists in c++17
+ const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideString, wideLength);
+ if (length != wideLength) {
+ LogError("utf8_to_wide convert string error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ return wideText;
+}
+
+inline std::string wide_to_utf8(const std::wstring& wideText) {
+ if (wideText.empty()) {
+ return {};
+ }
+
+ std::string narrowText;
+ int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr);
+ if (narrowLength == 0) {
+ LogError("wide_to_utf8 get size error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ // WideCharToMultiByte returns number of chars of the input buffer, regardless of null terminitor
+ narrowText.resize(narrowLength, 0);
+ char* narrowString = const_cast<char*>(narrowText.data()); // mutable data() only exists in c++17
+ const int length =
+ ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowString, narrowLength, nullptr, nullptr);
+ if (length != narrowLength) {
+ LogError("wide_to_utf8 convert string error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ return narrowText;
+}
+
+static inline char* PlatformUtilsGetEnv(const char* name) {
+ const std::wstring wname = utf8_to_wide(name);
+ const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
+
+ // GetEnvironmentVariable returns 0 when environment variable does not exist
+ if (valSize == 0) {
+ return nullptr;
+ }
+
+ // GetEnvironmentVariable returns size including null terminator for "query size" call.
+ std::wstring wValue(valSize, 0);
+ wchar_t* wValueData = const_cast<wchar_t*>(wValue.data()); // mutable data() only exists in c++17
+
+ // GetEnvironmentVariable returns string length, excluding null terminator for "get value" call.
+ const int length = ::GetEnvironmentVariableW(wname.c_str(), wValueData, (DWORD)wValue.size());
+ if (!length) {
+ LogError("GetEnvironmentVariable get value error: " + std::to_string(::GetLastError()));
+ return nullptr;
+ }
+
+ const std::string value = wide_to_utf8(wValue);
+
+ // Allocate the space necessary for the result
+ char* retVal = new char[value.size() + 1]{};
+ value.copy(retVal, value.size());
+ return retVal;
+}
+
+static inline char* PlatformUtilsGetSecureEnv(const char* name) {
+ // No secure version for Windows as far as I know
+ return PlatformUtilsGetEnv(name);
+}
+
+static inline void PlatformUtilsFreeEnv(char* val) {
+ if (nullptr != val) {
+ delete[] val;
+ val = nullptr;
+ }
+}
+
+#else // Not Linux or Windows
+
+static inline char *PlatformUtilsGetEnv(const char *name) {
+ // Stub func
+ (void)name;
+ return nullptr;
+}
+
+static inline char *PlatformUtilsGetSecureEnv(const char *name) {
+ // Stub func
+ (void)name;
+ return nullptr;
+}
+
+static inline void PlatformUtilsFreeEnv(char *val) {
+ // Stub func
+ (void)val;
+}
+
+static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string &file_name) {
+ // Stub func
+ (void)major_version;
+ (void)file_name;
+ return false;
+}
+
+#endif
diff --git a/extern/openxr/src/common/xr_dependencies.h b/extern/openxr/src/common/xr_dependencies.h
new file mode 100644
index 00000000000..81d0092c791
--- /dev/null
+++ b/extern/openxr/src/common/xr_dependencies.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2018-2019 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file includes headers with types which openxr.h depends on in order
+// to compile when platforms, graphics apis, and the like are enabled.
+
+#pragma once
+
+#ifdef XR_USE_PLATFORM_ANDROID
+#include <android/native_window.h>
+#endif // XR_USE_PLATFORM_ANDROID
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM))
+// Enable desktop partition APIs, such as RegOpenKeyEx, LoadLibraryEx, PathFileExists etc.
+#undef WINAPI_PARTITION_DESKTOP
+#define WINAPI_PARTITION_DESKTOP 1
+#endif
+
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#endif // XR_USE_PLATFORM_WIN32
+
+#ifdef XR_USE_GRAPHICS_API_D3D11
+#include <d3d11.h>
+#endif // XR_USE_GRAPHICS_API_D3D11
+
+#ifdef XR_USE_GRAPHICS_API_D3D12
+#include <d3d12.h>
+#endif // XR_USE_GRAPHICS_API_D3D12
+
+#ifdef XR_USE_PLATFORM_XLIB
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif // XR_USE_PLATFORM_XLIB
+
+#ifdef XR_USE_PLATFORM_XCB
+#include <xcb/xcb.h>
+#endif // XR_USE_PLATFORM_XCB
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL
+#if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB)
+#include <GL/glx.h>
+#endif // (XR_USE_PLATFORM_XLIB || XR_USE_PLATFORM_XCB)
+#ifdef XR_USE_PLATFORM_XCB
+#include <xcb/glx.h>
+#endif // XR_USE_PLATFORM_XCB
+#ifdef XR_USE_PLATFORM_MACOS
+#include <CL/cl_gl_ext.h>
+#endif // XR_USE_PLATFORM_MACOS
+#endif // XR_USE_GRAPHICS_API_OPENGL
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
+#include <EGL/egl.h>
+#endif // XR_USE_GRAPHICS_API_OPENGL_ES
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+#include <vulkan/vulkan.h>
+#endif // XR_USE_GRAPHICS_API_VULKAN
+
+#ifdef XR_USE_PLATFORM_WAYLAND
+#include "wayland-client.h"
+#endif // XR_USE_PLATFORM_WAYLAND
diff --git a/extern/openxr/src/common/xr_linear.h b/extern/openxr/src/common/xr_linear.h
new file mode 100644
index 00000000000..663c346401b
--- /dev/null
+++ b/extern/openxr/src/common/xr_linear.h
@@ -0,0 +1,773 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2016 Oculus VR, LLC.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: J.M.P. van Waveren
+//
+
+#ifndef XR_LINEAR_H_
+#define XR_LINEAR_H_
+
+#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX) || defined(OS_LINUX_WAYLAND)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
+
+#include <openxr/openxr.h>
+
+/*
+================================================================================================
+
+Description : Vector, matrix and quaternion math.
+Author : J.M.P. van Waveren
+Date : 12/10/2016
+Language : C99
+Format : Indent 4 spaces - no tabs.
+Copyright : Copyright (c) 2016 Oculus VR, LLC. All Rights reserved.
+
+
+DESCRIPTION
+===========
+
+All matrices are column-major.
+
+INTERFACE
+=========
+
+XrVector2f
+XrVector3f
+XrVector4f
+XrQuaternionf
+XrMatrix4x4f
+
+inline static void XrVector3f_Set(XrVector3f* v, const float value);
+inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value);
+inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction);
+inline static void XrVector3f_Normalize(XrVector3f* v);
+inline static float XrVector3f_Length(const XrVector3f* v);
+
+inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction);
+
+inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result);
+inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z);
+inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
+ const float degreesZ);
+inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z);
+inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
+ const XrQuaternionf* rotation, const XrVector3f* scale);
+inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, const float tanAngleLeft, const float tanAngleRight,
+ const float tanAngleUp, float const tanAngleDown, const float nearZ,
+ const float farZ);
+inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, const float fovDegreesLeft, const float fovDegreesRight,
+ const float fovDegreeUp, const float fovDegreesDown, const float nearZ,
+ const float farZ);
+inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* src);
+inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
+ const XrVector3f* maxs);
+
+inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon);
+inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon);
+inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon);
+inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon);
+
+inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src);
+
+inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b);
+inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src);
+
+inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v);
+inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v);
+
+inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
+ const XrVector3f* mins, const XrVector3f* maxs);
+inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs);
+
+================================================================================================
+*/
+
+#include <assert.h>
+#include <math.h>
+#include <stdbool.h>
+
+#define MATH_PI 3.14159265358979323846f
+
+#define DEFAULT_NEAR_Z 0.015625f // exact floating point representation
+#define INFINITE_FAR_Z 0.0f
+
+static const XrColor4f XrColorRed = {1.0f, 0.0f, 0.0f, 1.0f};
+static const XrColor4f XrColorGreen = {0.0f, 1.0f, 0.0f, 1.0f};
+static const XrColor4f XrColorBlue = {0.0f, 0.0f, 1.0f, 1.0f};
+static const XrColor4f XrColorYellow = {1.0f, 1.0f, 0.0f, 1.0f};
+static const XrColor4f XrColorPurple = {1.0f, 0.0f, 1.0f, 1.0f};
+static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f};
+static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f};
+static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f};
+
+enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D };
+
+// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
+struct XrMatrix4x4f {
+ float m[16];
+};
+
+inline static float XrRcpSqrt(const float x) {
+ const float SMALLEST_NON_DENORMAL = 1.1754943508222875e-038f; // ( 1U << 23 )
+ const float rcp = (x >= SMALLEST_NON_DENORMAL) ? 1.0f / sqrtf(x) : 1.0f;
+ return rcp;
+}
+
+inline static void XrVector3f_Set(XrVector3f* v, const float value) {
+ v->x = value;
+ v->y = value;
+ v->z = value;
+}
+
+inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = a->x + b->x;
+ result->y = a->y + b->y;
+ result->z = a->z + b->z;
+}
+
+inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = a->x - b->x;
+ result->y = a->y - b->y;
+ result->z = a->z - b->z;
+}
+
+inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = (a->x < b->x) ? a->x : b->x;
+ result->y = (a->y < b->y) ? a->y : b->y;
+ result->z = (a->z < b->z) ? a->z : b->z;
+}
+
+inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = (a->x > b->x) ? a->x : b->x;
+ result->y = (a->y > b->y) ? a->y : b->y;
+ result->z = (a->z > b->z) ? a->z : b->z;
+}
+
+inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value) {
+ result->x = (fabsf(a->x) > value) ? ((a->x > 0.0f) ? (a->x - value) : (a->x + value)) : 0.0f;
+ result->y = (fabsf(a->y) > value) ? ((a->y > 0.0f) ? (a->y - value) : (a->y + value)) : 0.0f;
+ result->z = (fabsf(a->z) > value) ? ((a->z > 0.0f) ? (a->z - value) : (a->z + value)) : 0.0f;
+}
+
+inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction) {
+ result->x = a->x + fraction * (b->x - a->x);
+ result->y = a->y + fraction * (b->y - a->y);
+ result->z = a->z + fraction * (b->z - a->z);
+}
+
+inline static float XrVector3f_Dot(const XrVector3f* a, const XrVector3f* b) { return a->x * b->x + a->y * b->y + a->z * b->z; }
+
+// Compute cross product, which generates a normal vector.
+// Direction vector can be determined by right-hand rule: Pointing index finder in
+// direction a and middle finger in direction b, thumb will point in Cross(a, b).
+inline static void XrVector3f_Cross(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = a->y * b->z - a->z * b->y;
+ result->y = a->z * b->x - a->x * b->z;
+ result->x = a->x * b->y - a->y * b->x;
+}
+
+inline static void XrVector3f_Normalize(XrVector3f* v) {
+ const float lengthRcp = XrRcpSqrt(v->x * v->x + v->y * v->y + v->z * v->z);
+ v->x *= lengthRcp;
+ v->y *= lengthRcp;
+ v->z *= lengthRcp;
+}
+
+inline static float XrVector3f_Length(const XrVector3f* v) { return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); }
+
+inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians) {
+ float s = sinf(angleInRadians / 2.0f);
+ float lengthRcp = XrRcpSqrt(axis->x * axis->x + axis->y * axis->y + axis->z * axis->z);
+ result->x = s * axis->x * lengthRcp;
+ result->y = s * axis->y * lengthRcp;
+ result->z = s * axis->z * lengthRcp;
+ result->w = cosf(angleInRadians / 2.0f);
+}
+
+inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction) {
+ const float s = a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w;
+ const float fa = 1.0f - fraction;
+ const float fb = (s < 0.0f) ? -fraction : fraction;
+ const float x = a->x * fa + b->x * fb;
+ const float y = a->y * fa + b->y * fb;
+ const float z = a->z * fa + b->z * fb;
+ const float w = a->w * fa + b->w * fb;
+ const float lengthRcp = XrRcpSqrt(x * x + y * y + z * z + w * w);
+ result->x = x * lengthRcp;
+ result->y = y * lengthRcp;
+ result->z = z * lengthRcp;
+ result->w = w * lengthRcp;
+}
+
+// Use left-multiplication to accumulate transformations.
+inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
+ result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
+ result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
+ result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
+ result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];
+
+ result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
+ result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
+ result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
+ result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];
+
+ result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
+ result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
+ result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
+ result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];
+
+ result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
+ result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
+ result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
+ result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
+}
+
+// Creates the transpose of the given matrix.
+inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
+ result->m[0] = src->m[0];
+ result->m[1] = src->m[4];
+ result->m[2] = src->m[8];
+ result->m[3] = src->m[12];
+
+ result->m[4] = src->m[1];
+ result->m[5] = src->m[5];
+ result->m[6] = src->m[9];
+ result->m[7] = src->m[13];
+
+ result->m[8] = src->m[2];
+ result->m[9] = src->m[6];
+ result->m[10] = src->m[10];
+ result->m[11] = src->m[14];
+
+ result->m[12] = src->m[3];
+ result->m[13] = src->m[7];
+ result->m[14] = src->m[11];
+ result->m[15] = src->m[15];
+}
+
+// Returns a 3x3 minor of a 4x4 matrix.
+inline static float XrMatrix4x4f_Minor(const XrMatrix4x4f* matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
+ return matrix->m[4 * r0 + c0] *
+ (matrix->m[4 * r1 + c1] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c1] * matrix->m[4 * r1 + c2]) -
+ matrix->m[4 * r0 + c1] *
+ (matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c2]) +
+ matrix->m[4 * r0 + c2] *
+ (matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c1] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c1]);
+}
+
+// Calculates the inverse of a 4x4 matrix.
+inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
+ const float rcpDet =
+ 1.0f / (src->m[0] * XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) - src->m[1] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) +
+ src->m[2] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) - src->m[3] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2));
+
+ result->m[0] = XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) * rcpDet;
+ result->m[1] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 1, 2, 3) * rcpDet;
+ result->m[2] = XrMatrix4x4f_Minor(src, 0, 1, 3, 1, 2, 3) * rcpDet;
+ result->m[3] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 1, 2, 3) * rcpDet;
+ result->m[4] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) * rcpDet;
+ result->m[5] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 2, 3) * rcpDet;
+ result->m[6] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 2, 3) * rcpDet;
+ result->m[7] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 2, 3) * rcpDet;
+ result->m[8] = XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) * rcpDet;
+ result->m[9] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 3) * rcpDet;
+ result->m[10] = XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 3) * rcpDet;
+ result->m[11] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 3) * rcpDet;
+ result->m[12] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2) * rcpDet;
+ result->m[13] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 2) * rcpDet;
+ result->m[14] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 2) * rcpDet;
+ result->m[15] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 2) * rcpDet;
+}
+
+// Calculates the inverse of a rigid body transform.
+inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
+ result->m[0] = src->m[0];
+ result->m[1] = src->m[4];
+ result->m[2] = src->m[8];
+ result->m[3] = 0.0f;
+ result->m[4] = src->m[1];
+ result->m[5] = src->m[5];
+ result->m[6] = src->m[9];
+ result->m[7] = 0.0f;
+ result->m[8] = src->m[2];
+ result->m[9] = src->m[6];
+ result->m[10] = src->m[10];
+ result->m[11] = 0.0f;
+ result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
+ result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
+ result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
+ result->m[15] = 1.0f;
+}
+
+// Creates an identity matrix.
+inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result) {
+ result->m[0] = 1.0f;
+ result->m[1] = 0.0f;
+ result->m[2] = 0.0f;
+ result->m[3] = 0.0f;
+ result->m[4] = 0.0f;
+ result->m[5] = 1.0f;
+ result->m[6] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[8] = 0.0f;
+ result->m[9] = 0.0f;
+ result->m[10] = 1.0f;
+ result->m[11] = 0.0f;
+ result->m[12] = 0.0f;
+ result->m[13] = 0.0f;
+ result->m[14] = 0.0f;
+ result->m[15] = 1.0f;
+}
+
+// Creates a translation matrix.
+inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z) {
+ result->m[0] = 1.0f;
+ result->m[1] = 0.0f;
+ result->m[2] = 0.0f;
+ result->m[3] = 0.0f;
+ result->m[4] = 0.0f;
+ result->m[5] = 1.0f;
+ result->m[6] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[8] = 0.0f;
+ result->m[9] = 0.0f;
+ result->m[10] = 1.0f;
+ result->m[11] = 0.0f;
+ result->m[12] = x;
+ result->m[13] = y;
+ result->m[14] = z;
+ result->m[15] = 1.0f;
+}
+
+// Creates a rotation matrix.
+// If -Z=forward, +Y=up, +X=right, then degreesX=pitch, degreesY=yaw, degreesZ=roll.
+inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
+ const float degreesZ) {
+ const float sinX = sinf(degreesX * (MATH_PI / 180.0f));
+ const float cosX = cosf(degreesX * (MATH_PI / 180.0f));
+ const XrMatrix4x4f rotationX = {{1, 0, 0, 0, 0, cosX, sinX, 0, 0, -sinX, cosX, 0, 0, 0, 0, 1}};
+ const float sinY = sinf(degreesY * (MATH_PI / 180.0f));
+ const float cosY = cosf(degreesY * (MATH_PI / 180.0f));
+ const XrMatrix4x4f rotationY = {{cosY, 0, -sinY, 0, 0, 1, 0, 0, sinY, 0, cosY, 0, 0, 0, 0, 1}};
+ const float sinZ = sinf(degreesZ * (MATH_PI / 180.0f));
+ const float cosZ = cosf(degreesZ * (MATH_PI / 180.0f));
+ const XrMatrix4x4f rotationZ = {{cosZ, sinZ, 0, 0, -sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
+ XrMatrix4x4f rotationXY;
+ XrMatrix4x4f_Multiply(&rotationXY, &rotationY, &rotationX);
+ XrMatrix4x4f_Multiply(result, &rotationZ, &rotationXY);
+}
+
+// Creates a scale matrix.
+inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z) {
+ result->m[0] = x;
+ result->m[1] = 0.0f;
+ result->m[2] = 0.0f;
+ result->m[3] = 0.0f;
+ result->m[4] = 0.0f;
+ result->m[5] = y;
+ result->m[6] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[8] = 0.0f;
+ result->m[9] = 0.0f;
+ result->m[10] = z;
+ result->m[11] = 0.0f;
+ result->m[12] = 0.0f;
+ result->m[13] = 0.0f;
+ result->m[14] = 0.0f;
+ result->m[15] = 1.0f;
+}
+
+// Creates a matrix from a quaternion.
+inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat) {
+ const float x2 = quat->x + quat->x;
+ const float y2 = quat->y + quat->y;
+ const float z2 = quat->z + quat->z;
+
+ const float xx2 = quat->x * x2;
+ const float yy2 = quat->y * y2;
+ const float zz2 = quat->z * z2;
+
+ const float yz2 = quat->y * z2;
+ const float wx2 = quat->w * x2;
+ const float xy2 = quat->x * y2;
+ const float wz2 = quat->w * z2;
+ const float xz2 = quat->x * z2;
+ const float wy2 = quat->w * y2;
+
+ result->m[0] = 1.0f - yy2 - zz2;
+ result->m[1] = xy2 + wz2;
+ result->m[2] = xz2 - wy2;
+ result->m[3] = 0.0f;
+
+ result->m[4] = xy2 - wz2;
+ result->m[5] = 1.0f - xx2 - zz2;
+ result->m[6] = yz2 + wx2;
+ result->m[7] = 0.0f;
+
+ result->m[8] = xz2 + wy2;
+ result->m[9] = yz2 - wx2;
+ result->m[10] = 1.0f - xx2 - yy2;
+ result->m[11] = 0.0f;
+
+ result->m[12] = 0.0f;
+ result->m[13] = 0.0f;
+ result->m[14] = 0.0f;
+ result->m[15] = 1.0f;
+}
+
+// Creates a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
+ const XrQuaternionf* rotation, const XrVector3f* scale) {
+ XrMatrix4x4f scaleMatrix;
+ XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
+
+ XrMatrix4x4f rotationMatrix;
+ XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
+
+ XrMatrix4x4f translationMatrix;
+ XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
+
+ XrMatrix4x4f combinedMatrix;
+ XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
+ XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
+}
+
+// Creates a projection matrix based on the specified dimensions.
+// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
+// The far plane is placed at infinity if farZ <= nearZ.
+// An infinite projection matrix is preferred for rasterization because, except for
+// things *right* up against the near plane, it always provides better precision:
+// "Tightening the Precision of Perspective Rendering"
+// Paul Upchurch, Mathieu Desbrun
+// Journal of Graphics Tools, Volume 16, Issue 1, 2012
+inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
+ const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
+ const float nearZ, const float farZ) {
+ const float tanAngleWidth = tanAngleRight - tanAngleLeft;
+
+ // Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
+ // Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
+ const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
+
+ // Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
+ // Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
+ const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
+
+ if (farZ <= nearZ) {
+ // place the far plane at infinity
+ result->m[0] = 2 / tanAngleWidth;
+ result->m[4] = 0;
+ result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
+ result->m[12] = 0;
+
+ result->m[1] = 0;
+ result->m[5] = 2 / tanAngleHeight;
+ result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
+ result->m[13] = 0;
+
+ result->m[2] = 0;
+ result->m[6] = 0;
+ result->m[10] = -1;
+ result->m[14] = -(nearZ + offsetZ);
+
+ result->m[3] = 0;
+ result->m[7] = 0;
+ result->m[11] = -1;
+ result->m[15] = 0;
+ } else {
+ // normal projection
+ result->m[0] = 2 / tanAngleWidth;
+ result->m[4] = 0;
+ result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
+ result->m[12] = 0;
+
+ result->m[1] = 0;
+ result->m[5] = 2 / tanAngleHeight;
+ result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
+ result->m[13] = 0;
+
+ result->m[2] = 0;
+ result->m[6] = 0;
+ result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
+ result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
+
+ result->m[3] = 0;
+ result->m[7] = 0;
+ result->m[11] = -1;
+ result->m[15] = 0;
+ }
+}
+
+// Creates a projection matrix based on the specified FOV.
+inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
+ const float nearZ, const float farZ) {
+ const float tanLeft = tanf(fov.angleLeft);
+ const float tanRight = tanf(fov.angleRight);
+
+ const float tanDown = tanf(fov.angleDown);
+ const float tanUp = tanf(fov.angleUp);
+
+ XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
+}
+
+// Creates a matrix that transforms the -1 to 1 cube to cover the given 'mins' and 'maxs' transformed with the given 'matrix'.
+inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
+ const XrVector3f* maxs) {
+ const XrVector3f offset = {(maxs->x + mins->x) * 0.5f, (maxs->y + mins->y) * 0.5f, (maxs->z + mins->z) * 0.5f};
+ const XrVector3f scale = {(maxs->x - mins->x) * 0.5f, (maxs->y - mins->y) * 0.5f, (maxs->z - mins->z) * 0.5f};
+
+ result->m[0] = matrix->m[0] * scale.x;
+ result->m[1] = matrix->m[1] * scale.x;
+ result->m[2] = matrix->m[2] * scale.x;
+ result->m[3] = matrix->m[3] * scale.x;
+
+ result->m[4] = matrix->m[4] * scale.y;
+ result->m[5] = matrix->m[5] * scale.y;
+ result->m[6] = matrix->m[6] * scale.y;
+ result->m[7] = matrix->m[7] * scale.y;
+
+ result->m[8] = matrix->m[8] * scale.z;
+ result->m[9] = matrix->m[9] * scale.z;
+ result->m[10] = matrix->m[10] * scale.z;
+ result->m[11] = matrix->m[11] * scale.z;
+
+ result->m[12] = matrix->m[12] + matrix->m[0] * offset.x + matrix->m[4] * offset.y + matrix->m[8] * offset.z;
+ result->m[13] = matrix->m[13] + matrix->m[1] * offset.x + matrix->m[5] * offset.y + matrix->m[9] * offset.z;
+ result->m[14] = matrix->m[14] + matrix->m[2] * offset.x + matrix->m[6] * offset.y + matrix->m[10] * offset.z;
+ result->m[15] = matrix->m[15] + matrix->m[3] * offset.x + matrix->m[7] * offset.y + matrix->m[11] * offset.z;
+}
+
+// Returns true if the given matrix is affine.
+inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon) {
+ return fabsf(matrix->m[3]) <= epsilon && fabsf(matrix->m[7]) <= epsilon && fabsf(matrix->m[11]) <= epsilon &&
+ fabsf(matrix->m[15] - 1.0f) <= epsilon;
+}
+
+// Returns true if the given matrix is orthogonal.
+inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (i != j) {
+ if (fabsf(matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
+ matrix->m[4 * i + 2] * matrix->m[4 * j + 2]) > epsilon) {
+ return false;
+ }
+ if (fabsf(matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
+ matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j]) > epsilon) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// Returns true if the given matrix is orthonormal.
+inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ const float kd = (i == j) ? 1.0f : 0.0f; // Kronecker delta
+ if (fabsf(kd - (matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
+ matrix->m[4 * i + 2] * matrix->m[4 * j + 2])) > epsilon) {
+ return false;
+ }
+ if (fabsf(kd - (matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
+ matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j])) > epsilon) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Returns true if the given matrix is a rigid body transform.
+inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon) {
+ return XrMatrix4x4f_IsAffine(matrix, epsilon) && XrMatrix4x4f_IsOrthonormal(matrix, epsilon);
+}
+
+// Get the translation from a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src) {
+ assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
+ assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
+
+ result->x = src->m[12];
+ result->y = src->m[13];
+ result->z = src->m[14];
+}
+
+// Get the rotation from a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src) {
+ assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
+ assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
+
+ const float rcpScaleX = XrRcpSqrt(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
+ const float rcpScaleY = XrRcpSqrt(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
+ const float rcpScaleZ = XrRcpSqrt(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
+ const float m[9] = {src->m[0] * rcpScaleX, src->m[1] * rcpScaleX, src->m[2] * rcpScaleX,
+ src->m[4] * rcpScaleY, src->m[5] * rcpScaleY, src->m[6] * rcpScaleY,
+ src->m[8] * rcpScaleZ, src->m[9] * rcpScaleZ, src->m[10] * rcpScaleZ};
+ if (m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] > 0.0f) {
+ float t = +m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->w = s * t;
+ result->z = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
+ result->y = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
+ result->x = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
+ } else if (m[0 * 3 + 0] > m[1 * 3 + 1] && m[0 * 3 + 0] > m[2 * 3 + 2]) {
+ float t = +m[0 * 3 + 0] - m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->x = s * t;
+ result->y = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
+ result->z = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
+ result->w = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
+ } else if (m[1 * 3 + 1] > m[2 * 3 + 2]) {
+ float t = -m[0 * 3 + 0] + m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->y = s * t;
+ result->x = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
+ result->w = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
+ result->z = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
+ } else {
+ float t = -m[0 * 3 + 0] - m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->z = s * t;
+ result->w = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
+ result->x = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
+ result->y = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
+ }
+}
+
+// Get the scale from a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src) {
+ assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
+ assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
+
+ result->x = sqrtf(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
+ result->y = sqrtf(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
+ result->z = sqrtf(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
+}
+
+// Transforms a 3D vector.
+inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v) {
+ const float w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15];
+ const float rcpW = 1.0f / w;
+ result->x = (m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12]) * rcpW;
+ result->y = (m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13]) * rcpW;
+ result->z = (m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14]) * rcpW;
+}
+
+// Transforms a 4D vector.
+inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v) {
+ result->x = m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12] * v->w;
+ result->y = m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13] * v->w;
+ result->z = m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14] * v->w;
+ result->w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15] * v->w;
+}
+
+// Transforms the 'mins' and 'maxs' bounds with the given 'matrix'.
+inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
+ const XrVector3f* mins, const XrVector3f* maxs) {
+ assert(XrMatrix4x4f_IsAffine(matrix, 1e-4f));
+
+ const XrVector3f center = {(mins->x + maxs->x) * 0.5f, (mins->y + maxs->y) * 0.5f, (mins->z + maxs->z) * 0.5f};
+ const XrVector3f extents = {maxs->x - center.x, maxs->y - center.y, maxs->z - center.z};
+ const XrVector3f newCenter = {matrix->m[0] * center.x + matrix->m[4] * center.y + matrix->m[8] * center.z + matrix->m[12],
+ matrix->m[1] * center.x + matrix->m[5] * center.y + matrix->m[9] * center.z + matrix->m[13],
+ matrix->m[2] * center.x + matrix->m[6] * center.y + matrix->m[10] * center.z + matrix->m[14]};
+ const XrVector3f newExtents = {
+ fabsf(extents.x * matrix->m[0]) + fabsf(extents.y * matrix->m[4]) + fabsf(extents.z * matrix->m[8]),
+ fabsf(extents.x * matrix->m[1]) + fabsf(extents.y * matrix->m[5]) + fabsf(extents.z * matrix->m[9]),
+ fabsf(extents.x * matrix->m[2]) + fabsf(extents.y * matrix->m[6]) + fabsf(extents.z * matrix->m[10])};
+ XrVector3f_Sub(resultMins, &newCenter, &newExtents);
+ XrVector3f_Add(resultMaxs, &newCenter, &newExtents);
+}
+
+// Returns true if the 'mins' and 'maxs' bounds is completely off to one side of the projection matrix.
+inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs) {
+ if (maxs->x <= mins->x && maxs->y <= mins->y && maxs->z <= mins->z) {
+ return false;
+ }
+
+ XrVector4f c[8];
+ for (int i = 0; i < 8; i++) {
+ const XrVector4f corner = {(i & 1) ? maxs->x : mins->x, (i & 2) ? maxs->y : mins->y, (i & 4) ? maxs->z : mins->z, 1.0f};
+ XrMatrix4x4f_TransformVector4f(&c[i], mvp, &corner);
+ }
+
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (c[i].x > -c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].x < c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (c[i].y > -c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].y < c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].z > -c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].z < c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+
+ return false;
+}
+
+#endif // XR_LINEAR_H_
diff --git a/extern/openxr/src/common_cmake_config.h.in b/extern/openxr/src/common_cmake_config.h.in
new file mode 100644
index 00000000000..1cf8fc2f169
--- /dev/null
+++ b/extern/openxr/src/common_cmake_config.h.in
@@ -0,0 +1,3 @@
+#cmakedefine HAVE_SECURE_GETENV
+#cmakedefine HAVE___SECURE_GETENV
+#cmakedefine XRLOADER_ENABLE_EXCEPTION_HANDLING
diff --git a/extern/openxr/src/loader/CMakeLists.txt b/extern/openxr/src/loader/CMakeLists.txt
new file mode 100644
index 00000000000..fa83233fe87
--- /dev/null
+++ b/extern/openxr/src/loader/CMakeLists.txt
@@ -0,0 +1,183 @@
+# Copyright (c) 2017 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author:
+#
+
+#set (CMAKE_VERBOSE_MAKEFILE 1)
+
+include(GNUInstallDirs)
+
+# Use this feature for Windows to automatically generate an exports file for the DLL.
+# See https://blog.kitware.com/create-dlls-on-windows-without-declspec-using-new-cmake-export-all-feature/
+include(GenerateExportHeader)
+set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS false)
+
+set(LOADER_NAME openxr_loader)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(FALLBACK_CONFIG_DIRS "/etc/xdg" CACHE STRING
+ "Search path to use when XDG_CONFIG_DIRS is unset or empty or the current process is SUID/SGID. Default is freedesktop compliant.")
+ set(FALLBACK_DATA_DIRS "/usr/local/share:/usr/share" CACHE STRING
+ "Search path to use when XDG_DATA_DIRS is unset or empty or the current process is SUID/SGID. Default is freedesktop compliant.")
+endif()
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ set(openxr_loader_RESOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc)
+ set(LOADER_NAME ${LOADER_NAME}-${MAJOR}_${MINOR})
+endif()
+
+# List of all files externally generated outside of the loader that the loader
+# needs to build with.
+SET(LOADER_EXTERNAL_GEN_FILES
+ ${COMMON_GENERATED_OUTPUT}
+)
+run_xr_xml_generate(loader_source_generator.py xr_generated_loader.hpp)
+run_xr_xml_generate(loader_source_generator.py xr_generated_loader.cpp)
+
+if(DYNAMIC_LOADER)
+ add_definitions(-DXRAPI_DLL_EXPORT)
+ set(LIBRARY_TYPE SHARED)
+else() # build static lib
+ set(LIBRARY_TYPE STATIC)
+endif()
+
+set(JSONCPP_ROOT_DIR ${CMAKE_SOURCE_DIR}/extern/jsoncpp)
+
+add_library(${LOADER_NAME} ${LIBRARY_TYPE}
+ api_layer_interface.cpp
+ api_layer_interface.hpp
+ loader_core.cpp
+ loader_instance.cpp
+ loader_instance.hpp
+ loader_logger.cpp
+ loader_logger.hpp
+ loader_logger_recorders.cpp
+ loader_logger_recorders.hpp
+ manifest_file.cpp
+ ${GENERATED_OUTPUT}
+ manifest_file.hpp
+ runtime_interface.cpp
+ runtime_interface.hpp
+ ${OPENXR_ROOT_DIR}/src/common/filesystem_utils.cpp
+ ${OPENXR_ROOT_DIR}/src/common/filesystem_utils.hpp
+ ${OPENXR_ROOT_DIR}/src/common/hex_and_handles.cpp
+ ${OPENXR_ROOT_DIR}/src/common/hex_and_handles.h
+ ${JSONCPP_ROOT_DIR}/src/json_reader.cpp
+ ${JSONCPP_ROOT_DIR}/src/json_value.cpp
+ ${JSONCPP_ROOT_DIR}/src/json_writer.cpp
+ ${LOADER_EXTERNAL_GEN_FILES}
+ ${openxr_loader_RESOURCE_FILE}
+)
+set_target_properties(${LOADER_NAME} PROPERTIES FOLDER ${LOADER_FOLDER})
+
+set_source_files_properties(
+ ${LOADER_EXTERNAL_GEN_FILES}
+ PROPERTIES GENERATED TRUE
+)
+add_dependencies(${LOADER_NAME}
+ generate_openxr_header
+ xr_global_generated_files
+)
+target_include_directories(${LOADER_NAME}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
+ PRIVATE ${CMAKE_BINARY_DIR}/include
+ PRIVATE ${CMAKE_BINARY_DIR}/src
+ PRIVATE ${OPENXR_ROOT_DIR}/src/common
+ PRIVATE ${JSONCPP_ROOT_DIR}/include
+)
+if(VulkanHeaders_FOUND)
+ target_include_directories(${LOADER_NAME}
+ PRIVATE ${Vulkan_INCLUDE_DIRS}
+ )
+endif()
+
+target_compile_definitions(${LOADER_NAME}
+ PRIVATE API_NAME="OpenXR"
+)
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ target_compile_definitions(${LOADER_NAME}
+ PRIVATE FALLBACK_CONFIG_DIRS="${FALLBACK_CONFIG_DIRS}"
+ PRIVATE FALLBACK_DATA_DIRS="${FALLBACK_DATA_DIRS}"
+ PRIVATE SYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}"
+ )
+ if(NOT(CMAKE_INSTALL_FULL_SYSCONFDIR STREQUAL "/etc"))
+ target_compile_definitions(openxr_loader PRIVATE EXTRASYSCONFDIR="/etc")
+ endif()
+
+ set_target_properties(${LOADER_NAME} PROPERTIES SOVERSION "${MAJOR}" VERSION "${MAJOR}.${MINOR}.${PATCH}")
+ target_link_libraries(${LOADER_NAME} -lstdc++fs -ldl -lpthread -lm)
+
+ add_custom_target(lib${LOADER_NAME}.so.${MAJOR}.${MINOR} ALL
+ COMMAND ${CMAKE_COMMAND} -E create_symlink lib${LOADER_NAME}.so.${MAJOR}.${MINOR}.${PATCH} lib${LOADER_NAME}.so.${MAJOR}.${MINOR})
+
+ install(TARGETS ${LOADER_NAME}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+ set(XR_API_VERSION "${MAJOR}.${MINOR}")
+ configure_file("openxr.pc.in" "openxr.pc" @ONLY)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/openxr.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ foreach(configuration in CMAKE_C_FLAGS_DEBUG
+ CMAKE_C_FLAGS_RELEASE
+ CMAKE_C_FLAGS_RELWITHDEBINFO
+ CMAKE_CXX_FLAGS_DEBUG
+ CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ # If building DLLs, force static CRT linkage
+ if(DYNAMIC_LOADER)
+ if (${configuration} MATCHES "/MD")
+# string(REGEX REPLACE "/MD" "/MT" ${configuration} "${${configuration}}")
+ endif()
+ else() # Otherwise for static libs, link the CRT dynamically
+ if (${configuration} MATCHES "/MT")
+# string(REGEX REPLACE "/MT" "/MD" ${configuration} "${${configuration}}")
+ endif()
+ endif()
+ endforeach()
+
+ target_link_libraries(${LOADER_NAME} shlwapi)
+ target_compile_options(${LOADER_NAME} PRIVATE)
+ generate_export_header(${LOADER_NAME})
+ # set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS false)
+
+ # Need to copy DLL to client directories so clients can easily load it.
+ if( (DYNAMIC_LOADER) AND (CMAKE_GENERATOR MATCHES "^Visual Studio.*") )
+ file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/${LOADER_NAME}.dll COPY_SRC_PATH )
+ # file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/triangle/$<CONFIGURATION>/ COPY_DST_TEST_PATH )
+ file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/hello_xr/$<CONFIGURATION>/ COPY_DST_TEST_PATH )
+ file( TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/loader_test/$<CONFIGURATION>/ COPY_DST_LOADER_TEST_PATH )
+ add_custom_command( TARGET ${LOADER_NAME} POST_BUILD
+ COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_TEST_PATH}
+ COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_LOADER_TEST_PATH}
+ )
+ endif()
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ target_compile_options(openxr_loader
+ PRIVATE -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wpointer-arith
+ PRIVATE -fno-strict-aliasing -fno-builtin-memcmp "$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>"
+ )
+ # For GCC version 7.1 or greater, we need to disable the implicit fallthrough warning since
+ # there's no consistent way to satisfy all compilers until they all accept the C++17 standard
+ if (CMAKE_COMPILER_IS_GNUCC AND NOT (CMAKE_CXX_COMPILER_VERSION LESS 7.1))
+ target_compile_options(openxr_loader PRIVATE -Wimplicit-fallthrough=0)
+ endif()
+endif()
+
+install(TARGETS ${LOADER_NAME} DESTINATION lib)
+
+# Custom commands to build dependencies for above targets
diff --git a/extern/openxr/src/loader/api_layer_interface.cpp b/extern/openxr/src/loader/api_layer_interface.cpp
new file mode 100644
index 00000000000..d3eba86425c
--- /dev/null
+++ b/extern/openxr/src/loader/api_layer_interface.cpp
@@ -0,0 +1,403 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "api_layer_interface.hpp"
+
+#include "loader_interfaces.h"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "manifest_file.hpp"
+#include "platform_utils.hpp"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#define OPENXR_ENABLE_LAYERS_ENV_VAR "XR_ENABLE_API_LAYERS"
+
+// Add any layers defined in the loader layer environment variable.
+static void AddEnvironmentApiLayers(const std::string& openxr_command, std::vector<std::string>& enabled_layers) {
+ char* layer_environment_variable = PlatformUtilsGetEnv(OPENXR_ENABLE_LAYERS_ENV_VAR);
+ if (nullptr != layer_environment_variable) {
+ std::string layers = layer_environment_variable;
+ PlatformUtilsFreeEnv(layer_environment_variable);
+
+ std::size_t last_found = 0;
+ std::size_t found = layers.find_first_of(PATH_SEPARATOR);
+ std::string cur_search;
+
+ // Handle any path listings in the string (separated by the appropriate path separator)
+ while (found != std::string::npos) {
+ cur_search = layers.substr(last_found, found);
+ enabled_layers.push_back(cur_search);
+ last_found = found + 1;
+ found = layers.find_first_of(PATH_SEPARATOR, last_found);
+ }
+
+ // If there's something remaining in the string, copy it over
+ if (last_found < layers.size()) {
+ cur_search = layers.substr(last_found);
+ enabled_layers.push_back(cur_search);
+ }
+ }
+}
+
+XrResult ApiLayerInterface::GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count,
+ uint32_t* outgoing_count, XrApiLayerProperties* api_layer_properties) {
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
+ uint32_t manifest_count = 0;
+
+ // Find any implicit layers which we may need to report information for.
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCESS == result) {
+ // Find any explicit layers which we may need to report information for.
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
+ }
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "ApiLayerInterface::GetApiLayerProperties - failed searching for API layer manifest files");
+ return result;
+ }
+
+ manifest_count = static_cast<uint32_t>(manifest_files.size());
+ if (0 == incoming_count) {
+ if (nullptr == outgoing_count) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ *outgoing_count = manifest_count;
+ } else if (nullptr != api_layer_properties) {
+ if (incoming_count < manifest_count && nullptr != api_layer_properties) {
+ LoaderLogger::LogErrorMessage(
+ "xrEnumerateInstanceExtensionProperties",
+ "VUID-xrEnumerateApiLayerProperties-propertyCapacityInput-parameter: insufficient space in array");
+ *outgoing_count = manifest_count;
+ return XR_ERROR_SIZE_INSUFFICIENT;
+ }
+
+ uint32_t prop = 0;
+ bool properties_valid = true;
+ for (; prop < incoming_count && prop < manifest_count; ++prop) {
+ if (XR_TYPE_API_LAYER_PROPERTIES != api_layer_properties[prop].type) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "VUID-XrApiLayerProperties-type-type: unknown type in api_layer_properties");
+ properties_valid = false;
+ }
+ if (nullptr != api_layer_properties[prop].next) {
+ LoaderLogger::LogErrorMessage(openxr_command, "VUID-XrApiLayerProperties-next-next: expected NULL");
+ properties_valid = false;
+ }
+ if (properties_valid) {
+ api_layer_properties[prop] = manifest_files[prop]->GetApiLayerProperties();
+ }
+ }
+ if (!properties_valid) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "VUID-xrEnumerateApiLayerProperties-properties-parameter: invalid properties");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (nullptr != outgoing_count) {
+ *outgoing_count = prop;
+ }
+ }
+ return XR_SUCCESS;
+}
+
+XrResult ApiLayerInterface::GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
+ std::vector<XrExtensionProperties>& extension_properties) {
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
+
+ // If a layer name is supplied, only use the information out of that one layer
+ if (nullptr != layer_name && 0 != strlen(layer_name)) {
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCESS == result) {
+ // Find any explicit layers which we may need to report information for.
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogErrorMessage(
+ openxr_command,
+ "ApiLayerInterface::GetInstanceExtensionProperties - failed searching for API layer manifest files");
+ return result;
+ }
+
+ bool found = false;
+ auto num_files = static_cast<uint32_t>(manifest_files.size());
+ for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
+ // If a layer with the provided name exists, get it's instance extension information.
+ if (manifest_files[man_file]->LayerName() == layer_name) {
+ manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
+ found = true;
+ break;
+ }
+ }
+
+ // If nothing found, report 0
+ if (!found) {
+ return XR_ERROR_API_LAYER_NOT_PRESENT;
+ }
+ }
+ // Otherwise, we want to add only implicit API layers and explicit API layers enabled using the environment variables
+ } else {
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCESS == result) {
+ // Find any environmentally enabled explicit layers. If they're present, treat them like implicit layers
+ // since we know that they're going to be enabled.
+ std::vector<std::string> env_enabled_layers;
+ AddEnvironmentApiLayers(openxr_command, env_enabled_layers);
+ if (!env_enabled_layers.empty()) {
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> exp_layer_man_files = {};
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, exp_layer_man_files);
+ if (XR_SUCCESS == result) {
+ for (auto l_iter = exp_layer_man_files.begin();
+ !exp_layer_man_files.empty() && l_iter != exp_layer_man_files.end();
+ /* No iterate */) {
+ for (std::string& enabled_layer : env_enabled_layers) {
+ // If this is an enabled layer, transfer it over to the manifest list.
+ if (enabled_layer == (*l_iter)->LayerName()) {
+ manifest_files.push_back(std::move(*l_iter));
+ break;
+ }
+ }
+ exp_layer_man_files.erase(l_iter);
+ }
+ }
+ }
+ }
+
+ // Grab the layer instance extensions information
+ auto num_files = static_cast<uint32_t>(manifest_files.size());
+ for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
+ manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
+ }
+ }
+ return XR_SUCCESS;
+}
+
+XrResult ApiLayerInterface::LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
+ const char* const* enabled_api_layer_names,
+ std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces) {
+ XrResult last_error = XR_SUCCESS;
+ bool any_loaded = false;
+ std::vector<bool> layer_found;
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> layer_manifest_files = {};
+
+ // Find any implicit layers which we may need to report information for.
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, layer_manifest_files);
+ if (XR_SUCCESS == result) {
+ // Find any explicit layers which we may need to report information for.
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, layer_manifest_files);
+ }
+
+ // Put all the enabled layers into a string vector
+ std::vector<std::string> enabled_api_layers = {};
+ AddEnvironmentApiLayers(openxr_command, enabled_api_layers);
+ if (enabled_api_layer_count > 0) {
+ if (nullptr == enabled_api_layer_names) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateInstance",
+ "VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter: enabledApiLayerCount is non-0 but array is NULL");
+ LoaderLogger::LogErrorMessage(
+ "xrCreateInstance", "VUID-xrCreateInstance-info-parameter: something wrong with XrInstanceCreateInfo contents");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ auto num_env_api_layers = static_cast<uint32_t>(enabled_api_layers.size());
+ uint32_t total_api_layers = num_env_api_layers + enabled_api_layer_count;
+ enabled_api_layers.resize(total_api_layers);
+ for (uint32_t layer = 0; layer < enabled_api_layer_count; ++layer) {
+ enabled_api_layers[num_env_api_layers + layer] = enabled_api_layer_names[layer];
+ }
+ }
+
+ // Initialize the layer found vector to false
+ layer_found.resize(enabled_api_layers.size());
+ for (auto&& layer : layer_found) {
+ layer = false;
+ }
+
+ for (std::unique_ptr<ApiLayerManifestFile>& manifest_file : layer_manifest_files) {
+ bool enabled = false;
+
+ // Always add implicit layers. They would only be in this list if they were enabled
+ // (i.e. the disable environment variable is not set).
+ if (manifest_file->Type() == MANIFEST_TYPE_IMPLICIT_API_LAYER) {
+ enabled = true;
+ } else {
+ // Only add explicit layers if they are called out by the application
+ for (uint32_t layer = 0; layer < enabled_api_layers.size(); ++layer) {
+ if (enabled_api_layers[layer] == manifest_file->LayerName()) {
+ layer_found[layer] = true;
+ enabled = true;
+ break;
+ }
+ }
+ }
+
+ // If this layer isn't enabled, skip it.
+ if (!enabled) {
+ continue;
+ }
+
+ LoaderPlatformLibraryHandle layer_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
+ if (nullptr == layer_library) {
+ if (!any_loaded) {
+ last_error = XR_ERROR_FILE_ACCESS_ERROR;
+ }
+ std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
+ std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
+ warning_message += manifest_file->LayerName();
+ warning_message += ", failed to load with message \"";
+ warning_message += library_message;
+ warning_message += "\"";
+ LoaderLogger::LogWarningMessage(openxr_command, warning_message);
+ continue;
+ }
+
+ // Get and settle on an layer interface version (using any provided name if required).
+ std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderApiLayerInterface");
+ auto negotiate = reinterpret_cast<PFN_xrNegotiateLoaderApiLayerInterface>(
+ LoaderPlatformLibraryGetProcAddr(layer_library, function_name));
+
+ if (nullptr == negotiate) {
+ std::ostringstream oss;
+ oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
+ << " because negotiation function " << function_name << " was not found";
+ LoaderLogger::LogErrorMessage(openxr_command, oss.str());
+ LoaderPlatformLibraryClose(layer_library);
+ last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
+ continue;
+ }
+
+ // Loader info for negotiation
+ XrNegotiateLoaderInfo loader_info = {};
+ loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
+ loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
+ loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
+ loader_info.minInterfaceVersion = 1;
+ loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
+ loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
+ loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
+
+ // Set up the layer return structure
+ XrNegotiateApiLayerRequest api_layer_info = {};
+ api_layer_info.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST;
+ api_layer_info.structVersion = XR_API_LAYER_INFO_STRUCT_VERSION;
+ api_layer_info.structSize = sizeof(XrNegotiateApiLayerRequest);
+
+ XrResult res = negotiate(&loader_info, manifest_file->LayerName().c_str(), &api_layer_info);
+ // If we supposedly succeeded, but got a nullptr for getInstanceProcAddr
+ // then something still went wrong, so return with an error.
+ if (XR_SUCCESS == res && nullptr == api_layer_info.getInstanceProcAddr) {
+ std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
+ warning_message += manifest_file->LayerName();
+ warning_message += ", negotiation did not return a valid getInstanceProcAddr";
+ LoaderLogger::LogWarningMessage(openxr_command, warning_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ }
+ if (XR_SUCCESS != res) {
+ if (!any_loaded) {
+ last_error = res;
+ }
+ std::ostringstream oss;
+ oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
+ << " due to failed negotiation with error " << res;
+ LoaderLogger::LogWarningMessage(openxr_command, oss.str());
+ LoaderPlatformLibraryClose(layer_library);
+ continue;
+ }
+
+ {
+ std::ostringstream oss;
+ oss << "ApiLayerInterface::LoadApiLayers succeeded loading layer " << manifest_file->LayerName()
+ << " using interface version " << api_layer_info.layerInterfaceVersion << " and OpenXR API version "
+ << XR_VERSION_MAJOR(api_layer_info.layerApiVersion) << "." << XR_VERSION_MINOR(api_layer_info.layerApiVersion);
+ LoaderLogger::LogInfoMessage(openxr_command, oss.str());
+ }
+
+ // Grab the list of extensions this layer supports for easy filtering after the
+ // xrCreateInstance call
+ std::vector<std::string> supported_extensions;
+ std::vector<XrExtensionProperties> extension_properties;
+ manifest_file->GetInstanceExtensionProperties(extension_properties);
+ supported_extensions.reserve(extension_properties.size());
+ for (XrExtensionProperties& ext_prop : extension_properties) {
+ supported_extensions.emplace_back(ext_prop.extensionName);
+ }
+
+ // Add this runtime to the vector
+ api_layer_interfaces.emplace_back(new ApiLayerInterface(manifest_file->LayerName(), layer_library, supported_extensions,
+ api_layer_info.getInstanceProcAddr,
+ api_layer_info.createApiLayerInstance));
+
+ // If we load one, clear all errors.
+ any_loaded = true;
+ last_error = XR_SUCCESS;
+ }
+
+ // If even one of the layers wasn't found, we want to return an error
+ for (uint32_t layer = 0; layer < layer_found.size(); ++layer) {
+ if (!layer_found[layer]) {
+ std::string error_message = "ApiLayerInterface::LoadApiLayers - failed to find layer ";
+ error_message += enabled_api_layers[layer];
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
+ }
+ }
+
+ // Always clear the manifest file list. Either we use them or we don't.
+ layer_manifest_files.clear();
+
+ // If we failed catastrophically for some reason, clean up everything.
+ if (XR_SUCCESS != last_error) {
+ api_layer_interfaces.clear();
+ }
+
+ return last_error;
+}
+
+ApiLayerInterface::ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
+ std::vector<std::string>& supported_extensions,
+ PFN_xrGetInstanceProcAddr get_instant_proc_addr,
+ PFN_xrCreateApiLayerInstance create_api_layer_instance)
+ : _layer_name(layer_name),
+ _layer_library(layer_library),
+ _get_instant_proc_addr(get_instant_proc_addr),
+ _create_api_layer_instance(create_api_layer_instance),
+ _supported_extensions(supported_extensions) {}
+
+ApiLayerInterface::~ApiLayerInterface() {
+ std::string info_message = "ApiLayerInterface being destroyed for layer ";
+ info_message += _layer_name;
+ LoaderLogger::LogInfoMessage("", info_message);
+ LoaderPlatformLibraryClose(_layer_library);
+}
+
+bool ApiLayerInterface::SupportsExtension(const std::string& extension_name) {
+ bool found_prop = false;
+ for (const std::string& supported_extension : _supported_extensions) {
+ if (supported_extension == extension_name) {
+ found_prop = true;
+ break;
+ }
+ }
+ return found_prop;
+}
diff --git a/extern/openxr/src/loader/api_layer_interface.hpp b/extern/openxr/src/loader/api_layer_interface.hpp
new file mode 100644
index 00000000000..8878a5b2834
--- /dev/null
+++ b/extern/openxr/src/loader/api_layer_interface.hpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <openxr/openxr.h>
+
+#include "loader_platform.hpp"
+#include "loader_interfaces.h"
+
+struct XrGeneratedDispatchTable;
+
+class ApiLayerInterface {
+ public:
+ // Factory method
+ static XrResult LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
+ const char* const* enabled_api_layer_names,
+ std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces);
+ // Static queries
+ static XrResult GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count, uint32_t* outgoing_count,
+ XrApiLayerProperties* api_layer_properties);
+ static XrResult GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
+ std::vector<XrExtensionProperties>& extension_properties);
+
+ ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
+ std::vector<std::string>& supported_extensions, PFN_xrGetInstanceProcAddr get_instant_proc_addr,
+ PFN_xrCreateApiLayerInstance create_api_layer_instance);
+ virtual ~ApiLayerInterface();
+
+ PFN_xrGetInstanceProcAddr GetInstanceProcAddrFuncPointer() { return _get_instant_proc_addr; }
+ PFN_xrCreateApiLayerInstance GetCreateApiLayerInstanceFuncPointer() { return _create_api_layer_instance; }
+
+ std::string LayerName() { return _layer_name; }
+
+ // Generated methods
+ void GenUpdateInstanceDispatchTable(XrInstance instance, std::unique_ptr<XrGeneratedDispatchTable>& table);
+ bool SupportsExtension(const std::string& extension_name);
+
+ private:
+ std::string _layer_name;
+ LoaderPlatformLibraryHandle _layer_library;
+ PFN_xrGetInstanceProcAddr _get_instant_proc_addr;
+ PFN_xrCreateApiLayerInstance _create_api_layer_instance;
+ std::vector<std::string> _supported_extensions;
+};
diff --git a/extern/openxr/src/loader/exception_handling.hpp b/extern/openxr/src/loader/exception_handling.hpp
new file mode 100644
index 00000000000..36a63df0568
--- /dev/null
+++ b/extern/openxr/src/loader/exception_handling.hpp
@@ -0,0 +1,45 @@
+// Copyright (c) 2019 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Ryan Pavlik <ryan.pavlik@collabora.com
+//
+// Provides protection for C ABI functions if standard library functions may throw.
+
+#pragma once
+
+#include "common_cmake_config.h"
+
+#ifdef XRLOADER_ENABLE_EXCEPTION_HANDLING
+#include <stdexcept>
+#define XRLOADER_ABI_TRY try
+#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM \
+ catch (const std::bad_alloc&) { \
+ LoaderLogger::LogErrorMessage("", "failed allocating memory"); \
+ return XR_ERROR_OUT_OF_MEMORY; \
+ }
+#define XRLOADER_ABI_CATCH_FALLBACK \
+ catch (const std::exception& e) { \
+ LoaderLogger::LogErrorMessage("", "Unknown failure: " + std::string(e.what())); \
+ return XR_ERROR_RUNTIME_FAILURE; \
+ } \
+ catch (...) { \
+ LoaderLogger::LogErrorMessage("", "Unknown failure"); \
+ return XR_ERROR_RUNTIME_FAILURE; \
+ }
+
+#else
+#define XRLOADER_ABI_TRY
+#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM
+#define XRLOADER_ABI_CATCH_FALLBACK
+#endif
diff --git a/extern/openxr/src/loader/loader.rc b/extern/openxr/src/loader/loader.rc
new file mode 100644
index 00000000000..71bad95287c
--- /dev/null
+++ b/extern/openxr/src/loader/loader.rc
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@LunarG.com>
+//
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// Start customize section
+// Edit this section for your build
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 0
+#define VERSION_PATCH 1111
+#define VERSION_BUILDNO 2222
+
+#define VERSION_BUILD_DESCRIPTION "Dev Build"
+
+// All builds except release builds should set this to 0.
+// Release builds should set this to 1.
+#define VERSION_IS_RELEASEBUILD 0
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// End of customize section
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#include "winres.h"
+
+#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_BUILDNO
+
+#define STRINGIZE2(s) #s
+#define STRINGIZE(s) STRINGIZE2(s)
+
+#if VERSION_IS_RELEASEBUILD==1
+ #define VER_FILE_DESCRIPTION_STR "OpenXR Loader"
+ #define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
+ "." STRINGIZE(VERSION_MINOR) \
+ "." STRINGIZE(VERSION_PATCH) \
+ "." STRINGIZE(VERSION_BUILDNO)
+#else
+ #define VER_FILE_DESCRIPTION_STR "OpenXR Loader - " VERSION_BUILD_DESCRIPTION
+ #define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \
+ "." STRINGIZE(VERSION_MINOR) \
+ "." STRINGIZE(VERSION_PATCH) \
+ "." STRINGIZE(VERSION_BUILDNO) \
+ "." VERSION_BUILD_DESCRIPTION
+#endif
+
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VER_FILE_VERSION
+ PRODUCTVERSION VER_FILE_VERSION
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+
+ FILEOS 0x00000L
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "04090000"
+ BEGIN
+ VALUE "FileDescription", VER_FILE_DESCRIPTION_STR
+ VALUE "FileVersion", VER_FILE_VERSION_STR
+ VALUE "LegalCopyright", "Copyright (C) 2015-2017"
+ VALUE "ProductName", "OpenXR Loader"
+ VALUE "ProductVersion", VER_FILE_VERSION_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 0000
+ END
+END
diff --git a/extern/openxr/src/loader/loader_core.cpp b/extern/openxr/src/loader/loader_core.cpp
new file mode 100644
index 00000000000..50866740a5c
--- /dev/null
+++ b/extern/openxr/src/loader/loader_core.cpp
@@ -0,0 +1,650 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#ifdef XR_OS_WINDOWS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "api_layer_interface.hpp"
+#include "exception_handling.hpp"
+#include "hex_and_handles.h"
+#include "loader_instance.hpp"
+#include "loader_logger_recorders.hpp"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "runtime_interface.hpp"
+#include "xr_generated_dispatch_table.h"
+#include "xr_generated_loader.hpp"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+// Flag to cause the one time to init to only occur one time.
+std::once_flag g_one_time_init_flag;
+
+// Global lock to prevent reading JSON manifest files at the same time.
+static std::mutex g_loader_json_mutex;
+
+// Global lock to prevent simultaneous instance creation/destruction
+static std::mutex g_loader_instance_mutex;
+
+// Utility template function meant to validate if a fixed size string contains
+// a null-terminator.
+template <size_t max_length>
+inline bool IsMissingNullTerminator(const char (&str)[max_length]) {
+ for (size_t index = 0; index < max_length; ++index) {
+ if (str[index] == '\0') {
+ return false;
+ }
+ }
+ return true;
+}
+
+extern "C" {
+
+// ---- Core 1.0 manual loader trampoline functions
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
+ uint32_t *propertyCountOutput,
+ XrApiLayerProperties *properties) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline");
+
+ // Make sure only one thread is attempting to read the JSON files at a time.
+ std::unique_lock<std::mutex> json_lock(g_loader_json_mutex);
+
+ XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput,
+ propertyCountOutput, properties);
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogErrorMessage("xrEnumerateApiLayerProperties", "Failed ApiLayerInterface::GetApiLayerProperties");
+ }
+
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL
+xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput,
+ XrExtensionProperties *properties) XRLOADER_ABI_TRY {
+ bool just_layer_properties = false;
+ LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Entering loader trampoline");
+
+ if (nullptr != layerName && 0 != strlen(layerName)) {
+ // Application is only interested in layer's properties, not all of them.
+ just_layer_properties = true;
+ }
+
+ std::vector<XrExtensionProperties> extension_properties = {};
+ XrResult result;
+
+ {
+ // Make sure only one thread is attempting to read the JSON files at a time.
+ std::unique_lock<std::mutex> json_lock(g_loader_json_mutex);
+
+ // Get the layer extension properties
+ result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName,
+ extension_properties);
+ if (XR_SUCCESS == result && !just_layer_properties) {
+ // If not specific to a layer, get the runtime extension properties
+ result = RuntimeInterface::LoadRuntime("xrEnumerateInstanceExtensionProperties");
+ if (XR_SUCCESS == result) {
+ RuntimeInterface::GetRuntime().GetInstanceExtensionProperties(extension_properties);
+ RuntimeInterface::UnloadRuntime("xrEnumerateInstanceExtensionProperties");
+ } else {
+ LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
+ "Failed to find default runtime with RuntimeInterface::LoadRuntime()");
+ }
+ }
+ }
+
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", "Failed querying extension properties");
+ return result;
+ }
+
+ // If this is not in reference to a specific layer, then add the loader-specific extension properties as well.
+ // These are extensions that the loader directly supports.
+ if (!just_layer_properties) {
+ auto loader_extension_props = LoaderInstance::LoaderSpecificExtensions();
+ for (XrExtensionProperties &loader_prop : loader_extension_props) {
+ bool found_prop = false;
+ for (XrExtensionProperties &existing_prop : extension_properties) {
+ if (0 == strcmp(existing_prop.extensionName, loader_prop.extensionName)) {
+ found_prop = true;
+ // Use the loader version if it is newer
+ if (existing_prop.extensionVersion < loader_prop.extensionVersion) {
+ existing_prop.extensionVersion = loader_prop.extensionVersion;
+ }
+ break;
+ }
+ }
+ // Only add extensions not supported by the loader
+ if (!found_prop) {
+ extension_properties.push_back(loader_prop);
+ }
+ }
+ }
+
+ auto num_extension_properties = static_cast<uint32_t>(extension_properties.size());
+ if (propertyCapacityInput == 0) {
+ if (nullptr == propertyCountOutput) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ *propertyCountOutput = num_extension_properties;
+ } else if (nullptr != properties) {
+ if (propertyCapacityInput < num_extension_properties) {
+ *propertyCountOutput = num_extension_properties;
+ LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter",
+ "xrEnumerateInstanceExtensionProperties", "insufficient space in array");
+ return XR_ERROR_SIZE_INSUFFICIENT;
+ }
+
+ uint32_t num_to_copy = num_extension_properties;
+ // Determine how many extension properties we can copy over
+ if (propertyCapacityInput < num_to_copy) {
+ num_to_copy = propertyCapacityInput;
+ }
+ bool properties_valid = true;
+ for (uint32_t prop = 0; prop < propertyCapacityInput && prop < extension_properties.size(); ++prop) {
+ if (XR_TYPE_EXTENSION_PROPERTIES != properties[prop].type) {
+ properties_valid = false;
+ LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-type-type",
+ "xrEnumerateInstanceExtensionProperties", "unknown type in properties");
+ }
+ if (nullptr != properties[prop].next) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-next-next",
+ "xrEnumerateInstanceExtensionProperties", "expected NULL");
+ properties_valid = false;
+ }
+ if (properties_valid) {
+ properties[prop] = extension_properties[prop];
+ }
+ }
+ if (!properties_valid) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-properties-parameter",
+ "xrEnumerateInstanceExtensionProperties", "invalid properties");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (nullptr != propertyCountOutput) {
+ *propertyCountOutput = num_to_copy;
+ }
+ }
+ LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Completed loader trampoline");
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *info,
+ XrInstance *instance) XRLOADER_ABI_TRY {
+ bool runtime_loaded = false;
+
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader trampoline");
+ if (nullptr == info) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", "must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If application requested OpenXR API version is higher than the loader version, then we need to throw
+ // an error.
+ uint16_t app_major = XR_VERSION_MAJOR(info->applicationInfo.apiVersion); // NOLINT
+ uint16_t app_minor = XR_VERSION_MINOR(info->applicationInfo.apiVersion); // NOLINT
+ uint16_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION); // NOLINT
+ uint16_t loader_minor = XR_VERSION_MINOR(XR_CURRENT_API_VERSION); // NOLINT
+ if (app_major > loader_major || (app_major == loader_major && app_minor > loader_minor)) {
+ std::ostringstream oss;
+ oss << "xrCreateInstance called with invalid API version " << app_major << "." << app_minor
+ << ". Max supported version is " << loader_major << "." << loader_minor;
+ LoaderLogger::LogErrorMessage("xrCreateInstance", oss.str());
+ return XR_ERROR_API_VERSION_UNSUPPORTED;
+ }
+
+ if (nullptr == instance) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-instance-parameter", "xrCreateInstance", "must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces;
+
+ // Make sure only one thread is attempting to read the JSON files and use the instance.
+ XrResult result;
+ {
+ std::unique_lock<std::mutex> json_lock(g_loader_json_mutex);
+ // Load the available runtime
+ result = RuntimeInterface::LoadRuntime("xrCreateInstance");
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading runtime information");
+ } else {
+ runtime_loaded = true;
+ // Load the appropriate layers
+ result = ApiLayerInterface::LoadApiLayers("xrCreateInstance", info->enabledApiLayerCount, info->enabledApiLayerNames,
+ api_layer_interfaces);
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading layer information");
+ }
+ }
+ }
+
+ if (XR_FAILED(result)) {
+ if (runtime_loaded) {
+ RuntimeInterface::UnloadRuntime("xrCreateInstance");
+ }
+ return result;
+ }
+
+ std::unique_lock<std::mutex> instance_lock(g_loader_instance_mutex);
+
+ // Create the loader instance (only send down first runtime interface)
+ XrInstance created_instance = XR_NULL_HANDLE;
+ result = LoaderInstance::CreateInstance(std::move(api_layer_interfaces), info, &created_instance);
+
+ if (XR_SUCCEEDED(result)) {
+ *instance = created_instance;
+
+ LoaderInstance *loader_instance = g_instance_map.Get(created_instance);
+
+ // Create a debug utils messenger if the create structure is in the "next" chain
+ const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
+ const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
+ while (next_header != nullptr) {
+ if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ LoaderLogger::LogInfoMessage("xrCreateInstance", "Found XrDebugUtilsMessengerCreateInfoEXT in \'next\' chain.");
+ dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
+ XrDebugUtilsMessengerEXT messenger;
+ result = xrCreateDebugUtilsMessengerEXT(*instance, dbg_utils_create_info, &messenger);
+ if (XR_SUCCESS != result) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ loader_instance->SetDefaultDebugUtilsMessenger(messenger);
+ break;
+ }
+ next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
+ }
+ }
+
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader trampoline");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader trampoline");
+ // Runtimes may detect XR_NULL_HANDLE provided as a required handle parameter and return XR_ERROR_HANDLE_INVALID. - 2.9
+ if (XR_NULL_HANDLE == instance) {
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ LoaderInstance *const loader_instance = g_instance_map.Get(instance);
+ if (loader_instance == nullptr) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyInstance-instance-parameter", "xrDestroyInstance",
+ "invalid instance");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+
+ // If we allocated a default debug utils messenger, free it
+ XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger();
+ if (messenger != XR_NULL_HANDLE) {
+ xrDestroyDebugUtilsMessengerEXT(messenger);
+ }
+
+ // Now destroy the instance
+ if (XR_SUCCESS != dispatch_table->DestroyInstance(instance)) {
+ LoaderLogger::LogErrorMessage("xrDestroyInstance", "Unknown error occurred calling down chain");
+ }
+
+ // Cleanup any map entries that may still be using this instance
+ LoaderCleanUpMapsForInstance(loader_instance);
+
+ // Lock the instance create/destroy mutex
+ std::unique_lock<std::mutex> loader_instance_lock(g_loader_instance_mutex);
+ delete loader_instance;
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader trampoline");
+
+ // Finally, unload the runtime if necessary
+ RuntimeInterface::UnloadRuntime("xrDestroyInstance");
+
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// ---- Core 1.0 manual loader terminator functions
+
+// Validate that the applicationInfo structure in the XrInstanceCreateInfo is valid.
+static XrResult ValidateApplicationInfo(LoaderInstance *loader_instance, const XrApplicationInfo &info) {
+ if (IsMissingNullTerminator<XR_MAX_APPLICATION_NAME_SIZE>(info.applicationName)) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-applicationName-parameter", "xrCreateInstance",
+ "application name missing NULL terminator.");
+ return XR_ERROR_NAME_INVALID;
+ }
+ if (IsMissingNullTerminator<XR_MAX_ENGINE_NAME_SIZE>(info.engineName)) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-engineName-parameter", "xrCreateInstance",
+ "engine name missing NULL terminator.");
+ return XR_ERROR_NAME_INVALID;
+ }
+ if (strlen(info.applicationName) == 0) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance",
+ "VUID-XrApplicationInfo-engineName-parameter: application name can not be empty.");
+ return XR_ERROR_NAME_INVALID;
+ }
+ return XR_SUCCESS;
+}
+
+// Validate that the XrInstanceCreateInfo is valid
+static XrResult ValidateInstanceCreateInfo(LoaderInstance *loader_instance, const XrInstanceCreateInfo *info) {
+ // Should have a valid 'type'
+ if (XR_TYPE_INSTANCE_CREATE_INFO != info->type) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-type-type", "xrCreateInstance",
+ "expected XR_TYPE_INSTANCE_CREATE_INFO.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Flags must be 0
+ if (0 != info->createFlags) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-createFlags-zerobitmask", "xrCreateInstance",
+ "flags must be 0.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // ApplicationInfo struct must be valid
+ XrResult result = ValidateApplicationInfo(loader_instance, info->applicationInfo);
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-applicationInfo-parameter", "xrCreateInstance",
+ "info->applicationInfo is not valid.");
+ return result;
+ }
+ // VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter already tested in LoadApiLayers()
+ if ((info->enabledExtensionCount != 0u) && nullptr == info->enabledExtensionNames) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter", "xrCreateInstance",
+ "enabledExtensionCount is non-0 but array is NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+}
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *info, XrInstance *instance) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader terminator");
+ LoaderInstance *loader_instance = reinterpret_cast<LoaderInstance *>(*instance);
+ XrResult result = ValidateInstanceCreateInfo(loader_instance, info);
+ if (XR_SUCCESS != result) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance",
+ "something wrong with XrInstanceCreateInfo contents");
+ return result;
+ }
+ result = RuntimeInterface::GetRuntime().CreateInstance(info, instance);
+ loader_instance->SetRuntimeInstance(*instance);
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *info,
+ const struct XrApiLayerCreateInfo * /*apiLayerInfo*/,
+ XrInstance *instance) {
+ return LoaderXrTermCreateInstance(info, instance);
+}
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
+ XrResult result;
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader terminator");
+ result = RuntimeInterface::GetRuntime().DestroyInstance(instance);
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// ---- Extension manual loader trampoline functions
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
+ XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader trampoline");
+
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (loader_instance == nullptr) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-instance-parameter",
+ "xrCreateDebugUtilsMessengerEXT", "invalid instance");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
+ std::string error_str = "The ";
+ error_str += XR_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ error_str += " extension has not been enabled prior to calling xrCreateDebugUtilsMessengerEXT";
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-extension-notenabled",
+ "xrCreateDebugUtilsMessengerEXT", error_str);
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ if (XR_SUCCESS == result && nullptr != messenger) {
+ result = g_debugutilsmessengerext_map.Insert(*messenger, *loader_instance);
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage("xrCreateDebugUtilsMessengerEXT",
+ "Failed inserting new messenger into map: may be null or not unique");
+ return result;
+ }
+ }
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader trampoline");
+ return result;
+}
+XRLOADER_ABI_CATCH_BAD_ALLOC_OOM XRLOADER_ABI_CATCH_FALLBACK
+
+ XRAPI_ATTR XrResult XRAPI_CALL
+ xrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
+ // TODO: get instance from messenger in loader
+ // Also, is the loader really doing all this every call?
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader trampoline");
+
+ if (XR_NULL_HANDLE == messenger) {
+ return XR_SUCCESS;
+ }
+
+ LoaderInstance *loader_instance = g_debugutilsmessengerext_map.Get(messenger);
+ if (loader_instance == nullptr) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyDebugUtilsMessengerEXT-messenger-parameter",
+ "xrDestroyDebugUtilsMessengerEXT", "invalid messenger");
+
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
+ std::string error_str = "The ";
+ error_str += XR_EXT_DEBUG_UTILS_EXTENSION_NAME;
+ error_str += " extension has not been enabled prior to calling xrDestroyDebugUtilsMessengerEXT";
+ LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyDebugUtilsMessengerEXT-extension-notenabled",
+ "xrDestroyDebugUtilsMessengerEXT", error_str);
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ XrResult result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader trampoline");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// ---- Extension manual loader terminator functions
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
+ XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader terminator");
+ if (nullptr == messenger) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter",
+ "xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ XrResult result = XR_SUCCESS;
+ // This extension is supported entirely by the loader which means the runtime may or may not support it.
+ if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) {
+ result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ } else {
+ // Just allocate a character so we have a unique value
+ char *temp_mess_ptr = new char;
+ *messenger = reinterpret_cast<XrDebugUtilsMessengerEXT>(temp_mess_ptr);
+ }
+ if (XR_SUCCESS == result) {
+ LoaderLogger::GetInstance().AddLogRecorder(MakeDebugUtilsLoaderLogRecorder(createInfo, *messenger));
+ RuntimeInterface::GetRuntime().TrackDebugMessenger(instance, *messenger);
+ }
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator");
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger);
+ XrResult result = XR_SUCCESS;
+ LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger));
+ RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger);
+ // This extension is supported entirely by the loader which means the runtime may or may not support it.
+ if (nullptr != dispatch_table->DestroyDebugUtilsMessengerEXT) {
+ result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
+ } else {
+ // Delete the character we would've created
+ delete (reinterpret_cast<char *>(MakeHandleGeneric(messenger)));
+ }
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
+ XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator");
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ XrResult result = XR_SUCCESS;
+ if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) {
+ result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+ } else {
+ // Only log the message from the loader if the runtime doesn't support this extension. If we did,
+ // then the user would receive multiple instances of the same message.
+ LoaderLogger::GetInstance().LogDebugUtilsMessage(messageSeverity, messageTypes, callbackData);
+ }
+ LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL
+LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator");
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ XrResult result = XR_SUCCESS;
+ if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) {
+ result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
+ }
+ LoaderLogger::GetInstance().AddObjectName(nameInfo->objectHandle, nameInfo->objectType, nameInfo->objectName);
+ LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(XrSession session,
+ const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-session-parameter",
+ "xrSessionBeginDebugUtilsLabelRegionEXT", "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
+ LoaderLogger::LogValidationErrorMessage("TBD", "xrSessionBeginDebugUtilsLabelRegionEXT",
+ "Extension entrypoint called without enabling appropriate extension",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+ if (nullptr == labelInfo) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
+ "xrSessionBeginDebugUtilsLabelRegionEXT", "labelInfo must be non-NULL",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo);
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
+ return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
+ }
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionEndDebugUtilsLabelRegionEXT-session-parameter",
+ "xrSessionEndDebugUtilsLabelRegionEXT", "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+ LoaderLogger::GetInstance().EndLabelRegion(session);
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
+ return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session);
+ }
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(XrSession session,
+ const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-session-parameter",
+ "xrSessionInsertDebugUtilsLabelEXT", "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
+ LoaderLogger::LogValidationErrorMessage("TBD", "xrSessionInsertDebugUtilsLabelEXT",
+ "Extension entrypoint called without enabling appropriate extension",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+ if (nullptr == labelInfo) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
+ "xrSessionInsertDebugUtilsLabelEXT", "labelInfo must be non-NULL",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ LoaderLogger::GetInstance().InsertLabel(session, labelInfo);
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) {
+ return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo);
+ }
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+} // extern "C"
diff --git a/extern/openxr/src/loader/loader_instance.cpp b/extern/openxr/src/loader/loader_instance.cpp
new file mode 100644
index 00000000000..67b0ee5be3e
--- /dev/null
+++ b/extern/openxr/src/loader/loader_instance.cpp
@@ -0,0 +1,235 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#ifdef XR_OS_WINDOWS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "loader_instance.hpp"
+
+#include "api_layer_interface.hpp"
+#include "hex_and_handles.h"
+#include "loader_interfaces.h"
+#include "loader_logger.hpp"
+#include "runtime_interface.hpp"
+#include "xr_generated_dispatch_table.h"
+#include "xr_generated_loader.hpp"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+// Extensions that are supported by the loader, but may not be supported
+// the the runtime.
+static const XrExtensionProperties g_debug_utils_props = {XR_TYPE_EXTENSION_PROPERTIES, nullptr, XR_EXT_DEBUG_UTILS_EXTENSION_NAME,
+ XR_EXT_debug_utils_SPEC_VERSION};
+const std::vector<XrExtensionProperties> LoaderInstance::_loader_supported_extensions = {g_debug_utils_props};
+
+// Factory method
+XrResult LoaderInstance::CreateInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces,
+ const XrInstanceCreateInfo* info, XrInstance* instance) {
+ XrResult last_error = XR_SUCCESS;
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering LoaderInstance::CreateInstance");
+
+ // Topmost means "closest to the application"
+ PFN_xrCreateInstance topmost_ci_fp = LoaderXrTermCreateInstance;
+ PFN_xrCreateApiLayerInstance topmost_cali_fp = LoaderXrTermCreateApiLayerInstance;
+
+ // Create the loader instance
+ std::unique_ptr<LoaderInstance> loader_instance(new LoaderInstance(std::move(api_layer_interfaces)));
+ *instance = reinterpret_cast<XrInstance>(loader_instance.get());
+
+ // Only start the xrCreateApiLayerInstance stack if we have layers.
+ std::vector<std::unique_ptr<ApiLayerInterface>>& layer_interfaces = loader_instance->LayerInterfaces();
+ if (!layer_interfaces.empty()) {
+ // Initialize an array of ApiLayerNextInfo structs
+ auto* next_info_list = new XrApiLayerNextInfo[layer_interfaces.size()];
+ auto ni_index = static_cast<uint32_t>(layer_interfaces.size() - 1);
+ for (uint32_t i = 0; i <= ni_index; i++) {
+ next_info_list[i].structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO;
+ next_info_list[i].structVersion = XR_API_LAYER_NEXT_INFO_STRUCT_VERSION;
+ next_info_list[i].structSize = sizeof(XrApiLayerNextInfo);
+ }
+
+ // Go through all layers, and override the instance pointers with the layer version. However,
+ // go backwards through the layer list so we replace in reverse order so the layers can call their next function
+ // appropriately.
+ XrApiLayerNextInfo* prev_nextinfo = nullptr;
+ PFN_xrGetInstanceProcAddr prev_gipa_fp = LoaderXrTermGetInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance prev_cali_fp = LoaderXrTermCreateApiLayerInstance;
+ for (auto layer_interface = layer_interfaces.rbegin(); layer_interface != layer_interfaces.rend(); ++layer_interface) {
+ // Collect current layer's function pointers
+ PFN_xrGetInstanceProcAddr cur_gipa_fp = (*layer_interface)->GetInstanceProcAddrFuncPointer();
+ PFN_xrCreateApiLayerInstance cur_cali_fp = (*layer_interface)->GetCreateApiLayerInstanceFuncPointer();
+ // Update topmosts
+ cur_gipa_fp(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&topmost_ci_fp));
+ topmost_cali_fp = cur_cali_fp;
+
+ // Fill in layer info and link previous (lower) layer fxn pointers
+ strncpy(next_info_list[ni_index].layerName, (*layer_interface)->LayerName().c_str(), XR_MAX_API_LAYER_NAME_SIZE - 1);
+ next_info_list[ni_index].layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
+ next_info_list[ni_index].next = prev_nextinfo;
+ next_info_list[ni_index].nextGetInstanceProcAddr = prev_gipa_fp;
+ next_info_list[ni_index].nextCreateApiLayerInstance = prev_cali_fp;
+
+ // Update saved pointers for next iteration
+ prev_nextinfo = &next_info_list[ni_index];
+ prev_gipa_fp = cur_gipa_fp;
+ prev_cali_fp = cur_cali_fp;
+ ni_index--;
+ }
+
+ // Populate the ApiLayerCreateInfo struct and pass to topmost CreateApiLayerInstance()
+ XrApiLayerCreateInfo api_layer_ci = {};
+ api_layer_ci.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO;
+ api_layer_ci.structVersion = XR_API_LAYER_CREATE_INFO_STRUCT_VERSION;
+ api_layer_ci.structSize = sizeof(XrApiLayerCreateInfo);
+ api_layer_ci.loaderInstance = reinterpret_cast<void*>(loader_instance.get());
+ api_layer_ci.settings_file_location[0] = '\0';
+ api_layer_ci.nextInfo = next_info_list;
+ last_error = topmost_cali_fp(info, &api_layer_ci, instance);
+
+ delete[] next_info_list;
+ } else {
+ last_error = topmost_ci_fp(info, instance);
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ // Check the list of enabled extensions to make sure something supports them, and, if we do,
+ // add it to the list of enabled extensions
+ for (uint32_t ext = 0; ext < info->enabledExtensionCount; ++ext) {
+ bool found = false;
+ // First check the runtime
+ if (RuntimeInterface::GetRuntime().SupportsExtension(info->enabledExtensionNames[ext])) {
+ found = true;
+ }
+ // Next check the loader
+ if (!found) {
+ for (auto loader_extension : LoaderInstance::_loader_supported_extensions) {
+ if (strcmp(loader_extension.extensionName, info->enabledExtensionNames[ext]) == 0) {
+ found = true;
+ break;
+ }
+ }
+ }
+ // Finally, check the enabled layers
+ if (!found) {
+ for (auto& layer_interface : layer_interfaces) {
+ if (layer_interface->SupportsExtension(info->enabledExtensionNames[ext])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ std::string msg = "LoaderInstance::CreateInstance, no support found for requested extension: ";
+ msg += info->enabledExtensionNames[ext];
+ LoaderLogger::LogErrorMessage("xrCreateInstance", msg);
+ last_error = XR_ERROR_EXTENSION_NOT_PRESENT;
+ break;
+ }
+ loader_instance->AddEnabledExtension(info->enabledExtensionNames[ext]);
+ }
+ } else {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "LoaderInstance::CreateInstance chained CreateInstance call failed");
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ // Create the top-level dispatch table for the instance. This will contain the function pointers to the
+ // first instantiation of every command, whether that is in a layer, or a runtime.
+ last_error = loader_instance->CreateDispatchTable(*instance);
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance",
+ "LoaderInstance::CreateInstance failed creating top-level dispatch table");
+ } else {
+ last_error = g_instance_map.Insert(*instance, *loader_instance);
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateInstance",
+ "LoaderInstance::CreateInstance failed inserting new instance into map: may be null or not unique");
+ }
+ }
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ std::ostringstream oss;
+ oss << "LoaderInstance::CreateInstance succeeded with ";
+ oss << loader_instance->LayerInterfaces().size();
+ oss << " layers enabled and runtime interface - created instance = ";
+ oss << HandleToHexString(*instance);
+ LoaderLogger::LogInfoMessage("xrCreateInstance", oss.str());
+ // Make the unique_ptr no longer delete this.
+ // Don't need to save the return value because we already set *instance
+ (void)loader_instance.release();
+ }
+
+ // Always clear the input lists. Either we use them or we don't.
+ api_layer_interfaces.clear();
+
+ return last_error;
+}
+
+LoaderInstance::LoaderInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces)
+ : _unique_id(0xDECAFBAD),
+ _api_version(XR_CURRENT_API_VERSION),
+ _api_layer_interfaces(std::move(api_layer_interfaces)),
+ _dispatch_valid(false),
+ _messenger(XR_NULL_HANDLE) {}
+
+LoaderInstance::~LoaderInstance() {
+ std::ostringstream oss;
+ oss << "Destroying LoaderInstance = ";
+ oss << PointerToHexString(this);
+ LoaderLogger::LogInfoMessage("xrDestroyInstance", oss.str());
+}
+
+XrResult LoaderInstance::CreateDispatchTable(XrInstance instance) {
+ XrResult res = XR_SUCCESS;
+ // Create the top-level dispatch table. First, we want to start with a dispatch table generated
+ // using the commands from the runtime, with the exception of commands that we need a terminator
+ // for. The loaderGenInitInstanceDispatchTable utility function handles that automatically for us.
+ std::unique_ptr<XrGeneratedDispatchTable> new_instance_dispatch_table(new XrGeneratedDispatchTable());
+ LoaderGenInitInstanceDispatchTable(_runtime_instance, new_instance_dispatch_table);
+
+ // Go through all layers, and override the instance pointers with the layer version. However,
+ // go backwards through the layer list so we replace in reverse order so the layers can call their next function
+ // appropriately.
+ if (!_api_layer_interfaces.empty()) {
+ (*_api_layer_interfaces.begin())->GenUpdateInstanceDispatchTable(instance, new_instance_dispatch_table);
+ }
+
+ // Set the top-level instance dispatch table to the top-most commands now that we've figured them out.
+ _dispatch_table = std::move(new_instance_dispatch_table);
+ _dispatch_valid = true;
+ return res;
+}
+
+bool LoaderInstance::ExtensionIsEnabled(const std::string& extension) {
+ for (std::string& cur_enabled : _enabled_extensions) {
+ if (cur_enabled == extension) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/extern/openxr/src/loader/loader_instance.hpp b/extern/openxr/src/loader/loader_instance.hpp
new file mode 100644
index 00000000000..5aeff39eaa3
--- /dev/null
+++ b/extern/openxr/src/loader/loader_instance.hpp
@@ -0,0 +1,155 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include "extra_algorithms.h"
+
+#include <openxr/openxr.h>
+
+#include <cmath>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+class LoaderInstance;
+class ApiLayerInterface;
+struct XrGeneratedDispatchTable;
+
+typedef std::unique_lock<std::mutex> UniqueLock;
+template <typename HandleType>
+class HandleLoaderMap {
+ public:
+ using handle_t = HandleType;
+ using map_t = std::unordered_map<HandleType, LoaderInstance*>;
+ using value_t = typename map_t::value_type;
+
+ /// Lookup a handle.
+ /// Returns nullptr if not found.
+ LoaderInstance* Get(HandleType handle);
+
+ /// Insert an info for the supplied handle.
+ /// Returns XR_ERROR_RUNTIME_FAILURE if it's null.
+ /// Does not error if already there, because the loader is not currently very good at cleaning up handles.
+ XrResult Insert(HandleType handle, LoaderInstance& loader);
+
+ /// Remove the info associated with the supplied handle.
+ /// Returns XR_ERROR_RUNTIME_FAILURE if it's null or not there.
+ XrResult Erase(HandleType handle);
+
+ /// Removes handles associated with a loader instance.
+ void RemoveHandlesForLoader(LoaderInstance& loader);
+
+ protected:
+ map_t instance_map_;
+ std::mutex mutex_;
+};
+
+class LoaderInstance {
+ public:
+ // Factory method
+ static XrResult CreateInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& layer_interfaces,
+ const XrInstanceCreateInfo* info, XrInstance* instance);
+
+ LoaderInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces);
+ virtual ~LoaderInstance();
+
+ bool IsValid() { return _unique_id == 0xDECAFBAD; }
+ XrVersion ApiVersion() { return _api_version; }
+ XrResult CreateDispatchTable(XrInstance instance);
+ void SetRuntimeInstance(XrInstance instance) { _runtime_instance = instance; }
+ const std::unique_ptr<XrGeneratedDispatchTable>& DispatchTable() { return _dispatch_table; }
+ std::vector<std::unique_ptr<ApiLayerInterface>>& LayerInterfaces() { return _api_layer_interfaces; }
+ void AddEnabledExtension(const std::string& extension) { return _enabled_extensions.push_back(extension); }
+ bool ExtensionIsEnabled(const std::string& extension);
+ static const std::vector<XrExtensionProperties>& LoaderSpecificExtensions() { return _loader_supported_extensions; }
+ XrDebugUtilsMessengerEXT DefaultDebugUtilsMessenger() { return _messenger; }
+ void SetDefaultDebugUtilsMessenger(XrDebugUtilsMessengerEXT messenger) { _messenger = messenger; }
+
+ private:
+ uint32_t _unique_id; // 0xDECAFBAD - for debugging
+ XrVersion _api_version;
+ std::vector<std::unique_ptr<ApiLayerInterface>> _api_layer_interfaces;
+ XrInstance _runtime_instance;
+ bool _dispatch_valid;
+ std::unique_ptr<XrGeneratedDispatchTable> _dispatch_table;
+ static const std::vector<XrExtensionProperties> _loader_supported_extensions;
+ std::vector<std::string> _enabled_extensions;
+ // Internal debug messenger created during xrCreateInstance
+ XrDebugUtilsMessengerEXT _messenger;
+};
+
+template <typename HandleType>
+inline LoaderInstance* HandleLoaderMap<HandleType>::Get(HandleType handle) {
+ if (handle == XR_NULL_HANDLE) {
+ return nullptr;
+ }
+ // Try to find the handle in the appropriate map
+ UniqueLock lock(mutex_);
+ auto entry_returned = instance_map_.find(handle);
+ if (entry_returned == instance_map_.end()) {
+ return nullptr;
+ }
+ return entry_returned->second;
+}
+
+template <typename HandleType>
+inline XrResult HandleLoaderMap<HandleType>::Insert(HandleType handle, LoaderInstance& loader) {
+ if (handle == XR_NULL_HANDLE) {
+ // Internal error in loader or runtime.
+ return XR_ERROR_RUNTIME_FAILURE;
+ }
+ UniqueLock lock(mutex_);
+ //! @todo This check is currently disabled, because the loader is not good at cleaning up handles when their parent handles are
+ //! destroyed.
+#if 0
+ auto entry_returned = instance_map_.find(handle);
+ if (entry_returned != instance_map_.end()) {
+ // Internal error in loader or runtime.
+ return XR_ERROR_RUNTIME_FAILURE;
+ }
+#endif
+ instance_map_[handle] = &loader;
+ return XR_SUCCESS;
+}
+
+template <typename HandleType>
+inline XrResult HandleLoaderMap<HandleType>::Erase(HandleType handle) {
+ if (handle == XR_NULL_HANDLE) {
+ // Internal error in loader or runtime.
+ return XR_ERROR_RUNTIME_FAILURE;
+ }
+ UniqueLock lock(mutex_);
+ auto entry_returned = instance_map_.find(handle);
+ if (entry_returned == instance_map_.end()) {
+ // Internal error in loader or runtime.
+ return XR_ERROR_RUNTIME_FAILURE;
+ }
+ instance_map_.erase(handle);
+ return XR_SUCCESS;
+}
+
+template <typename HandleType>
+inline void HandleLoaderMap<HandleType>::RemoveHandlesForLoader(LoaderInstance& loader) {
+ UniqueLock lock(mutex_);
+ auto search_value = &loader;
+ map_erase_if(instance_map_, [=](value_t const& data) { return data.second && data.second == search_value; });
+}
diff --git a/extern/openxr/src/loader/loader_logger.cpp b/extern/openxr/src/loader/loader_logger.cpp
new file mode 100644
index 00000000000..9e4a9bdbed4
--- /dev/null
+++ b/extern/openxr/src/loader/loader_logger.cpp
@@ -0,0 +1,405 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "loader_logger.hpp"
+
+#include "extra_algorithms.h"
+#include "hex_and_handles.h"
+#include "loader_logger_recorders.hpp"
+#include "platform_utils.hpp"
+
+#include <openxr/openxr.h>
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+std::unique_ptr<LoaderLogger> LoaderLogger::_instance;
+std::once_flag LoaderLogger::_once_flag;
+
+std::string XrLoaderLogObjectInfo::ToString() const {
+ std::ostringstream oss;
+ oss << Uint64ToHexString(handle);
+ if (!name.empty()) {
+ oss << " (" << name << ")";
+ }
+ return oss.str();
+}
+
+bool LoaderLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT /*message_severity*/,
+ XrDebugUtilsMessageTypeFlagsEXT /*message_type*/,
+ const XrDebugUtilsMessengerCallbackDataEXT* /*callback_data*/) {
+ return false;
+}
+
+void ObjectInfoCollection::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
+ // If name is empty, we should erase it
+ if (object_name.empty()) {
+ vector_remove_if_and_erase(_object_info, [=](XrLoaderLogObjectInfo const& info) { return info.handle == object_handle; });
+ return;
+ }
+ // Otherwise, add it or update the name
+
+ XrLoaderLogObjectInfo new_obj = {object_handle, object_type};
+
+ // If it already exists, update the name
+ auto lookup_info = LookUpStoredObjectInfo(new_obj);
+ if (lookup_info != nullptr) {
+ lookup_info->name = object_name;
+ return;
+ }
+
+ // It doesn't exist, so add a new info block
+ new_obj.name = object_name;
+ _object_info.push_back(new_obj);
+}
+
+XrLoaderLogObjectInfo const* ObjectInfoCollection::LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info) const {
+ auto e = _object_info.end();
+ auto it = std::find_if(_object_info.begin(), e, [&](XrLoaderLogObjectInfo const& stored) { return Equivalent(stored, info); });
+ if (it != e) {
+ return &(*it);
+ }
+ return nullptr;
+}
+
+XrLoaderLogObjectInfo* ObjectInfoCollection::LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info) {
+ auto e = _object_info.end();
+ auto it = std::find_if(_object_info.begin(), e, [&](XrLoaderLogObjectInfo const& stored) { return Equivalent(stored, info); });
+ if (it != e) {
+ return &(*it);
+ }
+ return nullptr;
+}
+
+bool ObjectInfoCollection::LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const {
+ auto info_lookup = LookUpStoredObjectInfo(info.objectHandle, info.objectType);
+ if (info_lookup != nullptr) {
+ info.objectName = info_lookup->name.c_str();
+ return true;
+ }
+ return false;
+}
+
+bool ObjectInfoCollection::LookUpObjectName(XrLoaderLogObjectInfo& info) const {
+ auto info_lookup = LookUpStoredObjectInfo(info);
+ if (info_lookup != nullptr) {
+ info.name = info_lookup->name;
+ return true;
+ }
+ return false;
+}
+
+// Utility functions for converting to/from XR_EXT_debug_utils values
+
+XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severities) {
+ XrLoaderLogMessageSeverityFlags log_severities = 0UL;
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
+ }
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
+ }
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
+ }
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
+ }
+ return log_severities;
+}
+
+XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
+ XrLoaderLogMessageSeverityFlags log_severities) {
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severities = 0UL;
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ }
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ }
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ }
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ }
+ return utils_severities;
+}
+
+XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types) {
+ XrLoaderLogMessageTypeFlagBits log_types = 0UL;
+ if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) != 0u) {
+ log_types |= XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT;
+ }
+ if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0u) {
+ log_types |= XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT;
+ }
+ if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0u) {
+ log_types |= XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT;
+ }
+ return log_types;
+}
+
+XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types) {
+ XrDebugUtilsMessageTypeFlagsEXT utils_types = 0UL;
+ if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT) != 0u) {
+ utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT) != 0u) {
+ utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ }
+ if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT) != 0u) {
+ utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ }
+ return utils_types;
+}
+
+LoaderLogger::LoaderLogger() {
+ // Add an error logger by default so that we at least get errors out to std::cerr.
+ AddLogRecorder(MakeStdErrLoaderLogRecorder(nullptr));
+
+ // If the environment variable to enable loader debugging is set, then enable the
+ // appropriate logging out to std::cout.
+ char* loader_debug = PlatformUtilsGetSecureEnv("XR_LOADER_DEBUG");
+ if (nullptr != loader_debug) {
+ std::string debug_string = loader_debug;
+ PlatformUtilsFreeEnv(loader_debug);
+ XrLoaderLogMessageSeverityFlags debug_flags = {};
+ if (debug_string == "error") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
+ } else if (debug_string == "warn") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
+ } else if (debug_string == "info") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
+ XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
+ } else if (debug_string == "all" || debug_string == "verbose") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
+ XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
+ }
+ AddLogRecorder(MakeStdOutLoaderLogRecorder(nullptr, debug_flags));
+ }
+}
+
+void LoaderLogger::AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder) { _recorders.push_back(std::move(recorder)); }
+
+void LoaderLogger::RemoveLogRecorder(uint64_t unique_id) {
+ vector_remove_if_and_erase(
+ _recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) { return recorder->UniqueId() == unique_id; });
+}
+
+bool LoaderLogger::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const std::string& message_id, const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects) {
+ XrLoaderLogMessengerCallbackData callback_data = {};
+ callback_data.message_id = message_id.c_str();
+ callback_data.command_name = command_name.c_str();
+ callback_data.message = message.c_str();
+
+ std::vector<XrDebugUtilsLabelEXT> labels;
+
+ // Copy objects into a vector we can modify and will keep around past the callback.
+ std::vector<XrLoaderLogObjectInfo> object_vector = objects;
+ for (auto& obj : object_vector) {
+ // Check for any names that have been associated with the objects and set them up here
+ _object_names.LookUpObjectName(obj);
+ // If this is a session, see if there are any labels associated with it for us to add
+ // to the callback content.
+ if (XR_OBJECT_TYPE_SESSION == obj.type) {
+ LookUpSessionLabels(obj.GetTypedHandle<XrSession>(), labels);
+ }
+ }
+ callback_data.objects = object_vector.empty() ? nullptr : object_vector.data();
+ callback_data.object_count = static_cast<uint8_t>(object_vector.size());
+
+ callback_data.session_labels = labels.empty() ? nullptr : labels.data();
+ callback_data.session_labels_count = static_cast<uint8_t>(labels.size());
+
+ bool exit_app = false;
+ for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
+ if ((recorder->MessageSeverities() & message_severity) == message_severity &&
+ (recorder->MessageTypes() & message_type) == message_type) {
+ exit_app |= recorder->LogMessage(message_severity, message_type, &callback_data);
+ }
+ }
+ return exit_app;
+}
+
+void LoaderLogger::LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const {
+ auto session_label_iterator = _session_labels.find(session);
+ if (session_label_iterator != _session_labels.end()) {
+ auto& internalSessionLabels = *session_label_iterator->second;
+ // Copy the debug utils labels in reverse order in the the labels vector.
+ std::transform(internalSessionLabels.rbegin(), internalSessionLabels.rend(), std::back_inserter(labels),
+ [](InternalSessionLabelPtr const& label) { return label->debug_utils_label; });
+ }
+}
+
+// Extension-specific logging functions
+bool LoaderLogger::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
+ XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
+ bool exit_app = false;
+ XrLoaderLogMessageSeverityFlags log_message_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
+ XrLoaderLogMessageTypeFlags log_message_type = DebugUtilsMessageTypesToLoaderLogMessageTypes(message_type);
+
+ bool obj_name_found = false;
+ std::vector<XrDebugUtilsLabelEXT> labels;
+ if (!_object_names.Empty() && callback_data->objectCount > 0) {
+ for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
+ auto& current_obj = callback_data->objects[obj];
+ auto stored_info = _object_names.LookUpStoredObjectInfo(current_obj.objectHandle, current_obj.objectType);
+ if (stored_info != nullptr) {
+ obj_name_found = true;
+ }
+
+ // If this is a session, see if there are any labels associated with it for us to add
+ // to the callback content.
+ if (XR_OBJECT_TYPE_SESSION == current_obj.objectType) {
+ XrSession session = TreatIntegerAsHandle<XrSession>(current_obj.objectHandle);
+ LookUpSessionLabels(session, labels);
+ }
+ }
+ }
+ // Use unmodified ones by default.
+ XrDebugUtilsMessengerCallbackDataEXT const* callback_data_to_use = callback_data;
+
+ XrDebugUtilsMessengerCallbackDataEXT new_callback_data = *callback_data;
+ std::vector<XrDebugUtilsObjectNameInfoEXT> new_objects;
+
+ // If a name or a label has been found, we should update it in a new version of the callback
+ if (obj_name_found || !labels.empty()) {
+ // Copy objects
+ new_objects =
+ std::vector<XrDebugUtilsObjectNameInfoEXT>(callback_data->objects, callback_data->objects + callback_data->objectCount);
+ for (auto& obj : new_objects) {
+ // Check for any names that have been associated with the objects and set them up here
+ _object_names.LookUpObjectName(obj);
+ }
+ new_callback_data.objects = new_objects.data();
+ new_callback_data.sessionLabelCount = static_cast<uint32_t>(labels.size());
+ new_callback_data.sessionLabels = labels.empty() ? nullptr : labels.data();
+ callback_data_to_use = &new_callback_data;
+ }
+
+ // Loop through the recorders
+ for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
+ // Only send the message if it's a debug utils recorder and of the type the recorder cares about.
+ if (recorder->Type() != XR_LOADER_LOG_DEBUG_UTILS ||
+ (recorder->MessageSeverities() & log_message_severity) != log_message_severity ||
+ (recorder->MessageTypes() & log_message_type) != log_message_type) {
+ continue;
+ }
+
+ exit_app |= recorder->LogDebugUtilsMessage(message_severity, message_type, callback_data_to_use);
+ }
+ return exit_app;
+}
+
+void LoaderLogger::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
+ _object_names.AddObjectName(object_handle, object_type, object_name);
+}
+
+// We always want to remove the old individual label before we do anything else.
+// So, do that in it's own method
+void LoaderLogger::RemoveIndividualLabel(InternalSessionLabelList& label_vec) {
+ if (!label_vec.empty() && label_vec.back()->is_individual_label) {
+ label_vec.pop_back();
+ }
+}
+
+InternalSessionLabelList* LoaderLogger::GetSessionLabelList(XrSession session) {
+ auto session_label_iterator = _session_labels.find(session);
+ if (session_label_iterator == _session_labels.end()) {
+ return nullptr;
+ }
+ return session_label_iterator->second.get();
+}
+
+InternalSessionLabelList& LoaderLogger::GetOrCreateSessionLabelList(XrSession session) {
+ InternalSessionLabelList* vec_ptr = GetSessionLabelList(session);
+ if (vec_ptr == nullptr) {
+ std::unique_ptr<InternalSessionLabelList> vec(new InternalSessionLabelList);
+ vec_ptr = vec.get();
+ _session_labels[session] = std::move(vec);
+ }
+ return *vec_ptr;
+}
+
+void LoaderLogger::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
+ auto& vec = GetOrCreateSessionLabelList(session);
+
+ // Individual labels do not stay around in the transition into a new label region
+ RemoveIndividualLabel(vec);
+
+ // Start the new label region
+ InternalSessionLabelPtr new_session_label(new InternalSessionLabel);
+ new_session_label->label_name = label_info->labelName;
+ new_session_label->debug_utils_label = *label_info;
+ new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
+ new_session_label->is_individual_label = false;
+ vec.emplace_back(std::move(new_session_label));
+}
+
+void LoaderLogger::EndLabelRegion(XrSession session) {
+ InternalSessionLabelList* vec_ptr = GetSessionLabelList(session);
+ if (vec_ptr == nullptr) {
+ return;
+ }
+
+ // Individual labels do not stay around in the transition out of label region
+ RemoveIndividualLabel(*vec_ptr);
+
+ // Remove the last label region
+ if (!vec_ptr->empty()) {
+ vec_ptr->pop_back();
+ }
+}
+
+void LoaderLogger::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
+ //! @todo only difference from BeginLabelRegion is value of is_individual_label
+ auto& vec = GetOrCreateSessionLabelList(session);
+
+ // Remove any individual layer that might already be there
+ RemoveIndividualLabel(vec);
+
+ // Insert a new individual label
+ InternalSessionLabelPtr new_session_label(new InternalSessionLabel);
+ new_session_label->label_name = label_info->labelName;
+ new_session_label->debug_utils_label = *label_info;
+ new_session_label->debug_utils_label.labelName = new_session_label->label_name.c_str();
+ new_session_label->is_individual_label = true;
+ vec.emplace_back(std::move(new_session_label));
+}
+
+// Called during xrDestroySession. We need to delete all session related labels.
+void LoaderLogger::DeleteSessionLabels(XrSession session) {
+ InternalSessionLabelList* vec_ptr = GetSessionLabelList(session);
+ if (vec_ptr == nullptr) {
+ return;
+ }
+ _session_labels.erase(session);
+}
diff --git a/extern/openxr/src/loader/loader_logger.hpp b/extern/openxr/src/loader/loader_logger.hpp
new file mode 100644
index 00000000000..4a10d0be178
--- /dev/null
+++ b/extern/openxr/src/loader/loader_logger.hpp
@@ -0,0 +1,289 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <openxr/openxr.h>
+
+#include "hex_and_handles.h"
+
+// Use internal versions of flags similar to XR_EXT_debug_utils so that
+// we're not tightly coupled to that extension. This way, if the extension
+// changes or gets replaced, we can be flexible in the loader.
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT 0x00000001
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT 0x00000010
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT 0x00000100
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT 0x00001000
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_DEFAULT_BITS 0x00000000
+typedef XrFlags64 XrLoaderLogMessageSeverityFlagBits;
+typedef XrFlags64 XrLoaderLogMessageSeverityFlags;
+
+#define XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT 0x00000001
+#define XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT 0x00000002
+#define XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT 0x00000004
+#define XR_LOADER_LOG_MESSAGE_TYPE_DEFAULT_BITS 0xffffffff
+typedef XrFlags64 XrLoaderLogMessageTypeFlagBits;
+typedef XrFlags64 XrLoaderLogMessageTypeFlags;
+
+struct XrLoaderLogObjectInfo {
+ //! Type-erased handle value
+ uint64_t handle;
+
+ //! Kind of object this handle refers to
+ XrObjectType type;
+
+ //! To be assigned by the application - not part of this object's identity
+ std::string name;
+
+ /// Un-erase the type of the handle and get it properly typed again.
+ ///
+ /// Note: Does not check the type before doing it!
+ template <typename HandleType>
+ HandleType& GetTypedHandle() {
+ return TreatIntegerAsHandle<HandleType&>(handle);
+ }
+
+ //! @overload
+ template <typename HandleType>
+ HandleType const& GetTypedHandle() const {
+ return TreatIntegerAsHandle<HandleType&>(handle);
+ }
+
+ XrLoaderLogObjectInfo() = default;
+
+ //! Create from a typed handle and object type
+ template <typename T>
+ XrLoaderLogObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
+
+ //! Create from an untyped handle value (integer) and object type
+ XrLoaderLogObjectInfo(uint64_t h, XrObjectType t) : handle(h), type(t) {}
+
+ std::string ToString() const;
+};
+
+//! True if the two object infos have the same handle value and handle type
+static inline bool Equivalent(XrLoaderLogObjectInfo const& a, XrLoaderLogObjectInfo const& b) {
+ return a.handle == b.handle && a.type == b.type;
+}
+//! @overload
+static inline bool Equivalent(XrDebugUtilsObjectNameInfoEXT const& a, XrLoaderLogObjectInfo const& b) {
+ return a.objectHandle == b.handle && a.objectType == b.type;
+}
+//! @overload
+static inline bool Equivalent(XrLoaderLogObjectInfo const& a, XrDebugUtilsObjectNameInfoEXT const& b) { return Equivalent(b, a); }
+
+struct XrLoaderLogMessengerCallbackData {
+ const char* message_id;
+ const char* command_name;
+ const char* message;
+ uint8_t object_count;
+ XrLoaderLogObjectInfo* objects;
+ uint8_t session_labels_count;
+ XrDebugUtilsLabelEXT* session_labels;
+};
+
+enum XrLoaderLogType {
+ XR_LOADER_LOG_UNKNOWN = 0,
+ XR_LOADER_LOG_STDERR,
+ XR_LOADER_LOG_STDOUT,
+ XR_LOADER_LOG_DEBUG_UTILS,
+};
+
+class LoaderLogRecorder {
+ public:
+ LoaderLogRecorder(XrLoaderLogType type, void* user_data, XrLoaderLogMessageSeverityFlags message_severities,
+ XrLoaderLogMessageTypeFlags message_types) {
+ _active = false;
+ _user_data = user_data;
+ _type = type;
+ _unique_id = 0;
+ _message_severities = message_severities;
+ _message_types = message_types;
+ }
+ virtual ~LoaderLogRecorder() = default;
+
+ XrLoaderLogType Type() { return _type; }
+
+ uint64_t UniqueId() { return _unique_id; }
+
+ XrLoaderLogMessageSeverityFlags MessageSeverities() { return _message_severities; }
+
+ XrLoaderLogMessageTypeFlags MessageTypes() { return _message_types; }
+
+ virtual void Start() { _active = true; }
+
+ bool IsPaused() { return _active; }
+
+ virtual void Pause() { _active = false; }
+
+ virtual void Resume() { _active = true; }
+
+ virtual void Stop() { _active = false; }
+
+ virtual bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) = 0;
+
+ // Extension-specific logging functions - defaults to do nothing.
+ virtual bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
+ XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
+
+ protected:
+ bool _active;
+ XrLoaderLogType _type;
+ uint64_t _unique_id;
+ void* _user_data;
+ XrLoaderLogMessageSeverityFlags _message_severities;
+ XrLoaderLogMessageTypeFlags _message_types;
+};
+
+class ObjectInfoCollection {
+ public:
+ //! Called from LoaderXrTermSetDebugUtilsObjectNameEXT - an empty name means remove
+ void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
+
+ //! Find the stored object info, if any, matching handle and type.
+ //! Return nullptr if not found.
+ XrLoaderLogObjectInfo const* LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info) const;
+ //! Find the stored object info, if any, matching handle and type.
+ //! Return nullptr if not found.
+ XrLoaderLogObjectInfo* LookUpStoredObjectInfo(XrLoaderLogObjectInfo const& info);
+
+ //! Find the stored object info, if any.
+ //! Return nullptr if not found.
+ XrLoaderLogObjectInfo const* LookUpStoredObjectInfo(uint64_t handle, XrObjectType type) const {
+ return LookUpStoredObjectInfo({handle, type});
+ }
+
+ //! Find the object name, if any, and update debug utils info accordingly.
+ //! Return true if found and updated.
+ bool LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const;
+
+ //! Find the object name, if any, and update logging info accordingly.
+ //! Return true if found and updated.
+ bool LookUpObjectName(XrLoaderLogObjectInfo& info) const;
+
+ //! Is the collection empty?
+ bool Empty() const { return _object_info.empty(); }
+
+ private:
+ // Object names that have been set for given objects
+ std::vector<XrLoaderLogObjectInfo> _object_info;
+};
+
+struct InternalSessionLabel {
+ XrDebugUtilsLabelEXT debug_utils_label;
+ std::string label_name;
+ bool is_individual_label;
+};
+
+using InternalSessionLabelPtr = std::unique_ptr<InternalSessionLabel>;
+using InternalSessionLabelList = std::vector<InternalSessionLabelPtr>;
+
+class LoaderLogger {
+ public:
+ static LoaderLogger& GetInstance() {
+ std::call_once(LoaderLogger::_once_flag, []() { _instance.reset(new LoaderLogger); });
+ return *(_instance.get());
+ }
+
+ void AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder);
+ void RemoveLogRecorder(uint64_t unique_id);
+
+ //! Called from LoaderXrTermSetDebugUtilsObjectNameEXT - an empty name means remove
+ void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
+ void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info);
+ void EndLabelRegion(XrSession session);
+ void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info);
+ void DeleteSessionLabels(XrSession session);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const std::string& message_id, const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {});
+ static bool LogErrorMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogWarningMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogInfoMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogVerboseMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogValidationErrorMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
+ vuid, command_name, message, objects);
+ }
+ static bool LogValidationWarningMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
+ const std::vector<XrLoaderLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
+ vuid, command_name, message, objects);
+ }
+
+ // Extension-specific logging functions
+ bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
+
+ private:
+ LoaderLogger();
+ LoaderLogger(const LoaderLogger&) = delete;
+ LoaderLogger& operator=(const LoaderLogger&) = delete;
+
+ /// Retrieve labels for the given session, if any, and push them in reverse order on the vector.
+ void LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const;
+
+ void RemoveIndividualLabel(InternalSessionLabelList& label_vec);
+ InternalSessionLabelList* GetSessionLabelList(XrSession session);
+ InternalSessionLabelList& GetOrCreateSessionLabelList(XrSession session);
+
+ static std::unique_ptr<LoaderLogger> _instance;
+ static std::once_flag _once_flag;
+
+ // List of available recorder objects
+ std::vector<std::unique_ptr<LoaderLogRecorder>> _recorders;
+
+ ObjectInfoCollection _object_names;
+ // Session labels
+ std::unordered_map<XrSession, std::unique_ptr<InternalSessionLabelList>> _session_labels;
+};
+
+// Utility functions for converting to/from XR_EXT_debug_utils values
+XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severities);
+XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
+ XrLoaderLogMessageSeverityFlags log_severities);
+XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types);
+XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types);
diff --git a/extern/openxr/src/loader/loader_logger_recorders.cpp b/extern/openxr/src/loader/loader_logger_recorders.cpp
new file mode 100644
index 00000000000..afa82133cb1
--- /dev/null
+++ b/extern/openxr/src/loader/loader_logger_recorders.cpp
@@ -0,0 +1,188 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "loader_logger_recorders.hpp"
+
+#include "hex_and_handles.h"
+#include "loader_logger.hpp"
+
+#include <openxr/openxr.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <iostream>
+
+// Anonymous namespace to keep these types private
+namespace {
+// With std::cerr: Standard Error logger, always on for now
+// With std::cout: Standard Output logger used with XR_LOADER_DEBUG
+class OstreamLoaderLogRecorder : public LoaderLogRecorder {
+ public:
+ OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) override;
+
+ private:
+ std::ostream& os_;
+};
+
+// Debug Utils logger used with XR_EXT_debug_utils
+class DebugUtilsLogRecorder : public LoaderLogRecorder {
+ public:
+ DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info, XrDebugUtilsMessengerEXT debug_messenger);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) override;
+
+ // Extension-specific logging functions
+ bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) override;
+
+ private:
+ PFN_xrDebugUtilsMessengerCallbackEXT _user_callback;
+};
+
+// Unified stdout/stderr logger
+OstreamLoaderLogRecorder::OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags)
+ : LoaderLogRecorder(XR_LOADER_LOG_STDOUT, user_data, flags, 0xFFFFFFFFUL), os_(os) {
+ // Automatically start
+ Start();
+}
+
+bool OstreamLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) {
+ if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
+ if (XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT > message_severity) {
+ os_ << "Verbose [";
+ } else if (XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT > message_severity) {
+ os_ << "Info [";
+ } else if (XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT > message_severity) {
+ os_ << "Warning [";
+ } else {
+ os_ << "Error [";
+ }
+ switch (message_type) {
+ case XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT:
+ os_ << "GENERAL";
+ break;
+ case XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT:
+ os_ << "SPEC";
+ break;
+ case XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT:
+ os_ << "PERF";
+ break;
+ default:
+ os_ << "UNKNOWN";
+ break;
+ }
+ os_ << " | " << callback_data->command_name << " | " << callback_data->message_id << "] : " << callback_data->message
+ << std::endl;
+
+ for (uint32_t obj = 0; obj < callback_data->object_count; ++obj) {
+ os_ << " Object[" << obj << "] = " << callback_data->objects[obj].ToString();
+ os_ << std::endl;
+ }
+ for (uint32_t label = 0; label < callback_data->session_labels_count; ++label) {
+ os_ << " SessionLabel[" << std::to_string(label) << "] = " << callback_data->session_labels[label].labelName;
+ os_ << std::endl;
+ }
+ }
+
+ // Return of "true" means that we should exit the application after the logged message. We
+ // don't want to do that for our internal logging. Only let a user return true.
+ return false;
+}
+
+// A logger associated with the XR_EXT_debug_utils extension
+
+DebugUtilsLogRecorder::DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
+ XrDebugUtilsMessengerEXT debug_messenger)
+ : LoaderLogRecorder(XR_LOADER_LOG_DEBUG_UTILS, static_cast<void*>(create_info->userData),
+ DebugUtilsSeveritiesToLoaderLogMessageSeverities(create_info->messageSeverities),
+ DebugUtilsMessageTypesToLoaderLogMessageTypes(create_info->messageTypes)),
+ _user_callback(create_info->userCallback) {
+ // Use the debug messenger value to uniquely identify this logger with that messenger
+ _unique_id = MakeHandleGeneric(debug_messenger);
+ Start();
+}
+
+// Extension-specific logging functions
+bool DebugUtilsLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) {
+ bool should_exit = false;
+ if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
+ XrDebugUtilsMessageTypeFlagsEXT utils_type = LoaderLogMessageTypesToDebugUtilsMessageTypes(message_type);
+
+ // Convert the loader log message into the debug utils log message information
+ XrDebugUtilsMessengerCallbackDataEXT utils_callback_data = {};
+ utils_callback_data.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ utils_callback_data.messageId = callback_data->message_id;
+ utils_callback_data.functionName = callback_data->command_name;
+ utils_callback_data.message = callback_data->message;
+ std::vector<XrDebugUtilsObjectNameInfoEXT> utils_objects;
+ utils_objects.resize(callback_data->object_count);
+ for (uint8_t object = 0; object < callback_data->object_count; ++object) {
+ utils_objects[object].type = XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ utils_objects[object].next = nullptr;
+ utils_objects[object].objectHandle = callback_data->objects[object].handle;
+ utils_objects[object].objectType = callback_data->objects[object].type;
+ utils_objects[object].objectName = callback_data->objects[object].name.c_str();
+ }
+ utils_callback_data.objectCount = callback_data->object_count;
+ utils_callback_data.objects = utils_objects.data();
+ utils_callback_data.sessionLabelCount = callback_data->session_labels_count;
+ utils_callback_data.sessionLabels = callback_data->session_labels;
+
+ // Call the user callback with the appropriate info
+ // Return of "true" means that we should exit the application after the logged message.
+ should_exit = (_user_callback(utils_severity, utils_type, &utils_callback_data, _user_data) == XR_TRUE);
+ }
+
+ return should_exit;
+}
+
+bool DebugUtilsLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
+ XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
+ // Call the user callback with the appropriate info
+ // Return of "true" means that we should exit the application after the logged message.
+ return (_user_callback(message_severity, message_type, callback_data, _user_data) == XR_TRUE);
+}
+
+} // namespace
+
+std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags) {
+ std::unique_ptr<LoaderLogRecorder> recorder(new OstreamLoaderLogRecorder(std::cout, user_data, flags));
+ return recorder;
+}
+std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data) {
+ std::unique_ptr<LoaderLogRecorder> recorder(
+ new OstreamLoaderLogRecorder(std::cerr, user_data, XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT));
+ return recorder;
+}
+std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
+ XrDebugUtilsMessengerEXT debug_messenger) {
+ std::unique_ptr<LoaderLogRecorder> recorder(new DebugUtilsLogRecorder(create_info, debug_messenger));
+ return recorder;
+}
diff --git a/extern/openxr/src/loader/loader_logger_recorders.hpp b/extern/openxr/src/loader/loader_logger_recorders.hpp
new file mode 100644
index 00000000000..77fbe879fc1
--- /dev/null
+++ b/extern/openxr/src/loader/loader_logger_recorders.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+#pragma once
+
+#include "loader_logger.hpp"
+
+#include <openxr/openxr.h>
+
+#include <memory>
+
+//! Standard Error logger, always on for now
+std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data);
+
+//! Standard Output logger used with XR_LOADER_DEBUG
+std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags);
+
+// Debug Utils logger used with XR_EXT_debug_utils
+std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
+ XrDebugUtilsMessengerEXT debug_messenger);
+
+// TODO: Add other Derived classes:
+// - FileLoaderLogRecorder - During/after xrCreateInstance
+// - PipeLoaderLogRecorder? - During/after xrCreateInstance
diff --git a/extern/openxr/src/loader/loader_platform.hpp b/extern/openxr/src/loader/loader_platform.hpp
new file mode 100644
index 00000000000..6095d4d9f52
--- /dev/null
+++ b/extern/openxr/src/loader/loader_platform.hpp
@@ -0,0 +1,215 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+// Author: Dave Houlton <daveh@lunarg.com>
+//
+
+#pragma once
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "xr_dependencies.h"
+#include "platform_utils.hpp"
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LOADER_EXPORT __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define LOADER_EXPORT __attribute__((visibility("default")))
+#else
+#define LOADER_EXPORT
+#endif
+
+// Environment variables
+#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+
+// Dynamic Loading of libraries:
+typedef void *LoaderPlatformLibraryHandle;
+static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
+ // When loading the library, we use RTLD_LAZY so that not all symbols have to be
+ // resolved at this time (which improves performance). Note that if not all symbols
+ // can be resolved, this could cause crashes later.
+ // For experimenting/debugging: Define the LD_BIND_NOW environment variable to force all
+ // symbols to be resolved here.
+ return dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
+}
+
+static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
+ (void)path;
+ return dlerror();
+}
+
+static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { dlclose(library); }
+
+static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
+ assert(library);
+ assert(!name.empty());
+ return dlsym(library, name.c_str());
+}
+
+static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
+ (void)name;
+ return dlerror();
+}
+
+#elif defined(XR_OS_WINDOWS)
+
+#define PATH_SEPARATOR ';'
+#define DIRECTORY_SYMBOL '\\'
+
+// Workaround for MS VS 2010/2013 missing snprintf and vsnprintf
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#include <stdint.h>
+
+static inline int32_t xr_vsnprintf(char *result_buffer, size_t buffer_size, const char *print_format, va_list varying_list) {
+ int32_t copy_count = -1;
+ if (buffer_size != 0) {
+ copy_count = _vsnprintf_s(result_buffer, buffer_size, _TRUNCATE, print_format, varying_list);
+ }
+ if (copy_count == -1) {
+ copy_count = _vscprintf(print_format, varying_list);
+ }
+ return copy_count;
+}
+
+static inline int32_t xr_snprintf(char *result_buffer, size_t buffer_size, const char *print_format, ...) {
+ va_list varying_list;
+ va_start(varying_list, print_format);
+ int32_t copy_count = xr_vsnprintf(result_buffer, buffer_size, print_format, varying_list);
+ va_end(varying_list);
+ return copy_count;
+}
+
+#define snprintf xr_snprintf
+#define vsnprintf xr_vsnprintf
+
+#endif
+
+static std::string DescribeError(uint32_t code, bool prefixErrorCode = true) {
+ std::string str;
+
+ if (prefixErrorCode) {
+ char prefixBuffer[64];
+ snprintf(prefixBuffer, sizeof(prefixBuffer), "0x%llx (%lld): ", (uint64_t)code, (int64_t)code);
+ str = prefixBuffer;
+ }
+
+ // Could use FORMAT_MESSAGE_FROM_HMODULE to specify an error source.
+ WCHAR errorBufferW[1024]{};
+ const DWORD errorBufferWCapacity = sizeof(errorBufferW) / sizeof(errorBufferW[0]);
+ const DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr);
+
+ if (length) { // If errorBufferW contains what we are looking for...
+ str += wide_to_utf8(errorBufferW);
+ } else {
+ str = "(unknown)";
+ }
+
+ return str;
+}
+
+// Dynamic Loading:
+typedef HMODULE LoaderPlatformLibraryHandle;
+static LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
+ const std::wstring pathW = utf8_to_wide(path);
+
+ // Try loading the library the original way first.
+ LoaderPlatformLibraryHandle handle = LoadLibraryW(pathW.c_str());
+
+ if (handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
+ const DWORD dwAttrib = GetFileAttributesW(pathW.c_str());
+ const bool fileExists = (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
+ if (fileExists) {
+ // If that failed, then try loading it with broader search folders.
+ handle = LoadLibraryExW(pathW.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
+ }
+ }
+
+ return handle;
+}
+
+static std::string LoaderPlatformLibraryOpenError(const std::string &path) {
+ std::stringstream ss;
+ const DWORD dwLastError = GetLastError();
+ const std::string strError = DescribeError(dwLastError);
+ ss << "Failed to open dynamic library " << path << " with error " << dwLastError << ": " << strError;
+ return ss.str();
+}
+
+static void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { FreeLibrary(library); }
+
+static void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
+ assert(library);
+ assert(name.size() > 0);
+ return GetProcAddress(library, name.c_str());
+}
+
+static std::string LoaderPlatformLibraryGetProcAddrAddrError(const std::string &name) {
+ std::stringstream ss;
+ ss << "Failed to find function " << name << " in dynamic library";
+ return ss.str();
+}
+
+#else // Not Linux or Windows
+
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+
+static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
+// Stub func
+#error("Unknown platform, undefined dynamic library routines resulting");
+ (void)path;
+}
+
+static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
+ // Stub func
+ (void)path;
+}
+
+static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) {
+ // Stub func
+ (void)library;
+}
+
+static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
+ // Stub func
+ void(library);
+ void(name);
+}
+
+static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
+ // Stub func
+ (void)name;
+}
+
+#endif
diff --git a/extern/openxr/src/loader/manifest_file.cpp b/extern/openxr/src/loader/manifest_file.cpp
new file mode 100644
index 00000000000..ae8830b2e64
--- /dev/null
+++ b/extern/openxr/src/loader/manifest_file.cpp
@@ -0,0 +1,977 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#ifdef XR_OS_WINDOWS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "manifest_file.hpp"
+
+#include "common_cmake_config.h"
+#include "filesystem_utils.hpp"
+#include "loader_platform.hpp"
+#include "platform_utils.hpp"
+#include "loader_logger.hpp"
+
+#include <json/json.h>
+#include <openxr/openxr.h>
+
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+// OpenXR paths and registry key locations
+#define OPENXR_RELATIVE_PATH "openxr/"
+#define OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/implicit.d"
+#define OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/explicit.d"
+#ifdef XR_OS_WINDOWS
+#define OPENXR_REGISTRY_LOCATION "SOFTWARE\\Khronos\\OpenXR\\"
+#define OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Implicit"
+#define OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Explicit"
+#endif
+
+// OpenXR Loader environment variables of interest
+#define OPENXR_RUNTIME_JSON_ENV_VAR "XR_RUNTIME_JSON"
+#define OPENXR_API_LAYER_PATH_ENV_VAR "XR_API_LAYER_PATH"
+
+#ifndef XRLOADER_ENABLE_EXCEPTION_HANDLING
+#if JSON_USE_EXCEPTIONS
+#error \
+ "Loader is configured to not catch exceptions, but jsoncpp was built with exception-throwing enabled, which could violate the C ABI. One of those two things needs to change."
+#endif // JSON_USE_EXCEPTIONS
+#endif // !XRLOADER_ENABLE_EXCEPTION_HANDLING
+
+// Utility functions for finding files in the appropriate paths
+
+static inline bool StringEndsWith(const std::string &value, const std::string &ending) {
+ if (ending.size() > value.size()) {
+ return false;
+ }
+ return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+}
+
+// If the file found is a manifest file name, add it to the out_files manifest list.
+static void AddIfJson(const std::string &full_file, std::vector<std::string> &manifest_files) {
+ if (full_file.empty() || !StringEndsWith(full_file, ".json")) {
+ return;
+ }
+ manifest_files.push_back(full_file);
+}
+
+// Check the current path for any manifest files. If the provided search_path is a directory, look for
+// all included JSON files in that directory. Otherwise, just check the provided search_path which should
+// be a single filename.
+static void CheckAllFilesInThePath(const std::string &search_path, bool is_directory_list,
+ std::vector<std::string> &manifest_files) {
+ if (FileSysUtilsPathExists(search_path)) {
+ std::string absolute_path;
+ if (!is_directory_list) {
+ // If the file exists, try to add it
+ if (FileSysUtilsIsRegularFile(search_path)) {
+ FileSysUtilsGetAbsolutePath(search_path, absolute_path);
+ AddIfJson(absolute_path, manifest_files);
+ }
+ } else {
+ std::vector<std::string> files;
+ if (FileSysUtilsFindFilesInPath(search_path, files)) {
+ for (std::string &cur_file : files) {
+ std::string relative_path;
+ FileSysUtilsCombinePaths(search_path, cur_file, relative_path);
+ if (!FileSysUtilsGetAbsolutePath(relative_path, absolute_path)) {
+ continue;
+ }
+ AddIfJson(absolute_path, manifest_files);
+ }
+ }
+ }
+ }
+}
+
+// Add all manifest files in the provided paths to the manifest_files list. If search_path
+// is made up of directory listings (versus direct manifest file names) search each path for
+// any manifest files.
+static void AddFilesInPath(const std::string &search_path, bool is_directory_list, std::vector<std::string> &manifest_files) {
+ std::size_t last_found = 0;
+ std::size_t found = search_path.find_first_of(PATH_SEPARATOR);
+ std::string cur_search;
+
+ // Handle any path listings in the string (separated by the appropriate path separator)
+ while (found != std::string::npos) {
+ // substr takes a start index and length.
+ std::size_t length = found - last_found;
+ cur_search = search_path.substr(last_found, length);
+
+ CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
+
+ // This works around issue if multiple path separator follow each other directly.
+ last_found = found;
+ while (found == last_found) {
+ last_found = found + 1;
+ found = search_path.find_first_of(PATH_SEPARATOR, last_found);
+ }
+ }
+
+ // If there's something remaining in the string, copy it over
+ if (last_found < search_path.size()) {
+ cur_search = search_path.substr(last_found);
+ CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
+ }
+}
+
+// Copy all paths listed in the cur_path string into output_path and append the appropriate relative_path onto the end of each.
+static void CopyIncludedPaths(bool is_directory_list, const std::string &cur_path, const std::string &relative_path,
+ std::string &output_path) {
+ if (!cur_path.empty()) {
+ std::size_t last_found = 0;
+ std::size_t found = cur_path.find_first_of(PATH_SEPARATOR);
+
+ // Handle any path listings in the string (separated by the appropriate path separator)
+ while (found != std::string::npos) {
+ std::size_t length = found - last_found;
+ output_path += cur_path.substr(last_found, length);
+ if (is_directory_list && (cur_path[found - 1] != '\\' && cur_path[found - 1] != '/')) {
+ output_path += DIRECTORY_SYMBOL;
+ }
+ output_path += relative_path;
+ output_path += PATH_SEPARATOR;
+
+ last_found = found;
+ found = cur_path.find_first_of(PATH_SEPARATOR, found + 1);
+ }
+
+ // If there's something remaining in the string, copy it over
+ size_t last_char = cur_path.size() - 1;
+ if (last_found != last_char) {
+ output_path += cur_path.substr(last_found);
+ if (is_directory_list && (cur_path[last_char] != '\\' && cur_path[last_char] != '/')) {
+ output_path += DIRECTORY_SYMBOL;
+ }
+ output_path += relative_path;
+ output_path += PATH_SEPARATOR;
+ }
+ }
+}
+
+// Look for data files in the provided paths, but first check the environment override to determine if we should use that instead.
+static void ReadDataFilesInSearchPaths(ManifestFileType type, const std::string &override_env_var, const std::string &relative_path,
+ bool &override_active, std::vector<std::string> &manifest_files) {
+ bool is_directory_list = true;
+ bool is_runtime = (type == MANIFEST_TYPE_RUNTIME);
+ char *override_env = nullptr;
+ std::string override_path;
+ std::string search_path;
+
+ if (!override_env_var.empty()) {
+#ifndef XR_OS_WINDOWS
+ if (geteuid() != getuid() || getegid() != getgid()) {
+ // Don't allow setuid apps to use the env var:
+ override_env = nullptr;
+ } else
+#endif
+ {
+ override_env = PlatformUtilsGetSecureEnv(override_env_var.c_str());
+ if (nullptr != override_env) {
+ // The runtime override is actually a specific list of filenames, not directories
+ if (is_runtime) {
+ is_directory_list = false;
+ }
+ override_path = override_env;
+ }
+ }
+ }
+
+ if (nullptr != override_env && !override_path.empty()) {
+ CopyIncludedPaths(is_directory_list, override_path, "", search_path);
+ PlatformUtilsFreeEnv(override_env);
+ override_active = true;
+ } else {
+ override_active = false;
+#ifndef XR_OS_WINDOWS
+ bool xdg_conf_dirs_alloc = true;
+ bool xdg_data_dirs_alloc = true;
+ const char home_additional[] = ".local/share/";
+
+ // Determine how much space is needed to generate the full search path
+ // for the current manifest files.
+ char *xdg_conf_dirs = PlatformUtilsGetSecureEnv("XDG_CONFIG_DIRS");
+ char *xdg_data_dirs = PlatformUtilsGetSecureEnv("XDG_DATA_DIRS");
+ char *xdg_data_home = PlatformUtilsGetSecureEnv("XDG_DATA_HOME");
+ char *home = PlatformUtilsGetSecureEnv("HOME");
+
+ if (nullptr == xdg_conf_dirs) {
+ xdg_conf_dirs_alloc = false;
+ }
+ if (nullptr == xdg_data_dirs) {
+ xdg_data_dirs_alloc = false;
+ }
+
+ if (nullptr == xdg_conf_dirs || xdg_conf_dirs[0] == '\0') {
+ CopyIncludedPaths(true, FALLBACK_CONFIG_DIRS, relative_path, search_path);
+ } else {
+ CopyIncludedPaths(true, xdg_conf_dirs, relative_path, search_path);
+ }
+
+ CopyIncludedPaths(true, SYSCONFDIR, relative_path, search_path);
+#if defined(EXTRASYSCONFDIR)
+ CopyIncludedPaths(true, EXTRASYSCONFDIR, relative_path, search_path);
+#endif
+
+ if (xdg_data_dirs == nullptr || xdg_data_dirs[0] == '\0') {
+ CopyIncludedPaths(true, FALLBACK_DATA_DIRS, relative_path, search_path);
+ } else {
+ CopyIncludedPaths(true, xdg_data_dirs, relative_path, search_path);
+ }
+
+ if (nullptr != xdg_data_home) {
+ CopyIncludedPaths(true, xdg_data_home, relative_path, search_path);
+ } else if (nullptr != home) {
+ std::string relative_home_path = home_additional;
+ relative_home_path += relative_path;
+ CopyIncludedPaths(true, home, relative_home_path, search_path);
+ }
+
+ if (xdg_conf_dirs_alloc) {
+ PlatformUtilsFreeEnv(xdg_conf_dirs);
+ }
+ if (xdg_data_dirs_alloc) {
+ PlatformUtilsFreeEnv(xdg_data_dirs);
+ }
+ if (nullptr != xdg_data_home) {
+ PlatformUtilsFreeEnv(xdg_data_home);
+ }
+ if (nullptr != home) {
+ PlatformUtilsFreeEnv(home);
+ }
+#endif
+ }
+
+ // Now, parse the paths and add any manifest files found in them.
+ AddFilesInPath(search_path, is_directory_list, manifest_files);
+}
+
+#ifdef XR_OS_LINUX
+
+// If ${name} has a nonempty value, return it; if both other arguments are supplied return
+// ${fallback_env}/fallback_path; otherwise, return whichever of ${fallback_env} and fallback_path
+// is supplied. If ${fallback_env} or ${fallback_env}/... would be returned but that environment
+// variable is unset or empty, return the empty string.
+static std::string GetXDGEnv(const char *name, const char *fallback_env, const char *fallback_path) {
+ char *path = PlatformUtilsGetSecureEnv(name);
+ std::string result;
+ if (path != nullptr) {
+ result = path;
+ PlatformUtilsFreeEnv(path);
+ if (!result.empty()) {
+ return result;
+ }
+ }
+ if (fallback_env != nullptr) {
+ char *path = PlatformUtilsGetSecureEnv(fallback_env);
+ if (path != nullptr) {
+ result = path;
+ PlatformUtilsFreeEnv(path);
+ }
+ if (result.empty()) {
+ return "";
+ }
+ if (fallback_path != nullptr) {
+ result += "/";
+ }
+ }
+ if (fallback_path != nullptr) {
+ result += fallback_path;
+ }
+ return result;
+}
+
+// Return the first instance of relative_path occurring in an XDG config dir according to standard
+// precedence order.
+static bool FindXDGConfigFile(const std::string &relative_path, std::string &out) {
+ out = GetXDGEnv("XDG_CONFIG_HOME", "HOME", ".config");
+ if (!out.empty()) {
+ out += "/";
+ out += relative_path;
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+ }
+
+ std::istringstream iss(GetXDGEnv("XDG_CONFIG_DIRS", nullptr, FALLBACK_CONFIG_DIRS));
+ std::string path;
+ while (std::getline(iss, path, PATH_SEPARATOR)) {
+ if (path.empty()) {
+ continue;
+ }
+ out = path;
+ out += "/";
+ out += relative_path;
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+ }
+
+ out = SYSCONFDIR;
+ out += "/";
+ out += relative_path;
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+
+#if defined(EXTRASYSCONFDIR)
+ out = EXTRASYSCONFDIR;
+ out += "/";
+ out += relative_path;
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+#endif
+
+ out.clear();
+ return false;
+}
+
+#endif
+
+#ifdef XR_OS_WINDOWS
+
+// Look for runtime data files in the provided paths, but first check the environment override to determine
+// if we should use that instead.
+static void ReadRuntimeDataFilesInRegistry(ManifestFileType type, const std::string &runtime_registry_location,
+ const std::string &default_runtime_value_name,
+ std::vector<std::string> &manifest_files) {
+ HKEY hkey;
+ DWORD access_flags;
+ wchar_t value_w[1024];
+ DWORD value_size_w = sizeof(value_w); // byte size of the buffer.
+
+ // Generate the full registry location for the registry information
+ std::string full_registry_location = OPENXR_REGISTRY_LOCATION;
+ full_registry_location += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
+ full_registry_location += runtime_registry_location;
+
+ const std::wstring full_registry_location_w = utf8_to_wide(full_registry_location);
+ const std::wstring default_runtime_value_name_w = utf8_to_wide(default_runtime_value_name);
+
+ // Use 64 bit regkey for 64bit application, and use 32 bit regkey in WOW for 32bit application.
+ access_flags = KEY_QUERY_VALUE;
+ LONG open_value = RegOpenKeyExW(HKEY_LOCAL_MACHINE, full_registry_location_w.c_str(), 0, access_flags, &hkey);
+
+ if (ERROR_SUCCESS != open_value) {
+ std::string warning_message = "ReadLayerDataFilesInRegistry - failed to open registry key ";
+ warning_message += full_registry_location;
+ LoaderLogger::LogWarningMessage("", warning_message);
+ } else if (ERROR_SUCCESS != RegGetValueW(hkey, nullptr, default_runtime_value_name_w.c_str(),
+ RRF_RT_REG_SZ | REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL,
+ reinterpret_cast<LPBYTE>(&value_w), &value_size_w)) {
+ std::string warning_message = "ReadLayerDataFilesInRegistry - failed to read registry value ";
+ warning_message += default_runtime_value_name;
+ LoaderLogger::LogWarningMessage("", warning_message);
+ } else {
+ AddFilesInPath(wide_to_utf8(value_w), false, manifest_files);
+ }
+}
+
+// Look for layer data files in the provided paths, but first check the environment override to determine
+// if we should use that instead.
+static void ReadLayerDataFilesInRegistry(ManifestFileType type, const std::string &registry_location,
+ std::vector<std::string> &manifest_files) {
+ HKEY hive[2] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
+ bool found[2] = {false, false};
+ HKEY hkey;
+ DWORD access_flags;
+ LONG rtn_value;
+ wchar_t name_w[1024]{};
+ DWORD value;
+ DWORD name_size = 1023;
+ DWORD value_size = sizeof(value);
+
+ for (uint8_t hive_index = 0; hive_index < 2; ++hive_index) {
+ DWORD key_index = 0;
+ std::string full_registry_location = OPENXR_REGISTRY_LOCATION;
+ full_registry_location += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
+ full_registry_location += registry_location;
+
+ access_flags = KEY_QUERY_VALUE;
+ std::wstring full_registry_location_w = utf8_to_wide(full_registry_location);
+ LONG open_value = RegOpenKeyExW(hive[hive_index], full_registry_location_w.c_str(), 0, access_flags, &hkey);
+ if (ERROR_SUCCESS != open_value) {
+ if (hive_index == 1 && !found[0]) {
+ std::string warning_message = "ReadLayerDataFilesInRegistry - failed to read registry location ";
+ warning_message += registry_location;
+ warning_message += " in either HKEY_LOCAL_MACHINE or KHEY_CURRENT_USER";
+ LoaderLogger::LogWarningMessage("", warning_message);
+ }
+ continue;
+ }
+ found[hive_index] = true;
+ while (ERROR_SUCCESS ==
+ (rtn_value = RegEnumValueW(hkey, key_index++, name_w, &name_size, NULL, NULL, (LPBYTE)&value, &value_size))) {
+ if (value_size == sizeof(value) && value == 0) {
+ const std::string filename = wide_to_utf8(name_w);
+ AddFilesInPath(filename, false, manifest_files);
+ }
+ // Reset some items for the next loop
+ name_size = 1023;
+ }
+ }
+}
+
+#endif // XR_OS_WINDOWS
+
+ManifestFile::ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path)
+ : _filename(filename), _type(type), _library_path(library_path) {}
+
+ManifestFile::~ManifestFile() = default;
+
+bool ManifestFile::IsValidJson(const Json::Value &root_node, JsonVersion &version) {
+ if (root_node["file_format_version"].isNull() || !root_node["file_format_version"].isString()) {
+ LoaderLogger::LogErrorMessage("", "ManifestFile::IsValidJson - JSON file missing \"file_format_version\"");
+ return false;
+ }
+ std::string file_format = root_node["file_format_version"].asString();
+ sscanf(file_format.c_str(), "%d.%d.%d", &version.major, &version.minor, &version.patch);
+
+ // Only version 1.0.0 is defined currently. Eventually we may have more version, but
+ // some of the versions may only be valid for layers or runtimes specifically.
+ if (version.major != 1 || version.minor != 0 || version.patch != 0) {
+ std::string error_message = "ManifestFile::IsValidJson - JSON \"file_format_version\" ";
+ error_message += std::to_string(version.major);
+ error_message += ".";
+ error_message += std::to_string(version.minor);
+ error_message += ".";
+ error_message += std::to_string(version.patch);
+ error_message += " is not supported";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return false;
+ }
+
+ return true;
+}
+
+static void GetExtensionProperties(const std::vector<ExtensionListing> &extensions, std::vector<XrExtensionProperties> &props) {
+ for (const auto &ext : extensions) {
+ auto it =
+ std::find_if(props.begin(), props.end(), [&](XrExtensionProperties &prop) { return prop.extensionName == ext.name; });
+ if (it != props.end()) {
+ it->extensionVersion = std::max(it->extensionVersion, ext.extension_version);
+ } else {
+ XrExtensionProperties prop = {};
+ prop.type = XR_TYPE_EXTENSION_PROPERTIES;
+ prop.next = nullptr;
+ strncpy(prop.extensionName, ext.name.c_str(), XR_MAX_EXTENSION_NAME_SIZE - 1);
+ prop.extensionName[XR_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
+ prop.extensionVersion = ext.extension_version;
+ props.push_back(prop);
+ }
+ }
+}
+
+// Return any instance extensions found in the manifest files in the proper form for
+// OpenXR (XrExtensionProperties).
+void ManifestFile::GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props) {
+ GetExtensionProperties(_instance_extensions, props);
+}
+
+// Return any device extensions found in the manifest files in the proper form for
+// OpenXR (XrExtensionProperties).
+void ManifestFile::GetDeviceExtensionProperties(std::vector<XrExtensionProperties> &props) {
+ GetExtensionProperties(_device_extensions, props);
+}
+
+const std::string &ManifestFile::GetFunctionName(const std::string &func_name) {
+ if (!_functions_renamed.empty()) {
+ auto found = _functions_renamed.find(func_name);
+ if (found != _functions_renamed.end()) {
+ return found->second;
+ }
+ }
+ return func_name;
+}
+
+RuntimeManifestFile::RuntimeManifestFile(const std::string &filename, const std::string &library_path)
+ : ManifestFile(MANIFEST_TYPE_RUNTIME, filename, library_path) {}
+
+RuntimeManifestFile::~RuntimeManifestFile() = default;
+
+void RuntimeManifestFile::CreateIfValid(const std::string &filename,
+ std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
+ std::ifstream json_stream = std::ifstream(filename, std::ifstream::in);
+ if (!json_stream.is_open()) {
+ std::string error_message = "RuntimeManifestFile::createIfValid failed to open ";
+ error_message += filename;
+ error_message += ". Does it exist?";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ Json::Reader reader;
+ Json::Value root_node = Json::nullValue;
+ Json::Value runtime_root_node = Json::nullValue;
+ JsonVersion file_version = {};
+ if (!reader.parse(json_stream, root_node, false) || root_node.isNull()) {
+ std::string error_message = "RuntimeManifestFile::CreateIfValid failed to parse ";
+ error_message += filename;
+ error_message += ". Is it a valid runtime manifest file? Error was:\n ";
+ error_message += reader.getFormattedErrorMessages();
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ if (!ManifestFile::IsValidJson(root_node, file_version)) {
+ std::string error_message = "RuntimeManifestFile::CreateIfValid isValidJson indicates ";
+ error_message += filename;
+ error_message += " is not a valid manifest file.";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ runtime_root_node = root_node["runtime"];
+ // The Runtime manifest file needs the "runtime" root as well as sub-nodes for "api_version" and
+ // "library_path". If any of those aren't there, fail.
+ if (runtime_root_node.isNull() || runtime_root_node["library_path"].isNull() || !runtime_root_node["library_path"].isString()) {
+ std::string error_message = "RuntimeManifestFile::CreateIfValid ";
+ error_message += filename;
+ error_message += " is missing required fields. Verify all proper fields exist.";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+
+ std::string lib_path = runtime_root_node["library_path"].asString();
+
+ // If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
+ // global library path.
+ if (lib_path.find('\\') != std::string::npos || lib_path.find('/') != std::string::npos) {
+ // If the library_path is an absolute path, just use that if it exists
+ if (FileSysUtilsIsAbsolutePath(lib_path)) {
+ if (!FileSysUtilsPathExists(lib_path)) {
+ std::string error_message = "RuntimeManifestFile::CreateIfValid ";
+ error_message += filename;
+ error_message += " library ";
+ error_message += lib_path;
+ error_message += " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ } else {
+ // Otherwise, treat the library path as a relative path based on the JSON file.
+ std::string combined_path;
+ std::string file_parent;
+ if (!FileSysUtilsGetParentPath(filename, file_parent) ||
+ !FileSysUtilsCombinePaths(file_parent, lib_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
+ std::string error_message = "RuntimeManifestFile::CreateIfValid ";
+ error_message += filename;
+ error_message += " library ";
+ error_message += combined_path;
+ error_message += " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ lib_path = combined_path;
+ }
+ }
+
+ // Add this runtime manifest file
+ manifest_files.emplace_back(new RuntimeManifestFile(filename, lib_path));
+
+ // Add any extensions to it after the fact.
+ Json::Value dev_exts = runtime_root_node["device_extensions"];
+ if (!dev_exts.isNull() && dev_exts.isArray()) {
+ for (Json::ValueIterator dev_ext_it = dev_exts.begin(); dev_ext_it != dev_exts.end(); ++dev_ext_it) {
+ Json::Value dev_ext = (*dev_ext_it);
+ Json::Value dev_ext_name = dev_ext["name"];
+ Json::Value dev_ext_version = dev_ext["extension_version"];
+ Json::Value dev_ext_entries = dev_ext["entrypoints"];
+ if (!dev_ext_name.isNull() && dev_ext_name.isString() && !dev_ext_version.isNull() && dev_ext_version.isUInt() &&
+ !dev_ext_entries.isNull() && dev_ext_entries.isArray()) {
+ ExtensionListing ext = {};
+ ext.name = dev_ext_name.asString();
+ ext.extension_version = dev_ext_version.asUInt();
+ for (Json::ValueIterator entry_it = dev_ext_entries.begin(); entry_it != dev_ext_entries.end(); ++entry_it) {
+ Json::Value entry = (*entry_it);
+ if (!entry.isNull() && entry.isString()) {
+ ext.entrypoints.push_back(entry.asString());
+ }
+ }
+ manifest_files.back()->_device_extensions.push_back(ext);
+ }
+ }
+ }
+
+ Json::Value inst_exts = runtime_root_node["instance_extensions"];
+ if (!inst_exts.isNull() && inst_exts.isArray()) {
+ for (Json::ValueIterator inst_ext_it = inst_exts.begin(); inst_ext_it != inst_exts.end(); ++inst_ext_it) {
+ Json::Value inst_ext = (*inst_ext_it);
+ Json::Value inst_ext_name = inst_ext["name"];
+ Json::Value inst_ext_version = inst_ext["extension_version"];
+ if (!inst_ext_name.isNull() && inst_ext_name.isString() && !inst_ext_version.isNull() && inst_ext_version.isUInt()) {
+ ExtensionListing ext = {};
+ ext.name = inst_ext_name.asString();
+ ext.extension_version = inst_ext_version.asUInt();
+ manifest_files.back()->_instance_extensions.push_back(ext);
+ }
+ }
+ }
+
+ Json::Value funcs_renamed = runtime_root_node["functions"];
+ if (!funcs_renamed.isNull() && !funcs_renamed.empty()) {
+ for (Json::ValueIterator func_it = funcs_renamed.begin(); func_it != funcs_renamed.end(); ++func_it) {
+ if (!(*func_it).isString()) {
+ std::string warning_message = "RuntimeManifestFile::CreateIfValid ";
+ warning_message += filename;
+ warning_message += " \"functions\" section contains non-string values.";
+ LoaderLogger::LogWarningMessage("", warning_message);
+ continue;
+ }
+ std::string original_name = func_it.key().asString();
+ std::string new_name = (*func_it).asString();
+ manifest_files.back()->_functions_renamed.insert(std::make_pair(original_name, new_name));
+ }
+ }
+}
+
+// Find all manifest files in the appropriate search paths/registries for the given type.
+XrResult RuntimeManifestFile::FindManifestFiles(ManifestFileType type,
+ std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
+ XrResult result = XR_SUCCESS;
+ if (MANIFEST_TYPE_RUNTIME != type) {
+ LoaderLogger::LogErrorMessage("", "RuntimeManifestFile::FindManifestFiles - unknown manifest file requested");
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+ std::string filename;
+ char *override_path = PlatformUtilsGetSecureEnv(OPENXR_RUNTIME_JSON_ENV_VAR);
+ if (override_path != nullptr && *override_path != '\0') {
+ filename = override_path;
+ PlatformUtilsFreeEnv(override_path);
+ std::string info_message = "RuntimeManifestFile::FindManifestFiles - using environment variable override runtime file ";
+ info_message += filename;
+ LoaderLogger::LogInfoMessage("", info_message);
+ } else {
+ PlatformUtilsFreeEnv(override_path);
+#ifdef XR_OS_WINDOWS
+ std::vector<std::string> filenames;
+ ReadRuntimeDataFilesInRegistry(type, "", "ActiveRuntime", filenames);
+ if (filenames.size() == 0) {
+ LoaderLogger::LogErrorMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - failed to find active runtime file in registry");
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+ if (filenames.size() > 1) {
+ LoaderLogger::LogWarningMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - found too many default runtime files in registry");
+ }
+ filename = filenames[0];
+#elif defined(XR_OS_LINUX)
+ const std::string relative_path =
+ "openxr/" + std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) + "/active_runtime.json";
+ if (!FindXDGConfigFile(relative_path, filename)) {
+ LoaderLogger::LogErrorMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+#else
+ if (!PlatformGetGlobalRuntimeFileName(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), filename)) {
+ LoaderLogger::LogErrorMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+#endif
+ std::string info_message = "RuntimeManifestFile::FindManifestFiles - using global runtime file ";
+ info_message += filename;
+ LoaderLogger::LogInfoMessage("", info_message);
+ }
+ RuntimeManifestFile::CreateIfValid(filename, manifest_files);
+ return result;
+}
+
+ApiLayerManifestFile::ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
+ const std::string &description, const JsonVersion &api_version,
+ const uint32_t &implementation_version, const std::string &library_path)
+ : ManifestFile(type, filename, library_path),
+ _api_version(api_version),
+ _layer_name(layer_name),
+ _description(description),
+ _implementation_version(implementation_version) {}
+
+ApiLayerManifestFile::~ApiLayerManifestFile() = default;
+
+void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::string &filename,
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
+ std::ifstream json_stream = std::ifstream(filename, std::ifstream::in);
+ Json::Reader reader;
+ Json::Value root_node = Json::nullValue;
+ if (!reader.parse(json_stream, root_node, false) || root_node.isNull()) {
+ std::string error_message = "ApiLayerManifestFile::CreateIfValid failed to parse ";
+ error_message += filename;
+ error_message += ". Is it a valid layer manifest file? Error was:\n";
+ error_message += reader.getFormattedErrorMessages();
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ JsonVersion file_version = {};
+ if (!ManifestFile::IsValidJson(root_node, file_version)) {
+ std::string error_message = "ApiLayerManifestFile::CreateIfValid isValidJson indicates ";
+ error_message += filename;
+ error_message += " is not a valid manifest file.";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+
+ Json::Value layer_root_node = root_node["api_layer"];
+
+ // The API Layer manifest file needs the "api_layer" root as well as other sub-nodes.
+ // If any of those aren't there, fail.
+ if (layer_root_node.isNull() || layer_root_node["name"].isNull() || !layer_root_node["name"].isString() ||
+ layer_root_node["api_version"].isNull() || !layer_root_node["api_version"].isString() ||
+ layer_root_node["library_path"].isNull() || !layer_root_node["library_path"].isString() ||
+ layer_root_node["implementation_version"].isNull() || !layer_root_node["implementation_version"].isString()) {
+ std::string error_message = "ApiLayerManifestFile::CreateIfValid ";
+ error_message += filename;
+ error_message += " is missing required fields. Verify all proper fields exist.";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ if (MANIFEST_TYPE_IMPLICIT_API_LAYER == type) {
+ bool enabled = true;
+ // Implicit layers require the disable environment variable.
+ if (layer_root_node["disable_environment"].isNull() || !layer_root_node["disable_environment"].isString()) {
+ std::string error_message = "ApiLayerManifestFile::CreateIfValid Implicit layer ";
+ error_message += filename;
+ error_message += " is missing \"disable_environment\"";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ // Check if there's an enable environment variable provided
+ if (!layer_root_node["enable_environment"].isNull() && layer_root_node["enable_environment"].isString()) {
+ char *enable_val = PlatformUtilsGetEnv(layer_root_node["enable_environment"].asString().c_str());
+ // If it's not set in the environment, disable the layer
+ if (nullptr == enable_val) {
+ enabled = false;
+ }
+ PlatformUtilsFreeEnv(enable_val);
+ }
+ // Check for the disable environment variable, which must be provided in the JSON
+ char *disable_val = PlatformUtilsGetEnv(layer_root_node["disable_environment"].asString().c_str());
+ // If the envar is set, disable the layer. Disable envar overrides enable above
+ if (nullptr != disable_val) {
+ enabled = false;
+ }
+ PlatformUtilsFreeEnv(disable_val);
+
+ // Not enabled, so pretend like it isn't even there.
+ if (!enabled) {
+ std::string info_message = "ApiLayerManifestFile::CreateIfValid Implicit layer ";
+ info_message += filename;
+ info_message += " is disabled";
+ LoaderLogger::LogInfoMessage("", info_message);
+ return;
+ }
+ }
+ std::string layer_name = layer_root_node["name"].asString();
+ std::string api_version_string = layer_root_node["api_version"].asString();
+ JsonVersion api_version = {};
+ sscanf(api_version_string.c_str(), "%d.%d", &api_version.major, &api_version.minor);
+ api_version.patch = 0;
+
+ if ((api_version.major == 0 && api_version.minor == 0) || api_version.major > XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) {
+ std::string warning_message = "ApiLayerManifestFile::CreateIfValid layer ";
+ warning_message += filename;
+ warning_message += " has invalid API Version. Skipping layer.";
+ LoaderLogger::LogWarningMessage("", warning_message);
+ return;
+ }
+
+ uint32_t implementation_version = atoi(layer_root_node["implementation_version"].asString().c_str());
+ std::string library_path = layer_root_node["library_path"].asString();
+
+ // If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
+ // global library path.
+ if (library_path.find('\\') != std::string::npos || library_path.find('/') != std::string::npos) {
+ // If the library_path is an absolute path, just use that if it exists
+ if (FileSysUtilsIsAbsolutePath(library_path)) {
+ if (!FileSysUtilsPathExists(library_path)) {
+ std::string error_message = "ApiLayerManifestFile::CreateIfValid ";
+ error_message += filename;
+ error_message += " library ";
+ error_message += library_path;
+ error_message += " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ } else {
+ // Otherwise, treat the library path as a relative path based on the JSON file.
+ std::string combined_path;
+ std::string file_parent;
+ if (!FileSysUtilsGetParentPath(filename, file_parent) ||
+ !FileSysUtilsCombinePaths(file_parent, library_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
+ std::string error_message = "ApiLayerManifestFile::CreateIfValid ";
+ error_message += filename;
+ error_message += " library ";
+ error_message += combined_path;
+ error_message += " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_message);
+ return;
+ }
+ library_path = combined_path;
+ }
+ }
+
+ std::string description;
+ if (!layer_root_node["description"].isNull() && layer_root_node["description"].isString()) {
+ description = layer_root_node["description"].asString();
+ }
+
+ // Add this layer manifest file
+ manifest_files.emplace_back(
+ new ApiLayerManifestFile(type, filename, layer_name, description, api_version, implementation_version, library_path));
+
+ // Add any extensions to it after the fact.
+ Json::Value dev_exts = layer_root_node["device_extensions"];
+ if (!dev_exts.isNull() && dev_exts.isArray()) {
+ for (Json::ValueIterator dev_ext_it = dev_exts.begin(); dev_ext_it != dev_exts.end(); ++dev_ext_it) {
+ Json::Value dev_ext = (*dev_ext_it);
+ Json::Value dev_ext_name = dev_ext["name"];
+ Json::Value dev_ext_version = dev_ext["extension_version"];
+ Json::Value dev_ext_entries = dev_ext["entrypoints"];
+ if (!dev_ext_name.isNull() && dev_ext_name.isString() && !dev_ext_version.isNull() && dev_ext_version.isString() &&
+ !dev_ext_entries.isNull() && dev_ext_entries.isArray()) {
+ ExtensionListing ext = {};
+ ext.name = dev_ext_name.asString();
+ ext.extension_version = atoi(dev_ext_version.asString().c_str());
+ for (Json::ValueIterator entry_it = dev_ext_entries.begin(); entry_it != dev_ext_entries.end(); ++entry_it) {
+ Json::Value entry = (*entry_it);
+ if (!entry.isNull() && entry.isString()) {
+ ext.entrypoints.push_back(entry.asString());
+ }
+ }
+ manifest_files.back()->_device_extensions.push_back(ext);
+ }
+ }
+ }
+
+ Json::Value inst_exts = layer_root_node["instance_extensions"];
+ if (!inst_exts.isNull() && inst_exts.isArray()) {
+ for (Json::ValueIterator inst_ext_it = inst_exts.begin(); inst_ext_it != inst_exts.end(); ++inst_ext_it) {
+ Json::Value inst_ext = (*inst_ext_it);
+ Json::Value inst_ext_name = inst_ext["name"];
+ Json::Value inst_ext_version = inst_ext["extension_version"];
+ if (!inst_ext_name.isNull() && inst_ext_name.isString() && !inst_ext_version.isNull() && inst_ext_version.isString()) {
+ ExtensionListing ext = {};
+ ext.name = inst_ext_name.asString();
+ ext.extension_version = atoi(inst_ext_version.asString().c_str());
+ manifest_files.back()->_instance_extensions.push_back(ext);
+ }
+ }
+ }
+
+ Json::Value funcs_renamed = layer_root_node["functions"];
+ if (!funcs_renamed.isNull() && !funcs_renamed.empty()) {
+ for (Json::ValueIterator func_it = funcs_renamed.begin(); func_it != funcs_renamed.end(); ++func_it) {
+ if (!(*func_it).isString()) {
+ std::string warning_message = "ApiLayerManifestFile::CreateIfValid ";
+ warning_message += filename;
+ warning_message += " \"functions\" section contains non-string values.";
+ LoaderLogger::LogWarningMessage("", warning_message);
+ continue;
+ }
+ std::string original_name = func_it.key().asString();
+ std::string new_name = (*func_it).asString();
+ manifest_files.back()->_functions_renamed.insert(std::make_pair(original_name, new_name));
+ }
+ }
+}
+
+XrApiLayerProperties ApiLayerManifestFile::GetApiLayerProperties() {
+ XrApiLayerProperties props = {};
+ props.type = XR_TYPE_API_LAYER_PROPERTIES;
+ props.next = nullptr;
+ props.layerVersion = _implementation_version;
+ props.specVersion = XR_MAKE_VERSION(_api_version.major, _api_version.minor, _api_version.patch);
+ strncpy(props.layerName, _layer_name.c_str(), XR_MAX_API_LAYER_NAME_SIZE - 1);
+ if (_layer_name.size() >= XR_MAX_API_LAYER_NAME_SIZE - 1) {
+ props.layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
+ }
+ strncpy(props.description, _description.c_str(), XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1);
+ if (_description.size() >= XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1) {
+ props.description[XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1] = '\0';
+ }
+ return props;
+}
+
+// Find all layer manifest files in the appropriate search paths/registries for the given type.
+XrResult ApiLayerManifestFile::FindManifestFiles(ManifestFileType type,
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
+ std::string relative_path;
+ std::string override_env_var;
+ std::string registry_location;
+
+ // Add the appropriate top-level folders for the relative path. These should be
+ // the string "openxr/" followed by the API major version as a string.
+ relative_path = OPENXR_RELATIVE_PATH;
+ relative_path += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
+
+ switch (type) {
+ case MANIFEST_TYPE_IMPLICIT_API_LAYER:
+ relative_path += OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH;
+ override_env_var = "";
+#ifdef XR_OS_WINDOWS
+ registry_location = OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION;
+#endif
+ break;
+ case MANIFEST_TYPE_EXPLICIT_API_LAYER:
+ relative_path += OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH;
+ override_env_var = OPENXR_API_LAYER_PATH_ENV_VAR;
+#ifdef XR_OS_WINDOWS
+ registry_location = OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION;
+#endif
+ break;
+ default:
+ LoaderLogger::LogErrorMessage("", "ApiLayerManifestFile::FindManifestFiles - unknown manifest file requested");
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+
+ bool override_active = false;
+ std::vector<std::string> filenames;
+ ReadDataFilesInSearchPaths(type, override_env_var, relative_path, override_active, filenames);
+
+#ifdef XR_OS_WINDOWS
+ // Read the registry if the override wasn't active.
+ if (!override_active) {
+ ReadLayerDataFilesInRegistry(type, registry_location, filenames);
+ }
+#endif
+
+ switch (type) {
+ case MANIFEST_TYPE_IMPLICIT_API_LAYER:
+ case MANIFEST_TYPE_EXPLICIT_API_LAYER:
+ for (std::string &cur_file : filenames) {
+ ApiLayerManifestFile::CreateIfValid(type, cur_file, manifest_files);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return XR_SUCCESS;
+}
diff --git a/extern/openxr/src/loader/manifest_file.hpp b/extern/openxr/src/loader/manifest_file.hpp
new file mode 100644
index 00000000000..affa9b9615f
--- /dev/null
+++ b/extern/openxr/src/loader/manifest_file.hpp
@@ -0,0 +1,121 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <openxr/openxr.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+namespace Json {
+class Value;
+}
+
+enum ManifestFileType {
+ MANIFEST_TYPE_UNDEFINED = 0,
+ MANIFEST_TYPE_RUNTIME,
+ MANIFEST_TYPE_IMPLICIT_API_LAYER,
+ MANIFEST_TYPE_EXPLICIT_API_LAYER,
+};
+
+struct JsonVersion {
+ uint32_t major;
+ uint32_t minor;
+ uint32_t patch;
+};
+
+struct ExtensionListing {
+ std::string name;
+ uint32_t extension_version;
+ std::vector<std::string> entrypoints;
+};
+
+// ManifestFile class -
+// Base class responsible for finding and parsing manifest files.
+class ManifestFile {
+ public:
+ ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path);
+ virtual ~ManifestFile();
+ static bool IsValidJson(const Json::Value &root, JsonVersion &version);
+
+ // We don't want any copy constructors
+ ManifestFile &operator=(const ManifestFile &manifest_file) = delete;
+
+ ManifestFileType Type() { return _type; }
+ std::string Filename() { return _filename; }
+ std::string LibraryPath() { return _library_path; }
+ void GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props);
+ void GetDeviceExtensionProperties(std::vector<XrExtensionProperties> &props);
+ const std::string &GetFunctionName(const std::string &func_name);
+
+ protected:
+ std::string _filename;
+ ManifestFileType _type;
+ std::string _library_path;
+ std::vector<ExtensionListing> _instance_extensions;
+ std::vector<ExtensionListing> _device_extensions;
+ std::unordered_map<std::string, std::string> _functions_renamed;
+};
+
+// RuntimeManifestFile class -
+// Responsible for finding and parsing Runtime-specific manifest files.
+class RuntimeManifestFile : public ManifestFile {
+ public:
+ // Factory method
+ static XrResult FindManifestFiles(ManifestFileType type, std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
+
+ RuntimeManifestFile(const std::string &filename, const std::string &library_path);
+ ~RuntimeManifestFile() override;
+ static void CreateIfValid(const std::string &filename, std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
+
+ // Non-copyable
+ RuntimeManifestFile(const RuntimeManifestFile &) = delete;
+ RuntimeManifestFile &operator=(const RuntimeManifestFile &) = delete;
+};
+
+// ApiLayerManifestFile class -
+// Responsible for finding and parsing API Layer-specific manifest files.
+class ApiLayerManifestFile : public ManifestFile {
+ public:
+ // Factory method
+ static XrResult FindManifestFiles(ManifestFileType type, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
+
+ ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
+ const std::string &description, const JsonVersion &api_version, const uint32_t &implementation_version,
+ const std::string &library_path);
+ ~ApiLayerManifestFile() override;
+ static void CreateIfValid(ManifestFileType type, const std::string &filename,
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
+
+ std::string LayerName() { return _layer_name; }
+ XrApiLayerProperties GetApiLayerProperties();
+
+ // Non-copyable
+ ApiLayerManifestFile(const ApiLayerManifestFile &) = delete;
+ ApiLayerManifestFile &operator=(const ApiLayerManifestFile &) = delete;
+
+ private:
+ JsonVersion _api_version;
+ std::string _layer_name;
+ std::string _description;
+ uint32_t _implementation_version;
+};
diff --git a/extern/openxr/src/loader/openxr.pc.in b/extern/openxr/src/loader/openxr.pc.in
new file mode 100644
index 00000000000..5d658bca5d9
--- /dev/null
+++ b/extern/openxr/src/loader/openxr.pc.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
+includedir=${prefix}/include
+
+Name: @CMAKE_PROJECT_NAME@
+Description: OpenXR Loader
+Version: @XR_API_VERSION@
+Libs: -L${libdir} -lopenxr_loader @PRIVATE_LIBS@
+Cflags: -I${includedir}
+
diff --git a/extern/openxr/src/loader/runtime_interface.cpp b/extern/openxr/src/loader/runtime_interface.cpp
new file mode 100644
index 00000000000..155a168e9eb
--- /dev/null
+++ b/extern/openxr/src/loader/runtime_interface.cpp
@@ -0,0 +1,342 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "runtime_interface.hpp"
+
+#include "manifest_file.hpp"
+#include "loader_interfaces.h"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "xr_generated_dispatch_table.h"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+std::unique_ptr<RuntimeInterface> RuntimeInterface::_single_runtime_interface;
+uint32_t RuntimeInterface::_single_runtime_count = 0;
+
+XrResult RuntimeInterface::LoadRuntime(const std::string& openxr_command) {
+ XrResult last_error = XR_SUCCESS;
+ bool any_loaded = false;
+
+ // If something's already loaded, we're done here.
+ if (_single_runtime_interface != nullptr) {
+ _single_runtime_count++;
+ return XR_SUCCESS;
+ }
+
+ std::vector<std::unique_ptr<RuntimeManifestFile>> runtime_manifest_files = {};
+
+ // Find the available runtimes which we may need to report information for.
+ last_error = RuntimeManifestFile::FindManifestFiles(MANIFEST_TYPE_RUNTIME, runtime_manifest_files);
+ if (XR_SUCCESS != last_error) {
+ LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - unknown error");
+ last_error = XR_ERROR_FILE_ACCESS_ERROR;
+ } else {
+ for (std::unique_ptr<RuntimeManifestFile>& manifest_file : runtime_manifest_files) {
+ LoaderPlatformLibraryHandle runtime_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
+ if (nullptr == runtime_library) {
+ if (!any_loaded) {
+ last_error = XR_ERROR_INSTANCE_LOST;
+ }
+ std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
+ std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ warning_message += manifest_file->Filename();
+ warning_message += ", failed to load with message \"";
+ warning_message += library_message;
+ warning_message += "\"";
+ LoaderLogger::LogErrorMessage(openxr_command, warning_message);
+ continue;
+ }
+
+ // Get and settle on an runtime interface version (using any provided name if required).
+ std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderRuntimeInterface");
+ auto negotiate = reinterpret_cast<PFN_xrNegotiateLoaderRuntimeInterface>(
+ LoaderPlatformLibraryGetProcAddr(runtime_library, function_name));
+
+ // Loader info for negotiation
+ XrNegotiateLoaderInfo loader_info = {};
+ loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
+ loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
+ loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
+ loader_info.minInterfaceVersion = 1;
+ loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_RUNTIME_VERSION;
+ loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
+ loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
+
+ // Set up the runtime return structure
+ XrNegotiateRuntimeRequest runtime_info = {};
+ runtime_info.structType = XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST;
+ runtime_info.structVersion = XR_RUNTIME_INFO_STRUCT_VERSION;
+ runtime_info.structSize = sizeof(XrNegotiateRuntimeRequest);
+
+ // Skip calling the negotiate function and fail if the function pointer
+ // could not get loaded
+ XrResult res = XR_ERROR_RUNTIME_FAILURE;
+ if (nullptr != negotiate) {
+ res = negotiate(&loader_info, &runtime_info);
+ }
+ // If we supposedly succeeded, but got a nullptr for GetInstanceProcAddr
+ // then something still went wrong, so return with an error.
+ if (XR_SUCCESS == res) {
+ uint32_t runtime_major = XR_VERSION_MAJOR(runtime_info.runtimeApiVersion);
+ uint32_t runtime_minor = XR_VERSION_MINOR(runtime_info.runtimeApiVersion);
+ uint32_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION);
+ if (nullptr == runtime_info.getInstanceProcAddr) {
+ std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ error_message += manifest_file->Filename();
+ error_message += ", negotiation succeeded but returned NULL getInstanceProcAddr";
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ } else if (0 >= runtime_info.runtimeInterfaceVersion ||
+ XR_CURRENT_LOADER_RUNTIME_VERSION < runtime_info.runtimeInterfaceVersion) {
+ std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ error_message += manifest_file->Filename();
+ error_message += ", negotiation succeeded but returned invalid interface version";
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ } else if (runtime_major != loader_major || (runtime_major == 0 && runtime_minor == 0)) {
+ std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ error_message += manifest_file->Filename();
+ error_message += ", OpenXR version returned not compatible with this loader";
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ }
+ }
+ if (XR_SUCCESS != res) {
+ if (!any_loaded) {
+ last_error = res;
+ }
+ std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ warning_message += manifest_file->Filename();
+ warning_message += ", negotiation failed with error ";
+ warning_message += std::to_string(res);
+ LoaderLogger::LogErrorMessage(openxr_command, warning_message);
+ LoaderPlatformLibraryClose(runtime_library);
+ continue;
+ }
+
+ std::string info_message = "RuntimeInterface::LoadRuntime succeeded loading runtime defined in manifest file ";
+ info_message += manifest_file->Filename();
+ info_message += " using interface version ";
+ info_message += std::to_string(runtime_info.runtimeInterfaceVersion);
+ info_message += " and OpenXR API version ";
+ info_message += std::to_string(XR_VERSION_MAJOR(runtime_info.runtimeApiVersion));
+ info_message += ".";
+ info_message += std::to_string(XR_VERSION_MINOR(runtime_info.runtimeApiVersion));
+ LoaderLogger::LogInfoMessage(openxr_command, info_message);
+
+ // Use this runtime
+ _single_runtime_interface.reset(new RuntimeInterface(runtime_library, runtime_info.getInstanceProcAddr));
+ _single_runtime_count++;
+
+ // Grab the list of extensions this runtime supports for easy filtering after the
+ // xrCreateInstance call
+ std::vector<std::string> supported_extensions;
+ std::vector<XrExtensionProperties> extension_properties;
+ _single_runtime_interface->GetInstanceExtensionProperties(extension_properties);
+ supported_extensions.reserve(extension_properties.size());
+ for (XrExtensionProperties ext_prop : extension_properties) {
+ supported_extensions.emplace_back(ext_prop.extensionName);
+ }
+ _single_runtime_interface->SetSupportedExtensions(supported_extensions);
+
+ // If we load one, clear all errors.
+ any_loaded = true;
+ last_error = XR_SUCCESS;
+ break;
+ }
+ }
+
+ // Always clear the manifest file list. Either we use them or we don't.
+ runtime_manifest_files.clear();
+
+ // We found no valid runtimes, throw the initialization failed message
+ if (!any_loaded) {
+ LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - failed to find a valid runtime");
+ last_error = XR_ERROR_INSTANCE_LOST;
+ }
+
+ return last_error;
+}
+
+void RuntimeInterface::UnloadRuntime(const std::string& openxr_command) {
+ if (_single_runtime_count == 1) {
+ _single_runtime_count = 0;
+ _single_runtime_interface.reset();
+ } else if (_single_runtime_count > 0) {
+ --_single_runtime_count;
+ }
+ LoaderLogger::LogInfoMessage(openxr_command, "RuntimeInterface being unloaded.");
+}
+
+XrResult RuntimeInterface::GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function) {
+ return _single_runtime_interface->_get_instant_proc_addr(instance, name, function);
+}
+
+const XrGeneratedDispatchTable* RuntimeInterface::GetDispatchTable(XrInstance instance) {
+ XrGeneratedDispatchTable* table = nullptr;
+ std::lock_guard<std::mutex> mlock(_single_runtime_interface->_dispatch_table_mutex);
+ auto it = _single_runtime_interface->_dispatch_table_map.find(instance);
+ if (it != _single_runtime_interface->_dispatch_table_map.end()) {
+ table = it->second.get();
+ }
+ return table;
+}
+
+const XrGeneratedDispatchTable* RuntimeInterface::GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger) {
+ XrInstance runtime_instance = XR_NULL_HANDLE;
+ {
+ std::lock_guard<std::mutex> mlock(_single_runtime_interface->_messenger_to_instance_mutex);
+ auto it = _single_runtime_interface->_messenger_to_instance_map.find(messenger);
+ if (it != _single_runtime_interface->_messenger_to_instance_map.end()) {
+ runtime_instance = it->second;
+ }
+ }
+ return GetDispatchTable(runtime_instance);
+}
+
+RuntimeInterface::RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instant_proc_addr)
+ : _runtime_library(runtime_library), _get_instant_proc_addr(get_instant_proc_addr) {}
+
+RuntimeInterface::~RuntimeInterface() {
+ std::string info_message = "RuntimeInterface being destroyed.";
+ LoaderLogger::LogInfoMessage("", info_message);
+ {
+ std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
+ _dispatch_table_map.clear();
+ }
+ LoaderPlatformLibraryClose(_runtime_library);
+}
+
+void RuntimeInterface::GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties) {
+ std::vector<XrExtensionProperties> runtime_extension_properties;
+ PFN_xrEnumerateInstanceExtensionProperties rt_xrEnumerateInstanceExtensionProperties;
+ _get_instant_proc_addr(XR_NULL_HANDLE, "xrEnumerateInstanceExtensionProperties",
+ reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrEnumerateInstanceExtensionProperties));
+ uint32_t count = 0;
+ uint32_t count_output = 0;
+ // Get the count from the runtime
+ rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, nullptr);
+ if (count_output > 0) {
+ runtime_extension_properties.resize(count_output);
+ count = count_output;
+ for (XrExtensionProperties& ext_prop : runtime_extension_properties) {
+ ext_prop.type = XR_TYPE_EXTENSION_PROPERTIES;
+ ext_prop.next = nullptr;
+ }
+ rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, runtime_extension_properties.data());
+ }
+ size_t ext_count = runtime_extension_properties.size();
+ size_t props_count = extension_properties.size();
+ for (size_t ext = 0; ext < ext_count; ++ext) {
+ bool found = false;
+ for (size_t prop = 0; prop < props_count; ++prop) {
+ // If we find it, then make sure the spec version matches that of the runtime instead of the
+ // layer.
+ if (strcmp(extension_properties[prop].extensionName, runtime_extension_properties[ext].extensionName) == 0) {
+ // Make sure the spec version used is the runtime's
+ extension_properties[prop].extensionVersion = runtime_extension_properties[ext].extensionVersion;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ extension_properties.push_back(runtime_extension_properties[ext]);
+ }
+ }
+}
+
+XrResult RuntimeInterface::CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance) {
+ XrResult res = XR_SUCCESS;
+ bool create_succeeded = false;
+ PFN_xrCreateInstance rt_xrCreateInstance;
+ _get_instant_proc_addr(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrCreateInstance));
+ res = rt_xrCreateInstance(info, instance);
+ if (XR_SUCCESS == res) {
+ create_succeeded = true;
+ std::unique_ptr<XrGeneratedDispatchTable> dispatch_table(new XrGeneratedDispatchTable());
+ GeneratedXrPopulateDispatchTable(dispatch_table.get(), *instance, _get_instant_proc_addr);
+ std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
+ _dispatch_table_map[*instance] = std::move(dispatch_table);
+ }
+
+ // If the failure occurred during the populate, clean up the instance we had picked up from the runtime
+ if (XR_SUCCESS != res && create_succeeded) {
+ PFN_xrDestroyInstance rt_xrDestroyInstance;
+ _get_instant_proc_addr(*instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
+ rt_xrDestroyInstance(*instance);
+ *instance = XR_NULL_HANDLE;
+ }
+
+ return res;
+}
+
+XrResult RuntimeInterface::DestroyInstance(XrInstance instance) {
+ if (XR_NULL_HANDLE != instance) {
+ // Destroy the dispatch table for this instance first
+ {
+ std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
+ auto map_iter = _dispatch_table_map.find(instance);
+ if (map_iter != _dispatch_table_map.end()) {
+ _dispatch_table_map.erase(map_iter);
+ }
+ }
+ // Now delete the instance
+ PFN_xrDestroyInstance rt_xrDestroyInstance;
+ _get_instant_proc_addr(instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
+ rt_xrDestroyInstance(instance);
+ }
+ return XR_SUCCESS;
+}
+
+bool RuntimeInterface::TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger) {
+ std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
+ _messenger_to_instance_map[messenger] = instance;
+ return true;
+}
+
+void RuntimeInterface::ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger) {
+ if (XR_NULL_HANDLE != messenger) {
+ std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
+ _messenger_to_instance_map.erase(messenger);
+ }
+}
+
+void RuntimeInterface::SetSupportedExtensions(std::vector<std::string>& supported_extensions) {
+ _supported_extensions = supported_extensions;
+}
+
+bool RuntimeInterface::SupportsExtension(const std::string& extension_name) {
+ bool found_prop = false;
+ for (const std::string& supported_extension : _supported_extensions) {
+ if (supported_extension == extension_name) {
+ found_prop = true;
+ break;
+ }
+ }
+ return found_prop;
+}
diff --git a/extern/openxr/src/loader/runtime_interface.hpp b/extern/openxr/src/loader/runtime_interface.hpp
new file mode 100644
index 00000000000..cb93584f9a0
--- /dev/null
+++ b/extern/openxr/src/loader/runtime_interface.hpp
@@ -0,0 +1,73 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include "loader_platform.hpp"
+
+#include <openxr/openxr.h>
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <mutex>
+#include <memory>
+
+struct XrGeneratedDispatchTable;
+
+class RuntimeInterface {
+ public:
+ virtual ~RuntimeInterface();
+
+ // Helper functions for loading and unloading the runtime (but only when necessary)
+ static XrResult LoadRuntime(const std::string& openxr_command);
+ static void UnloadRuntime(const std::string& openxr_command);
+ static RuntimeInterface& GetRuntime() { return *(_single_runtime_interface.get()); }
+ static XrResult GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
+ static const XrGeneratedDispatchTable* GetDispatchTable(XrInstance instance);
+ static const XrGeneratedDispatchTable* GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger);
+
+ void GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties);
+ bool SupportsExtension(const std::string& extension_name);
+ XrResult CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance);
+ XrResult DestroyInstance(XrInstance instance);
+ bool TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger);
+ void ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger);
+
+ // No default construction
+ RuntimeInterface() = delete;
+
+ // Non-copyable
+ RuntimeInterface(const RuntimeInterface&) = delete;
+ RuntimeInterface& operator=(const RuntimeInterface&) = delete;
+
+ private:
+ RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instant_proc_addr);
+ void SetSupportedExtensions(std::vector<std::string>& supported_extensions);
+
+ static std::unique_ptr<RuntimeInterface> _single_runtime_interface;
+ static uint32_t _single_runtime_count;
+ LoaderPlatformLibraryHandle _runtime_library;
+ PFN_xrGetInstanceProcAddr _get_instant_proc_addr;
+ std::unordered_map<XrInstance, std::unique_ptr<XrGeneratedDispatchTable>> _dispatch_table_map;
+ std::mutex _dispatch_table_mutex;
+ std::unordered_map<XrDebugUtilsMessengerEXT, XrInstance> _messenger_to_instance_map;
+ std::mutex _messenger_to_instance_mutex;
+ std::vector<std::string> _supported_extensions;
+};
diff --git a/extern/openxr/src/loader/xr_generated_loader.cpp b/extern/openxr/src/loader/xr_generated_loader.cpp
new file mode 100644
index 00000000000..f9c873480b2
--- /dev/null
+++ b/extern/openxr/src/loader/xr_generated_loader.cpp
@@ -0,0 +1,2568 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See loader_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "xr_generated_loader.hpp"
+
+#include "api_layer_interface.hpp"
+#include "exception_handling.hpp"
+#include "hex_and_handles.h"
+#include "loader_instance.hpp"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "runtime_interface.hpp"
+#include "xr_generated_dispatch_table.h"
+#include "xr_generated_utilities.h"
+
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#include <cstring>
+#include <memory>
+#include <new>
+#include <string>
+#include <unordered_map>
+
+// Unordered maps to lookup the instance for a given object type
+HandleLoaderMap<XrInstance> g_instance_map;
+HandleLoaderMap<XrSession> g_session_map;
+HandleLoaderMap<XrSpace> g_space_map;
+HandleLoaderMap<XrAction> g_action_map;
+HandleLoaderMap<XrSwapchain> g_swapchain_map;
+HandleLoaderMap<XrActionSet> g_actionset_map;
+HandleLoaderMap<XrDebugUtilsMessengerEXT> g_debugutilsmessengerext_map;
+
+// Function used to clean up any residual map values that point to an instance prior to that
+// instance being deleted.
+void LoaderCleanUpMapsForInstance(LoaderInstance *instance) {
+ g_instance_map.RemoveHandlesForLoader(*instance);
+ g_session_map.RemoveHandlesForLoader(*instance);
+ g_space_map.RemoveHandlesForLoader(*instance);
+ g_action_map.RemoveHandlesForLoader(*instance);
+ g_swapchain_map.RemoveHandlesForLoader(*instance);
+ g_actionset_map.RemoveHandlesForLoader(*instance);
+ g_debugutilsmessengerext_map.RemoveHandlesForLoader(*instance);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Automatically generated instance trampolines and terminators
+
+// ---- Core 1.0 commands
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetInstanceProperties-instance-parameter",
+ "xrGetInstanceProperties",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetInstanceProperties(instance, instanceProperties);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrPollEvent-instance-parameter",
+ "xrPollEvent",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->PollEvent(instance, eventData);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrResultToString-instance-parameter",
+ "xrResultToString",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->ResultToString(instance, value, buffer);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderGenTermXrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]) {
+ XrResult result = GeneratedXrUtilitiesResultToString(value, buffer);
+ if (XR_SUCCEEDED(result)) {
+ return result;
+ }
+ // If we did not find it in the generated code, ask the runtime.
+ const XrGeneratedDispatchTable* dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ if (nullptr != dispatch_table->ResultToString) {
+ result = dispatch_table->ResultToString(instance, value, buffer);
+ }
+ return result;
+}
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrStructureTypeToString-instance-parameter",
+ "xrStructureTypeToString",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->StructureTypeToString(instance, value, buffer);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderGenTermXrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) {
+ XrResult result = GeneratedXrUtilitiesStructureTypeToString(value, buffer);
+ if (XR_SUCCEEDED(result)) {
+ return result;
+ }
+ // If we did not find it in the generated code, ask the runtime.
+ const XrGeneratedDispatchTable* dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ if (nullptr != dispatch_table->StructureTypeToString) {
+ result = dispatch_table->StructureTypeToString(instance, value, buffer);
+ }
+ return result;
+}
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetSystem-instance-parameter",
+ "xrGetSystem",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetSystem(instance, getInfo, systemId);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetSystemProperties-instance-parameter",
+ "xrGetSystemProperties",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetSystemProperties(instance, systemId, properties);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateEnvironmentBlendModes-instance-parameter",
+ "xrEnumerateEnvironmentBlendModes",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateEnvironmentBlendModes(instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateSession-instance-parameter",
+ "xrCreateSession",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateSession(instance, createInfo, session);
+ if (XR_SUCCESS == result && nullptr != session) {
+ XrResult insert_result = g_session_map.Insert(*session, *loader_instance);
+ if (XR_FAILED(insert_result)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateSession",
+ "Failed inserting new session into map: may be null or not unique");
+ }
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
+ XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ // Destroy the mapping entry for this item if it was valid.
+ if (nullptr != loader_instance) {
+ g_session_map.Erase(session);
+ }
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrDestroySession-session-parameter",
+ "xrDestroySession",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->DestroySession(session);
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateReferenceSpaces-session-parameter",
+ "xrEnumerateReferenceSpaces",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateReferenceSpaces(session, spaceCapacityInput, spaceCountOutput, spaces);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateReferenceSpace-session-parameter",
+ "xrCreateReferenceSpace",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateReferenceSpace(session, createInfo, space);
+ if (XR_SUCCESS == result && nullptr != space) {
+ XrResult insert_result = g_space_map.Insert(*space, *loader_instance);
+ if (XR_FAILED(insert_result)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateReferenceSpace",
+ "Failed inserting new space into map: may be null or not unique");
+ }
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetReferenceSpaceBoundsRect-session-parameter",
+ "xrGetReferenceSpaceBoundsRect",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetReferenceSpaceBoundsRect(session, referenceSpaceType, bounds);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateActionSpace-session-parameter",
+ "xrCreateActionSpace",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateActionSpace(session, createInfo, space);
+ if (XR_SUCCESS == result && nullptr != space) {
+ XrResult insert_result = g_space_map.Insert(*space, *loader_instance);
+ if (XR_FAILED(insert_result)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateActionSpace",
+ "Failed inserting new space into map: may be null or not unique");
+ }
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_space_map.Get(space);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrLocateSpace-space-parameter",
+ "xrLocateSpace",
+ "space is not a valid XrSpace",
+ {XrLoaderLogObjectInfo{space, XR_OBJECT_TYPE_SPACE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->LocateSpace(space, baseSpace, time, location);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
+ XrSpace space) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_space_map.Get(space);
+ // Destroy the mapping entry for this item if it was valid.
+ if (nullptr != loader_instance) {
+ g_space_map.Erase(space);
+ }
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrDestroySpace-space-parameter",
+ "xrDestroySpace",
+ "space is not a valid XrSpace",
+ {XrLoaderLogObjectInfo{space, XR_OBJECT_TYPE_SPACE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->DestroySpace(space);
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateViewConfigurations-instance-parameter",
+ "xrEnumerateViewConfigurations",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateViewConfigurations(instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetViewConfigurationProperties-instance-parameter",
+ "xrGetViewConfigurationProperties",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetViewConfigurationProperties(instance, systemId, viewConfigurationType, configurationProperties);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateViewConfigurationViews-instance-parameter",
+ "xrEnumerateViewConfigurationViews",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateViewConfigurationViews(instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateSwapchainFormats-session-parameter",
+ "xrEnumerateSwapchainFormats",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateSwapchainFormats(session, formatCapacityInput, formatCountOutput, formats);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateSwapchain-session-parameter",
+ "xrCreateSwapchain",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateSwapchain(session, createInfo, swapchain);
+ if (XR_SUCCESS == result && nullptr != swapchain) {
+ XrResult insert_result = g_swapchain_map.Insert(*swapchain, *loader_instance);
+ if (XR_FAILED(insert_result)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateSwapchain",
+ "Failed inserting new swapchain into map: may be null or not unique");
+ }
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
+ XrSwapchain swapchain) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_swapchain_map.Get(swapchain);
+ // Destroy the mapping entry for this item if it was valid.
+ if (nullptr != loader_instance) {
+ g_swapchain_map.Erase(swapchain);
+ }
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrDestroySwapchain-swapchain-parameter",
+ "xrDestroySwapchain",
+ "swapchain is not a valid XrSwapchain",
+ {XrLoaderLogObjectInfo{swapchain, XR_OBJECT_TYPE_SWAPCHAIN}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->DestroySwapchain(swapchain);
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_swapchain_map.Get(swapchain);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateSwapchainImages-swapchain-parameter",
+ "xrEnumerateSwapchainImages",
+ "swapchain is not a valid XrSwapchain",
+ {XrLoaderLogObjectInfo{swapchain, XR_OBJECT_TYPE_SWAPCHAIN}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateSwapchainImages(swapchain, imageCapacityInput, imageCountOutput, images);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_swapchain_map.Get(swapchain);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrAcquireSwapchainImage-swapchain-parameter",
+ "xrAcquireSwapchainImage",
+ "swapchain is not a valid XrSwapchain",
+ {XrLoaderLogObjectInfo{swapchain, XR_OBJECT_TYPE_SWAPCHAIN}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->AcquireSwapchainImage(swapchain, acquireInfo, index);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_swapchain_map.Get(swapchain);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrWaitSwapchainImage-swapchain-parameter",
+ "xrWaitSwapchainImage",
+ "swapchain is not a valid XrSwapchain",
+ {XrLoaderLogObjectInfo{swapchain, XR_OBJECT_TYPE_SWAPCHAIN}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->WaitSwapchainImage(swapchain, waitInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_swapchain_map.Get(swapchain);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrReleaseSwapchainImage-swapchain-parameter",
+ "xrReleaseSwapchainImage",
+ "swapchain is not a valid XrSwapchain",
+ {XrLoaderLogObjectInfo{swapchain, XR_OBJECT_TYPE_SWAPCHAIN}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->ReleaseSwapchainImage(swapchain, releaseInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrBeginSession-session-parameter",
+ "xrBeginSession",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->BeginSession(session, beginInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
+ XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEndSession-session-parameter",
+ "xrEndSession",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EndSession(session);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
+ XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrRequestExitSession-session-parameter",
+ "xrRequestExitSession",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->RequestExitSession(session);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrWaitFrame-session-parameter",
+ "xrWaitFrame",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->WaitFrame(session, frameWaitInfo, frameState);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrBeginFrame-session-parameter",
+ "xrBeginFrame",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->BeginFrame(session, frameBeginInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEndFrame-session-parameter",
+ "xrEndFrame",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EndFrame(session, frameEndInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrLocateViews-session-parameter",
+ "xrLocateViews",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->LocateViews(session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrStringToPath-instance-parameter",
+ "xrStringToPath",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->StringToPath(instance, pathString, path);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrPathToString-instance-parameter",
+ "xrPathToString",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->PathToString(instance, path, bufferCapacityInput, bufferCountOutput, buffer);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateActionSet-instance-parameter",
+ "xrCreateActionSet",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateActionSet(instance, createInfo, actionSet);
+ if (XR_SUCCESS == result && nullptr != actionSet) {
+ XrResult insert_result = g_actionset_map.Insert(*actionSet, *loader_instance);
+ if (XR_FAILED(insert_result)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateActionSet",
+ "Failed inserting new actionset into map: may be null or not unique");
+ }
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
+ XrActionSet actionSet) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_actionset_map.Get(actionSet);
+ // Destroy the mapping entry for this item if it was valid.
+ if (nullptr != loader_instance) {
+ g_actionset_map.Erase(actionSet);
+ }
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrDestroyActionSet-actionSet-parameter",
+ "xrDestroyActionSet",
+ "actionSet is not a valid XrActionSet",
+ {XrLoaderLogObjectInfo{actionSet, XR_OBJECT_TYPE_ACTION_SET}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->DestroyActionSet(actionSet);
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_actionset_map.Get(actionSet);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateAction-actionSet-parameter",
+ "xrCreateAction",
+ "actionSet is not a valid XrActionSet",
+ {XrLoaderLogObjectInfo{actionSet, XR_OBJECT_TYPE_ACTION_SET}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->CreateAction(actionSet, createInfo, action);
+ if (XR_SUCCESS == result && nullptr != action) {
+ XrResult insert_result = g_action_map.Insert(*action, *loader_instance);
+ if (XR_FAILED(insert_result)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateAction",
+ "Failed inserting new action into map: may be null or not unique");
+ }
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
+ XrAction action) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_action_map.Get(action);
+ // Destroy the mapping entry for this item if it was valid.
+ if (nullptr != loader_instance) {
+ g_action_map.Erase(action);
+ }
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrDestroyAction-action-parameter",
+ "xrDestroyAction",
+ "action is not a valid XrAction",
+ {XrLoaderLogObjectInfo{action, XR_OBJECT_TYPE_ACTION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ result = dispatch_table->DestroyAction(action);
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrSuggestInteractionProfileBindings-instance-parameter",
+ "xrSuggestInteractionProfileBindings",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->SuggestInteractionProfileBindings(instance, suggestedBindings);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrAttachSessionActionSets-session-parameter",
+ "xrAttachSessionActionSets",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->AttachSessionActionSets(session, attachInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetCurrentInteractionProfile-session-parameter",
+ "xrGetCurrentInteractionProfile",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetCurrentInteractionProfile(session, topLevelUserPath, interactionProfile);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetActionStateBoolean-session-parameter",
+ "xrGetActionStateBoolean",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetActionStateBoolean(session, getInfo, state);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetActionStateFloat-session-parameter",
+ "xrGetActionStateFloat",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetActionStateFloat(session, getInfo, state);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetActionStateVector2f-session-parameter",
+ "xrGetActionStateVector2f",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetActionStateVector2f(session, getInfo, state);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetActionStatePose-session-parameter",
+ "xrGetActionStatePose",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetActionStatePose(session, getInfo, state);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrSyncActions-session-parameter",
+ "xrSyncActions",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->SyncActions(session, syncInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrEnumerateBoundSourcesForAction-session-parameter",
+ "xrEnumerateBoundSourcesForAction",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->EnumerateBoundSourcesForAction(session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetInputSourceLocalizedName-session-parameter",
+ "xrGetInputSourceLocalizedName",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->GetInputSourceLocalizedName(session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrApplyHapticFeedback-session-parameter",
+ "xrApplyHapticFeedback",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->ApplyHapticFeedback(session, hapticActionInfo, hapticFeedback);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrStopHapticFeedback-session-parameter",
+ "xrStopHapticFeedback",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ return dispatch_table->StopHapticFeedback(session, hapticActionInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+
+// ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
+ XrSession session,
+ XrAndroidThreadTypeKHR threadType,
+ uint32_t threadId) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrSetAndroidApplicationThreadKHR-session-parameter",
+ "xrSetAndroidApplicationThreadKHR",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_android_thread_settings")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSetAndroidApplicationThreadKHR-extension-notenabled",
+ "xrSetAndroidApplicationThreadKHR",
+ "The XR_KHR_android_thread_settings extension has not been enabled prior to calling xrSetAndroidApplicationThreadKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->SetAndroidApplicationThreadKHR(session, threadType, threadId);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+
+// ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
+ XrSession session,
+ const XrSwapchainCreateInfo* info,
+ XrSwapchain* swapchain,
+ jobject* surface) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrCreateSwapchainAndroidSurfaceKHR-session-parameter",
+ "xrCreateSwapchainAndroidSurfaceKHR",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ XrResult result = XR_SUCCESS;
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_android_surface_swapchain")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateSwapchainAndroidSurfaceKHR-extension-notenabled",
+ "xrCreateSwapchainAndroidSurfaceKHR",
+ "The XR_KHR_android_surface_swapchain extension has not been enabled prior to calling xrCreateSwapchainAndroidSurfaceKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ result = dispatch_table->CreateSwapchainAndroidSurfaceKHR(session, info, swapchain, surface);
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+
+// ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLKHR* graphicsRequirements) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetOpenGLGraphicsRequirementsKHR-instance-parameter",
+ "xrGetOpenGLGraphicsRequirementsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_opengl_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetOpenGLGraphicsRequirementsKHR-extension-notenabled",
+ "xrGetOpenGLGraphicsRequirementsKHR",
+ "The XR_KHR_opengl_enable extension has not been enabled prior to calling xrGetOpenGLGraphicsRequirementsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetOpenGLGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+
+// ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetOpenGLESGraphicsRequirementsKHR-instance-parameter",
+ "xrGetOpenGLESGraphicsRequirementsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_opengl_es_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetOpenGLESGraphicsRequirementsKHR-extension-notenabled",
+ "xrGetOpenGLESGraphicsRequirementsKHR",
+ "The XR_KHR_opengl_es_enable extension has not been enabled prior to calling xrGetOpenGLESGraphicsRequirementsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetOpenGLESGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+
+// ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetVulkanInstanceExtensionsKHR-instance-parameter",
+ "xrGetVulkanInstanceExtensionsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetVulkanInstanceExtensionsKHR-extension-notenabled",
+ "xrGetVulkanInstanceExtensionsKHR",
+ "The XR_KHR_vulkan_enable extension has not been enabled prior to calling xrGetVulkanInstanceExtensionsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetVulkanInstanceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetVulkanDeviceExtensionsKHR-instance-parameter",
+ "xrGetVulkanDeviceExtensionsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetVulkanDeviceExtensionsKHR-extension-notenabled",
+ "xrGetVulkanDeviceExtensionsKHR",
+ "The XR_KHR_vulkan_enable extension has not been enabled prior to calling xrGetVulkanDeviceExtensionsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetVulkanDeviceExtensionsKHR(instance, systemId, bufferCapacityInput, bufferCountOutput, buffer);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ VkInstance vkInstance,
+ VkPhysicalDevice* vkPhysicalDevice) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetVulkanGraphicsDeviceKHR-instance-parameter",
+ "xrGetVulkanGraphicsDeviceKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetVulkanGraphicsDeviceKHR-extension-notenabled",
+ "xrGetVulkanGraphicsDeviceKHR",
+ "The XR_KHR_vulkan_enable extension has not been enabled prior to calling xrGetVulkanGraphicsDeviceKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetVulkanGraphicsDeviceKHR(instance, systemId, vkInstance, vkPhysicalDevice);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetVulkanGraphicsRequirementsKHR-instance-parameter",
+ "xrGetVulkanGraphicsRequirementsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetVulkanGraphicsRequirementsKHR-extension-notenabled",
+ "xrGetVulkanGraphicsRequirementsKHR",
+ "The XR_KHR_vulkan_enable extension has not been enabled prior to calling xrGetVulkanGraphicsRequirementsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetVulkanGraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+
+// ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D11KHR* graphicsRequirements) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetD3D11GraphicsRequirementsKHR-instance-parameter",
+ "xrGetD3D11GraphicsRequirementsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_D3D11_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetD3D11GraphicsRequirementsKHR-extension-notenabled",
+ "xrGetD3D11GraphicsRequirementsKHR",
+ "The XR_KHR_D3D11_enable extension has not been enabled prior to calling xrGetD3D11GraphicsRequirementsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetD3D11GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+
+// ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D12KHR* graphicsRequirements) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetD3D12GraphicsRequirementsKHR-instance-parameter",
+ "xrGetD3D12GraphicsRequirementsKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_D3D12_enable")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetD3D12GraphicsRequirementsKHR-extension-notenabled",
+ "xrGetD3D12GraphicsRequirementsKHR",
+ "The XR_KHR_D3D12_enable extension has not been enabled prior to calling xrGetD3D12GraphicsRequirementsKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetD3D12GraphicsRequirementsKHR(instance, systemId, graphicsRequirements);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+
+// ---- XR_KHR_visibility_mask extension commands
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVisibilityMaskKHR(
+ XrSession session,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewIndex,
+ XrVisibilityMaskTypeKHR visibilityMaskType,
+ XrVisibilityMaskKHR* visibilityMask) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrGetVisibilityMaskKHR-session-parameter",
+ "xrGetVisibilityMaskKHR",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_visibility_mask")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetVisibilityMaskKHR-extension-notenabled",
+ "xrGetVisibilityMaskKHR",
+ "The XR_KHR_visibility_mask extension has not been enabled prior to calling xrGetVisibilityMaskKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->GetVisibilityMaskKHR(session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+
+// ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
+ XrInstance instance,
+ const LARGE_INTEGER* performanceCounter,
+ XrTime* time) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrConvertWin32PerformanceCounterToTimeKHR-instance-parameter",
+ "xrConvertWin32PerformanceCounterToTimeKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_win32_convert_performance_counter_time")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrConvertWin32PerformanceCounterToTimeKHR-extension-notenabled",
+ "xrConvertWin32PerformanceCounterToTimeKHR",
+ "The XR_KHR_win32_convert_performance_counter_time extension has not been enabled prior to calling xrConvertWin32PerformanceCounterToTimeKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->ConvertWin32PerformanceCounterToTimeKHR(instance, performanceCounter, time);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+#if defined(XR_USE_PLATFORM_WIN32)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
+ XrInstance instance,
+ XrTime time,
+ LARGE_INTEGER* performanceCounter) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrConvertTimeToWin32PerformanceCounterKHR-instance-parameter",
+ "xrConvertTimeToWin32PerformanceCounterKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_win32_convert_performance_counter_time")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrConvertTimeToWin32PerformanceCounterKHR-extension-notenabled",
+ "xrConvertTimeToWin32PerformanceCounterKHR",
+ "The XR_KHR_win32_convert_performance_counter_time extension has not been enabled prior to calling xrConvertTimeToWin32PerformanceCounterKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->ConvertTimeToWin32PerformanceCounterKHR(instance, time, performanceCounter);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+
+// ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
+ XrInstance instance,
+ const struct timespec* timespecTime,
+ XrTime* time) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrConvertTimespecTimeToTimeKHR-instance-parameter",
+ "xrConvertTimespecTimeToTimeKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_convert_timespec_time")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrConvertTimespecTimeToTimeKHR-extension-notenabled",
+ "xrConvertTimespecTimeToTimeKHR",
+ "The XR_KHR_convert_timespec_time extension has not been enabled prior to calling xrConvertTimespecTimeToTimeKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->ConvertTimespecTimeToTimeKHR(instance, timespecTime, time);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_TIMESPEC)
+
+#if defined(XR_USE_TIMESPEC)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
+ XrInstance instance,
+ XrTime time,
+ struct timespec* timespecTime) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrConvertTimeToTimespecTimeKHR-instance-parameter",
+ "xrConvertTimeToTimespecTimeKHR",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_KHR_convert_timespec_time")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrConvertTimeToTimespecTimeKHR-extension-notenabled",
+ "xrConvertTimeToTimespecTimeKHR",
+ "The XR_KHR_convert_timespec_time extension has not been enabled prior to calling xrConvertTimeToTimespecTimeKHR");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->ConvertTimeToTimespecTimeKHR(instance, time, timespecTime);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+#endif // defined(XR_USE_TIMESPEC)
+
+
+// ---- XR_EXT_performance_settings extension commands
+XRAPI_ATTR XrResult XRAPI_CALL xrPerfSettingsSetPerformanceLevelEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsLevelEXT level) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrPerfSettingsSetPerformanceLevelEXT-session-parameter",
+ "xrPerfSettingsSetPerformanceLevelEXT",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_EXT_performance_settings")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrPerfSettingsSetPerformanceLevelEXT-extension-notenabled",
+ "xrPerfSettingsSetPerformanceLevelEXT",
+ "The XR_EXT_performance_settings extension has not been enabled prior to calling xrPerfSettingsSetPerformanceLevelEXT");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->PerfSettingsSetPerformanceLevelEXT(session, domain, level);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+
+// ---- XR_EXT_thermal_query extension commands
+XRAPI_ATTR XrResult XRAPI_CALL xrThermalGetTemperatureTrendEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsNotificationLevelEXT* notificationLevel,
+ float* tempHeadroom,
+ float* tempSlope) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_session_map.Get(session);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrThermalGetTemperatureTrendEXT-session-parameter",
+ "xrThermalGetTemperatureTrendEXT",
+ "session is not a valid XrSession",
+ {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_EXT_thermal_query")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrThermalGetTemperatureTrendEXT-extension-notenabled",
+ "xrThermalGetTemperatureTrendEXT",
+ "The XR_EXT_thermal_query extension has not been enabled prior to calling xrThermalGetTemperatureTrendEXT");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->ThermalGetTemperatureTrendEXT(session, domain, notificationLevel, tempHeadroom, tempSlope);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+
+// ---- XR_EXT_debug_utils extension commands
+XRAPI_ATTR XrResult XRAPI_CALL xrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrSetDebugUtilsObjectNameEXT-instance-parameter",
+ "xrSetDebugUtilsObjectNameEXT",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSetDebugUtilsObjectNameEXT-extension-notenabled",
+ "xrSetDebugUtilsObjectNameEXT",
+ "The XR_EXT_debug_utils extension has not been enabled prior to calling xrSetDebugUtilsObjectNameEXT");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance = g_instance_map.Get(instance);
+ if (nullptr == loader_instance) {
+ LoaderLogger::LogValidationErrorMessage(
+ "VUID-xrSubmitDebugUtilsMessageEXT-instance-parameter",
+ "xrSubmitDebugUtilsMessageEXT",
+ "instance is not a valid XrInstance",
+ {XrLoaderLogObjectInfo{instance, XR_OBJECT_TYPE_INSTANCE}});
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();
+ if (!loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSubmitDebugUtilsMessageEXT-extension-notenabled",
+ "xrSubmitDebugUtilsMessageEXT",
+ "The XR_EXT_debug_utils extension has not been enabled prior to calling xrSubmitDebugUtilsMessageEXT");
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+
+ return dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(XrInstance instance, const char* name,
+ PFN_xrVoidFunction* function) XRLOADER_ABI_TRY {
+ if (nullptr == function) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter",
+ "xrGetInstanceProcAddr", "Invalid Function pointer");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (nullptr == name) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter",
+ "xrGetInstanceProcAddr", "Invalid Name pointer");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Initialize the function to nullptr in case it does not get caught in a known case
+ *function = nullptr;
+ if (name[0] == 'x' && name[1] == 'r') {
+ std::string func_name = &name[2];
+ LoaderInstance * const loader_instance = g_instance_map.Get(instance);
+ if (instance == XR_NULL_HANDLE) {
+ // Null instance is allowed for 3 specific API entry points, otherwise return error
+ if (!((func_name == "CreateInstance") ||
+ (func_name == "EnumerateApiLayerProperties") ||
+ (func_name == "EnumerateInstanceExtensionProperties"))) {
+ std::string error_str = "XR_NULL_HANDLE for instance but query for ";
+ error_str += name;
+ error_str += " requires a valid instance";
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-instance-parameter",
+ "xrGetInstanceProcAddr", error_str);
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+ else if (loader_instance == nullptr) {
+ std::string error_str = "Invalid handle for instance (query for ";
+ error_str += name;
+ error_str += " )";
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-instance-parameter",
+ "xrGetInstanceProcAddr", error_str);
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ // ---- Core 1.0 commands
+
+ if (func_name == "GetInstanceProcAddr") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetInstanceProcAddr);
+ } else if (func_name == "EnumerateApiLayerProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateApiLayerProperties);
+ } else if (func_name == "EnumerateInstanceExtensionProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateInstanceExtensionProperties);
+ } else if (func_name == "CreateInstance") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateInstance);
+ } else if (func_name == "DestroyInstance") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrDestroyInstance);
+ } else if (func_name == "GetInstanceProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetInstanceProperties);
+ } else if (func_name == "PollEvent") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrPollEvent);
+ } else if (func_name == "ResultToString") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrResultToString);
+ } else if (func_name == "StructureTypeToString") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrStructureTypeToString);
+ } else if (func_name == "GetSystem") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetSystem);
+ } else if (func_name == "GetSystemProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetSystemProperties);
+ } else if (func_name == "EnumerateEnvironmentBlendModes") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateEnvironmentBlendModes);
+ } else if (func_name == "CreateSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateSession);
+ } else if (func_name == "DestroySession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->DestroySession);
+ } else if (func_name == "EnumerateReferenceSpaces") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->EnumerateReferenceSpaces);
+ } else if (func_name == "CreateReferenceSpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->CreateReferenceSpace);
+ } else if (func_name == "GetReferenceSpaceBoundsRect") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetReferenceSpaceBoundsRect);
+ } else if (func_name == "CreateActionSpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->CreateActionSpace);
+ } else if (func_name == "LocateSpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->LocateSpace);
+ } else if (func_name == "DestroySpace") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->DestroySpace);
+ } else if (func_name == "EnumerateViewConfigurations") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateViewConfigurations);
+ } else if (func_name == "GetViewConfigurationProperties") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetViewConfigurationProperties);
+ } else if (func_name == "EnumerateViewConfigurationViews") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateViewConfigurationViews);
+ } else if (func_name == "EnumerateSwapchainFormats") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->EnumerateSwapchainFormats);
+ } else if (func_name == "CreateSwapchain") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->CreateSwapchain);
+ } else if (func_name == "DestroySwapchain") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->DestroySwapchain);
+ } else if (func_name == "EnumerateSwapchainImages") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->EnumerateSwapchainImages);
+ } else if (func_name == "AcquireSwapchainImage") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->AcquireSwapchainImage);
+ } else if (func_name == "WaitSwapchainImage") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->WaitSwapchainImage);
+ } else if (func_name == "ReleaseSwapchainImage") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->ReleaseSwapchainImage);
+ } else if (func_name == "BeginSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->BeginSession);
+ } else if (func_name == "EndSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->EndSession);
+ } else if (func_name == "RequestExitSession") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->RequestExitSession);
+ } else if (func_name == "WaitFrame") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->WaitFrame);
+ } else if (func_name == "BeginFrame") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->BeginFrame);
+ } else if (func_name == "EndFrame") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->EndFrame);
+ } else if (func_name == "LocateViews") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->LocateViews);
+ } else if (func_name == "StringToPath") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrStringToPath);
+ } else if (func_name == "PathToString") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrPathToString);
+ } else if (func_name == "CreateActionSet") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateActionSet);
+ } else if (func_name == "DestroyActionSet") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->DestroyActionSet);
+ } else if (func_name == "CreateAction") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->CreateAction);
+ } else if (func_name == "DestroyAction") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->DestroyAction);
+ } else if (func_name == "SuggestInteractionProfileBindings") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrSuggestInteractionProfileBindings);
+ } else if (func_name == "AttachSessionActionSets") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->AttachSessionActionSets);
+ } else if (func_name == "GetCurrentInteractionProfile") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetCurrentInteractionProfile);
+ } else if (func_name == "GetActionStateBoolean") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetActionStateBoolean);
+ } else if (func_name == "GetActionStateFloat") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetActionStateFloat);
+ } else if (func_name == "GetActionStateVector2f") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetActionStateVector2f);
+ } else if (func_name == "GetActionStatePose") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetActionStatePose);
+ } else if (func_name == "SyncActions") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->SyncActions);
+ } else if (func_name == "EnumerateBoundSourcesForAction") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->EnumerateBoundSourcesForAction);
+ } else if (func_name == "GetInputSourceLocalizedName") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetInputSourceLocalizedName);
+ } else if (func_name == "ApplyHapticFeedback") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->ApplyHapticFeedback);
+ } else if (func_name == "StopHapticFeedback") {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->StopHapticFeedback);
+
+ // ---- XR_KHR_android_thread_settings extension commands
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+ } else if (func_name == "SetAndroidApplicationThreadKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_android_thread_settings")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->SetAndroidApplicationThreadKHR);
+ }
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+ } else if (func_name == "CreateSwapchainAndroidSurfaceKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_android_surface_swapchain")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->CreateSwapchainAndroidSurfaceKHR);
+ }
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ } else if (func_name == "GetOpenGLGraphicsRequirementsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_opengl_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetOpenGLGraphicsRequirementsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ } else if (func_name == "GetOpenGLESGraphicsRequirementsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_opengl_es_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetOpenGLESGraphicsRequirementsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "GetVulkanInstanceExtensionsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetVulkanInstanceExtensionsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "GetVulkanDeviceExtensionsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetVulkanDeviceExtensionsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "GetVulkanGraphicsDeviceKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetVulkanGraphicsDeviceKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ } else if (func_name == "GetVulkanGraphicsRequirementsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_vulkan_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetVulkanGraphicsRequirementsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ } else if (func_name == "GetD3D11GraphicsRequirementsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_D3D11_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetD3D11GraphicsRequirementsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ } else if (func_name == "GetD3D12GraphicsRequirementsKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_D3D12_enable")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetD3D12GraphicsRequirementsKHR);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+
+ } else if (func_name == "GetVisibilityMaskKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_visibility_mask")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->GetVisibilityMaskKHR);
+ }
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+
+#if defined(XR_USE_PLATFORM_WIN32)
+ } else if (func_name == "ConvertWin32PerformanceCounterToTimeKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_win32_convert_performance_counter_time")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrConvertWin32PerformanceCounterToTimeKHR);
+ }
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ } else if (func_name == "ConvertTimeToWin32PerformanceCounterKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_win32_convert_performance_counter_time")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrConvertTimeToWin32PerformanceCounterKHR);
+ }
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+
+#if defined(XR_USE_TIMESPEC)
+ } else if (func_name == "ConvertTimespecTimeToTimeKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_convert_timespec_time")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrConvertTimespecTimeToTimeKHR);
+ }
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ } else if (func_name == "ConvertTimeToTimespecTimeKHR") {
+ if (loader_instance->ExtensionIsEnabled("XR_KHR_convert_timespec_time")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrConvertTimeToTimespecTimeKHR);
+ }
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_EXT_performance_settings extension commands
+
+ } else if (func_name == "PerfSettingsSetPerformanceLevelEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_performance_settings")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->PerfSettingsSetPerformanceLevelEXT);
+ }
+
+ // ---- XR_EXT_thermal_query extension commands
+
+ } else if (func_name == "ThermalGetTemperatureTrendEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_thermal_query")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(loader_instance->DispatchTable()->ThermalGetTemperatureTrendEXT);
+ }
+
+ // ---- XR_EXT_debug_utils extension commands
+
+ } else if (func_name == "SetDebugUtilsObjectNameEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrSetDebugUtilsObjectNameEXT);
+ }
+ } else if (func_name == "CreateDebugUtilsMessengerEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateDebugUtilsMessengerEXT);
+ }
+ } else if (func_name == "DestroyDebugUtilsMessengerEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrDestroyDebugUtilsMessengerEXT);
+ }
+ } else if (func_name == "SubmitDebugUtilsMessageEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrSubmitDebugUtilsMessageEXT);
+ }
+ } else if (func_name == "SessionBeginDebugUtilsLabelRegionEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrSessionBeginDebugUtilsLabelRegionEXT);
+ }
+ } else if (func_name == "SessionEndDebugUtilsLabelRegionEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrSessionEndDebugUtilsLabelRegionEXT);
+ }
+ } else if (func_name == "SessionInsertDebugUtilsLabelEXT") {
+ if (loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(xrSessionInsertDebugUtilsLabelEXT);
+ }
+ }
+ }
+ if (*function == nullptr) {
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// Terminator GetInstanceProcAddr function
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance instance, const char* name,
+ PFN_xrVoidFunction* function) XRLOADER_ABI_TRY {
+
+ // A few instance commands need to go through a loader terminator.
+ // Otherwise, go directly to the runtime version of the command if it exists.
+ if (0 == strcmp(name, "xrGetInstanceProcAddr")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermGetInstanceProcAddr);
+ } else if (0 == strcmp(name, "xrCreateInstance")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateInstance);
+ } else if (0 == strcmp(name, "xrDestroyInstance")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyInstance);
+ } else if (0 == strcmp(name, "xrResultToString")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderGenTermXrResultToString);
+ } else if (0 == strcmp(name, "xrStructureTypeToString")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderGenTermXrStructureTypeToString);
+ } else if (0 == strcmp(name, "xrSetDebugUtilsObjectNameEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSetDebugUtilsObjectNameEXT);
+ } else if (0 == strcmp(name, "xrCreateDebugUtilsMessengerEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateDebugUtilsMessengerEXT);
+ } else if (0 == strcmp(name, "xrDestroyDebugUtilsMessengerEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyDebugUtilsMessengerEXT);
+ } else if (0 == strcmp(name, "xrSubmitDebugUtilsMessageEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSubmitDebugUtilsMessageEXT);
+ } else if (0 == strcmp(name, "xrCreateApiLayerInstance")) {
+ // Special layer version of xrCreateInstance terminator. If we get called this by a layer,
+ // we simply re-direct the information back into the standard xrCreateInstance terminator.
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateApiLayerInstance);
+ }
+ if (nullptr != *function) {
+ return XR_SUCCESS;
+ }
+ return RuntimeInterface::GetInstanceProcAddr(instance, name, function);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// Instance Init Dispatch Table (put all terminators in first)
+void LoaderGenInitInstanceDispatchTable(XrInstance instance, std::unique_ptr<XrGeneratedDispatchTable>& table) {
+
+ // ---- Core 1_0 commands
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetInstanceProcAddr", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetInstanceProcAddr));
+ table->EnumerateApiLayerProperties = nullptr;
+ table->EnumerateInstanceExtensionProperties = nullptr;
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateInstance));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroyInstance));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetInstanceProperties", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetInstanceProperties));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrPollEvent", reinterpret_cast<PFN_xrVoidFunction*>(&table->PollEvent));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrResultToString", reinterpret_cast<PFN_xrVoidFunction*>(&table->ResultToString));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrStructureTypeToString", reinterpret_cast<PFN_xrVoidFunction*>(&table->StructureTypeToString));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetSystem", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetSystem));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetSystemProperties", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetSystemProperties));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateEnvironmentBlendModes", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateEnvironmentBlendModes));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateSession", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateSession));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroySession", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroySession));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateReferenceSpaces", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateReferenceSpaces));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateReferenceSpace", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateReferenceSpace));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetReferenceSpaceBoundsRect", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetReferenceSpaceBoundsRect));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateActionSpace", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateActionSpace));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrLocateSpace", reinterpret_cast<PFN_xrVoidFunction*>(&table->LocateSpace));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroySpace", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroySpace));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateViewConfigurations", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateViewConfigurations));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetViewConfigurationProperties", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetViewConfigurationProperties));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateViewConfigurationViews", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateViewConfigurationViews));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateSwapchainFormats", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateSwapchainFormats));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateSwapchain", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateSwapchain));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroySwapchain", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroySwapchain));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateSwapchainImages", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateSwapchainImages));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrAcquireSwapchainImage", reinterpret_cast<PFN_xrVoidFunction*>(&table->AcquireSwapchainImage));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrWaitSwapchainImage", reinterpret_cast<PFN_xrVoidFunction*>(&table->WaitSwapchainImage));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrReleaseSwapchainImage", reinterpret_cast<PFN_xrVoidFunction*>(&table->ReleaseSwapchainImage));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrBeginSession", reinterpret_cast<PFN_xrVoidFunction*>(&table->BeginSession));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEndSession", reinterpret_cast<PFN_xrVoidFunction*>(&table->EndSession));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrRequestExitSession", reinterpret_cast<PFN_xrVoidFunction*>(&table->RequestExitSession));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrWaitFrame", reinterpret_cast<PFN_xrVoidFunction*>(&table->WaitFrame));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrBeginFrame", reinterpret_cast<PFN_xrVoidFunction*>(&table->BeginFrame));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEndFrame", reinterpret_cast<PFN_xrVoidFunction*>(&table->EndFrame));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrLocateViews", reinterpret_cast<PFN_xrVoidFunction*>(&table->LocateViews));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrStringToPath", reinterpret_cast<PFN_xrVoidFunction*>(&table->StringToPath));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrPathToString", reinterpret_cast<PFN_xrVoidFunction*>(&table->PathToString));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateActionSet", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateActionSet));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroyActionSet", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroyActionSet));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateAction", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateAction));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroyAction", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroyAction));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSuggestInteractionProfileBindings", reinterpret_cast<PFN_xrVoidFunction*>(&table->SuggestInteractionProfileBindings));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrAttachSessionActionSets", reinterpret_cast<PFN_xrVoidFunction*>(&table->AttachSessionActionSets));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetCurrentInteractionProfile", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetCurrentInteractionProfile));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetActionStateBoolean", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetActionStateBoolean));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetActionStateFloat", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetActionStateFloat));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetActionStateVector2f", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetActionStateVector2f));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetActionStatePose", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetActionStatePose));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSyncActions", reinterpret_cast<PFN_xrVoidFunction*>(&table->SyncActions));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrEnumerateBoundSourcesForAction", reinterpret_cast<PFN_xrVoidFunction*>(&table->EnumerateBoundSourcesForAction));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetInputSourceLocalizedName", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetInputSourceLocalizedName));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrApplyHapticFeedback", reinterpret_cast<PFN_xrVoidFunction*>(&table->ApplyHapticFeedback));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrStopHapticFeedback", reinterpret_cast<PFN_xrVoidFunction*>(&table->StopHapticFeedback));
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSetAndroidApplicationThreadKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->SetAndroidApplicationThreadKHR));
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateSwapchainAndroidSurfaceKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateSwapchainAndroidSurfaceKHR));
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetOpenGLGraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetOpenGLGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetOpenGLESGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetVulkanInstanceExtensionsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetVulkanInstanceExtensionsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetVulkanDeviceExtensionsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetVulkanDeviceExtensionsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetVulkanGraphicsDeviceKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetVulkanGraphicsDeviceKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetVulkanGraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetVulkanGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetD3D11GraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetD3D11GraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetD3D12GraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetD3D12GraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ LoaderXrTermGetInstanceProcAddr(instance, "xrGetVisibilityMaskKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->GetVisibilityMaskKHR));
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrConvertWin32PerformanceCounterToTimeKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->ConvertWin32PerformanceCounterToTimeKHR));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrConvertTimeToWin32PerformanceCounterKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->ConvertTimeToWin32PerformanceCounterKHR));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrConvertTimespecTimeToTimeKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->ConvertTimespecTimeToTimeKHR));
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ LoaderXrTermGetInstanceProcAddr(instance, "xrConvertTimeToTimespecTimeKHR", reinterpret_cast<PFN_xrVoidFunction*>(&table->ConvertTimeToTimespecTimeKHR));
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_EXT_performance_settings extension commands
+ LoaderXrTermGetInstanceProcAddr(instance, "xrPerfSettingsSetPerformanceLevelEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->PerfSettingsSetPerformanceLevelEXT));
+
+ // ---- XR_EXT_thermal_query extension commands
+ LoaderXrTermGetInstanceProcAddr(instance, "xrThermalGetTemperatureTrendEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->ThermalGetTemperatureTrendEXT));
+
+ // ---- XR_EXT_debug_utils extension commands
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSetDebugUtilsObjectNameEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->SetDebugUtilsObjectNameEXT));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrCreateDebugUtilsMessengerEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->CreateDebugUtilsMessengerEXT));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrDestroyDebugUtilsMessengerEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->DestroyDebugUtilsMessengerEXT));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSubmitDebugUtilsMessageEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->SubmitDebugUtilsMessageEXT));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->SessionBeginDebugUtilsLabelRegionEXT));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSessionEndDebugUtilsLabelRegionEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->SessionEndDebugUtilsLabelRegionEXT));
+ LoaderXrTermGetInstanceProcAddr(instance, "xrSessionInsertDebugUtilsLabelEXT", reinterpret_cast<PFN_xrVoidFunction*>(&table->SessionInsertDebugUtilsLabelEXT));
+}
+
+// Instance Update Dispatch Table with an API Layer Interface
+void ApiLayerInterface::GenUpdateInstanceDispatchTable(XrInstance instance, std::unique_ptr<XrGeneratedDispatchTable>& table) {
+ PFN_xrVoidFunction cur_func_ptr;
+
+ // ---- Core 1_0 commands
+ table->GetInstanceProcAddr = _get_instant_proc_addr;
+ _get_instant_proc_addr(instance, "xrCreateInstance", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateInstance = reinterpret_cast<PFN_xrCreateInstance>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroyInstance", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroyInstance = reinterpret_cast<PFN_xrDestroyInstance>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetInstanceProperties", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetInstanceProperties = reinterpret_cast<PFN_xrGetInstanceProperties>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrPollEvent", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->PollEvent = reinterpret_cast<PFN_xrPollEvent>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrResultToString", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ResultToString = reinterpret_cast<PFN_xrResultToString>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrStructureTypeToString", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->StructureTypeToString = reinterpret_cast<PFN_xrStructureTypeToString>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetSystem", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetSystem = reinterpret_cast<PFN_xrGetSystem>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetSystemProperties", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetSystemProperties = reinterpret_cast<PFN_xrGetSystemProperties>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateEnvironmentBlendModes", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateEnvironmentBlendModes = reinterpret_cast<PFN_xrEnumerateEnvironmentBlendModes>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateSession", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateSession = reinterpret_cast<PFN_xrCreateSession>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroySession", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroySession = reinterpret_cast<PFN_xrDestroySession>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateReferenceSpaces", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateReferenceSpaces = reinterpret_cast<PFN_xrEnumerateReferenceSpaces>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateReferenceSpace", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateReferenceSpace = reinterpret_cast<PFN_xrCreateReferenceSpace>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetReferenceSpaceBoundsRect", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetReferenceSpaceBoundsRect = reinterpret_cast<PFN_xrGetReferenceSpaceBoundsRect>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateActionSpace", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateActionSpace = reinterpret_cast<PFN_xrCreateActionSpace>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrLocateSpace", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->LocateSpace = reinterpret_cast<PFN_xrLocateSpace>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroySpace", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroySpace = reinterpret_cast<PFN_xrDestroySpace>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateViewConfigurations", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateViewConfigurations = reinterpret_cast<PFN_xrEnumerateViewConfigurations>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetViewConfigurationProperties", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetViewConfigurationProperties = reinterpret_cast<PFN_xrGetViewConfigurationProperties>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateViewConfigurationViews", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateViewConfigurationViews = reinterpret_cast<PFN_xrEnumerateViewConfigurationViews>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateSwapchainFormats", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateSwapchainFormats = reinterpret_cast<PFN_xrEnumerateSwapchainFormats>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateSwapchain", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateSwapchain = reinterpret_cast<PFN_xrCreateSwapchain>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroySwapchain", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroySwapchain = reinterpret_cast<PFN_xrDestroySwapchain>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateSwapchainImages", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateSwapchainImages = reinterpret_cast<PFN_xrEnumerateSwapchainImages>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrAcquireSwapchainImage", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->AcquireSwapchainImage = reinterpret_cast<PFN_xrAcquireSwapchainImage>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrWaitSwapchainImage", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->WaitSwapchainImage = reinterpret_cast<PFN_xrWaitSwapchainImage>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrReleaseSwapchainImage", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ReleaseSwapchainImage = reinterpret_cast<PFN_xrReleaseSwapchainImage>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrBeginSession", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->BeginSession = reinterpret_cast<PFN_xrBeginSession>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEndSession", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EndSession = reinterpret_cast<PFN_xrEndSession>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrRequestExitSession", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->RequestExitSession = reinterpret_cast<PFN_xrRequestExitSession>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrWaitFrame", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->WaitFrame = reinterpret_cast<PFN_xrWaitFrame>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrBeginFrame", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->BeginFrame = reinterpret_cast<PFN_xrBeginFrame>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEndFrame", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EndFrame = reinterpret_cast<PFN_xrEndFrame>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrLocateViews", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->LocateViews = reinterpret_cast<PFN_xrLocateViews>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrStringToPath", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->StringToPath = reinterpret_cast<PFN_xrStringToPath>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrPathToString", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->PathToString = reinterpret_cast<PFN_xrPathToString>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateActionSet", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateActionSet = reinterpret_cast<PFN_xrCreateActionSet>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroyActionSet", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroyActionSet = reinterpret_cast<PFN_xrDestroyActionSet>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateAction", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateAction = reinterpret_cast<PFN_xrCreateAction>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroyAction", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroyAction = reinterpret_cast<PFN_xrDestroyAction>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrSuggestInteractionProfileBindings", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SuggestInteractionProfileBindings = reinterpret_cast<PFN_xrSuggestInteractionProfileBindings>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrAttachSessionActionSets", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->AttachSessionActionSets = reinterpret_cast<PFN_xrAttachSessionActionSets>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetCurrentInteractionProfile", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetCurrentInteractionProfile = reinterpret_cast<PFN_xrGetCurrentInteractionProfile>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetActionStateBoolean", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetActionStateBoolean = reinterpret_cast<PFN_xrGetActionStateBoolean>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetActionStateFloat", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetActionStateFloat = reinterpret_cast<PFN_xrGetActionStateFloat>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetActionStateVector2f", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetActionStateVector2f = reinterpret_cast<PFN_xrGetActionStateVector2f>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetActionStatePose", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetActionStatePose = reinterpret_cast<PFN_xrGetActionStatePose>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrSyncActions", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SyncActions = reinterpret_cast<PFN_xrSyncActions>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrEnumerateBoundSourcesForAction", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->EnumerateBoundSourcesForAction = reinterpret_cast<PFN_xrEnumerateBoundSourcesForAction>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrGetInputSourceLocalizedName", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetInputSourceLocalizedName = reinterpret_cast<PFN_xrGetInputSourceLocalizedName>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrApplyHapticFeedback", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ApplyHapticFeedback = reinterpret_cast<PFN_xrApplyHapticFeedback>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrStopHapticFeedback", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->StopHapticFeedback = reinterpret_cast<PFN_xrStopHapticFeedback>(cur_func_ptr);
+ }
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ _get_instant_proc_addr(instance, "xrSetAndroidApplicationThreadKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SetAndroidApplicationThreadKHR = reinterpret_cast<PFN_xrSetAndroidApplicationThreadKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ _get_instant_proc_addr(instance, "xrCreateSwapchainAndroidSurfaceKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateSwapchainAndroidSurfaceKHR = reinterpret_cast<PFN_xrCreateSwapchainAndroidSurfaceKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ _get_instant_proc_addr(instance, "xrGetOpenGLGraphicsRequirementsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetOpenGLGraphicsRequirementsKHR = reinterpret_cast<PFN_xrGetOpenGLGraphicsRequirementsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ _get_instant_proc_addr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetOpenGLESGraphicsRequirementsKHR = reinterpret_cast<PFN_xrGetOpenGLESGraphicsRequirementsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ _get_instant_proc_addr(instance, "xrGetVulkanInstanceExtensionsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetVulkanInstanceExtensionsKHR = reinterpret_cast<PFN_xrGetVulkanInstanceExtensionsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ _get_instant_proc_addr(instance, "xrGetVulkanDeviceExtensionsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetVulkanDeviceExtensionsKHR = reinterpret_cast<PFN_xrGetVulkanDeviceExtensionsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ _get_instant_proc_addr(instance, "xrGetVulkanGraphicsDeviceKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetVulkanGraphicsDeviceKHR = reinterpret_cast<PFN_xrGetVulkanGraphicsDeviceKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ _get_instant_proc_addr(instance, "xrGetVulkanGraphicsRequirementsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetVulkanGraphicsRequirementsKHR = reinterpret_cast<PFN_xrGetVulkanGraphicsRequirementsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ _get_instant_proc_addr(instance, "xrGetD3D11GraphicsRequirementsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetD3D11GraphicsRequirementsKHR = reinterpret_cast<PFN_xrGetD3D11GraphicsRequirementsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ _get_instant_proc_addr(instance, "xrGetD3D12GraphicsRequirementsKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetD3D12GraphicsRequirementsKHR = reinterpret_cast<PFN_xrGetD3D12GraphicsRequirementsKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ _get_instant_proc_addr(instance, "xrGetVisibilityMaskKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->GetVisibilityMaskKHR = reinterpret_cast<PFN_xrGetVisibilityMaskKHR>(cur_func_ptr);
+ }
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ _get_instant_proc_addr(instance, "xrConvertWin32PerformanceCounterToTimeKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ConvertWin32PerformanceCounterToTimeKHR = reinterpret_cast<PFN_xrConvertWin32PerformanceCounterToTimeKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ _get_instant_proc_addr(instance, "xrConvertTimeToWin32PerformanceCounterKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ConvertTimeToWin32PerformanceCounterKHR = reinterpret_cast<PFN_xrConvertTimeToWin32PerformanceCounterKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ _get_instant_proc_addr(instance, "xrConvertTimespecTimeToTimeKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ConvertTimespecTimeToTimeKHR = reinterpret_cast<PFN_xrConvertTimespecTimeToTimeKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ _get_instant_proc_addr(instance, "xrConvertTimeToTimespecTimeKHR", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ConvertTimeToTimespecTimeKHR = reinterpret_cast<PFN_xrConvertTimeToTimespecTimeKHR>(cur_func_ptr);
+ }
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_EXT_performance_settings extension commands
+ _get_instant_proc_addr(instance, "xrPerfSettingsSetPerformanceLevelEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->PerfSettingsSetPerformanceLevelEXT = reinterpret_cast<PFN_xrPerfSettingsSetPerformanceLevelEXT>(cur_func_ptr);
+ }
+
+ // ---- XR_EXT_thermal_query extension commands
+ _get_instant_proc_addr(instance, "xrThermalGetTemperatureTrendEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->ThermalGetTemperatureTrendEXT = reinterpret_cast<PFN_xrThermalGetTemperatureTrendEXT>(cur_func_ptr);
+ }
+
+ // ---- XR_EXT_debug_utils extension commands
+ _get_instant_proc_addr(instance, "xrSetDebugUtilsObjectNameEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SetDebugUtilsObjectNameEXT = reinterpret_cast<PFN_xrSetDebugUtilsObjectNameEXT>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrCreateDebugUtilsMessengerEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->CreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_xrCreateDebugUtilsMessengerEXT>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrDestroyDebugUtilsMessengerEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->DestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_xrDestroyDebugUtilsMessengerEXT>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrSubmitDebugUtilsMessageEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SubmitDebugUtilsMessageEXT = reinterpret_cast<PFN_xrSubmitDebugUtilsMessageEXT>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SessionBeginDebugUtilsLabelRegionEXT = reinterpret_cast<PFN_xrSessionBeginDebugUtilsLabelRegionEXT>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrSessionEndDebugUtilsLabelRegionEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SessionEndDebugUtilsLabelRegionEXT = reinterpret_cast<PFN_xrSessionEndDebugUtilsLabelRegionEXT>(cur_func_ptr);
+ }
+ _get_instant_proc_addr(instance, "xrSessionInsertDebugUtilsLabelEXT", &cur_func_ptr);
+ if (nullptr != cur_func_ptr) {
+ table->SessionInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_xrSessionInsertDebugUtilsLabelEXT>(cur_func_ptr);
+ }
+}
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/extern/openxr/src/loader/xr_generated_loader.hpp b/extern/openxr/src/loader/xr_generated_loader.hpp
new file mode 100644
index 00000000000..a87116b5997
--- /dev/null
+++ b/extern/openxr/src/loader/xr_generated_loader.hpp
@@ -0,0 +1,307 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See loader_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+#include <unordered_map>
+#include <thread>
+#include <mutex>
+
+#include "xr_dependencies.h"
+#include "openxr/openxr.h"
+#include "openxr/openxr_platform.h"
+
+#include "loader_interfaces.h"
+
+#include "loader_instance.hpp"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Loader manually generated function prototypes
+
+
+// ---- Core 1.0 loader manual functions
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(
+ XrInstance instance,
+ const char* name,
+ PFN_xrVoidFunction* function);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(
+ XrInstance instance,
+ const char* name,
+ PFN_xrVoidFunction* function);
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(
+ uint32_t propertyCapacityInput,
+ uint32_t* propertyCountOutput,
+ XrApiLayerProperties* properties);
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(
+ const char* layerName,
+ uint32_t propertyCapacityInput,
+ uint32_t* propertyCountOutput,
+ XrExtensionProperties* properties);
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(
+ const XrInstanceCreateInfo* createInfo,
+ XrInstance* instance);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(
+ const XrInstanceCreateInfo* createInfo,
+ XrInstance* instance);
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(
+ XrInstance instance);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(
+ XrInstance instance);
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties);
+XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData);
+XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]);
+XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId);
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties);
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes);
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session);
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes);
+XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties);
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views);
+XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path);
+XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet);
+XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings);
+
+// ---- XR_KHR_opengl_enable loader manual functions
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+// ---- XR_KHR_opengl_es_enable loader manual functions
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+// ---- XR_KHR_vulkan_enable loader manual functions
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ VkInstance vkInstance,
+ VkPhysicalDevice* vkPhysicalDevice);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+// ---- XR_KHR_D3D11_enable loader manual functions
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+// ---- XR_KHR_D3D12_enable loader manual functions
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+// ---- XR_KHR_win32_convert_performance_counter_time loader manual functions
+#if defined(XR_USE_PLATFORM_WIN32)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
+ XrInstance instance,
+ const LARGE_INTEGER* performanceCounter,
+ XrTime* time);
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
+ XrInstance instance,
+ XrTime time,
+ LARGE_INTEGER* performanceCounter);
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+// ---- XR_KHR_convert_timespec_time loader manual functions
+#if defined(XR_USE_TIMESPEC)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
+ XrInstance instance,
+ const struct timespec* timespecTime,
+ XrTime* time);
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
+ XrInstance instance,
+ XrTime time,
+ struct timespec* timespecTime);
+#endif // defined(XR_USE_TIMESPEC)
+
+// ---- XR_EXT_debug_utils loader manual functions
+XRAPI_ATTR XrResult XRAPI_CALL xrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger);
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger);
+XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(
+ XrSession session);
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+
+// Special use function to handle creating API Layer information during xrCreateInstance
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo* info,
+ const struct XrApiLayerCreateInfo* apiLayerInfo,
+ XrInstance* instance);
+
+
+// Generated loader terminator prototypes
+XRAPI_ATTR XrResult XRAPI_CALL LoaderGenTermXrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]);
+XRAPI_ATTR XrResult XRAPI_CALL LoaderGenTermXrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+// Instance Init Dispatch Table (put all terminators in first)
+void LoaderGenInitInstanceDispatchTable(XrInstance runtime_instance,
+ std::unique_ptr<XrGeneratedDispatchTable>& table);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// Unordered maps and mutexes to lookup the instance for a given object type
+extern HandleLoaderMap<XrInstance> g_instance_map;
+extern HandleLoaderMap<XrSession> g_session_map;
+extern HandleLoaderMap<XrSpace> g_space_map;
+extern HandleLoaderMap<XrAction> g_action_map;
+extern HandleLoaderMap<XrSwapchain> g_swapchain_map;
+extern HandleLoaderMap<XrActionSet> g_actionset_map;
+extern HandleLoaderMap<XrDebugUtilsMessengerEXT> g_debugutilsmessengerext_map;
+
+// Function used to clean up any residual map values that point to an instance prior to that
+// instance being deleted.
+void LoaderCleanUpMapsForInstance(LoaderInstance *instance);
+
+
diff --git a/extern/openxr/src/version.cmake b/extern/openxr/src/version.cmake
new file mode 100644
index 00000000000..2b71d7796ca
--- /dev/null
+++ b/extern/openxr/src/version.cmake
@@ -0,0 +1,41 @@
+# Copyright (c) 2017-2019 The Khronos Group Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Set up the OpenXR version variables, used by several targets in this project.
+set(MAJOR "0")
+set(MINOR "0")
+set(PATCH "0")
+
+if(EXISTS "${OPENXR_ROOT_DIR}/specification/registry/xr.xml")
+ file(STRINGS ${OPENXR_ROOT_DIR}/specification/registry/xr.xml lines REGEX "#define <name>XR_CURRENT_API_VERSION")
+else()
+ file(STRINGS ${OPENXR_ROOT_DIR}/include/openxr/openxr.h lines REGEX "#define XR_CURRENT_API_VERSION")
+endif()
+list(LENGTH lines len)
+if(${len} EQUAL 1)
+ list(GET lines 0 cur_line)
+ # Erase everything up to the open parentheses
+ string(REGEX REPLACE "^[^\(]+" "" VERSION_BEFORE_ERASED ${cur_line})
+ # Erase everything after the close parentheses
+ string(REGEX REPLACE "[^\)]+$" "" VERSION_AFTER_ERASED ${VERSION_BEFORE_ERASED})
+ # Erase the parentheses
+ string(REPLACE "(" "" VERSION_AFTER_ERASED2 ${VERSION_AFTER_ERASED})
+ string(REPLACE ")" "" VERSION_AFTER_ERASED3 ${VERSION_AFTER_ERASED2})
+ string(REPLACE " " "" VERSION_AFTER_ERASED4 ${VERSION_AFTER_ERASED3})
+ string(REGEX REPLACE "^([0-9]+)\\,[0-9]+\\,[0-9]+" "\\1" MAJOR "${VERSION_AFTER_ERASED4}")
+ string(REGEX REPLACE "^[0-9]+\\,([0-9]+)\\,[0-9]+" "\\1" MINOR "${VERSION_AFTER_ERASED4}")
+ string(REGEX REPLACE "^[0-9]+\\,[0-9]+\\,([0-9]+)" "\\1" PATCH "${VERSION_AFTER_ERASED4}")
+else()
+ message(FATAL_ERROR "Unable to fetch major/minor version from registry or header")
+endif()
diff --git a/extern/openxr/src/xr_generated_dispatch_table.c b/extern/openxr/src/xr_generated_dispatch_table.c
new file mode 100644
index 00000000000..a2e30e4e88d
--- /dev/null
+++ b/extern/openxr/src/xr_generated_dispatch_table.c
@@ -0,0 +1,175 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See utility_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#include "xr_generated_dispatch_table.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Helper function to populate an instance dispatch table
+void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
+ XrInstance instance,
+ PFN_xrGetInstanceProcAddr get_inst_proc_addr) {
+
+ // ---- Core 1.0 commands
+ table->GetInstanceProcAddr = get_inst_proc_addr;
+ (get_inst_proc_addr(instance, "xrCreateInstance", (PFN_xrVoidFunction*)&table->CreateInstance));
+ (get_inst_proc_addr(instance, "xrDestroyInstance", (PFN_xrVoidFunction*)&table->DestroyInstance));
+ (get_inst_proc_addr(instance, "xrGetInstanceProperties", (PFN_xrVoidFunction*)&table->GetInstanceProperties));
+ (get_inst_proc_addr(instance, "xrPollEvent", (PFN_xrVoidFunction*)&table->PollEvent));
+ (get_inst_proc_addr(instance, "xrResultToString", (PFN_xrVoidFunction*)&table->ResultToString));
+ (get_inst_proc_addr(instance, "xrStructureTypeToString", (PFN_xrVoidFunction*)&table->StructureTypeToString));
+ (get_inst_proc_addr(instance, "xrGetSystem", (PFN_xrVoidFunction*)&table->GetSystem));
+ (get_inst_proc_addr(instance, "xrGetSystemProperties", (PFN_xrVoidFunction*)&table->GetSystemProperties));
+ (get_inst_proc_addr(instance, "xrEnumerateEnvironmentBlendModes", (PFN_xrVoidFunction*)&table->EnumerateEnvironmentBlendModes));
+ (get_inst_proc_addr(instance, "xrCreateSession", (PFN_xrVoidFunction*)&table->CreateSession));
+ (get_inst_proc_addr(instance, "xrDestroySession", (PFN_xrVoidFunction*)&table->DestroySession));
+ (get_inst_proc_addr(instance, "xrEnumerateReferenceSpaces", (PFN_xrVoidFunction*)&table->EnumerateReferenceSpaces));
+ (get_inst_proc_addr(instance, "xrCreateReferenceSpace", (PFN_xrVoidFunction*)&table->CreateReferenceSpace));
+ (get_inst_proc_addr(instance, "xrGetReferenceSpaceBoundsRect", (PFN_xrVoidFunction*)&table->GetReferenceSpaceBoundsRect));
+ (get_inst_proc_addr(instance, "xrCreateActionSpace", (PFN_xrVoidFunction*)&table->CreateActionSpace));
+ (get_inst_proc_addr(instance, "xrLocateSpace", (PFN_xrVoidFunction*)&table->LocateSpace));
+ (get_inst_proc_addr(instance, "xrDestroySpace", (PFN_xrVoidFunction*)&table->DestroySpace));
+ (get_inst_proc_addr(instance, "xrEnumerateViewConfigurations", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurations));
+ (get_inst_proc_addr(instance, "xrGetViewConfigurationProperties", (PFN_xrVoidFunction*)&table->GetViewConfigurationProperties));
+ (get_inst_proc_addr(instance, "xrEnumerateViewConfigurationViews", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurationViews));
+ (get_inst_proc_addr(instance, "xrEnumerateSwapchainFormats", (PFN_xrVoidFunction*)&table->EnumerateSwapchainFormats));
+ (get_inst_proc_addr(instance, "xrCreateSwapchain", (PFN_xrVoidFunction*)&table->CreateSwapchain));
+ (get_inst_proc_addr(instance, "xrDestroySwapchain", (PFN_xrVoidFunction*)&table->DestroySwapchain));
+ (get_inst_proc_addr(instance, "xrEnumerateSwapchainImages", (PFN_xrVoidFunction*)&table->EnumerateSwapchainImages));
+ (get_inst_proc_addr(instance, "xrAcquireSwapchainImage", (PFN_xrVoidFunction*)&table->AcquireSwapchainImage));
+ (get_inst_proc_addr(instance, "xrWaitSwapchainImage", (PFN_xrVoidFunction*)&table->WaitSwapchainImage));
+ (get_inst_proc_addr(instance, "xrReleaseSwapchainImage", (PFN_xrVoidFunction*)&table->ReleaseSwapchainImage));
+ (get_inst_proc_addr(instance, "xrBeginSession", (PFN_xrVoidFunction*)&table->BeginSession));
+ (get_inst_proc_addr(instance, "xrEndSession", (PFN_xrVoidFunction*)&table->EndSession));
+ (get_inst_proc_addr(instance, "xrRequestExitSession", (PFN_xrVoidFunction*)&table->RequestExitSession));
+ (get_inst_proc_addr(instance, "xrWaitFrame", (PFN_xrVoidFunction*)&table->WaitFrame));
+ (get_inst_proc_addr(instance, "xrBeginFrame", (PFN_xrVoidFunction*)&table->BeginFrame));
+ (get_inst_proc_addr(instance, "xrEndFrame", (PFN_xrVoidFunction*)&table->EndFrame));
+ (get_inst_proc_addr(instance, "xrLocateViews", (PFN_xrVoidFunction*)&table->LocateViews));
+ (get_inst_proc_addr(instance, "xrStringToPath", (PFN_xrVoidFunction*)&table->StringToPath));
+ (get_inst_proc_addr(instance, "xrPathToString", (PFN_xrVoidFunction*)&table->PathToString));
+ (get_inst_proc_addr(instance, "xrCreateActionSet", (PFN_xrVoidFunction*)&table->CreateActionSet));
+ (get_inst_proc_addr(instance, "xrDestroyActionSet", (PFN_xrVoidFunction*)&table->DestroyActionSet));
+ (get_inst_proc_addr(instance, "xrCreateAction", (PFN_xrVoidFunction*)&table->CreateAction));
+ (get_inst_proc_addr(instance, "xrDestroyAction", (PFN_xrVoidFunction*)&table->DestroyAction));
+ (get_inst_proc_addr(instance, "xrSuggestInteractionProfileBindings", (PFN_xrVoidFunction*)&table->SuggestInteractionProfileBindings));
+ (get_inst_proc_addr(instance, "xrAttachSessionActionSets", (PFN_xrVoidFunction*)&table->AttachSessionActionSets));
+ (get_inst_proc_addr(instance, "xrGetCurrentInteractionProfile", (PFN_xrVoidFunction*)&table->GetCurrentInteractionProfile));
+ (get_inst_proc_addr(instance, "xrGetActionStateBoolean", (PFN_xrVoidFunction*)&table->GetActionStateBoolean));
+ (get_inst_proc_addr(instance, "xrGetActionStateFloat", (PFN_xrVoidFunction*)&table->GetActionStateFloat));
+ (get_inst_proc_addr(instance, "xrGetActionStateVector2f", (PFN_xrVoidFunction*)&table->GetActionStateVector2f));
+ (get_inst_proc_addr(instance, "xrGetActionStatePose", (PFN_xrVoidFunction*)&table->GetActionStatePose));
+ (get_inst_proc_addr(instance, "xrSyncActions", (PFN_xrVoidFunction*)&table->SyncActions));
+ (get_inst_proc_addr(instance, "xrEnumerateBoundSourcesForAction", (PFN_xrVoidFunction*)&table->EnumerateBoundSourcesForAction));
+ (get_inst_proc_addr(instance, "xrGetInputSourceLocalizedName", (PFN_xrVoidFunction*)&table->GetInputSourceLocalizedName));
+ (get_inst_proc_addr(instance, "xrApplyHapticFeedback", (PFN_xrVoidFunction*)&table->ApplyHapticFeedback));
+ (get_inst_proc_addr(instance, "xrStopHapticFeedback", (PFN_xrVoidFunction*)&table->StopHapticFeedback));
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ (get_inst_proc_addr(instance, "xrSetAndroidApplicationThreadKHR", (PFN_xrVoidFunction*)&table->SetAndroidApplicationThreadKHR));
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ (get_inst_proc_addr(instance, "xrCreateSwapchainAndroidSurfaceKHR", (PFN_xrVoidFunction*)&table->CreateSwapchainAndroidSurfaceKHR));
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ (get_inst_proc_addr(instance, "xrGetOpenGLGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ (get_inst_proc_addr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLESGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanInstanceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanInstanceExtensionsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanDeviceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanDeviceExtensionsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsDeviceKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ (get_inst_proc_addr(instance, "xrGetD3D11GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D11GraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ (get_inst_proc_addr(instance, "xrGetD3D12GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D12GraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ (get_inst_proc_addr(instance, "xrGetVisibilityMaskKHR", (PFN_xrVoidFunction*)&table->GetVisibilityMaskKHR));
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrConvertWin32PerformanceCounterToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertWin32PerformanceCounterToTimeKHR));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrConvertTimeToWin32PerformanceCounterKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToWin32PerformanceCounterKHR));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ (get_inst_proc_addr(instance, "xrConvertTimespecTimeToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimespecTimeToTimeKHR));
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ (get_inst_proc_addr(instance, "xrConvertTimeToTimespecTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToTimespecTimeKHR));
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_EXT_performance_settings extension commands
+ (get_inst_proc_addr(instance, "xrPerfSettingsSetPerformanceLevelEXT", (PFN_xrVoidFunction*)&table->PerfSettingsSetPerformanceLevelEXT));
+
+ // ---- XR_EXT_thermal_query extension commands
+ (get_inst_proc_addr(instance, "xrThermalGetTemperatureTrendEXT", (PFN_xrVoidFunction*)&table->ThermalGetTemperatureTrendEXT));
+
+ // ---- XR_EXT_debug_utils extension commands
+ (get_inst_proc_addr(instance, "xrSetDebugUtilsObjectNameEXT", (PFN_xrVoidFunction*)&table->SetDebugUtilsObjectNameEXT));
+ (get_inst_proc_addr(instance, "xrCreateDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->CreateDebugUtilsMessengerEXT));
+ (get_inst_proc_addr(instance, "xrDestroyDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->DestroyDebugUtilsMessengerEXT));
+ (get_inst_proc_addr(instance, "xrSubmitDebugUtilsMessageEXT", (PFN_xrVoidFunction*)&table->SubmitDebugUtilsMessageEXT));
+ (get_inst_proc_addr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionBeginDebugUtilsLabelRegionEXT));
+ (get_inst_proc_addr(instance, "xrSessionEndDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionEndDebugUtilsLabelRegionEXT));
+ (get_inst_proc_addr(instance, "xrSessionInsertDebugUtilsLabelEXT", (PFN_xrVoidFunction*)&table->SessionInsertDebugUtilsLabelEXT));
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/extern/openxr/src/xr_generated_dispatch_table.h b/extern/openxr/src/xr_generated_dispatch_table.h
new file mode 100644
index 00000000000..3203464fd5f
--- /dev/null
+++ b/extern/openxr/src/xr_generated_dispatch_table.h
@@ -0,0 +1,181 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See utility_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Generated dispatch table
+struct XrGeneratedDispatchTable {
+
+ // ---- Core 1.0 commands
+ PFN_xrGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_xrEnumerateApiLayerProperties EnumerateApiLayerProperties;
+ PFN_xrEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_xrCreateInstance CreateInstance;
+ PFN_xrDestroyInstance DestroyInstance;
+ PFN_xrGetInstanceProperties GetInstanceProperties;
+ PFN_xrPollEvent PollEvent;
+ PFN_xrResultToString ResultToString;
+ PFN_xrStructureTypeToString StructureTypeToString;
+ PFN_xrGetSystem GetSystem;
+ PFN_xrGetSystemProperties GetSystemProperties;
+ PFN_xrEnumerateEnvironmentBlendModes EnumerateEnvironmentBlendModes;
+ PFN_xrCreateSession CreateSession;
+ PFN_xrDestroySession DestroySession;
+ PFN_xrEnumerateReferenceSpaces EnumerateReferenceSpaces;
+ PFN_xrCreateReferenceSpace CreateReferenceSpace;
+ PFN_xrGetReferenceSpaceBoundsRect GetReferenceSpaceBoundsRect;
+ PFN_xrCreateActionSpace CreateActionSpace;
+ PFN_xrLocateSpace LocateSpace;
+ PFN_xrDestroySpace DestroySpace;
+ PFN_xrEnumerateViewConfigurations EnumerateViewConfigurations;
+ PFN_xrGetViewConfigurationProperties GetViewConfigurationProperties;
+ PFN_xrEnumerateViewConfigurationViews EnumerateViewConfigurationViews;
+ PFN_xrEnumerateSwapchainFormats EnumerateSwapchainFormats;
+ PFN_xrCreateSwapchain CreateSwapchain;
+ PFN_xrDestroySwapchain DestroySwapchain;
+ PFN_xrEnumerateSwapchainImages EnumerateSwapchainImages;
+ PFN_xrAcquireSwapchainImage AcquireSwapchainImage;
+ PFN_xrWaitSwapchainImage WaitSwapchainImage;
+ PFN_xrReleaseSwapchainImage ReleaseSwapchainImage;
+ PFN_xrBeginSession BeginSession;
+ PFN_xrEndSession EndSession;
+ PFN_xrRequestExitSession RequestExitSession;
+ PFN_xrWaitFrame WaitFrame;
+ PFN_xrBeginFrame BeginFrame;
+ PFN_xrEndFrame EndFrame;
+ PFN_xrLocateViews LocateViews;
+ PFN_xrStringToPath StringToPath;
+ PFN_xrPathToString PathToString;
+ PFN_xrCreateActionSet CreateActionSet;
+ PFN_xrDestroyActionSet DestroyActionSet;
+ PFN_xrCreateAction CreateAction;
+ PFN_xrDestroyAction DestroyAction;
+ PFN_xrSuggestInteractionProfileBindings SuggestInteractionProfileBindings;
+ PFN_xrAttachSessionActionSets AttachSessionActionSets;
+ PFN_xrGetCurrentInteractionProfile GetCurrentInteractionProfile;
+ PFN_xrGetActionStateBoolean GetActionStateBoolean;
+ PFN_xrGetActionStateFloat GetActionStateFloat;
+ PFN_xrGetActionStateVector2f GetActionStateVector2f;
+ PFN_xrGetActionStatePose GetActionStatePose;
+ PFN_xrSyncActions SyncActions;
+ PFN_xrEnumerateBoundSourcesForAction EnumerateBoundSourcesForAction;
+ PFN_xrGetInputSourceLocalizedName GetInputSourceLocalizedName;
+ PFN_xrApplyHapticFeedback ApplyHapticFeedback;
+ PFN_xrStopHapticFeedback StopHapticFeedback;
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ PFN_xrSetAndroidApplicationThreadKHR SetAndroidApplicationThreadKHR;
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ PFN_xrCreateSwapchainAndroidSurfaceKHR CreateSwapchainAndroidSurfaceKHR;
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ PFN_xrGetOpenGLGraphicsRequirementsKHR GetOpenGLGraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ PFN_xrGetOpenGLESGraphicsRequirementsKHR GetOpenGLESGraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanInstanceExtensionsKHR GetVulkanInstanceExtensionsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanDeviceExtensionsKHR GetVulkanDeviceExtensionsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanGraphicsDeviceKHR GetVulkanGraphicsDeviceKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanGraphicsRequirementsKHR GetVulkanGraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ PFN_xrGetD3D11GraphicsRequirementsKHR GetD3D11GraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ PFN_xrGetD3D12GraphicsRequirementsKHR GetD3D12GraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ PFN_xrGetVisibilityMaskKHR GetVisibilityMaskKHR;
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrConvertWin32PerformanceCounterToTimeKHR ConvertWin32PerformanceCounterToTimeKHR;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrConvertTimeToWin32PerformanceCounterKHR ConvertTimeToWin32PerformanceCounterKHR;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ PFN_xrConvertTimespecTimeToTimeKHR ConvertTimespecTimeToTimeKHR;
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ PFN_xrConvertTimeToTimespecTimeKHR ConvertTimeToTimespecTimeKHR;
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_EXT_performance_settings extension commands
+ PFN_xrPerfSettingsSetPerformanceLevelEXT PerfSettingsSetPerformanceLevelEXT;
+
+ // ---- XR_EXT_thermal_query extension commands
+ PFN_xrThermalGetTemperatureTrendEXT ThermalGetTemperatureTrendEXT;
+
+ // ---- XR_EXT_debug_utils extension commands
+ PFN_xrSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
+ PFN_xrCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
+ PFN_xrDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
+ PFN_xrSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
+ PFN_xrSessionBeginDebugUtilsLabelRegionEXT SessionBeginDebugUtilsLabelRegionEXT;
+ PFN_xrSessionEndDebugUtilsLabelRegionEXT SessionEndDebugUtilsLabelRegionEXT;
+ PFN_xrSessionInsertDebugUtilsLabelEXT SessionInsertDebugUtilsLabelEXT;
+};
+
+
+// Prototype for dispatch table helper function
+void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
+ XrInstance instance,
+ PFN_xrGetInstanceProcAddr get_inst_proc_addr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/extern/openxr/src/xr_generated_utilities.c b/extern/openxr/src/xr_generated_utilities.c
new file mode 100644
index 00000000000..7bb5b5ba3c2
--- /dev/null
+++ b/extern/openxr/src/xr_generated_utilities.c
@@ -0,0 +1,488 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See utility_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#ifdef _WIN32
+// Disable Windows warning about using strncpy_s instead of strncpy
+#define _CRT_SECURE_NO_WARNINGS 1
+#endif // _WIN32
+
+#include "xr_generated_utilities.h"
+
+#include <openxr/openxr.h>
+
+#include <stdio.h>
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XrResult GeneratedXrUtilitiesResultToString(XrResult result,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]) {
+ if (NULL == buffer) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ XrResult int_result = XR_SUCCESS;
+ switch (result) {
+ case XR_SUCCESS:
+ strncpy(buffer, "XR_SUCCESS", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_TIMEOUT_EXPIRED:
+ strncpy(buffer, "XR_TIMEOUT_EXPIRED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_SESSION_LOSS_PENDING:
+ strncpy(buffer, "XR_SESSION_LOSS_PENDING", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_EVENT_UNAVAILABLE:
+ strncpy(buffer, "XR_EVENT_UNAVAILABLE", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_SPACE_BOUNDS_UNAVAILABLE:
+ strncpy(buffer, "XR_SPACE_BOUNDS_UNAVAILABLE", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_SESSION_NOT_FOCUSED:
+ strncpy(buffer, "XR_SESSION_NOT_FOCUSED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_FRAME_DISCARDED:
+ strncpy(buffer, "XR_FRAME_DISCARDED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_VALIDATION_FAILURE:
+ strncpy(buffer, "XR_ERROR_VALIDATION_FAILURE", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_RUNTIME_FAILURE:
+ strncpy(buffer, "XR_ERROR_RUNTIME_FAILURE", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_OUT_OF_MEMORY:
+ strncpy(buffer, "XR_ERROR_OUT_OF_MEMORY", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_API_VERSION_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_API_VERSION_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_INITIALIZATION_FAILED:
+ strncpy(buffer, "XR_ERROR_INITIALIZATION_FAILED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_FUNCTION_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_FUNCTION_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_FEATURE_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_FEATURE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_EXTENSION_NOT_PRESENT:
+ strncpy(buffer, "XR_ERROR_EXTENSION_NOT_PRESENT", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_LIMIT_REACHED:
+ strncpy(buffer, "XR_ERROR_LIMIT_REACHED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SIZE_INSUFFICIENT:
+ strncpy(buffer, "XR_ERROR_SIZE_INSUFFICIENT", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_HANDLE_INVALID:
+ strncpy(buffer, "XR_ERROR_HANDLE_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_INSTANCE_LOST:
+ strncpy(buffer, "XR_ERROR_INSTANCE_LOST", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SESSION_RUNNING:
+ strncpy(buffer, "XR_ERROR_SESSION_RUNNING", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SESSION_NOT_RUNNING:
+ strncpy(buffer, "XR_ERROR_SESSION_NOT_RUNNING", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SESSION_LOST:
+ strncpy(buffer, "XR_ERROR_SESSION_LOST", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SYSTEM_INVALID:
+ strncpy(buffer, "XR_ERROR_SYSTEM_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_PATH_INVALID:
+ strncpy(buffer, "XR_ERROR_PATH_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_PATH_COUNT_EXCEEDED:
+ strncpy(buffer, "XR_ERROR_PATH_COUNT_EXCEEDED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_PATH_FORMAT_INVALID:
+ strncpy(buffer, "XR_ERROR_PATH_FORMAT_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_PATH_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_PATH_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_LAYER_INVALID:
+ strncpy(buffer, "XR_ERROR_LAYER_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_LAYER_LIMIT_EXCEEDED:
+ strncpy(buffer, "XR_ERROR_LAYER_LIMIT_EXCEEDED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SWAPCHAIN_RECT_INVALID:
+ strncpy(buffer, "XR_ERROR_SWAPCHAIN_RECT_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_ACTION_TYPE_MISMATCH:
+ strncpy(buffer, "XR_ERROR_ACTION_TYPE_MISMATCH", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SESSION_NOT_READY:
+ strncpy(buffer, "XR_ERROR_SESSION_NOT_READY", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_SESSION_NOT_STOPPING:
+ strncpy(buffer, "XR_ERROR_SESSION_NOT_STOPPING", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_TIME_INVALID:
+ strncpy(buffer, "XR_ERROR_TIME_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_REFERENCE_SPACE_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_REFERENCE_SPACE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_FILE_ACCESS_ERROR:
+ strncpy(buffer, "XR_ERROR_FILE_ACCESS_ERROR", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_FILE_CONTENTS_INVALID:
+ strncpy(buffer, "XR_ERROR_FILE_CONTENTS_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_FORM_FACTOR_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_FORM_FACTOR_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_FORM_FACTOR_UNAVAILABLE:
+ strncpy(buffer, "XR_ERROR_FORM_FACTOR_UNAVAILABLE", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_API_LAYER_NOT_PRESENT:
+ strncpy(buffer, "XR_ERROR_API_LAYER_NOT_PRESENT", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_CALL_ORDER_INVALID:
+ strncpy(buffer, "XR_ERROR_CALL_ORDER_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_GRAPHICS_DEVICE_INVALID:
+ strncpy(buffer, "XR_ERROR_GRAPHICS_DEVICE_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_POSE_INVALID:
+ strncpy(buffer, "XR_ERROR_POSE_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_INDEX_OUT_OF_RANGE:
+ strncpy(buffer, "XR_ERROR_INDEX_OUT_OF_RANGE", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED:
+ strncpy(buffer, "XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_NAME_DUPLICATED:
+ strncpy(buffer, "XR_ERROR_NAME_DUPLICATED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_NAME_INVALID:
+ strncpy(buffer, "XR_ERROR_NAME_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_ACTIONSET_NOT_ATTACHED:
+ strncpy(buffer, "XR_ERROR_ACTIONSET_NOT_ATTACHED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_ACTIONSETS_ALREADY_ATTACHED:
+ strncpy(buffer, "XR_ERROR_ACTIONSETS_ALREADY_ATTACHED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_LOCALIZED_NAME_DUPLICATED:
+ strncpy(buffer, "XR_ERROR_LOCALIZED_NAME_DUPLICATED", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_LOCALIZED_NAME_INVALID:
+ strncpy(buffer, "XR_ERROR_LOCALIZED_NAME_INVALID", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR:
+ strncpy(buffer, "XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ case XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR:
+ strncpy(buffer, "XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR", XR_MAX_RESULT_STRING_SIZE);
+ break;
+ default:
+ // Unknown result type
+ if (XR_SUCCEEDED(result)) {
+ snprintf(buffer, XR_MAX_RESULT_STRING_SIZE, "XR_UNKNOWN_SUCCESS_%d", result);
+ } else {
+ snprintf(buffer, XR_MAX_RESULT_STRING_SIZE, "XR_UNKNOWN_FAILURE_%d", result);
+ }
+ int_result = XR_ERROR_VALIDATION_FAILURE;
+ break;
+ }
+ return int_result;
+}
+
+XrResult GeneratedXrUtilitiesStructureTypeToString(XrStructureType struct_type,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) {
+ if (NULL == buffer) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ XrResult int_result = XR_SUCCESS;
+ switch (struct_type) {
+ case XR_TYPE_UNKNOWN:
+ strncpy(buffer, "XR_TYPE_UNKNOWN", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_API_LAYER_PROPERTIES:
+ strncpy(buffer, "XR_TYPE_API_LAYER_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EXTENSION_PROPERTIES:
+ strncpy(buffer, "XR_TYPE_EXTENSION_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_INSTANCE_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_INSTANCE_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SYSTEM_GET_INFO:
+ strncpy(buffer, "XR_TYPE_SYSTEM_GET_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SYSTEM_PROPERTIES:
+ strncpy(buffer, "XR_TYPE_SYSTEM_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VIEW_LOCATE_INFO:
+ strncpy(buffer, "XR_TYPE_VIEW_LOCATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VIEW:
+ strncpy(buffer, "XR_TYPE_VIEW", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SESSION_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_SESSION_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SESSION_BEGIN_INFO:
+ strncpy(buffer, "XR_TYPE_SESSION_BEGIN_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VIEW_STATE:
+ strncpy(buffer, "XR_TYPE_VIEW_STATE", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_FRAME_END_INFO:
+ strncpy(buffer, "XR_TYPE_FRAME_END_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_HAPTIC_VIBRATION:
+ strncpy(buffer, "XR_TYPE_HAPTIC_VIBRATION", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_BUFFER:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_BUFFER", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_STATE_BOOLEAN:
+ strncpy(buffer, "XR_TYPE_ACTION_STATE_BOOLEAN", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_STATE_FLOAT:
+ strncpy(buffer, "XR_TYPE_ACTION_STATE_FLOAT", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_STATE_VECTOR2F:
+ strncpy(buffer, "XR_TYPE_ACTION_STATE_VECTOR2F", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_STATE_POSE:
+ strncpy(buffer, "XR_TYPE_ACTION_STATE_POSE", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_SET_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_ACTION_SET_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_ACTION_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_INSTANCE_PROPERTIES:
+ strncpy(buffer, "XR_TYPE_INSTANCE_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_FRAME_WAIT_INFO:
+ strncpy(buffer, "XR_TYPE_FRAME_WAIT_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_PROJECTION", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_QUAD:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_QUAD", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_REFERENCE_SPACE_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_REFERENCE_SPACE_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_SPACE_CREATE_INFO:
+ strncpy(buffer, "XR_TYPE_ACTION_SPACE_CREATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VIEW_CONFIGURATION_VIEW:
+ strncpy(buffer, "XR_TYPE_VIEW_CONFIGURATION_VIEW", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SPACE_LOCATION:
+ strncpy(buffer, "XR_TYPE_SPACE_LOCATION", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SPACE_VELOCITY:
+ strncpy(buffer, "XR_TYPE_SPACE_VELOCITY", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_FRAME_STATE:
+ strncpy(buffer, "XR_TYPE_FRAME_STATE", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VIEW_CONFIGURATION_PROPERTIES:
+ strncpy(buffer, "XR_TYPE_VIEW_CONFIGURATION_PROPERTIES", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_FRAME_BEGIN_INFO:
+ strncpy(buffer, "XR_TYPE_FRAME_BEGIN_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_EVENTS_LOST:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_EVENTS_LOST", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING:
+ strncpy(buffer, "XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_INTERACTION_PROFILE_STATE:
+ strncpy(buffer, "XR_TYPE_INTERACTION_PROFILE_STATE", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTION_STATE_GET_INFO:
+ strncpy(buffer, "XR_TYPE_ACTION_STATE_GET_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_HAPTIC_ACTION_INFO:
+ strncpy(buffer, "XR_TYPE_HAPTIC_ACTION_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO:
+ strncpy(buffer, "XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_ACTIONS_SYNC_INFO:
+ strncpy(buffer, "XR_TYPE_ACTIONS_SYNC_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO:
+ strncpy(buffer, "XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO:
+ strncpy(buffer, "XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_CUBE_KHR:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_CUBE_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR:
+ strncpy(buffer, "XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR:
+ strncpy(buffer, "XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR:
+ strncpy(buffer, "XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT:
+ strncpy(buffer, "XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT:
+ strncpy(buffer, "XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:
+ strncpy(buffer, "XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_DEBUG_UTILS_LABEL_EXT:
+ strncpy(buffer, "XR_TYPE_DEBUG_UTILS_LABEL_EXT", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_D3D11_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_D3D11_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_BINDING_D3D12_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_BINDING_D3D12_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR:
+ strncpy(buffer, "XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR:
+ strncpy(buffer, "XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_VISIBILITY_MASK_KHR:
+ strncpy(buffer, "XR_TYPE_VISIBILITY_MASK_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR:
+ strncpy(buffer, "XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR", XR_MAX_STRUCTURE_NAME_SIZE);
+ break;
+ default:
+ // Unknown structure type
+ snprintf(buffer, XR_MAX_STRUCTURE_NAME_SIZE, "XR_UNKNOWN_STRUCTURE_TYPE_%d", struct_type);
+ int_result = XR_ERROR_VALIDATION_FAILURE;
+ break;
+ }
+ return int_result;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/extern/openxr/src/xr_generated_utilities.h b/extern/openxr/src/xr_generated_utilities.h
new file mode 100644
index 00000000000..11ae94f0f73
--- /dev/null
+++ b/extern/openxr/src/xr_generated_utilities.h
@@ -0,0 +1,43 @@
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See utility_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <openxr/openxr.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XrResult GeneratedXrUtilitiesResultToString(XrResult result,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]);
+XrResult GeneratedXrUtilitiesStructureTypeToString(XrStructureType struct_type,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// Current API version of the utililties
+#define XR_UTILITIES_API_VERSION XR_CURRENT_API_VERSION
+
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index b096fecced8..93a8871c32f 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -270,11 +270,13 @@ elseif(WIN32)
)
list(APPEND SRC
+ intern/GHOST_ContextD3D.cpp
intern/GHOST_DisplayManagerWin32.cpp
intern/GHOST_DropTargetWin32.cpp
intern/GHOST_SystemWin32.cpp
intern/GHOST_WindowWin32.cpp
+ intern/GHOST_ContextD3D.h
intern/GHOST_DisplayManagerWin32.h
intern/GHOST_DropTargetWin32.h
intern/GHOST_SystemWin32.h
@@ -345,6 +347,43 @@ elseif(WIN32)
endif()
+if(WITH_OPENXR)
+ list(APPEND SRC
+ intern/GHOST_Xr.cpp
+ intern/GHOST_XrContext.cpp
+ intern/GHOST_XrEvent.cpp
+ intern/GHOST_XrGraphicsBinding.cpp
+ intern/GHOST_XrSession.cpp
+
+ GHOST_IXrContext.h
+ intern/GHOST_Xr_intern.h
+ intern/GHOST_Xr_openxr_includes.h
+ intern/GHOST_XrContext.h
+ intern/GHOST_IXrGraphicsBinding.h
+ intern/GHOST_XrSession.h
+ )
+ list(APPEND INC
+ )
+ list(APPEND INC_SYS
+ ${OPENXR_SDK_INCLUDES}
+ )
+
+ include(xr_platform_defines)
+
+ if(OPENXR_USE_BUNDLED_SRC)
+ if(WIN32)
+ set(OPENXR_LOADER_NAME openxr_loader-1_0)
+ else()
+ set(OPENXR_LOADER_NAME openxr_loader)
+ endif()
+
+ list(APPEND LIB ${OPENXR_LOADER_NAME})
+ list(APPEND INC ../../extern/openxr/include)
+ endif()
+
+ add_definitions(-DWITH_OPENXR)
+endif()
+
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 0f735711b24..557503783e5 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -31,21 +31,6 @@ extern "C" {
#endif
/**
- * Creates a "handle" for a C++ GHOST object.
- * A handle is just an opaque pointer to an empty struct.
- * In the API the pointer is cast to the actual C++ class.
- * The 'name' argument to the macro is the name of the handle to create.
- */
-
-GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
-GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
-GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
-GHOST_DECLARE_HANDLE(GHOST_EventHandle);
-GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
-GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
-GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
-
-/**
* Definition of a callback routine that receives events.
* \param event The event received.
* \param userdata The callback's user data, supplied to GHOST_CreateSystem.
@@ -193,6 +178,36 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
GHOST_ContextHandle contexthandle);
+#ifdef WIN32
+/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \param systemhandle The handle to the system
+ * \return A handle to the new context ( == NULL if creation failed).
+ */
+GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle);
+
+/**
+ * Dispose of a context.
+ * \param systemhandle The handle to the system
+ * \param contexthandle Handle to the context to be disposed.
+ * \return Indication of success.
+ */
+GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle,
+ GHOST_ContextHandle contexthandle);
+#endif
+
+GHOST_TSuccess GHOST_BlitOpenGLOffscreenContext(GHOST_WindowHandle windowhandle,
+ GHOST_ContextHandle offscreen_contexthandle);
+
+extern GHOST_TSuccess GHOST_ContextBlitOpenGLOffscreenContext(
+ GHOST_ContextHandle onscreen_contexthandle,
+ GHOST_ContextHandle offscreen_contexthandle,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height);
+
+extern GHOST_ContextHandle GHOST_GetWindowContext(GHOST_WindowHandle windowhandle);
+
/**
* Returns the window user data.
* \param windowhandle The handle to the window
@@ -208,6 +223,11 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl
extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata);
/**
+ * Returns whether a window is rendered upside down compared to OpenGL.
+ */
+extern int GHOST_isUpsideDownWindow(GHOST_WindowHandle windowhandle);
+
+/**
* Dispose a window.
* \param systemhandle The handle to the system
* \param windowhandle Handle to the window to be disposed.
@@ -663,6 +683,13 @@ extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
/**
+ * Swaps front and back buffers of a context.
+ * \param contexthandle The handle to the context
+ * \return A success indicator.
+ */
+extern GHOST_TSuccess GHOST_SwapContextBuffers(GHOST_ContextHandle contexthandle);
+
+/**
* Sets the swap interval for swapBuffers.
* \param interval The swap interval to use.
* \return A boolean success indicator.
@@ -709,6 +736,16 @@ extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthand
/**
* Get the OpenGL framebuffer handle that serves as a default framebuffer.
*/
+extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
+
+/**
+ * Returns whether a context is rendered upside down compared to OpenGL.
+ */
+extern int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle);
+
+/**
+ * Get the OpenGL framebuffer handle that serves as a default framebuffer.
+ */
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windwHandle);
/**
@@ -941,6 +978,37 @@ extern void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
*/
extern void GHOST_EndIME(GHOST_WindowHandle windowhandle);
+#ifdef WITH_OPENXR
+
+/* xr-context */
+
+/**
+ * Set a custom callback to be executed whenever an error occurs. Should be set before calling
+ * #GHOST_XrContextCreate().
+ */
+void GHOST_XrErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
+
+GHOST_XrContextHandle GHOST_XrContextCreate(const GHOST_XrContextCreateInfo *create_info);
+void GHOST_XrContextDestroy(GHOST_XrContextHandle xr_context);
+
+void GHOST_XrGraphicsContextBindFuncs(GHOST_XrContextHandle xr_context,
+ GHOST_XrGraphicsContextBindFn bind_fn,
+ GHOST_XrGraphicsContextUnbindFn unbind_fn);
+
+void GHOST_XrDrawViewFunc(GHOST_XrContextHandle xr_context, GHOST_XrDrawViewFn draw_view_fn);
+
+/* sessions */
+void GHOST_XrSessionStart(GHOST_XrContextHandle xr_context,
+ const GHOST_XrSessionBeginInfo *begin_info);
+void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_context);
+int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle);
+int GHOST_XrSessionShouldRunDrawLoop(const GHOST_XrContextHandle xr_context);
+void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_context, void *customdata);
+
+/* events */
+GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h
index a341e18ca0a..3bad8db115f 100644
--- a/intern/ghost/GHOST_IContext.h
+++ b/intern/ghost/GHOST_IContext.h
@@ -56,6 +56,16 @@ class GHOST_IContext {
*/
virtual GHOST_TSuccess releaseDrawingContext() = 0;
+ virtual GHOST_TSuccess blitOpenGLOffscreenContext(class GHOST_Context *offscreen,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height) = 0;
+
+ virtual unsigned int getDefaultFramebuffer() = 0;
+
+ virtual GHOST_TSuccess swapBuffers() = 0;
+
+ virtual bool isUpsideDown() const = 0;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
#endif
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index f0ceb7fb8ba..124d78a75d8 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -265,6 +265,12 @@ class GHOST_ISystem {
virtual GHOST_IContext *createOffscreenContext() = 0;
/**
+ * Overload to allow requesting a different context type. By default only OpenGL is supported.
+ * However by explicitly overloading this a system may add support for others.
+ */
+ virtual GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type) = 0;
+
+ /**
* Dispose of a context.
* \param context Pointer to the context to be disposed.
* \return Indication of success.
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 1a1844bfe41..212e7ff8d13 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -77,6 +77,10 @@ class GHOST_IWindow {
*/
virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0;
+ virtual class GHOST_IContext *getDrawingContext() = 0;
+
+ virtual GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_IContext *offscreen) = 0;
+
/**
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
@@ -242,6 +246,11 @@ class GHOST_IWindow {
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
/**
+ * Returns if the window is rendered upside down compared to OpenGL.
+ */
+ virtual bool isUpsideDown() const = 0;
+
+ /**
* Returns the tablet data (pressure etc).
* \return The tablet data (pressure etc).
*/
diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h
new file mode 100644
index 00000000000..968c98ad42e
--- /dev/null
+++ b/intern/ghost/GHOST_IXrContext.h
@@ -0,0 +1,43 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_IXRCONTEXT_H__
+#define __GHOST_IXRCONTEXT_H__
+
+#include "GHOST_Types.h"
+
+class GHOST_IXrContext {
+ public:
+ virtual ~GHOST_IXrContext() = default;
+
+ virtual void startSession(const GHOST_XrSessionBeginInfo *begin_info) = 0;
+ virtual void endSession() = 0;
+ virtual bool hasSession() const = 0;
+ virtual bool shouldRunSessionDrawLoop() const = 0;
+ virtual void drawSessionViews(void *draw_customdata) = 0;
+
+ virtual void dispatchErrorMessage(const class GHOST_XrException *) const = 0;
+
+ virtual void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
+ GHOST_XrGraphicsContextUnbindFn unbind_fn) = 0;
+ virtual void setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn) = 0;
+};
+
+#endif // __GHOST_IXRCONTEXT_H__
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 68516c3ecf8..b7ccb59a3a5 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -41,6 +41,22 @@
} * name
#endif
+/**
+ * Creates a "handle" for a C++ GHOST object.
+ * A handle is just an opaque pointer to an empty struct.
+ * In the API the pointer is cast to the actual C++ class.
+ * The 'name' argument to the macro is the name of the handle to create.
+ */
+
+GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
+GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
+GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
+GHOST_DECLARE_HANDLE(GHOST_EventHandle);
+GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
+GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
+GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
+GHOST_DECLARE_HANDLE(GHOST_XrContextHandle);
+
typedef char GHOST_TInt8;
typedef unsigned char GHOST_TUns8;
typedef short GHOST_TInt16;
@@ -129,7 +145,10 @@ typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWind
typedef enum {
GHOST_kDrawingContextTypeNone = 0,
- GHOST_kDrawingContextTypeOpenGL
+ GHOST_kDrawingContextTypeOpenGL,
+#ifdef WIN32
+ GHOST_kDrawingContextTypeD3D,
+#endif
} GHOST_TDrawingContextType;
typedef enum {
@@ -542,4 +561,81 @@ struct GHOST_TimerTaskHandle__;
typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_TUns64 time);
#endif
+#ifdef WITH_OPENXR
+
+/**
+ * The XR view (i.e. the OpenXR runtime) may require a different graphics library than OpenGL. An
+ * offscreen texture of the viewport will then be drawn into using OpenGL, but the final texture
+ * draw call will happen through another lib (say DirectX).
+ *
+ * This enum defines the possible graphics bindings to attempt to enable.
+ */
+typedef enum {
+ GHOST_kXrGraphicsUnknown = 0,
+ GHOST_kXrGraphicsOpenGL,
+# ifdef WIN32
+ GHOST_kXrGraphicsD3D11,
+# endif
+ /* For later */
+ // GHOST_kXrGraphicsVulkan,
+} GHOST_TXrGraphicsBinding;
+/* An array of GHOST_TXrGraphicsBinding items defining the candidate bindings to use. The first
+ * available candidate will be chosen, so order defines priority. */
+typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
+
+typedef struct {
+ float position[3];
+ /* Blender convention (w, x, y, z) */
+ float orientation_quat[4];
+} GHOST_XrPose;
+
+enum {
+ GHOST_kXrContextDebug = (1 << 0),
+ GHOST_kXrContextDebugTime = (1 << 1),
+};
+
+typedef struct {
+ const GHOST_XrGraphicsBindingCandidates gpu_binding_candidates;
+ unsigned int gpu_binding_candidates_count;
+
+ unsigned int context_flag;
+} GHOST_XrContextCreateInfo;
+
+typedef struct {
+ GHOST_XrPose base_pose;
+} GHOST_XrSessionBeginInfo;
+
+typedef struct {
+ int ofsx, ofsy;
+ int width, height;
+
+ GHOST_XrPose pose;
+
+ struct {
+ float angle_left, angle_right;
+ float angle_up, angle_down;
+ } fov;
+} GHOST_XrDrawViewInfo;
+
+typedef struct {
+ const char *user_message;
+
+ /** File path and line number the error was found at. */
+ const char *source_location;
+
+ void *customdata;
+} GHOST_XrError;
+
+typedef void (*GHOST_XrErrorHandlerFn)(const GHOST_XrError *);
+
+typedef void *(*GHOST_XrGraphicsContextBindFn)(GHOST_TXrGraphicsBinding graphics_lib);
+typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_TXrGraphicsBinding graphics_lib,
+ void *graphics_context);
+/* XXX hacky: returns GHOST_ContextHandle so DirectX binding can get a handle to the OpenGL
+ * offscreen context. */
+typedef GHOST_ContextHandle (*GHOST_XrDrawViewFn)(const GHOST_XrDrawViewInfo *draw_view,
+ void *customdata);
+
+#endif
+
#endif // __GHOST_TYPES_H__
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 78f171af7d1..98579985693 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -30,7 +30,9 @@
#include "GHOST_ISystem.h"
#include "GHOST_IEvent.h"
#include "GHOST_IEventConsumer.h"
+#include "GHOST_IXrContext.h"
#include "intern/GHOST_CallbackEventConsumer.h"
+#include "intern/GHOST_XrException.h"
GHOST_SystemHandle GHOST_CreateSystem(void)
{
@@ -127,6 +129,51 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
return system->disposeContext(context);
}
+#ifdef WIN32
+GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+
+ return (GHOST_ContextHandle)system->createOffscreenContext(GHOST_kDrawingContextTypeD3D);
+}
+
+GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle,
+ GHOST_ContextHandle contexthandle)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+ GHOST_IContext *context = (GHOST_IContext *)contexthandle;
+
+ return system->disposeContext(context);
+}
+
+#endif
+
+GHOST_TSuccess GHOST_BlitOpenGLOffscreenContext(GHOST_WindowHandle windowhandle,
+ GHOST_ContextHandle offscreen_contexthandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+
+ return window->blitOpenGLOffscreenContext((GHOST_IContext *)offscreen_contexthandle);
+}
+
+GHOST_TSuccess GHOST_ContextBlitOpenGLOffscreenContext(GHOST_ContextHandle onscreen_contexthandle,
+ GHOST_ContextHandle offscreen_contexthandle,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height)
+{
+ GHOST_IContext *context = (GHOST_IContext *)onscreen_contexthandle;
+
+ return context->blitOpenGLOffscreenContext(
+ (class GHOST_Context *)offscreen_contexthandle, width, height);
+}
+
+GHOST_ContextHandle GHOST_GetWindowContext(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+
+ return (GHOST_ContextHandle)window->getDrawingContext();
+}
+
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
const char *title,
GHOST_TInt32 left,
@@ -156,6 +203,13 @@ void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr
window->setUserData(userdata);
}
+int GHOST_isUpsideDownWindow(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+
+ return window->isUpsideDown();
+}
+
GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle windowhandle)
{
@@ -586,6 +640,13 @@ GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle)
return window->swapBuffers();
}
+GHOST_TSuccess GHOST_SwapContextBuffers(GHOST_ContextHandle contexthandle)
+{
+ GHOST_IContext *context = (GHOST_IContext *)contexthandle;
+
+ return context->swapBuffers();
+}
+
GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interval)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -621,6 +682,20 @@ GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
return context->releaseDrawingContext();
}
+unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
+{
+ GHOST_IContext *context = (GHOST_IContext *)contexthandle;
+
+ return context->getDefaultFramebuffer();
+}
+
+int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle)
+{
+ GHOST_IContext *context = (GHOST_IContext *)contexthandle;
+
+ return context->isUpsideDown();
+}
+
unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
@@ -830,3 +905,70 @@ void GHOST_EndIME(GHOST_WindowHandle windowhandle)
}
#endif /* WITH_INPUT_IME */
+
+#ifdef WITH_OPENXR
+
+# define GHOST_XR_CAPI_CALL(call, ctx) \
+ try { \
+ call; \
+ } \
+ catch (GHOST_XrException & e) { \
+ (ctx)->dispatchErrorMessage(&e); \
+ }
+
+# define GHOST_XR_CAPI_CALL_RET(call, ctx) \
+ try { \
+ return call; \
+ } \
+ catch (GHOST_XrException & e) { \
+ (ctx)->dispatchErrorMessage(&e); \
+ }
+
+void GHOST_XrSessionStart(GHOST_XrContextHandle xr_contexthandle,
+ const GHOST_XrSessionBeginInfo *begin_info)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL(xr_context->startSession(begin_info), xr_context);
+}
+
+void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_contexthandle)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL(xr_context->endSession(), xr_context);
+}
+
+int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle)
+{
+ const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL_RET(xr_context->hasSession(), xr_context);
+ return 0; // Only reached if exception is thrown.
+}
+
+int GHOST_XrSessionShouldRunDrawLoop(const GHOST_XrContextHandle xr_contexthandle)
+{
+ const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL_RET(xr_context->shouldRunSessionDrawLoop(), xr_context);
+ return 0; // Only reached if exception is thrown.
+}
+
+void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_contexthandle, void *draw_customdata)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL(xr_context->drawSessionViews(draw_customdata), xr_context);
+}
+
+void GHOST_XrGraphicsContextBindFuncs(GHOST_XrContextHandle xr_contexthandle,
+ GHOST_XrGraphicsContextBindFn bind_fn,
+ GHOST_XrGraphicsContextUnbindFn unbind_fn)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL(xr_context->setGraphicsContextBindFuncs(bind_fn, unbind_fn), xr_context);
+}
+
+void GHOST_XrDrawViewFunc(GHOST_XrContextHandle xr_contexthandle, GHOST_XrDrawViewFn draw_view_fn)
+{
+ GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+ GHOST_XR_CAPI_CALL(xr_context->setDrawViewFunc(draw_view_fn), xr_context);
+}
+
+#endif
diff --git a/intern/ghost/intern/GHOST_Context.cpp b/intern/ghost/intern/GHOST_Context.cpp
index 0d167209909..4df47006a56 100644
--- a/intern/ghost/intern/GHOST_Context.cpp
+++ b/intern/ghost/intern/GHOST_Context.cpp
@@ -149,3 +149,68 @@ void GHOST_Context::initClearGL()
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.000, 0.000, 0.000, 0.000);
}
+
+GHOST_TSuccess GHOST_Context::blitOpenGLOffscreenContext(GHOST_Context *offscreen,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height)
+{
+ GLuint fbo_offscreen;
+ GLuint fbo_onscreen;
+ GLuint render_buf_shared;
+ GLint fbo_prev_draw;
+
+ if ((m_type != GHOST_kDrawingContextTypeOpenGL) ||
+ (offscreen->m_type != GHOST_kDrawingContextTypeOpenGL)) {
+ return GHOST_kFailure;
+ }
+
+ offscreen->setDefaultFramebufferSize(width, height);
+
+ /* Logic here:
+ * We can't simply blit from one context's framebuffer into the other. Unlike Framebuffers/FBOs,
+ * Renderbuffers can be shared though. So create one, and blit the offscreen context framebuffer
+ * contents into it. To share it, an FBO has to be created for each context though, as the
+ * default framebuffer doesn't allow any attachments. */
+
+ offscreen->activateDrawingContext();
+
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo_prev_draw);
+
+ /* Create shared renderbuffer */
+ glGenRenderbuffers(1, &render_buf_shared);
+ glBindRenderbuffer(GL_RENDERBUFFER, render_buf_shared);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
+
+ /* Create offscreen FBO and assign renderbuffer */
+ glGenFramebuffers(1, &fbo_offscreen);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_offscreen);
+ glFramebufferRenderbuffer(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf_shared);
+
+ /* Blit offscreen framebuffer into renderbuffer */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_prev_draw);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_offscreen);
+ glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ glDeleteFramebuffers(1, &fbo_offscreen); /* Can delete already. Do before context change. */
+
+ activateDrawingContext();
+
+ /* Create onscreen FBO and assign renderbuffer */
+ glGenFramebuffers(1, &fbo_onscreen);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_onscreen);
+ glFramebufferRenderbuffer(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf_shared);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_onscreen);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getDefaultFramebuffer());
+ /* Finally, blit to onscreen buffer. */
+ glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ glDeleteFramebuffers(1, &fbo_onscreen);
+ glDeleteRenderbuffers(1, &render_buf_shared);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index bbf6d6a510d..0bc2aa21119 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -38,7 +38,8 @@ class GHOST_Context : public GHOST_IContext {
* Constructor.
* \param stereoVisual Stereo visual for quad buffered stereo.
*/
- GHOST_Context(bool stereoVisual) : m_stereoVisual(stereoVisual)
+ GHOST_Context(GHOST_TDrawingContextType type, bool stereoVisual)
+ : m_type(type), m_stereoVisual(stereoVisual)
{
}
@@ -119,6 +120,11 @@ class GHOST_Context : public GHOST_IContext {
return m_stereoVisual;
}
+ inline bool isUpsideDown() const
+ {
+ return false;
+ }
+
/**
* Gets the OpenGL framebuffer associated with the OpenGL context
* \return The ID of an OpenGL framebuffer object.
@@ -128,9 +134,26 @@ class GHOST_Context : public GHOST_IContext {
return 0;
}
+ /**
+ * For offscreen rendering, we create an invisible window. So this can be used to update the
+ * offscreen buffer size by changing the size of this context's window.
+ *
+ * \note This actually changes the window size! That is the only way to change the default
+ * framebuffer size. Better only use for offscreen contexts.
+ */
+ virtual GHOST_TSuccess setDefaultFramebufferSize(GHOST_TUns32 /*width*/, GHOST_TUns32 /*height*/)
+ {
+ return GHOST_kFailure;
+ }
+
+ GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_Context *offscreen,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height);
+
protected:
void initContextGLEW();
+ GHOST_TDrawingContextType m_type;
bool m_stereoVisual;
static void initClearGL();
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index 12c340ffe97..5448c85e1f5 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -55,7 +55,7 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
NSView *metalView,
CAMetalLayer *metalLayer,
NSOpenGLView *openGLView)
- : GHOST_Context(stereoVisual),
+ : GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
m_metalView(metalView),
m_metalLayer(metalLayer),
m_metalCmdQueue(nil),
diff --git a/intern/ghost/intern/GHOST_ContextD3D.cpp b/intern/ghost/intern/GHOST_ContextD3D.cpp
new file mode 100644
index 00000000000..8e357a80702
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextD3D.cpp
@@ -0,0 +1,500 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include <iostream>
+#include <string>
+
+#include <GL/glew.h>
+#include <GL/wglew.h>
+
+#include "GHOST_ContextWGL.h" /* For shared drawing */
+#include "GHOST_ContextD3D.h"
+
+// #define USE_DRAW_D3D_TEST_TRIANGLE
+
+HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
+PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN GHOST_ContextD3D::s_D3D11CreateDeviceAndSwapChainFn = NULL;
+
+#ifdef USE_DRAW_D3D_TEST_TRIANGLE
+static void drawTestTriangle(ID3D11Device *m_device,
+ ID3D11DeviceContext *m_device_ctx,
+ HWND hwnd,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height);
+#endif
+
+class SharedOpenGLContext {
+ ID3D11Device *m_d3d_device;
+ GHOST_ContextWGL *m_wgl_ctx;
+ /* NV_DX_interop2 requires ID3D11Texture2D as backbuffer when sharing with GL_RENDERBUFFER */
+ ID3D11Texture2D *m_d3d_render_target;
+ GLuint m_gl_render_buf;
+
+ public:
+ struct SharedData {
+ HANDLE device;
+ GLuint fbo;
+ HANDLE render_buf{nullptr};
+ } m_shared;
+
+ /* XXX Should have a map of render_target items to shared resource data (SharedData) to
+ * allow multiple shared surfaces in a context. Current code assumes a single one. That would be
+ * an issue if we wanted to use the OpenXR provided textures (changes for each eye and each
+ * redraw) and not the constant D3D swapchain texture like now. */
+ SharedOpenGLContext(ID3D11Device *d3d_device,
+ GHOST_ContextWGL *wgl_ctx,
+ ID3D11Texture2D *render_target)
+ : m_d3d_device(d3d_device), m_wgl_ctx(wgl_ctx), m_d3d_render_target(render_target)
+ {
+ }
+ ~SharedOpenGLContext()
+ {
+ if (m_shared.render_buf) {
+ wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
+ }
+ if (m_shared.device) {
+ wglDXCloseDeviceNV(m_shared.device);
+ }
+ glDeleteFramebuffers(1, &m_shared.fbo);
+ glDeleteRenderbuffers(1, &m_gl_render_buf);
+ }
+
+ void reregisterSharedObject()
+ {
+ if (m_shared.render_buf) {
+ wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
+ m_shared.render_buf = nullptr;
+ }
+
+ m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device,
+ m_d3d_render_target,
+ m_gl_render_buf,
+ GL_RENDERBUFFER,
+ WGL_ACCESS_READ_WRITE_NV);
+ if (!m_shared.render_buf) {
+ fprintf(stderr, "Error registering shared object using wglDXRegisterObjectNV()\n");
+ return;
+ }
+ }
+
+ GHOST_TSuccess initialize()
+ {
+ m_wgl_ctx->activateDrawingContext();
+
+ m_shared.device = wglDXOpenDeviceNV(m_d3d_device);
+ if (m_shared.device == NULL) {
+ fprintf(stderr, "Error opening shared device using wglDXOpenDeviceNV()\n");
+ return GHOST_kFailure;
+ }
+
+ /* Build the renderbuffer. */
+ glGenRenderbuffers(1, &m_gl_render_buf);
+ glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_buf);
+
+ reregisterSharedObject();
+
+ /* Build the framebuffer */
+ glGenFramebuffers(1, &m_shared.fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, m_shared.fbo);
+ glFramebufferRenderbuffer(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_buf);
+
+ return GHOST_kSuccess;
+ }
+ void update(int width, int height)
+ {
+ m_wgl_ctx->setDefaultFramebufferSize(width, height);
+ m_wgl_ctx->activateDrawingContext();
+ /* TODO avoid re-registering if resource to share has not changed. */
+ reregisterSharedObject();
+ }
+
+ void beginGLOnly()
+ {
+ wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
+ }
+ void endGLOnly()
+ {
+ wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
+ }
+};
+
+GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
+ : GHOST_Context(GHOST_kDrawingContextTypeD3D, stereoVisual), m_hWnd(hWnd)
+{
+}
+
+GHOST_ContextD3D::~GHOST_ContextD3D()
+{
+ delete glshared;
+ m_swapchain->Release();
+ m_backbuffer_view->Release();
+ m_device->Release();
+ m_device_ctx->ClearState();
+ m_device_ctx->Release();
+}
+
+GHOST_TSuccess GHOST_ContextD3D::swapBuffers()
+{
+ HRESULT res = m_swapchain->Present(0, 0);
+ return (res == S_OK) ? GHOST_kSuccess : GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::activateDrawingContext()
+{
+ return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::releaseDrawingContext()
+{
+ return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::setDefaultFramebufferSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ RECT rect = {0, 0, (long)width, (long)height};
+ RECT winrect;
+
+ /* To use swapchain buffers/textures with custom size, the hidden window has to be resized. */
+
+ GetWindowRect(m_hWnd, &winrect);
+
+ WIN32_CHK(AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, 0));
+
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+
+ if (((winrect.right - winrect.left) != width) || ((winrect.bottom - winrect.top) != height)) {
+ return SetWindowPos(m_hWnd,
+ HWND_TOP,
+ 0,
+ 0,
+ width,
+ height,
+ SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOZORDER) ?
+ GHOST_kSuccess :
+ GHOST_kFailure;
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::updateSwapchain(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ HRESULT hres;
+ DXGI_SWAP_CHAIN_DESC swapchain_desc;
+
+ m_swapchain->GetDesc(&swapchain_desc);
+
+ if ((swapchain_desc.BufferDesc.Width == width) && (swapchain_desc.BufferDesc.Height == height)) {
+ // Nothing to do.
+ return GHOST_kSuccess;
+ }
+
+#define CHECK_HRES \
+ if (hres != S_OK) { \
+ printf("Error updating swapchain (error code %x): %s line %i\n", hres, __FILE__, __LINE__); \
+ } \
+ (void)0
+
+ setDefaultFramebufferSize(width, height);
+
+ m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
+
+ m_backbuffer_view->Release();
+ m_device_ctx->ClearState();
+
+ hres = m_swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
+ CHECK_HRES;
+
+ ID3D11Texture2D *buf;
+ hres = m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&buf);
+ CHECK_HRES;
+
+ hres = m_device->CreateRenderTargetView(buf, NULL, &m_backbuffer_view);
+ CHECK_HRES;
+ buf->Release();
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::setupD3DLib()
+{
+ if (s_d3d_lib == NULL) {
+ s_d3d_lib = LoadLibraryA("d3d11.dll");
+
+ WIN32_CHK(s_d3d_lib != NULL);
+
+ if (s_d3d_lib == NULL) {
+ fprintf(stderr, "LoadLibrary(\"d3d11.dll\") failed!\n");
+ return GHOST_kFailure;
+ }
+ }
+
+ if (s_D3D11CreateDeviceAndSwapChainFn == NULL) {
+ s_D3D11CreateDeviceAndSwapChainFn = (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(
+ s_d3d_lib, "D3D11CreateDeviceAndSwapChain");
+
+ WIN32_CHK(s_D3D11CreateDeviceAndSwapChainFn != NULL);
+
+ if (s_D3D11CreateDeviceAndSwapChainFn == NULL) {
+ fprintf(stderr, "GetProcAddress(s_d3d_lib, \"D3D11CreateDeviceAndSwapChain\") failed!\n");
+ return GHOST_kFailure;
+ }
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::initializeDrawingContext()
+{
+ if (setupD3DLib() == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
+
+ DXGI_SWAP_CHAIN_DESC sd{};
+
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.SampleDesc.Count = 1;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.BufferCount = 3;
+ sd.OutputWindow = m_hWnd;
+ sd.Windowed = TRUE;
+ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ HRESULT hres = s_D3D11CreateDeviceAndSwapChainFn(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ // D3D11_CREATE_DEVICE_DEBUG,
+ 0,
+ NULL,
+ 0,
+ D3D11_SDK_VERSION,
+ &sd,
+ &m_swapchain,
+ &m_device,
+ NULL,
+ &m_device_ctx);
+ WIN32_CHK(hres == S_OK);
+
+ ID3D11Texture2D *back_buffer;
+ m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&back_buffer);
+
+ m_device->CreateRenderTargetView(back_buffer, nullptr, &m_backbuffer_view);
+ back_buffer->Release();
+
+ m_swapchain->Present(0, 0);
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::releaseNativeHandles()
+{
+ return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
+ ID3D11RenderTargetView *render_target,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height)
+{
+ if (!(WGL_NV_DX_interop && WGL_NV_DX_interop2)) {
+ fprintf(stderr,
+ "Error: Can't render OpenGL framebuffer using Direct3D. NV_DX_interop extension not "
+ "available.");
+ return GHOST_kFailure;
+ }
+ m_device_ctx->OMSetRenderTargets(1, &render_target, nullptr);
+
+ offscreen_ctx->activateDrawingContext();
+
+ GLint fbo;
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo);
+
+ if (glshared == NULL) {
+ ID3D11Resource *backbuffer_res;
+ ID3D11Texture2D *backbuffer_tex;
+ render_target->GetResource(&backbuffer_res);
+ backbuffer_res->QueryInterface<ID3D11Texture2D>(&backbuffer_tex);
+
+ glshared = new SharedOpenGLContext(
+ m_device, (GHOST_ContextWGL *)offscreen_ctx, backbuffer_tex);
+ backbuffer_res->Release();
+ backbuffer_tex->Release();
+
+ if (glshared->initialize() == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
+ }
+ SharedOpenGLContext::SharedData *shared = &glshared->m_shared;
+
+ glshared->update(width, height);
+
+ const float clear_col[] = {0.8f, 0.5f, 1.0f, 1.0f};
+ m_device_ctx->ClearRenderTargetView(render_target, clear_col);
+
+ glshared->beginGLOnly();
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shared->fbo);
+ GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (err != GL_FRAMEBUFFER_COMPLETE) {
+ fprintf(stderr, "Error: Framebuffer incomplete %u\n", err);
+ return GHOST_kFailure;
+ }
+
+ /* Not needed, usefull for debugging. */
+ initClearGL();
+
+ /* No glBlitNamedFramebuffer, gotta be 3.3 compatible. */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shared->fbo);
+ glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ glshared->endGLOnly();
+
+#ifdef USE_DRAW_D3D_TEST_TRIANGLE
+ drawTestTriangle(m_device.Get(), m_device_ctx.Get(), m_hWnd, width, height);
+#endif
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height)
+{
+ updateSwapchain(width, height);
+ return blitOpenGLOffscreenContext(offscreen_ctx, m_backbuffer_view, width, height);
+}
+
+#ifdef USE_DRAW_D3D_TEST_TRIANGLE
+# pragma comment(lib, "D3DCompiler.lib")
+
+const static std::string vertex_shader_str{
+ "struct VSOut {"
+ "float3 color : Color;"
+ "float4 pos : SV_POSITION;"
+ "};"
+
+ "VSOut main(float2 pos : Position, float3 color : Color)"
+ "{"
+ " VSOut vso;"
+ " vso.pos = float4(pos.x, pos.y, 0.0f, 1.0f);"
+ " vso.color = color;"
+ " return vso;"
+ "}"};
+const static std::string pixel_shader_str{
+ " float4 main(float3 color : Color) : SV_TARGET"
+ "{"
+ " return float4(color, 1.0f);"
+ "}"};
+
+# include <d3dcompiler.h>
+
+static void drawTestTriangle(ID3D11Device *m_device,
+ ID3D11DeviceContext *m_device_ctx,
+ HWND hwnd,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height)
+{
+ struct Vertex {
+ float x, y;
+ unsigned char r, g, b, a;
+ };
+ Vertex vertices[] = {
+ {0.0f, 0.5f, 255, 0, 0},
+ {0.5f, -0.5f, 0, 255, 0},
+ {-0.5f, -0.5f, 0, 0, 255},
+
+ };
+ const unsigned int stride = sizeof(Vertex);
+ const unsigned int offset = 0;
+ ID3D11Buffer *vertex_buffer;
+
+ D3D11_BUFFER_DESC buffer_desc{};
+ buffer_desc.Usage = D3D11_USAGE_DEFAULT;
+ buffer_desc.ByteWidth = sizeof(vertices);
+ buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+
+ D3D11_SUBRESOURCE_DATA init_data{};
+ init_data.pSysMem = vertices;
+
+ m_device->CreateBuffer(&buffer_desc, &init_data, &vertex_buffer);
+ m_device_ctx->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset);
+
+ Microsoft::WRL::ComPtr<ID3DBlob> blob;
+ D3DCompile(pixel_shader_str.c_str(),
+ pixel_shader_str.length(),
+ NULL,
+ NULL,
+ NULL,
+ "main",
+ "ps_5_0",
+ 0,
+ 0,
+ &blob,
+ NULL);
+ Microsoft::WRL::ComPtr<ID3D11PixelShader> pixel_shader;
+ m_device->CreatePixelShader(
+ blob->GetBufferPointer(), blob->GetBufferSize(), NULL, &pixel_shader);
+
+ D3DCompile(vertex_shader_str.c_str(),
+ vertex_shader_str.length(),
+ NULL,
+ NULL,
+ NULL,
+ "main",
+ "vs_5_0",
+ 0,
+ 0,
+ &blob,
+ NULL);
+ Microsoft::WRL::ComPtr<ID3D11VertexShader> vertex_shader;
+ m_device->CreateVertexShader(
+ blob->GetBufferPointer(), blob->GetBufferSize(), NULL, &vertex_shader);
+
+ m_device_ctx->PSSetShader(pixel_shader.Get(), NULL, 0);
+ m_device_ctx->VSSetShader(vertex_shader.Get(), 0, 0);
+
+ Microsoft::WRL::ComPtr<ID3D11InputLayout> input_layout;
+ const D3D11_INPUT_ELEMENT_DESC input_desc[] = {
+ {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ };
+ m_device->CreateInputLayout(input_desc,
+ (unsigned int)std::size(input_desc),
+ blob->GetBufferPointer(),
+ blob->GetBufferSize(),
+ &input_layout);
+ m_device_ctx->IASetInputLayout(input_layout.Get());
+
+ m_device_ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ D3D11_VIEWPORT viewport = {};
+ viewport.Width = width;
+ viewport.Height = height;
+ viewport.MaxDepth = 1;
+ m_device_ctx->RSSetViewports(1, &viewport);
+
+ m_device_ctx->Draw(std::size(vertices), 0);
+}
+#endif
diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h
new file mode 100644
index 00000000000..4fa58ed6fbe
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextD3D.h
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_CONTEXTD3D_H__
+#define __GHOST_CONTEXTD3D_H__
+
+#ifndef WIN32
+# error WIN32 only!
+#endif // WIN32
+
+#include <D3D11.h>
+
+#include "GHOST_Context.h"
+
+class GHOST_ContextD3D : public GHOST_Context {
+ /* XR code needs low level graphics data to send to OpenXR. */
+ friend class GHOST_XrGraphicsBindingD3D;
+
+ public:
+ GHOST_ContextD3D(bool stereoVisual, HWND hWnd);
+ ~GHOST_ContextD3D();
+
+ /**
+ * Swaps front and back buffers of a window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess swapBuffers();
+
+ /**
+ * Activates the drawing context of this window.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess activateDrawingContext();
+
+ /**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ GHOST_TSuccess setDefaultFramebufferSize(GHOST_TUns32 width, GHOST_TUns32 height);
+
+ /**
+ * Call immediately after new to initialize. If this fails then immediately delete the object.
+ * \return Indication as to whether initialization has succeeded.
+ */
+ GHOST_TSuccess initializeDrawingContext();
+
+ /**
+ * Updates the drawing context of this window. Needed
+ * whenever the window is changed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess updateDrawingContext()
+ {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * Checks if it is OK for a remove the native display
+ * \return Indication as to whether removal has succeeded.
+ */
+ GHOST_TSuccess releaseNativeHandles();
+
+ /**
+ * Sets the swap interval for swapBuffers.
+ * \param interval The swap interval to use.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess setSwapInterval(int /*interval*/)
+ {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * Gets the current swap interval for swapBuffers.
+ * \param intervalOut Variable to store the swap interval if it can be read.
+ * \return Whether the swap interval can be read.
+ */
+ GHOST_TSuccess getSwapInterval(int &)
+ {
+ return GHOST_kFailure;
+ }
+
+ /**
+ * Gets the OpenGL framebuffer associated with the OpenGL context
+ * \return The ID of an OpenGL framebuffer object.
+ */
+ unsigned int getDefaultFramebuffer()
+ {
+ return 0;
+ }
+
+ GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height);
+ GHOST_TSuccess blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
+ ID3D11RenderTargetView *render_target,
+ GHOST_TInt32 width,
+ GHOST_TInt32 height);
+
+ bool isUpsideDown() const
+ {
+ return true;
+ }
+
+ private:
+ GHOST_TSuccess setupD3DLib();
+ GHOST_TSuccess updateSwapchain(GHOST_TUns32 width, GHOST_TUns32 height);
+
+ static HMODULE s_d3d_lib;
+ static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN s_D3D11CreateDeviceAndSwapChainFn;
+
+ HWND m_hWnd;
+
+ ID3D11Device *m_device;
+ ID3D11DeviceContext *m_device_ctx;
+ IDXGISwapChain *m_swapchain;
+ ID3D11RenderTargetView *m_backbuffer_view;
+
+ class SharedOpenGLContext *glshared{nullptr};
+};
+
+#endif /* __GHOST_CONTEXTD3D_H__ */
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
index d4eeda2a9ef..a7c94448fe6 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -208,7 +208,7 @@ GHOST_ContextEGL::GHOST_ContextEGL(bool stereoVisual,
EGLint contextFlags,
EGLint contextResetNotificationStrategy,
EGLenum api)
- : GHOST_Context(stereoVisual),
+ : GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
m_nativeDisplay(nativeDisplay),
m_nativeWindow(nativeWindow),
m_contextProfileMask(contextProfileMask),
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
index fac75f299fc..8bde9f69b02 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.cpp
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -52,7 +52,7 @@ GHOST_ContextGLX::GHOST_ContextGLX(bool stereoVisual,
int contextMinorVersion,
int contextFlags,
int contextResetNotificationStrategy)
- : GHOST_Context(stereoVisual),
+ : GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
m_display(display),
m_fbconfig(fbconfig),
m_window(window),
@@ -273,6 +273,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
m_window = (Window)glXCreatePbuffer(m_display, framebuffer_config[0], pbuffer_attribs);
}
+ m_fbconfig = framebuffer_config[0];
XFree(framebuffer_config);
}
}
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
index ba8df7dac1b..07d2601cd17 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.h
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -38,6 +38,9 @@
#endif
class GHOST_ContextGLX : public GHOST_Context {
+ /* XR code needs low level graphics data to send to OpenXR. */
+ friend class GHOST_XrGraphicsBindingOpenGL;
+
public:
/**
* Constructor.
diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h
index 2a3c08701b4..b68f1dc9076 100644
--- a/intern/ghost/intern/GHOST_ContextNone.h
+++ b/intern/ghost/intern/GHOST_ContextNone.h
@@ -30,7 +30,8 @@
class GHOST_ContextNone : public GHOST_Context {
public:
- GHOST_ContextNone(bool stereoVisual) : GHOST_Context(stereoVisual), m_swapInterval(1)
+ GHOST_ContextNone(bool stereoVisual)
+ : GHOST_Context(GHOST_kDrawingContextTypeNone, stereoVisual), m_swapInterval(1)
{
}
diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp
index bf0737e5efa..3b26343ca92 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.cpp
+++ b/intern/ghost/intern/GHOST_ContextSDL.cpp
@@ -41,7 +41,7 @@ GHOST_ContextSDL::GHOST_ContextSDL(bool stereoVisual,
int contextMinorVersion,
int contextFlags,
int contextResetNotificationStrategy)
- : GHOST_Context(stereoVisual),
+ : GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
m_window(window),
m_hidden_window(NULL),
m_contextProfileMask(contextProfileMask),
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
index d4851450ce8..c88b6d71609 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -24,6 +24,7 @@
*/
#include "GHOST_ContextWGL.h"
+#include "GHOST_Rect.h"
#include <tchar.h>
@@ -31,6 +32,8 @@
#include <cassert>
#include <vector>
+#include <windef.h>
+
HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
int GHOST_ContextWGL::s_sharedCount = 0;
@@ -49,7 +52,7 @@ GHOST_ContextWGL::GHOST_ContextWGL(bool stereoVisual,
int contextMinorVersion,
int contextFlags,
int contextResetNotificationStrategy)
- : GHOST_Context(stereoVisual),
+ : GHOST_Context(GHOST_kDrawingContextTypeOpenGL, stereoVisual),
m_hWnd(hWnd),
m_hDC(hDC),
m_contextProfileMask(contextProfileMask),
@@ -140,6 +143,35 @@ GHOST_TSuccess GHOST_ContextWGL::releaseDrawingContext()
}
}
+GHOST_TSuccess GHOST_ContextWGL::setDefaultFramebufferSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ RECT rect = {0, 0, (long)width, (long)height};
+ RECT winrect;
+
+ /* To get a default framebuffer with custom size, the hidden window has to be resized. */
+
+ GetWindowRect(m_hWnd, &winrect);
+
+ WIN32_CHK(AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, 0));
+
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+
+ if (((winrect.right - winrect.left) != width) || ((winrect.bottom - winrect.top) != height)) {
+ return SetWindowPos(m_hWnd,
+ HWND_TOP,
+ 0,
+ 0,
+ width,
+ height,
+ SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOZORDER) ?
+ GHOST_kSuccess :
+ GHOST_kFailure;
+ }
+
+ return GHOST_kSuccess;
+}
+
/* Ron Fosner's code for weighting pixel formats and forcing software.
* See http://www.opengl.org/resources/faq/technical/weight.cpp
*/
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index a990e42c4ff..99d1bb6efe5 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -35,6 +35,9 @@
#endif
class GHOST_ContextWGL : public GHOST_Context {
+ /* XR code needs low level graphics data to send to OpenXR. */
+ friend class GHOST_XrGraphicsBindingOpenGL;
+
public:
/**
* Constructor.
@@ -99,6 +102,8 @@ class GHOST_ContextWGL : public GHOST_Context {
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
+ GHOST_TSuccess setDefaultFramebufferSize(GHOST_TUns32 width, GHOST_TUns32 height);
+
private:
int choose_pixel_format(bool stereoVisual, bool needAlpha);
int choose_pixel_format_arb(bool stereoVisual, bool needAlpha);
diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
new file mode 100644
index 00000000000..8470827c2dd
--- /dev/null
+++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
@@ -0,0 +1,73 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_IXRGRAPHICSBINDING_H__
+#define __GHOST_IXRGRAPHICSBINDING_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "GHOST_Xr_openxr_includes.h"
+
+class GHOST_IXrGraphicsBinding {
+ friend std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
+ GHOST_TXrGraphicsBinding type);
+
+ public:
+ union {
+#if defined(WITH_X11)
+ XrGraphicsBindingOpenGLXlibKHR glx;
+#elif defined(WIN32)
+ XrGraphicsBindingOpenGLWin32KHR wgl;
+ XrGraphicsBindingD3D11KHR d3d11;
+#endif
+ } oxr_binding;
+
+ /**
+ * Does __not__ require this object is initialized (can be called prior to
+ * #initFromGhostContext). It's actually meant to be called first.
+ *
+ * \param r_requirement_info Return argument to retrieve an informal string on the requirements
+ * to be met. Useful for error/debug messages.
+ */
+ virtual bool checkVersionRequirements(class GHOST_Context *ghost_ctx,
+ XrInstance instance,
+ XrSystemId system_id,
+ std::string *r_requirement_info) const = 0;
+ virtual void initFromGhostContext(class GHOST_Context *ghost_ctx) = 0;
+ virtual bool chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
+ int64_t *r_result) const = 0;
+ virtual std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(
+ uint32_t image_count) = 0;
+ virtual void drawViewBegin(XrSwapchainImageBaseHeader *swapchain_image) = 0;
+ virtual void drawViewEnd(XrSwapchainImageBaseHeader *swapchain_image,
+ const GHOST_XrDrawViewInfo *draw_info,
+ class GHOST_Context *ogl_ctx) = 0;
+
+ protected:
+ /* Use GHOST_XrGraphicsBindingCreateFromType */
+ GHOST_IXrGraphicsBinding() = default;
+};
+
+std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
+ GHOST_TXrGraphicsBinding type);
+
+#endif /* __GHOST_IXRGRAPHICSBINDING_H__ */
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 21935abed9c..224f0fab90c 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -121,6 +121,16 @@ GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow *window)
return success;
}
+GHOST_IContext *GHOST_System::createOffscreenContext(GHOST_TDrawingContextType type)
+{
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ return createOffscreenContext();
+ default:
+ return NULL;
+ }
+}
+
bool GHOST_System::validWindow(GHOST_IWindow *window)
{
return m_windowManager->getWindowFound(window);
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index fbf8af01e59..bea61f42674 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -120,6 +120,19 @@ class GHOST_System : public GHOST_ISystem {
GHOST_TSuccess disposeWindow(GHOST_IWindow *window);
/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+ virtual GHOST_IContext *createOffscreenContext() = 0;
+
+ /**
+ * Overload to allow requesting a different context type. By default only OpenGL is supported.
+ * However by explicitly overloading this a system may add support for others.
+ */
+ GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type);
+
+ /**
* Returns whether a window is valid.
* \param window Pointer to the window to be checked.
* \return Indication of validity.
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 9073ed9944b..47cbece963f 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -21,6 +21,7 @@
* \ingroup GHOST
*/
+#include "GHOST_ContextD3D.h"
#include "GHOST_SystemWin32.h"
#include "GHOST_EventDragnDrop.h"
@@ -296,6 +297,29 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title,
return window;
}
+LRESULT WINAPI offscreen_s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lResult = 0;
+ bool event_handled = false;
+
+ switch (msg) {
+ case WM_GETMINMAXINFO: {
+ ::DefWindowProc(hwnd, msg, wParam, lParam);
+ MINMAXINFO *mmi = (MINMAXINFO *)lParam;
+ mmi->ptMaxTrackSize.x = LONG_MAX;
+ mmi->ptMaxTrackSize.y = LONG_MAX;
+ event_handled = true;
+ break;
+ }
+ }
+
+ if (!event_handled) {
+ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ return lResult;
+}
+
/**
* Create a new offscreen context.
* Never explicitly delete the window, use #disposeContext() instead.
@@ -305,9 +329,30 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext()
{
bool debug_context = false; /* TODO: inform as a parameter */
+ /* TODO Doesn't use STATIC class to allow offscreen context framebuffer bigger than screen size.
+ * For that, WM_GETMINMAXINFO event has to be listented to in custom WndProc callback. Need to
+ * verify this doesn't cause side effects, also, de-duplicate class definition.
+ */
GHOST_Context *context;
+ WNDCLASSW wc = {0};
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = offscreen_s_wndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = ::GetModuleHandle(0);
+ wc.hCursor = ::LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground =
+#ifdef INW32_COMPISITING
+ (HBRUSH)CreateSolidBrush
+#endif
+ (0x00000000);
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = L"GHOST_OffscreenWindowClass";
+
+ // Use RegisterClassEx for setting small icon
+ ::RegisterClassW(&wc);
- HWND wnd = CreateWindowA("STATIC",
+ HWND wnd = CreateWindowA("GHOST_OffscreenWindowClass",
"BlenderGLEW",
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0,
@@ -406,6 +451,69 @@ GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context)
return GHOST_kSuccess;
}
+/**
+ * Create a new offscreen DirectX 11 context.
+ * Never explicitly delete the window, use #disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+GHOST_IContext *GHOST_SystemWin32::createOffscreenContextD3D()
+{
+ GHOST_Context *context;
+
+ /* TODO Doesn't use STATIC class to allow offscreen context framebuffer bigger than screen size.
+ * For that, WM_GETMINMAXINFO event has to be listented to in custom WndProc callback. Need to
+ * verify this doesn't cause side effects, also, de-duplicate class definition.
+ */
+ WNDCLASSW wc = {0};
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = offscreen_s_wndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = ::GetModuleHandle(0);
+ wc.hCursor = ::LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground =
+#ifdef INW32_COMPISITING
+ (HBRUSH)CreateSolidBrush
+#endif
+ (0x00000000);
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = L"GHOST_OffscreenWindowClass";
+
+ // Use RegisterClassEx for setting small icon
+ ::RegisterClassW(&wc);
+
+ HWND wnd = CreateWindowA("GHOST_OffscreenWindowClass",
+ "BlenderD3D",
+ WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ 0,
+ 0,
+ 64,
+ 64,
+ NULL,
+ NULL,
+ GetModuleHandle(NULL),
+ NULL);
+
+ context = new GHOST_ContextD3D(false, wnd);
+ if (context->initializeDrawingContext() == GHOST_kFailure) {
+ delete context;
+ }
+
+ return context;
+}
+
+GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_TDrawingContextType type)
+{
+ switch (type) {
+ case GHOST_kDrawingContextTypeOpenGL:
+ return createOffscreenContext();
+ case GHOST_kDrawingContextTypeD3D:
+ return createOffscreenContextD3D();
+ default:
+ return NULL;
+ }
+}
+
bool GHOST_SystemWin32::processEvents(bool waitForEvent)
{
MSG msg;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 7ac6a3e3e20..c911cafc567 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -134,6 +134,13 @@ class GHOST_SystemWin32 : public GHOST_System {
GHOST_IContext *createOffscreenContext();
/**
+ * Create a new offscreen context.
+ * Never explicitly delete the window, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+ GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type);
+
+ /**
* Dispose of a context.
* \param context Pointer to the context to be disposed.
* \return Indication of success.
@@ -235,6 +242,8 @@ class GHOST_SystemWin32 : public GHOST_System {
*/
GHOST_TSuccess exit();
+ GHOST_IContext *createOffscreenContextD3D();
+
/**
* Converts raw WIN32 key codes from the wndproc to GHOST keys.
* \param vKey The virtual key from hardKey
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index ca19e251279..e639562f96e 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -114,6 +114,21 @@ unsigned int GHOST_Window::getDefaultFramebuffer()
return (m_context) ? m_context->getDefaultFramebuffer() : 0;
}
+GHOST_TSuccess GHOST_Window::blitOpenGLOffscreenContext(GHOST_IContext *offscreen_ctx)
+{
+ GHOST_Rect rect;
+
+ getWindowBounds(rect);
+
+ return m_context->blitOpenGLOffscreenContext(
+ (GHOST_Context *)offscreen_ctx, rect.getWidth(), rect.getHeight());
+}
+
+bool GHOST_Window::isUpsideDown() const
+{
+ return m_context->isUpsideDown();
+}
+
GHOST_TSuccess GHOST_Window::activateDrawingContext()
{
return m_context->activateDrawingContext();
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 5f9e8ffdd5e..64515d9e5ee 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -221,6 +221,11 @@ class GHOST_Window : public GHOST_IWindow {
*/
virtual bool getModifiedState();
+ inline GHOST_IContext *getDrawingContext()
+ {
+ return (GHOST_IContext *)m_context;
+ }
+
/**
* Returns the type of drawing context used in this window.
* \return The current type of drawing context.
@@ -261,6 +266,8 @@ class GHOST_Window : public GHOST_IWindow {
*/
virtual unsigned int getDefaultFramebuffer();
+ virtual GHOST_TSuccess blitOpenGLOffscreenContext(class GHOST_IContext *offscreen_ctx);
+
/**
* Returns the window user data.
* \return The window user data.
@@ -279,6 +286,8 @@ class GHOST_Window : public GHOST_IWindow {
m_userData = userData;
}
+ bool isUpsideDown() const;
+
float getNativePixelSize(void)
{
if (m_nativePixelSize > 0.0f)
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index e8b36c59366..d0b00063294 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -23,6 +23,7 @@
#define _USE_MATH_DEFINES
+#include "GHOST_ContextD3D.h"
#include "GHOST_WindowWin32.h"
#include "GHOST_SystemWin32.h"
#include "GHOST_DropTargetWin32.h"
@@ -724,6 +725,19 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
# error // must specify either core or compat at build time
#endif
}
+ else if (type == GHOST_kDrawingContextTypeD3D) {
+ GHOST_Context *context;
+
+ context = new GHOST_ContextD3D(false, m_hWnd);
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ delete context;
+ }
+
+ return context;
+ }
return NULL;
}
diff --git a/intern/ghost/intern/GHOST_Xr.cpp b/intern/ghost/intern/GHOST_Xr.cpp
new file mode 100644
index 00000000000..3d89e860dae
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Xr.cpp
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ *
+ * Abstraction for XR (VR, AR, MR, ..) access via OpenXR.
+ */
+
+#include <cassert>
+#include <string>
+
+#include "GHOST_C-api.h"
+
+#include "GHOST_Xr_intern.h"
+#include "GHOST_XrContext.h"
+#include "GHOST_XrException.h"
+
+/**
+ * \brief Initialize the window manager XR-Context.
+ * Includes setting up the OpenXR instance, querying available extensions and API layers,
+ * enabling extensions (currently graphics binding extension only) and API layers.
+ */
+GHOST_XrContextHandle GHOST_XrContextCreate(const GHOST_XrContextCreateInfo *create_info)
+{
+ GHOST_XrContext *xr_context = new GHOST_XrContext(create_info);
+
+ // TODO GHOST_XrContext's should probably be owned by the GHOST_System, which will handle context
+ // creation and destruction. Try-catch logic can be moved to C-API then.
+ try {
+ xr_context->initialize(create_info);
+ }
+ catch (GHOST_XrException &e) {
+ xr_context->dispatchErrorMessage(&e);
+ delete xr_context;
+
+ return nullptr;
+ }
+
+ return (GHOST_XrContextHandle)xr_context;
+}
+
+void GHOST_XrContextDestroy(GHOST_XrContextHandle xr_contexthandle)
+{
+ delete (GHOST_XrContext *)xr_contexthandle;
+}
+
+void GHOST_XrErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata)
+{
+ GHOST_XrContext::setErrorHandler(handler_fn, customdata);
+}
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
new file mode 100644
index 00000000000..813fdf19f5a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -0,0 +1,533 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ *
+ * Abstraction for XR (VR, AR, MR, ..) access via OpenXR.
+ */
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "GHOST_Types.h"
+#include "GHOST_Xr_intern.h"
+#include "GHOST_XrException.h"
+#include "GHOST_XrSession.h"
+
+#include "GHOST_XrContext.h"
+
+struct OpenXRInstanceData {
+ XrInstance instance{XR_NULL_HANDLE};
+
+ std::vector<XrExtensionProperties> extensions;
+ std::vector<XrApiLayerProperties> layers;
+
+ static PFN_xrCreateDebugUtilsMessengerEXT s_xrCreateDebugUtilsMessengerEXT_fn;
+ static PFN_xrDestroyDebugUtilsMessengerEXT s_xrDestroyDebugUtilsMessengerEXT_fn;
+
+ XrDebugUtilsMessengerEXT debug_messenger{XR_NULL_HANDLE};
+};
+
+PFN_xrCreateDebugUtilsMessengerEXT OpenXRInstanceData::s_xrCreateDebugUtilsMessengerEXT_fn =
+ nullptr;
+PFN_xrDestroyDebugUtilsMessengerEXT OpenXRInstanceData::s_xrDestroyDebugUtilsMessengerEXT_fn =
+ nullptr;
+
+GHOST_XrErrorHandlerFn GHOST_XrContext::s_error_handler = nullptr;
+void *GHOST_XrContext::s_error_handler_customdata = nullptr;
+
+/* -------------------------------------------------------------------- */
+/** \name Create, Initialize and Destruct
+ *
+ * \{ */
+
+GHOST_XrContext::GHOST_XrContext(const GHOST_XrContextCreateInfo *create_info)
+ : m_oxr(new OpenXRInstanceData()),
+ m_debug(create_info->context_flag & GHOST_kXrContextDebug),
+ m_debug_time(create_info->context_flag & GHOST_kXrContextDebugTime)
+{
+}
+GHOST_XrContext::~GHOST_XrContext()
+{
+ // TODO OpenXR calls here can fail, but we should not throw an exception in the destructor.
+
+ if (m_oxr->debug_messenger != XR_NULL_HANDLE) {
+ assert(m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn != nullptr);
+ m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn(m_oxr->debug_messenger);
+ }
+ if (m_oxr->instance != XR_NULL_HANDLE) {
+ xrDestroyInstance(m_oxr->instance);
+ m_oxr->instance = XR_NULL_HANDLE;
+ }
+}
+
+void GHOST_XrContext::initialize(const GHOST_XrContextCreateInfo *create_info)
+{
+ enumerateApiLayers();
+ enumerateExtensions();
+ XR_DEBUG_ONLY_CALL(this, printAvailableAPILayersAndExtensionsInfo());
+
+ m_gpu_binding_type = determineGraphicsBindingTypeToEnable(create_info);
+
+ assert(m_oxr->instance == XR_NULL_HANDLE);
+ createOpenXRInstance();
+ printInstanceInfo();
+ XR_DEBUG_ONLY_CALL(this, initDebugMessenger());
+}
+
+void GHOST_XrContext::createOpenXRInstance()
+{
+ XrInstanceCreateInfo create_info{XR_TYPE_INSTANCE_CREATE_INFO};
+
+ std::string("Blender").copy(create_info.applicationInfo.applicationName,
+ XR_MAX_APPLICATION_NAME_SIZE);
+ create_info.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
+
+ getAPILayersToEnable(m_enabled_layers);
+ getExtensionsToEnable(m_enabled_extensions);
+ create_info.enabledApiLayerCount = m_enabled_layers.size();
+ create_info.enabledApiLayerNames = m_enabled_layers.data();
+ create_info.enabledExtensionCount = m_enabled_extensions.size();
+ create_info.enabledExtensionNames = m_enabled_extensions.data();
+ XR_DEBUG_ONLY_CALL(this, printExtensionsAndAPILayersToEnable());
+
+ CHECK_XR(xrCreateInstance(&create_info, &m_oxr->instance),
+ "Failed to connect to an OpenXR runtime.");
+}
+
+/** \} */ /* Create, Initialize and Destruct */
+
+/* -------------------------------------------------------------------- */
+/** \name Debug Printing
+ *
+ * \{ */
+
+void GHOST_XrContext::printInstanceInfo()
+{
+ assert(m_oxr->instance != XR_NULL_HANDLE);
+
+ XrInstanceProperties instance_properties{XR_TYPE_INSTANCE_PROPERTIES};
+ CHECK_XR(xrGetInstanceProperties(m_oxr->instance, &instance_properties),
+ "Failed to get OpenXR runtime information. Do you have an active runtime set up?");
+
+ printf("Connected to OpenXR runtime: %s (Version %u.%u.%u)\n",
+ instance_properties.runtimeName,
+ XR_VERSION_MAJOR(instance_properties.runtimeVersion),
+ XR_VERSION_MINOR(instance_properties.runtimeVersion),
+ XR_VERSION_PATCH(instance_properties.runtimeVersion));
+}
+
+void GHOST_XrContext::printAvailableAPILayersAndExtensionsInfo()
+{
+ puts("Available OpenXR API-layers/extensions:");
+ for (XrApiLayerProperties &layer_info : m_oxr->layers) {
+ printf("Layer: %s\n", layer_info.layerName);
+ }
+ for (XrExtensionProperties &ext_info : m_oxr->extensions) {
+ printf("Extension: %s\n", ext_info.extensionName);
+ }
+}
+
+void GHOST_XrContext::printExtensionsAndAPILayersToEnable()
+{
+ for (const char *layer_name : m_enabled_layers) {
+ printf("Enabling OpenXR API-Layer: %s\n", layer_name);
+ }
+ for (const char *ext_name : m_enabled_extensions) {
+ printf("Enabling OpenXR Extension: %s\n", ext_name);
+ }
+}
+
+static XrBool32 debug_messenger_func(XrDebugUtilsMessageSeverityFlagsEXT /*messageSeverity*/,
+ XrDebugUtilsMessageTypeFlagsEXT /*messageTypes*/,
+ const XrDebugUtilsMessengerCallbackDataEXT *callbackData,
+ void * /*userData*/)
+{
+ puts("OpenXR Debug Message:");
+ puts(callbackData->message);
+ return XR_FALSE; // OpenXR spec suggests always returning false.
+}
+
+void GHOST_XrContext::initDebugMessenger()
+{
+ XrDebugUtilsMessengerCreateInfoEXT create_info{XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+
+ /* Extension functions need to be obtained through xrGetInstanceProcAddr */
+ if (XR_FAILED(xrGetInstanceProcAddr(
+ m_oxr->instance,
+ "xrCreateDebugUtilsMessengerEXT",
+ (PFN_xrVoidFunction *)&m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn)) ||
+ XR_FAILED(xrGetInstanceProcAddr(
+ m_oxr->instance,
+ "xrDestroyDebugUtilsMessengerEXT",
+ (PFN_xrVoidFunction *)&m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn))) {
+ m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn = nullptr;
+ m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn = nullptr;
+
+ fprintf(stderr,
+ "Could not use XR_EXT_debug_utils to enable debug prints. Not a fatal error, "
+ "continuing without the messenger.\n");
+ return;
+ }
+
+ create_info.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
+ XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
+ XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+ XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ create_info.messageTypes = XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+ XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ create_info.userCallback = debug_messenger_func;
+
+ if (XR_FAILED(m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn(
+ m_oxr->instance, &create_info, &m_oxr->debug_messenger))) {
+ fprintf(stderr,
+ "Failed to create OpenXR debug messenger. Not a fatal error, continuing without the "
+ "messenger.\n");
+ return;
+ }
+}
+
+/** \} */ /* Debug Printing */
+
+/* -------------------------------------------------------------------- */
+/** \name Error handling
+ *
+ * \{ */
+
+void GHOST_XrContext::dispatchErrorMessage(const GHOST_XrException *exception) const
+{
+ std::ostringstream stream_err_location;
+ std::string str_err_location;
+ GHOST_XrError error;
+
+ stream_err_location << exception->m_file << ":" << exception->m_line;
+ str_err_location = stream_err_location.str();
+
+ error.user_message = exception->m_msg;
+ error.source_location = str_err_location.c_str();
+ error.customdata = s_error_handler_customdata;
+
+ XR_DEBUG_ONLY_CALL(this,
+ fprintf(stderr,
+ "Error: \t%s\n\tOpenXR error value: %i\n\tSource: (%s)\n",
+ error.user_message,
+ exception->m_res,
+ error.source_location));
+
+ /* Potentially destroys GHOST_XrContext */
+ s_error_handler(&error);
+}
+
+void GHOST_XrContext::setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata)
+{
+ s_error_handler = handler_fn;
+ s_error_handler_customdata = customdata;
+}
+
+/** \} */ /* Error handling */
+
+/* -------------------------------------------------------------------- */
+/** \name OpenXR API-Layers and Extensions
+ *
+ * \{ */
+
+/**
+ * \param layer_name May be NULL for extensions not belonging to a specific layer.
+ */
+void GHOST_XrContext::enumerateExtensionsEx(std::vector<XrExtensionProperties> &extensions,
+ const char *layer_name)
+{
+ uint32_t extension_count = 0;
+
+ /* Get count for array creation/init first. */
+ CHECK_XR(xrEnumerateInstanceExtensionProperties(layer_name, 0, &extension_count, nullptr),
+ "Failed to query OpenXR runtime information. Do you have an active runtime set up?");
+
+ if (extension_count == 0) {
+ /* Extensions are optional, can successfully exit. */
+ return;
+ }
+
+ for (uint32_t i = 0; i < extension_count; i++) {
+ XrExtensionProperties ext{XR_TYPE_EXTENSION_PROPERTIES};
+ extensions.push_back(ext);
+ }
+
+ /* Actually get the extensions. */
+ CHECK_XR(xrEnumerateInstanceExtensionProperties(
+ layer_name, extension_count, &extension_count, extensions.data()),
+ "Failed to query OpenXR runtime information. Do you have an active runtime set up?");
+}
+void GHOST_XrContext::enumerateExtensions()
+{
+ enumerateExtensionsEx(m_oxr->extensions, nullptr);
+}
+
+void GHOST_XrContext::enumerateApiLayers()
+{
+ uint32_t layer_count = 0;
+
+ /* Get count for array creation/init first. */
+ CHECK_XR(xrEnumerateApiLayerProperties(0, &layer_count, nullptr),
+ "Failed to query OpenXR runtime information. Do you have an active runtime set up?");
+
+ if (layer_count == 0) {
+ /* Layers are optional, can safely exit. */
+ return;
+ }
+
+ m_oxr->layers = std::vector<XrApiLayerProperties>(layer_count);
+ for (XrApiLayerProperties &layer : m_oxr->layers) {
+ layer.type = XR_TYPE_API_LAYER_PROPERTIES;
+ }
+
+ /* Actually get the layers. */
+ CHECK_XR(xrEnumerateApiLayerProperties(layer_count, &layer_count, m_oxr->layers.data()),
+ "Failed to query OpenXR runtime information. Do you have an active runtime set up?");
+ for (XrApiLayerProperties &layer : m_oxr->layers) {
+ /* Each layer may have own extensions */
+ enumerateExtensionsEx(m_oxr->extensions, layer.layerName);
+ }
+}
+
+static bool openxr_layer_is_available(const std::vector<XrApiLayerProperties> layers_info,
+ const std::string &layer_name)
+{
+ for (const XrApiLayerProperties &layer_info : layers_info) {
+ if (layer_info.layerName == layer_name) {
+ return true;
+ }
+ }
+
+ return false;
+}
+static bool openxr_extension_is_available(const std::vector<XrExtensionProperties> extensions_info,
+ const std::string &extension_name)
+{
+ for (const XrExtensionProperties &ext_info : extensions_info) {
+ if (ext_info.extensionName == extension_name) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Gather an array of names for the API-layers to enable.
+ */
+void GHOST_XrContext::getAPILayersToEnable(std::vector<const char *> &r_ext_names)
+{
+ static std::vector<std::string> try_layers;
+
+ try_layers.clear();
+
+ XR_DEBUG_ONLY_CALL(this, try_layers.push_back("XR_APILAYER_LUNARG_core_validation"));
+
+ r_ext_names.reserve(try_layers.size());
+
+ for (const std::string &layer : try_layers) {
+ if (openxr_layer_is_available(m_oxr->layers, layer)) {
+ r_ext_names.push_back(layer.c_str());
+ }
+ }
+}
+
+static const char *openxr_ext_name_from_wm_gpu_binding(GHOST_TXrGraphicsBinding binding)
+{
+ switch (binding) {
+ case GHOST_kXrGraphicsOpenGL:
+ return XR_KHR_OPENGL_ENABLE_EXTENSION_NAME;
+#ifdef WIN32
+ case GHOST_kXrGraphicsD3D11:
+ return XR_KHR_D3D11_ENABLE_EXTENSION_NAME;
+#endif
+ case GHOST_kXrGraphicsUnknown:
+ assert(false);
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+/**
+ * Gather an array of names for the extensions to enable.
+ */
+void GHOST_XrContext::getExtensionsToEnable(std::vector<const char *> &r_ext_names)
+{
+ assert(m_gpu_binding_type != GHOST_kXrGraphicsUnknown);
+
+ const char *gpu_binding = openxr_ext_name_from_wm_gpu_binding(m_gpu_binding_type);
+ static std::vector<std::string> try_ext;
+
+ try_ext.clear();
+
+ /* Try enabling debug extension */
+#ifndef WIN32
+ XR_DEBUG_ONLY_CALL(this, try_ext.push_back(XR_EXT_DEBUG_UTILS_EXTENSION_NAME));
+#endif
+
+ r_ext_names.reserve(try_ext.size() + 1); /* + 1 for graphics binding extension. */
+
+ /* Add graphics binding extension. */
+ assert(gpu_binding);
+ assert(openxr_extension_is_available(m_oxr->extensions, gpu_binding));
+ r_ext_names.push_back(gpu_binding);
+
+ for (const std::string &ext : try_ext) {
+ if (openxr_extension_is_available(m_oxr->extensions, ext)) {
+ r_ext_names.push_back(ext.c_str());
+ }
+ }
+}
+
+/**
+ * Decide which graphics binding extension to use based on
+ * #GHOST_XrContextCreateInfo.gpu_binding_candidates and available extensions.
+ */
+GHOST_TXrGraphicsBinding GHOST_XrContext::determineGraphicsBindingTypeToEnable(
+ const GHOST_XrContextCreateInfo *create_info)
+{
+ assert(create_info->gpu_binding_candidates != NULL);
+ assert(create_info->gpu_binding_candidates_count > 0);
+
+ for (uint32_t i = 0; i < create_info->gpu_binding_candidates_count; i++) {
+ assert(create_info->gpu_binding_candidates[i] != GHOST_kXrGraphicsUnknown);
+ const char *ext_name = openxr_ext_name_from_wm_gpu_binding(
+ create_info->gpu_binding_candidates[i]);
+ if (openxr_extension_is_available(m_oxr->extensions, ext_name)) {
+ return create_info->gpu_binding_candidates[i];
+ }
+ }
+
+ return GHOST_kXrGraphicsUnknown;
+}
+
+/** \} */ /* OpenXR API-Layers and Extensions */
+
+/* -------------------------------------------------------------------- */
+/** \name Session management
+ *
+ * Manage session lifetime and delegate public calls to #GHOST_XrSession.
+ * \{ */
+
+void GHOST_XrContext::startSession(const GHOST_XrSessionBeginInfo *begin_info)
+{
+ if (m_session == nullptr) {
+ m_session = std::unique_ptr<GHOST_XrSession>(new GHOST_XrSession(this));
+ }
+
+ m_session->start(begin_info);
+}
+void GHOST_XrContext::endSession()
+{
+ m_session->end();
+ m_session = nullptr;
+}
+
+bool GHOST_XrContext::hasSession() const
+{
+ return m_session != nullptr;
+}
+
+bool GHOST_XrContext::shouldRunSessionDrawLoop() const
+{
+ return m_session && m_session->shouldRunDrawLoop();
+}
+
+void GHOST_XrContext::drawSessionViews(void *draw_customdata)
+{
+ m_session->draw(draw_customdata);
+}
+
+/**
+ * Delegates event to session, allowing context to destruct the session if needed.
+ */
+void GHOST_XrContext::handleSessionStateChange(const XrEventDataSessionStateChanged *lifecycle)
+{
+ if (m_session &&
+ m_session->handleStateChangeEvent(lifecycle) == GHOST_XrSession::SESSION_DESTROY) {
+ m_session = nullptr;
+ }
+}
+
+/** \} */ /* Session Management */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Accessors and Mutators
+ *
+ * Public as in, exposed in the Ghost API.
+ * \{ */
+
+/**
+ * Set context for binding and unbinding a graphics context for a session. The binding callback
+ * may create a new context thereby. In fact that's the sole reason for this callback approach to
+ * binding. Just make sure to have an unbind function set that properly destructs.
+ *
+ * \param bind_fn Function to retrieve (possibly create) a graphics context.
+ * \param unbind_fn Function to release (possibly free) a graphics context.
+ */
+void GHOST_XrContext::setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
+ GHOST_XrGraphicsContextUnbindFn unbind_fn)
+{
+ if (m_session) {
+ m_session->unbindGraphicsContext();
+ }
+ m_custom_funcs.gpu_ctx_bind_fn = bind_fn;
+ m_custom_funcs.gpu_ctx_unbind_fn = unbind_fn;
+}
+
+void GHOST_XrContext::setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn)
+{
+ m_custom_funcs.draw_view_fn = draw_view_fn;
+}
+
+/** \} */ /* Public Accessors and Mutators */
+
+/* -------------------------------------------------------------------- */
+/** \name Ghost Internal Accessors and Mutators
+ *
+ * \{ */
+
+const GHOST_XrCustomFuncs *GHOST_XrContext::getCustomFuncs() const
+{
+ return &m_custom_funcs;
+}
+
+GHOST_TXrGraphicsBinding GHOST_XrContext::getGraphicsBindingType() const
+{
+ return m_gpu_binding_type;
+}
+
+XrInstance GHOST_XrContext::getInstance() const
+{
+ return m_oxr->instance;
+}
+
+bool GHOST_XrContext::isDebugMode() const
+{
+ return m_debug;
+}
+
+bool GHOST_XrContext::isDebugTimeMode() const
+{
+ return m_debug_time;
+}
+
+/** \} */ /* Ghost Internal Accessors and Mutators */
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
new file mode 100644
index 00000000000..3cf33fb6950
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -0,0 +1,111 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_XRCONTEXT_H__
+#define __GHOST_XRCONTEXT_H__
+
+#include <memory>
+#include <vector>
+#include "GHOST_IXrContext.h"
+
+struct GHOST_XrCustomFuncs {
+ /** Function to retrieve (possibly create) a graphics context */
+ GHOST_XrGraphicsContextBindFn gpu_ctx_bind_fn{nullptr};
+ /** Function to release (possibly free) a graphics context */
+ GHOST_XrGraphicsContextUnbindFn gpu_ctx_unbind_fn{nullptr};
+
+ /** Custom per-view draw function for Blender side drawing. */
+ GHOST_XrDrawViewFn draw_view_fn{nullptr};
+};
+
+/**
+ * \brief Main GHOST container to manage OpenXR through.
+ *
+ * Creating a context using #GHOST_XrContextCreate involves dynamically connecting to the OpenXR
+ * runtime, likely reading the OS OpenXR configuration (i.e. active_runtime.json). So this is
+ * something that should better be done using lazy-initialization.
+ */
+class GHOST_XrContext : public GHOST_IXrContext {
+ public:
+ GHOST_XrContext(const GHOST_XrContextCreateInfo *create_info);
+ ~GHOST_XrContext();
+ void initialize(const GHOST_XrContextCreateInfo *create_info);
+
+ void startSession(const GHOST_XrSessionBeginInfo *begin_info) override;
+ void endSession() override;
+ bool hasSession() const override;
+ bool shouldRunSessionDrawLoop() const override;
+ void drawSessionViews(void *draw_customdata) override;
+
+ static void setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
+ void dispatchErrorMessage(const class GHOST_XrException *exception) const override;
+
+ void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
+ GHOST_XrGraphicsContextUnbindFn unbind_fn) override;
+ void setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn) override;
+
+ void handleSessionStateChange(const XrEventDataSessionStateChanged *lifecycle);
+
+ const GHOST_XrCustomFuncs *getCustomFuncs() const;
+ GHOST_TXrGraphicsBinding getGraphicsBindingType() const;
+ XrInstance getInstance() const;
+ bool isDebugMode() const;
+ bool isDebugTimeMode() const;
+
+ private:
+ std::unique_ptr<struct OpenXRInstanceData> m_oxr;
+
+ /* The active GHOST XR Session. Null while no session runs. */
+ std::unique_ptr<class GHOST_XrSession> m_session;
+
+ /** Active graphics binding type. */
+ GHOST_TXrGraphicsBinding m_gpu_binding_type{GHOST_kXrGraphicsUnknown};
+
+ /** Names of enabled extensions */
+ std::vector<const char *> m_enabled_extensions;
+ /** Names of enabled API-layers */
+ std::vector<const char *> m_enabled_layers;
+
+ static GHOST_XrErrorHandlerFn s_error_handler;
+ static void *s_error_handler_customdata;
+ GHOST_XrCustomFuncs m_custom_funcs;
+
+ /** Enable debug message prints and OpenXR API validation layers */
+ bool m_debug{false};
+ bool m_debug_time{false};
+
+ void createOpenXRInstance();
+ void initDebugMessenger();
+
+ void printInstanceInfo();
+ void printAvailableAPILayersAndExtensionsInfo();
+ void printExtensionsAndAPILayersToEnable();
+
+ void enumerateApiLayers();
+ void enumerateExtensions();
+ void enumerateExtensionsEx(std::vector<XrExtensionProperties> &extensions,
+ const char *layer_name);
+ void getAPILayersToEnable(std::vector<const char *> &r_ext_names);
+ void getExtensionsToEnable(std::vector<const char *> &r_ext_names);
+ GHOST_TXrGraphicsBinding determineGraphicsBindingTypeToEnable(
+ const GHOST_XrContextCreateInfo *create_info);
+};
+
+#endif // __GHOST_XRCONTEXT_H__
diff --git a/intern/ghost/intern/GHOST_XrEvent.cpp b/intern/ghost/intern/GHOST_XrEvent.cpp
new file mode 100644
index 00000000000..0b625e84f3f
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrEvent.cpp
@@ -0,0 +1,60 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include <iostream>
+
+#include "GHOST_C-api.h"
+#include "GHOST_Xr_intern.h"
+#include "GHOST_XrContext.h"
+
+static bool GHOST_XrEventPollNext(XrInstance instance, XrEventDataBuffer &r_event_data)
+{
+ /* (Re-)initialize as required by specification */
+ r_event_data.type = XR_TYPE_EVENT_DATA_BUFFER;
+ r_event_data.next = nullptr;
+
+ return (xrPollEvent(instance, &r_event_data) == XR_SUCCESS);
+}
+
+GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_contexthandle)
+{
+ GHOST_XrContext *xr_context = (GHOST_XrContext *)xr_contexthandle;
+ XrEventDataBuffer event_buffer; /* structure big enought to hold all possible events */
+
+ if (xr_context == NULL) {
+ return GHOST_kFailure;
+ }
+
+ while (GHOST_XrEventPollNext(xr_context->getInstance(), event_buffer)) {
+ XrEventDataBaseHeader *event = (XrEventDataBaseHeader *)&event_buffer; /* base event struct */
+
+ switch (event->type) {
+ case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
+ xr_context->handleSessionStateChange((XrEventDataSessionStateChanged *)event);
+ return GHOST_kSuccess;
+
+ default:
+ XR_DEBUG_PRINTF(xr_context, "Unhandled event: %i\n", event->type);
+ return GHOST_kFailure;
+ }
+ }
+
+ return GHOST_kFailure;
+}
diff --git a/intern/ghost/intern/GHOST_XrException.h b/intern/ghost/intern/GHOST_XrException.h
new file mode 100644
index 00000000000..9682c7a81d9
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrException.h
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_XREXCEPTION_H__
+#define __GHOST_XREXCEPTION_H__
+
+#include <exception>
+
+class GHOST_XrException : public std::exception {
+ friend class GHOST_XrContext;
+
+ public:
+ GHOST_XrException(const char *msg, const char *file, int line, int res = 0)
+ : std::exception(), m_msg(msg), m_file(file), m_line(line), m_res(res)
+ {
+ }
+
+ const char *what() const noexcept override
+ {
+ return m_msg;
+ }
+
+ private:
+ const char *m_msg;
+ const char *m_file;
+ const int m_line;
+ int m_res;
+};
+
+#endif // __GHOST_XREXCEPTION_H__
diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
new file mode 100644
index 00000000000..fc9ec516fdf
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
@@ -0,0 +1,306 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include <algorithm>
+#include <list>
+#include <sstream>
+
+#if defined(WITH_X11)
+# include "GHOST_ContextGLX.h"
+#elif defined(WIN32)
+# include "GHOST_ContextWGL.h"
+# include "GHOST_ContextD3D.h"
+#endif
+#include "GHOST_C-api.h"
+#include "GHOST_Xr_intern.h"
+
+#include "GHOST_IXrGraphicsBinding.h"
+
+static bool choose_swapchain_format_from_candidates(std::vector<int64_t> gpu_binding_formats,
+ std::vector<int64_t> runtime_formats,
+ int64_t *r_result)
+{
+ if (gpu_binding_formats.empty()) {
+ return false;
+ }
+
+ auto res = std::find_first_of(gpu_binding_formats.begin(),
+ gpu_binding_formats.end(),
+ runtime_formats.begin(),
+ runtime_formats.end());
+ if (res == gpu_binding_formats.end()) {
+ return false;
+ }
+
+ *r_result = *res;
+ return true;
+}
+
+class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
+ public:
+ ~GHOST_XrGraphicsBindingOpenGL()
+ {
+ if (m_fbo != 0) {
+ glDeleteFramebuffers(1, &m_fbo);
+ }
+ }
+
+ bool checkVersionRequirements(GHOST_Context *ghost_ctx,
+ XrInstance instance,
+ XrSystemId system_id,
+ std::string *r_requirement_info) const override
+ {
+#if defined(WITH_X11)
+ GHOST_ContextGLX *ctx_gl = static_cast<GHOST_ContextGLX *>(ghost_ctx);
+#else
+ GHOST_ContextWGL *ctx_gl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
+#endif
+ XrGraphicsRequirementsOpenGLKHR gpu_requirements{XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR};
+ const XrVersion gl_version = XR_MAKE_VERSION(
+ ctx_gl->m_contextMajorVersion, ctx_gl->m_contextMinorVersion, 0);
+
+ xrGetOpenGLGraphicsRequirementsKHR(instance, system_id, &gpu_requirements);
+
+ if (r_requirement_info) {
+ std::ostringstream strstream;
+ strstream << "Min OpenGL version "
+ << XR_VERSION_MAJOR(gpu_requirements.minApiVersionSupported) << "."
+ << XR_VERSION_MINOR(gpu_requirements.minApiVersionSupported) << std::endl;
+ strstream << "Max OpenGL version "
+ << XR_VERSION_MAJOR(gpu_requirements.maxApiVersionSupported) << "."
+ << XR_VERSION_MINOR(gpu_requirements.maxApiVersionSupported) << std::endl;
+
+ *r_requirement_info = strstream.str();
+ }
+
+ return (gl_version >= gpu_requirements.minApiVersionSupported) &&
+ (gl_version <= gpu_requirements.maxApiVersionSupported);
+ }
+
+ void initFromGhostContext(GHOST_Context *ghost_ctx) override
+ {
+#if defined(WITH_X11)
+ GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx);
+ XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig);
+
+ oxr_binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
+ oxr_binding.glx.xDisplay = ctx_glx->m_display;
+ oxr_binding.glx.glxFBConfig = ctx_glx->m_fbconfig;
+ oxr_binding.glx.glxDrawable = ctx_glx->m_window;
+ oxr_binding.glx.glxContext = ctx_glx->m_context;
+ oxr_binding.glx.visualid = visual_info->visualid;
+#elif defined(WIN32)
+ GHOST_ContextWGL *ctx_wgl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
+
+ oxr_binding.wgl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
+ oxr_binding.wgl.hDC = ctx_wgl->m_hDC;
+ oxr_binding.wgl.hGLRC = ctx_wgl->m_hGLRC;
+#endif
+
+ /* Generate a framebuffer to use for blitting into the texture */
+ glGenFramebuffers(1, &m_fbo);
+ }
+
+ bool chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
+ int64_t *r_result) const override
+ {
+ std::vector<int64_t> gpu_binding_formats = {GL_RGBA8};
+ return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
+ }
+
+ std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
+ {
+ std::vector<XrSwapchainImageOpenGLKHR> ogl_images(image_count);
+ std::vector<XrSwapchainImageBaseHeader *> base_images;
+
+ // Need to return vector of base header pointers, so of a different type. Need to build a new
+ // list with this type, and keep the initial one alive.
+ for (XrSwapchainImageOpenGLKHR &image : ogl_images) {
+ image.type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR;
+ base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
+ }
+
+ // Keep alive.
+ m_image_cache.push_back(std::move(ogl_images));
+
+ return base_images;
+ }
+
+ void drawViewBegin(XrSwapchainImageBaseHeader * /*swapchain_image*/) override
+ {
+ }
+ void drawViewEnd(XrSwapchainImageBaseHeader *swapchain_image,
+ const GHOST_XrDrawViewInfo *draw_info,
+ GHOST_Context *ogl_ctx) override
+ {
+ XrSwapchainImageOpenGLKHR *ogl_swapchain_image = reinterpret_cast<XrSwapchainImageOpenGLKHR *>(
+ swapchain_image);
+
+ ogl_ctx->activateDrawingContext();
+ ogl_ctx->setDefaultFramebufferSize(draw_info->width, draw_info->height);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
+
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ogl_swapchain_image->image, 0);
+
+ glBlitFramebuffer(draw_info->ofsx,
+ draw_info->ofsy,
+ draw_info->ofsx + draw_info->width,
+ draw_info->ofsy + draw_info->height,
+ draw_info->ofsx,
+ draw_info->ofsy,
+ draw_info->ofsx + draw_info->width,
+ draw_info->ofsy + draw_info->height,
+ GL_COLOR_BUFFER_BIT,
+ GL_LINEAR);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ private:
+ std::list<std::vector<XrSwapchainImageOpenGLKHR>> m_image_cache;
+ GLuint m_fbo{0};
+};
+
+#ifdef WIN32
+class GHOST_XrGraphicsBindingD3D : public GHOST_IXrGraphicsBinding {
+ public:
+ bool checkVersionRequirements(GHOST_Context *ghost_ctx,
+ XrInstance instance,
+ XrSystemId system_id,
+ std::string *r_requirement_info) const override
+ {
+
+ GHOST_ContextD3D *ctx_dx = static_cast<GHOST_ContextD3D *>(ghost_ctx);
+ XrGraphicsRequirementsD3D11KHR gpu_requirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
+
+ xrGetD3D11GraphicsRequirementsKHR(instance, system_id, &gpu_requirements);
+
+ if (r_requirement_info) {
+ std::ostringstream strstream;
+ strstream << "Min DirectX 11 Feature Level " << gpu_requirements.minFeatureLevel
+ << std::endl;
+
+ *r_requirement_info = std::move(strstream.str());
+ }
+
+ return ctx_dx->m_device->GetFeatureLevel() >= gpu_requirements.minFeatureLevel;
+ }
+
+ void initFromGhostContext(GHOST_Context *ghost_ctx) override
+ {
+ GHOST_ContextD3D *ctx_d3d = static_cast<GHOST_ContextD3D *>(ghost_ctx);
+
+ oxr_binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
+ oxr_binding.d3d11.device = ctx_d3d->m_device;
+ m_ghost_ctx = ctx_d3d;
+ }
+
+ bool chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
+ int64_t *r_result) const override
+ {
+ std::vector<int64_t> gpu_binding_formats = {DXGI_FORMAT_R8G8B8A8_UNORM};
+ return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
+ }
+
+ std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
+ {
+ std::vector<XrSwapchainImageD3D11KHR> d3d_images(image_count);
+ std::vector<XrSwapchainImageBaseHeader *> base_images;
+
+ // Need to return vector of base header pointers, so of a different type. Need to build a new
+ // list with this type, and keep the initial one alive.
+ for (XrSwapchainImageD3D11KHR &image : d3d_images) {
+ image.type = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR;
+ base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
+ }
+
+ // Keep alive.
+ m_image_cache.push_back(std::move(d3d_images));
+
+ return base_images;
+ }
+
+ void drawViewBegin(XrSwapchainImageBaseHeader * /*swapchain_image*/) override
+ {
+ }
+ void drawViewEnd(XrSwapchainImageBaseHeader *swapchain_image,
+ const GHOST_XrDrawViewInfo *draw_info,
+ GHOST_Context *ogl_ctx) override
+ {
+ XrSwapchainImageD3D11KHR *d3d_swapchain_image = reinterpret_cast<XrSwapchainImageD3D11KHR *>(
+ swapchain_image);
+
+# if 0
+ /* Ideally we'd just create a render target view for the OpenXR swapchain image texture and
+ * blit from the OpenGL context into it. The NV_DX_interop extension doesn't want to work with
+ * this though. At least not with Optimus hardware. See:
+ * https://github.com/mpv-player/mpv/issues/2949#issuecomment-197262807.
+ * Note: Even if this worked, the blitting code only supports one shared resource by now, we'd
+ * need at least two (for each eye). We could also entirely re-register shared resources all
+ * the time. Also, the runtime might recreate the swapchain image so the shared resource would
+ * have to be re-registered then as well. */
+
+ ID3D11RenderTargetView *rtv;
+ CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(D3D11_RTV_DIMENSION_TEXTURE2D,
+ DXGI_FORMAT_R8G8B8A8_UNORM);
+
+ m_ghost_ctx->m_device->CreateRenderTargetView(d3d_swapchain_image->texture, &rtv_desc, &rtv);
+ m_ghost_ctx->blitOpenGLOffscreenContext(ogl_ctx, rtv, draw_info->width, draw_info->height);
+# else
+ ID3D11Resource *res;
+ ID3D11Texture2D *tex;
+
+ ogl_ctx->activateDrawingContext();
+ m_ghost_ctx->blitOpenGLOffscreenContext(ogl_ctx, draw_info->width, draw_info->height);
+
+ m_ghost_ctx->m_backbuffer_view->GetResource(&res);
+ res->QueryInterface<ID3D11Texture2D>(&tex);
+
+ m_ghost_ctx->m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
+ m_ghost_ctx->m_device_ctx->CopyResource(d3d_swapchain_image->texture, tex);
+
+ res->Release();
+ tex->Release();
+# endif
+ }
+
+ private:
+ GHOST_ContextD3D *m_ghost_ctx;
+ std::list<std::vector<XrSwapchainImageD3D11KHR>> m_image_cache;
+};
+#endif // WIN32
+
+std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
+ GHOST_TXrGraphicsBinding type)
+{
+ switch (type) {
+ case GHOST_kXrGraphicsOpenGL:
+ return std::unique_ptr<GHOST_XrGraphicsBindingOpenGL>(new GHOST_XrGraphicsBindingOpenGL());
+#ifdef WIN32
+ case GHOST_kXrGraphicsD3D11:
+ return std::unique_ptr<GHOST_XrGraphicsBindingD3D>(new GHOST_XrGraphicsBindingD3D());
+#endif
+ default:
+ return nullptr;
+ }
+}
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
new file mode 100644
index 00000000000..a5eb7a891d7
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -0,0 +1,554 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <cstdio>
+#include <list>
+#include <sstream>
+
+#include "GHOST_C-api.h"
+
+#include "GHOST_IXrGraphicsBinding.h"
+#include "GHOST_Xr_intern.h"
+#include "GHOST_XrContext.h"
+#include "GHOST_XrException.h"
+
+#include "GHOST_XrSession.h"
+
+struct OpenXRSessionData {
+ XrSystemId system_id{XR_NULL_SYSTEM_ID};
+ XrSession session{XR_NULL_HANDLE};
+ XrSessionState session_state{XR_SESSION_STATE_UNKNOWN};
+
+ // Only stereo rendering supported now.
+ const XrViewConfigurationType view_type{XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO};
+ XrSpace reference_space;
+ std::vector<XrView> views;
+ std::vector<XrSwapchain> swapchains;
+ std::map<XrSwapchain, std::vector<XrSwapchainImageBaseHeader *>> swapchain_images;
+ int32_t swapchain_image_width, swapchain_image_height;
+};
+
+struct GHOST_XrDrawInfo {
+ XrFrameState frame_state;
+
+ /** Time at frame start to benchmark frame render durations. */
+ std::chrono::high_resolution_clock::time_point frame_begin_time;
+ /* Time previous frames took for rendering (in ms) */
+ std::list<double> last_frame_times;
+};
+
+/* -------------------------------------------------------------------- */
+/** \name Create, Initialize and Destruct
+ *
+ * \{ */
+
+GHOST_XrSession::GHOST_XrSession(GHOST_XrContext *xr_context)
+ : m_context(xr_context), m_oxr(new OpenXRSessionData())
+{
+}
+
+GHOST_XrSession::~GHOST_XrSession()
+{
+ // TODO OpenXR calls here can fail, but we should not throw an exception in the destructor.
+
+ unbindGraphicsContext();
+
+ for (XrSwapchain &swapchain : m_oxr->swapchains) {
+ xrDestroySwapchain(swapchain);
+ }
+ m_oxr->swapchains.clear();
+ if (m_oxr->reference_space != XR_NULL_HANDLE) {
+ xrDestroySpace(m_oxr->reference_space);
+ }
+ if (m_oxr->session != XR_NULL_HANDLE) {
+ xrDestroySession(m_oxr->session);
+ }
+
+ m_oxr->session = XR_NULL_HANDLE;
+ m_oxr->session_state = XR_SESSION_STATE_UNKNOWN;
+}
+
+/**
+ * A system in OpenXR the combination of some sort of HMD plus controllers and whatever other
+ * devices are managed through OpenXR. So this attempts to init the HMD and the other devices.
+ */
+void GHOST_XrSession::initSystem()
+{
+ assert(m_context->getInstance() != XR_NULL_HANDLE);
+ assert(m_oxr->system_id == XR_NULL_SYSTEM_ID);
+
+ XrSystemGetInfo system_info{};
+ system_info.type = XR_TYPE_SYSTEM_GET_INFO;
+ system_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
+
+ CHECK_XR(xrGetSystem(m_context->getInstance(), &system_info, &m_oxr->system_id),
+ "Failed to get device information. Is a device plugged in?");
+}
+
+/** \} */ /* Create, Initialize and Destruct */
+
+/* -------------------------------------------------------------------- */
+/** \name State Management
+ *
+ * \{ */
+
+static void create_reference_space(OpenXRSessionData *oxr, const GHOST_XrPose *base_pose)
+{
+ XrReferenceSpaceCreateInfo create_info{XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
+ create_info.poseInReferenceSpace.orientation.w = 1.0f;
+
+ create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
+#if 0
+ create_info.poseInReferenceSpace.position.x = base_pose->position[0];
+ create_info.poseInReferenceSpace.position.y = base_pose->position[2];
+ create_info.poseInReferenceSpace.position.z = -base_pose->position[1];
+ create_info.poseInReferenceSpace.orientation.x = base_pose->orientation_quat[1];
+ create_info.poseInReferenceSpace.orientation.y = base_pose->orientation_quat[3];
+ create_info.poseInReferenceSpace.orientation.z = -base_pose->orientation_quat[2];
+ create_info.poseInReferenceSpace.orientation.w = base_pose->orientation_quat[0];
+#else
+ (void)base_pose;
+#endif
+
+ CHECK_XR(xrCreateReferenceSpace(oxr->session, &create_info, &oxr->reference_space),
+ "Failed to create reference space.");
+}
+
+void GHOST_XrSession::start(const GHOST_XrSessionBeginInfo *begin_info)
+{
+ assert(m_context->getInstance() != XR_NULL_HANDLE);
+ assert(m_oxr->session == XR_NULL_HANDLE);
+ if (m_context->getCustomFuncs()->gpu_ctx_bind_fn == nullptr) {
+ THROW_XR(
+ "Invalid API usage: No way to bind graphics context to the XR session. Call "
+ "GHOST_XrGraphicsContextBindFuncs() with valid parameters before starting the "
+ "session (through GHOST_XrSessionStart()).");
+ }
+
+ initSystem();
+
+ bindGraphicsContext();
+ if (m_gpu_ctx == nullptr) {
+ THROW_XR(
+ "Invalid API usage: No graphics context returned through the callback set with "
+ "GHOST_XrGraphicsContextBindFuncs(). This is required for session starting (through "
+ "GHOST_XrSessionStart()).");
+ }
+
+ std::string requirement_str;
+ m_gpu_binding = GHOST_XrGraphicsBindingCreateFromType(m_context->getGraphicsBindingType());
+ if (!m_gpu_binding->checkVersionRequirements(
+ m_gpu_ctx, m_context->getInstance(), m_oxr->system_id, &requirement_str)) {
+ std::ostringstream strstream;
+ strstream << "Available graphics context version does not meet the following requirements: "
+ << requirement_str;
+ THROW_XR(strstream.str().c_str());
+ }
+ m_gpu_binding->initFromGhostContext(m_gpu_ctx);
+
+ XrSessionCreateInfo create_info{};
+ create_info.type = XR_TYPE_SESSION_CREATE_INFO;
+ create_info.systemId = m_oxr->system_id;
+ create_info.next = &m_gpu_binding->oxr_binding;
+
+ CHECK_XR(xrCreateSession(m_context->getInstance(), &create_info, &m_oxr->session),
+ "Failed to create VR session. The OpenXR runtime may have additional requirements for "
+ "the graphics driver that are not met. Other causes are possible too however.\nTip: "
+ "The --debug-xr command line option for Blender might allow the runtime to output "
+ "detailed error information to the command line.");
+
+ prepareDrawing();
+ create_reference_space(m_oxr.get(), &begin_info->base_pose);
+}
+
+void GHOST_XrSession::end()
+{
+ assert(m_oxr->session != XR_NULL_HANDLE);
+
+ CHECK_XR(xrEndSession(m_oxr->session), "Failed to cleanly end the VR session.");
+ unbindGraphicsContext();
+ m_draw_info = nullptr;
+}
+
+GHOST_XrSession::eLifeExpectancy GHOST_XrSession::handleStateChangeEvent(
+ const XrEventDataSessionStateChanged *lifecycle)
+{
+ /* Runtime may send events for apparently destroyed session. Our handle should be NULL then. */
+ assert((m_oxr->session == XR_NULL_HANDLE) || (m_oxr->session == lifecycle->session));
+
+ switch (lifecycle->state) {
+ case XR_SESSION_STATE_READY: {
+ XrSessionBeginInfo begin_info{XR_TYPE_SESSION_BEGIN_INFO};
+
+ begin_info.primaryViewConfigurationType = m_oxr->view_type;
+ CHECK_XR(xrBeginSession(m_oxr->session, &begin_info),
+ "Failed to cleanly begin the VR session.");
+ break;
+ }
+ case XR_SESSION_STATE_STOPPING:
+ /* Runtime will change state to STATE_EXITING, don't destruct session yet. */
+ end();
+ break;
+ case XR_SESSION_STATE_EXITING:
+ return SESSION_DESTROY;
+ default:
+ break;
+ }
+
+ /* GHOST session state is managed through this. Set last so on parallel execution of GHOST_Xr
+ * calls, state changes only take effect once previous operations in this functions are done. */
+ m_oxr->session_state = lifecycle->state;
+
+ return SESSION_KEEP_ALIVE;
+}
+/** \} */ /* State Management */
+
+/* -------------------------------------------------------------------- */
+/** \name Drawing
+ *
+ * \{ */
+
+static std::vector<XrSwapchainImageBaseHeader *> swapchain_images_create(
+ XrSwapchain swapchain, GHOST_IXrGraphicsBinding *gpu_binding)
+{
+ std::vector<XrSwapchainImageBaseHeader *> images;
+ uint32_t image_count;
+
+ CHECK_XR(xrEnumerateSwapchainImages(swapchain, 0, &image_count, nullptr),
+ "Failed to get count of swapchain images to create for the VR session.");
+ images = gpu_binding->createSwapchainImages(image_count);
+ CHECK_XR(xrEnumerateSwapchainImages(swapchain, images.size(), &image_count, images[0]),
+ "Failed to create swapchain images for the VR session.");
+
+ return images;
+}
+
+static unique_oxr_ptr<XrSwapchain> swapchain_create(const XrSession session,
+ GHOST_IXrGraphicsBinding *gpu_binding,
+ const XrViewConfigurationView *xr_view)
+{
+ XrSwapchainCreateInfo create_info{XR_TYPE_SWAPCHAIN_CREATE_INFO};
+ unique_oxr_ptr<XrSwapchain> swapchain(xrDestroySwapchain);
+ uint32_t format_count = 0;
+ int64_t chosen_format;
+
+ CHECK_XR(xrEnumerateSwapchainFormats(session, 0, &format_count, nullptr),
+ "Failed to get count of swapchain image formats.");
+ std::vector<int64_t> swapchain_formats(format_count);
+ CHECK_XR(xrEnumerateSwapchainFormats(
+ session, swapchain_formats.size(), &format_count, swapchain_formats.data()),
+ "Failed to get swapchain image formats.");
+ assert(swapchain_formats.size() == format_count);
+
+ if (!gpu_binding->chooseSwapchainFormat(swapchain_formats, &chosen_format)) {
+ THROW_XR("Error: No format matching OpenXR runtime supported swapchain formats found.");
+ }
+
+ create_info.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT |
+ XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
+ create_info.format = chosen_format;
+ create_info.sampleCount = xr_view->recommendedSwapchainSampleCount;
+ create_info.width = xr_view->recommendedImageRectWidth;
+ create_info.height = xr_view->recommendedImageRectHeight;
+ create_info.faceCount = 1;
+ create_info.arraySize = 1;
+ create_info.mipCount = 1;
+ CHECK_XR(swapchain.construct(xrCreateSwapchain, session, &create_info),
+ "Failed to create OpenXR swapchain.");
+
+ return swapchain;
+}
+
+void GHOST_XrSession::prepareDrawing()
+{
+ std::vector<XrViewConfigurationView> view_configs;
+ uint32_t view_count;
+
+ CHECK_XR(
+ xrEnumerateViewConfigurationViews(
+ m_context->getInstance(), m_oxr->system_id, m_oxr->view_type, 0, &view_count, nullptr),
+ "Failed to get count of view configurations.");
+ view_configs.resize(view_count, {XR_TYPE_VIEW_CONFIGURATION_VIEW});
+ CHECK_XR(xrEnumerateViewConfigurationViews(m_context->getInstance(),
+ m_oxr->system_id,
+ m_oxr->view_type,
+ view_configs.size(),
+ &view_count,
+ view_configs.data()),
+ "Failed to get count of view configurations.");
+
+ for (const XrViewConfigurationView &view : view_configs) {
+ unique_oxr_ptr<XrSwapchain> swapchain = swapchain_create(
+ m_oxr->session, m_gpu_binding.get(), &view);
+ auto images = swapchain_images_create(swapchain.get(), m_gpu_binding.get());
+
+ m_oxr->swapchain_image_width = view.recommendedImageRectWidth;
+ m_oxr->swapchain_image_height = view.recommendedImageRectHeight;
+ m_oxr->swapchains.push_back(swapchain.get());
+ m_oxr->swapchain_images.insert(std::make_pair(swapchain.get(), std::move(images)));
+
+ swapchain.release();
+ }
+
+ m_oxr->views.resize(view_count, {XR_TYPE_VIEW});
+
+ m_draw_info = std::unique_ptr<GHOST_XrDrawInfo>(new GHOST_XrDrawInfo());
+}
+
+void GHOST_XrSession::beginFrameDrawing()
+{
+ XrFrameWaitInfo wait_info{XR_TYPE_FRAME_WAIT_INFO};
+ XrFrameBeginInfo begin_info{XR_TYPE_FRAME_BEGIN_INFO};
+ XrFrameState frame_state{XR_TYPE_FRAME_STATE};
+
+ CHECK_XR(xrWaitFrame(m_oxr->session, &wait_info, &frame_state),
+ "Failed to synchronize frame rates between Blender and the device.");
+
+ CHECK_XR(xrBeginFrame(m_oxr->session, &begin_info),
+ "Failed to submit frame rendering start state.");
+
+ m_draw_info->frame_state = frame_state;
+
+ if (m_context->isDebugTimeMode()) {
+ m_draw_info->frame_begin_time = std::chrono::high_resolution_clock::now();
+ }
+}
+
+static void print_debug_timings(GHOST_XrDrawInfo *draw_info)
+{
+ /** Render time of last 8 frames (in ms) to calculate an average. */
+ std::chrono::duration<double, std::milli> duration = std::chrono::high_resolution_clock::now() -
+ draw_info->frame_begin_time;
+ const double duration_ms = duration.count();
+ const int avg_frame_count = 8;
+ double avg_ms_tot = 0.0;
+
+ if (draw_info->last_frame_times.size() >= avg_frame_count) {
+ draw_info->last_frame_times.pop_front();
+ assert(draw_info->last_frame_times.size() == avg_frame_count - 1);
+ }
+ draw_info->last_frame_times.push_back(duration_ms);
+ for (double ms_iter : draw_info->last_frame_times) {
+ avg_ms_tot += ms_iter;
+ }
+
+ printf("VR frame render time: %.0fms - %.2f FPS (%.2f FPS 8 frames average)\n",
+ duration_ms,
+ 1000.0 / duration_ms,
+ 1000.0 / (avg_ms_tot / draw_info->last_frame_times.size()));
+}
+
+void GHOST_XrSession::endFrameDrawing(std::vector<XrCompositionLayerBaseHeader *> *layers)
+{
+ XrFrameEndInfo end_info{XR_TYPE_FRAME_END_INFO};
+
+ end_info.displayTime = m_draw_info->frame_state.predictedDisplayTime;
+ end_info.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
+ end_info.layerCount = layers->size();
+ end_info.layers = layers->data();
+
+ CHECK_XR(xrEndFrame(m_oxr->session, &end_info), "Failed to submit rendered frame.");
+
+ if (m_context->isDebugTimeMode()) {
+ print_debug_timings(m_draw_info.get());
+ }
+}
+
+void GHOST_XrSession::draw(void *draw_customdata)
+{
+ std::vector<XrCompositionLayerProjectionView>
+ projection_layer_views; // Keep alive until xrEndFrame() call!
+ XrCompositionLayerProjection proj_layer;
+ std::vector<XrCompositionLayerBaseHeader *> layers;
+
+ assert(shouldRunDrawLoop());
+
+ beginFrameDrawing();
+
+ if (m_draw_info->frame_state.shouldRender) {
+ proj_layer = drawLayer(projection_layer_views, draw_customdata);
+ layers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader *>(&proj_layer));
+ }
+
+ endFrameDrawing(&layers);
+}
+
+static void ghost_xr_draw_view_info_from_view(const XrView &view, GHOST_XrDrawViewInfo &r_info)
+{
+#if 0
+ /* Set and convert to Blender coodinate space */
+ r_info.pose.position[0] = view.pose.position.x;
+ r_info.pose.position[1] = -view.pose.position.z;
+ r_info.pose.position[2] = view.pose.position.y;
+ r_info.pose.orientation_quat[0] = view.pose.orientation.w;
+ r_info.pose.orientation_quat[1] = view.pose.orientation.x;
+ r_info.pose.orientation_quat[2] = -view.pose.orientation.z;
+ r_info.pose.orientation_quat[3] = view.pose.orientation.y;
+#else
+ r_info.pose.position[0] = view.pose.position.x;
+ r_info.pose.position[1] = view.pose.position.y;
+ r_info.pose.position[2] = view.pose.position.z;
+ r_info.pose.orientation_quat[0] = view.pose.orientation.w;
+ r_info.pose.orientation_quat[1] = view.pose.orientation.x;
+ r_info.pose.orientation_quat[2] = view.pose.orientation.y;
+ r_info.pose.orientation_quat[3] = view.pose.orientation.z;
+#endif
+
+ r_info.fov.angle_left = view.fov.angleLeft;
+ r_info.fov.angle_right = view.fov.angleRight;
+ r_info.fov.angle_up = view.fov.angleUp;
+ r_info.fov.angle_down = view.fov.angleDown;
+}
+
+void GHOST_XrSession::drawView(XrSwapchain swapchain,
+ XrCompositionLayerProjectionView &proj_layer_view,
+ XrView &view,
+ void *draw_customdata)
+{
+ XrSwapchainImageAcquireInfo acquire_info{XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO};
+ XrSwapchainImageWaitInfo wait_info{XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO};
+ XrSwapchainImageReleaseInfo release_info{XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO};
+ XrSwapchainImageBaseHeader *swapchain_image;
+ GHOST_XrDrawViewInfo draw_view_info{};
+ GHOST_ContextHandle draw_ctx;
+ uint32_t swapchain_idx;
+
+ CHECK_XR(xrAcquireSwapchainImage(swapchain, &acquire_info, &swapchain_idx),
+ "Failed to acquire swapchain image for the VR session.");
+ wait_info.timeout = XR_INFINITE_DURATION;
+ CHECK_XR(xrWaitSwapchainImage(swapchain, &wait_info),
+ "Failed to acquire swapchain image for the VR session.");
+
+ proj_layer_view.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
+ proj_layer_view.pose = view.pose;
+ proj_layer_view.fov = view.fov;
+ proj_layer_view.subImage.swapchain = swapchain;
+ proj_layer_view.subImage.imageRect.offset = {0, 0};
+ proj_layer_view.subImage.imageRect.extent = {m_oxr->swapchain_image_width,
+ m_oxr->swapchain_image_height};
+
+ swapchain_image = m_oxr->swapchain_images[swapchain][swapchain_idx];
+
+ draw_view_info.ofsx = proj_layer_view.subImage.imageRect.offset.x;
+ draw_view_info.ofsy = proj_layer_view.subImage.imageRect.offset.y;
+ draw_view_info.width = proj_layer_view.subImage.imageRect.extent.width;
+ draw_view_info.height = proj_layer_view.subImage.imageRect.extent.height;
+ ghost_xr_draw_view_info_from_view(view, draw_view_info);
+
+ m_gpu_binding->drawViewBegin(swapchain_image);
+ draw_ctx = m_context->getCustomFuncs()->draw_view_fn(&draw_view_info, draw_customdata);
+ m_gpu_binding->drawViewEnd(swapchain_image, &draw_view_info, (GHOST_Context *)draw_ctx);
+
+ CHECK_XR(xrReleaseSwapchainImage(swapchain, &release_info),
+ "Failed to release swapchain image used to submit VR session frame.");
+}
+
+XrCompositionLayerProjection GHOST_XrSession::drawLayer(
+ std::vector<XrCompositionLayerProjectionView> &proj_layer_views, void *draw_customdata)
+{
+ XrViewLocateInfo viewloc_info{XR_TYPE_VIEW_LOCATE_INFO};
+ XrViewState view_state{XR_TYPE_VIEW_STATE};
+ XrCompositionLayerProjection layer{XR_TYPE_COMPOSITION_LAYER_PROJECTION};
+ uint32_t view_count;
+
+ viewloc_info.viewConfigurationType = m_oxr->view_type;
+ viewloc_info.displayTime = m_draw_info->frame_state.predictedDisplayTime;
+ viewloc_info.space = m_oxr->reference_space;
+
+ CHECK_XR(xrLocateViews(m_oxr->session,
+ &viewloc_info,
+ &view_state,
+ m_oxr->views.size(),
+ &view_count,
+ m_oxr->views.data()),
+ "Failed to query frame view and projection state.");
+ assert(m_oxr->swapchains.size() == view_count);
+
+ proj_layer_views.resize(view_count);
+
+ for (uint32_t view_idx = 0; view_idx < view_count; view_idx++) {
+ drawView(m_oxr->swapchains[view_idx],
+ proj_layer_views[view_idx],
+ m_oxr->views[view_idx],
+ draw_customdata);
+ }
+
+ layer.space = m_oxr->reference_space;
+ layer.viewCount = proj_layer_views.size();
+ layer.views = proj_layer_views.data();
+
+ return layer;
+}
+
+/** \} */ /* Drawing */
+
+/* -------------------------------------------------------------------- */
+/** \name State Queries
+ *
+ * \{ */
+
+bool GHOST_XrSession::shouldRunDrawLoop() const
+{
+ if (m_oxr->session == XR_NULL_HANDLE) {
+ return false;
+ }
+ switch (m_oxr->session_state) {
+ case XR_SESSION_STATE_READY:
+ case XR_SESSION_STATE_SYNCHRONIZED:
+ case XR_SESSION_STATE_VISIBLE:
+ case XR_SESSION_STATE_FOCUSED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/** \} */ /* State Queries */
+
+/* -------------------------------------------------------------------- */
+/** \name Graphics Context Injection
+ *
+ * Sessions need access to Ghost graphics context information. Additionally, this API allows
+ * creating contexts on the fly (created on start, destructed on end). For this, callbacks to bind
+ * (potentially create) and unbind (potentially destruct) a Ghost graphics context have to be set,
+ * which will be called on session start and end respectively.
+ *
+ * \{ */
+
+void GHOST_XrSession::bindGraphicsContext()
+{
+ const GHOST_XrCustomFuncs *custom_funcs = m_context->getCustomFuncs();
+ assert(custom_funcs->gpu_ctx_bind_fn);
+ m_gpu_ctx = static_cast<GHOST_Context *>(
+ custom_funcs->gpu_ctx_bind_fn(m_context->getGraphicsBindingType()));
+}
+void GHOST_XrSession::unbindGraphicsContext()
+{
+ const GHOST_XrCustomFuncs *custom_funcs = m_context->getCustomFuncs();
+ if (custom_funcs->gpu_ctx_unbind_fn) {
+ custom_funcs->gpu_ctx_unbind_fn(m_context->getGraphicsBindingType(), m_gpu_ctx);
+ }
+ m_gpu_ctx = nullptr;
+}
+
+/** \} */ /* Graphics Context Injection */
diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h
new file mode 100644
index 00000000000..56bba7130b0
--- /dev/null
+++ b/intern/ghost/intern/GHOST_XrSession.h
@@ -0,0 +1,77 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_XRSESSION_H__
+#define __GHOST_XRSESSION_H__
+
+#include <map>
+#include <memory>
+
+class GHOST_XrSession {
+ public:
+ enum eLifeExpectancy {
+ SESSION_KEEP_ALIVE,
+ SESSION_DESTROY,
+ };
+
+ GHOST_XrSession(class GHOST_XrContext *xr_context);
+ ~GHOST_XrSession();
+
+ void start(const GHOST_XrSessionBeginInfo *begin_info);
+ void end();
+
+ eLifeExpectancy handleStateChangeEvent(const struct XrEventDataSessionStateChanged *lifecycle);
+
+ bool shouldRunDrawLoop() const;
+
+ void unbindGraphicsContext(); /* public so context can ensure it's unbound as needed. */
+
+ void draw(void *draw_customdata);
+
+ private:
+ /** Pointer back to context managing this session. Would be nice to avoid, but needed to access
+ * custom callbacks set before session start. */
+ class GHOST_XrContext *m_context;
+
+ std::unique_ptr<struct OpenXRSessionData> m_oxr; /* Could use stack, but PImpl is preferable */
+
+ /** Active Ghost graphic context. Owned by Blender, not GHOST. */
+ class GHOST_Context *m_gpu_ctx{nullptr};
+ std::unique_ptr<class GHOST_IXrGraphicsBinding> m_gpu_binding;
+
+ /** Rendering information. Set when drawing starts. */
+ std::unique_ptr<struct GHOST_XrDrawInfo> m_draw_info;
+
+ void initSystem();
+
+ void bindGraphicsContext();
+
+ void prepareDrawing();
+ XrCompositionLayerProjection drawLayer(
+ std::vector<XrCompositionLayerProjectionView> &proj_layer_views, void *draw_customdata);
+ void drawView(XrSwapchain swapchain,
+ XrCompositionLayerProjectionView &proj_layer_view,
+ XrView &view,
+ void *draw_customdata);
+ void beginFrameDrawing();
+ void endFrameDrawing(std::vector<XrCompositionLayerBaseHeader *> *layers);
+};
+
+#endif /* GHOST_XRSESSION_H__ */
diff --git a/intern/ghost/intern/GHOST_Xr_intern.h b/intern/ghost/intern/GHOST_Xr_intern.h
new file mode 100644
index 00000000000..df68ccedd4f
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Xr_intern.h
@@ -0,0 +1,123 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#ifndef __GHOST_XR_INTERN_H__
+#define __GHOST_XR_INTERN_H__
+
+#include <memory>
+#include <vector>
+
+#include "GHOST_Xr_openxr_includes.h"
+
+#define CHECK_XR(call, error_msg) \
+ { \
+ XrResult _res = call; \
+ if (XR_FAILED(_res)) { \
+ throw GHOST_XrException(error_msg, __FILE__, __LINE__, _res); \
+ } \
+ }
+
+#define THROW_XR(error_msg) throw GHOST_XrException(error_msg, __FILE__, __LINE__);
+
+#define XR_DEBUG_ONLY_BEGIN(ctx) \
+ if ((ctx)->isDebugMode()) { \
+ (void)0
+#define XR_DEBUG_ONLY_END \
+ } \
+ (void)0
+
+#define XR_DEBUG_PRINTF(ctx, ...) \
+ if ((ctx)->isDebugMode()) { \
+ printf(__VA_ARGS__); \
+ } \
+ (void)0
+
+#define XR_DEBUG_ONLY_CALL(ctx, call) \
+ if ((ctx)->isDebugMode()) { \
+ call; \
+ } \
+ (void)0
+
+/**
+ * Helper for RAII usage of OpenXR handles (defined with XR_DEFINE_HANDLE). This is based on
+ * `std::unique_ptr`, to give similar behavior and usage (e.g. functions like #get() and #release()
+ * are supported).
+ */
+template<typename _OXR_HANDLE> class unique_oxr_ptr {
+ public:
+ using xr_destroy_func = XrResult (*)(_OXR_HANDLE);
+
+ unique_oxr_ptr(xr_destroy_func destroy_fn) : m_destroy_fn(destroy_fn)
+ {
+ }
+
+ unique_oxr_ptr(unique_oxr_ptr &&other) : m_ptr(other.release()), m_destroy_fn(other.m_destroy_fn)
+ {
+ }
+
+ /**
+ * Construct the pointer from a xrCreate function passed as \a create_fn, with additional
+ * arguments forwarded from \a args.
+ * For example, this:
+ * \code
+ * some_unique_oxr_ptr.contruct(xrCreateFoo, some_arg, some_other_arg);
+ * \endcode
+ * effectively results in this call:
+ * \code
+ * xrCreateFoo(some_arg, some_other_arg, &some_unique_oxr_ptr.m_ptr);
+ * \endcode
+ */
+ template<typename _create_func, typename... _Args>
+ XrResult construct(_create_func create_fn, _Args &&... args)
+ {
+ assert(m_ptr == XR_NULL_HANDLE);
+ return create_fn(std::forward<_Args>(args)..., &m_ptr);
+ }
+
+ ~unique_oxr_ptr()
+ {
+ if (m_ptr != XR_NULL_HANDLE) {
+ m_destroy_fn(m_ptr);
+ }
+ }
+
+ _OXR_HANDLE get()
+ {
+ return m_ptr;
+ }
+
+ _OXR_HANDLE release()
+ {
+ _OXR_HANDLE ptr = get();
+ m_ptr = XR_NULL_HANDLE;
+ return ptr;
+ }
+
+ /* operator= defines not needed for now. */
+
+ unique_oxr_ptr(const unique_oxr_ptr &) = delete;
+ unique_oxr_ptr &operator=(const unique_oxr_ptr &) = delete;
+
+ private:
+ _OXR_HANDLE m_ptr{XR_NULL_HANDLE};
+ xr_destroy_func m_destroy_fn;
+};
+
+#endif /* __GHOST_XR_INTERN_H__ */
diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
new file mode 100644
index 00000000000..925d6037750
--- /dev/null
+++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
@@ -0,0 +1,52 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ *
+ * \note This is taken mostly from the OpenXR SDK, but with modified D3D versions (e.g. d3d11_4.h
+ * -> d3d11.h). Take care for that when updating, we don't want to require newest Win SDKs to be
+ * installed.
+ */
+
+#ifndef __GHOST_XR_SYSTEM_INCLUDES_H__
+#define __GHOST_XR_SYSTEM_INCLUDES_H__
+
+/* Platform headers */
+#ifdef XR_USE_PLATFORM_WIN32
+# define WIN32_LEAN_AND_MEAN
+# define NOMINMAX
+# include <windows.h>
+#endif
+
+/* Graphics headers */
+#ifdef XR_USE_GRAPHICS_API_D3D10
+# include <d3d10_1.h>
+#endif
+#ifdef XR_USE_GRAPHICS_API_D3D11
+# include <d3d11.h>
+#endif
+#ifdef XR_USE_GRAPHICS_API_D3D12
+# include <d3d12.h>
+#endif
+#ifdef WITH_X11
+# include <GL/glxew.h>
+#endif
+
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#endif /* __GHOST_XR_SYSTEM_INCLUDES_H__ */
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index f735e7b770f..43d5bae5fb3 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -555,11 +555,14 @@ class TOPBAR_MT_window(Menu):
if sys.platform[:3] == "win":
layout.separator()
layout.operator("wm.console_toggle", icon='CONSOLE')
+ layout.separator()
if context.scene.render.use_multiview:
layout.separator()
layout.operator("wm.set_stereo_3d")
+ # TODO WITH_OPENXR
+ layout.operator("wm.xr_session_toggle")
class TOPBAR_MT_help(Menu):
bl_label = "Help"
diff --git a/release/windows/batch/blender_oculus.cmd b/release/windows/batch/blender_oculus.cmd
new file mode 100644
index 00000000000..39dcfebcbf1
--- /dev/null
+++ b/release/windows/batch/blender_oculus.cmd
@@ -0,0 +1,10 @@
+@echo off
+echo Starting blender with oculus openXR support, this assumes the oculus runtime
+echo is installed in the default location, if this is not the case please adjust the
+echo path inside oculus.josn
+echo.
+echo please note that openXR support is EXTREMELY experimental at this point
+echo.
+pause
+set XR_RUNTIME_JSON=%~dp0oculus.json
+blender \ No newline at end of file
diff --git a/release/windows/batch/oculus.json b/release/windows/batch/oculus.json
new file mode 100644
index 00000000000..6df75041ca0
--- /dev/null
+++ b/release/windows/batch/oculus.json
@@ -0,0 +1,7 @@
+{
+ "file_format_version": "1.0.0",
+ "runtime": {
+ "library_path": "c:\\Program Files\\Oculus\\Support\\oculus-runtime\\LibOVRRT64_1.dll"
+ },
+ "api_layer": { }
+}
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index bee76c09cbc..de875457b2e 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -151,6 +151,8 @@ enum {
G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/
G_DEBUG_GPU_SHADERS = (1 << 18), /* GLSL shaders */
G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 19), /* force gpu workarounds bypassing detections. */
+ G_DEBUG_XR = (1 << 20), /* XR/OpenXR messages */
+ G_DEBUG_XR_TIME = (1 << 21), /* XR/OpenXR timing messages */
};
#define G_DEBUG_ALL \
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index d9bd87d97b5..5719fc0164b 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -613,6 +613,10 @@ if(WITH_OPENVDB)
endif()
endif()
+if(WITH_OPENXR)
+ add_definitions(-DWITH_OPENXR)
+endif()
+
## Warnings as errors, this is too strict!
#if(MSVC)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index d5485765844..c1618061b38 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -610,6 +610,13 @@ void perspective_m4(float mat[4][4],
const float top,
const float nearClip,
const float farClip);
+void perspective_m4_fov(float mat[4][4],
+ const float angle_left,
+ const float angle_right,
+ const float angle_up,
+ const float angle_down,
+ const float nearClip,
+ const float farClip);
void orthographic_m4(float mat[4][4],
const float left,
const float right,
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 7cdac6b1497..3a562778af7 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -4364,6 +4364,33 @@ void perspective_m4(float mat[4][4],
mat[3][3] = 0.0f;
}
+void perspective_m4_fov(float mat[4][4],
+ const float angle_left,
+ const float angle_right,
+ const float angle_up,
+ const float angle_down,
+ const float nearClip,
+ const float farClip)
+{
+ const float tan_angle_left = tanf(angle_left);
+ const float tan_angle_right = tanf(angle_right);
+ const float tan_angle_up = tanf(angle_up);
+ const float tan_angle_down = tanf(angle_down);
+ const float Xdelta = tan_angle_right - tan_angle_left;
+ const float Ydelta = tan_angle_up - tan_angle_down;
+
+ mat[0][0] = 2 / Xdelta;
+ mat[1][1] = 2 / Ydelta;
+ mat[2][0] = (tan_angle_right + tan_angle_left) / Xdelta;
+ mat[2][1] = (tan_angle_up + tan_angle_down) / Ydelta;
+ mat[2][2] = -(farClip + nearClip) / (farClip - nearClip);
+ mat[2][3] = -1;
+ mat[3][2] = -(farClip * (nearClip + nearClip)) / (farClip - nearClip);
+
+ mat[0][1] = mat[0][2] = mat[0][3] = mat[1][0] = mat[1][2] = mat[1][3] = mat[3][0] = mat[3][1] =
+ mat[3][3] = 0.0f;
+}
+
/* translate a matrix created by orthographic_m4 or perspective_m4 in XY coords
* (used to jitter the view) */
void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x, const float y)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 44bb07d87f8..a73ca6e896c 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -7702,6 +7702,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
wm->undo_stack = NULL;
wm->message_bus = NULL;
+ wm->xr_context = NULL;
BLI_listbase_clear(&wm->jobs);
BLI_listbase_clear(&wm->drags);
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index be04452f079..f9963fa67b7 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -159,6 +159,11 @@ void DRW_opengl_context_destroy(void);
void DRW_opengl_context_enable(void);
void DRW_opengl_context_disable(void);
+/* Not nice to expose these. Code to render offscreen viewports can save expensive context switches
+ * by using this directly however. */
+void *DRW_opengl_context_get(void);
+void *DRW_gpu_context_get(void);
+
/* For garbage collection */
void DRW_cache_free_old_batches(struct Main *bmain);
@@ -166,8 +171,12 @@ void DRW_cache_free_old_batches(struct Main *bmain);
void DRW_opengl_context_enable_ex(bool restore);
void DRW_opengl_context_disable_ex(bool restore);
+void DRW_opengl_render_context_enable_ex(void *re_gl_context);
void DRW_opengl_render_context_enable(void *re_gl_context);
+void DRW_opengl_render_context_disable_ex(void *re_gl_context);
void DRW_opengl_render_context_disable(void *re_gl_context);
+void DRW_render_context_draw_begin();
+void DRW_render_context_draw_end();
void DRW_gawain_render_context_enable(void *re_gpu_context);
void DRW_gawain_render_context_disable(void *re_gpu_context);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index a6c671a631a..4b958a74bf9 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -524,7 +524,7 @@ const float *DRW_viewport_pixelsize_get(void)
return &DST.pixsize;
}
-static void drw_viewport_cache_resize(void)
+void drw_viewport_cache_resize(void)
{
/* Release the memiter before clearing the mempools that references them */
GPU_viewport_cache_release(DST.viewport);
@@ -3010,20 +3010,50 @@ void DRW_opengl_context_disable(void)
DRW_opengl_context_disable_ex(true);
}
-void DRW_opengl_render_context_enable(void *re_gl_context)
+void *DRW_opengl_context_get(void)
+{
+ return DST.gl_context;
+}
+
+void *DRW_gpu_context_get(void)
+{
+ return DST.gpu_context;
+}
+
+void DRW_opengl_render_context_enable_ex(void *re_gl_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
BLI_assert(!BLI_thread_is_main());
- /* TODO get rid of the blocking. Only here because of the static global DST. */
- BLI_ticket_mutex_lock(DST.gl_context_mutex);
WM_opengl_context_activate(re_gl_context);
}
+void DRW_opengl_render_context_enable(void *re_gl_context)
+{
+ DRW_opengl_render_context_enable_ex(re_gl_context);
+ DRW_render_context_draw_begin();
+}
-void DRW_opengl_render_context_disable(void *re_gl_context)
+void DRW_opengl_render_context_disable_ex(void *re_gl_context)
{
GPU_flush();
WM_opengl_context_release(re_gl_context);
+}
+void DRW_opengl_render_context_disable(void *re_gl_context)
+{
+ DRW_opengl_render_context_disable_ex(re_gl_context);
+ DRW_render_context_draw_end();
+}
+
+void DRW_render_context_draw_begin()
+{
+ BLI_assert(!BLI_thread_is_main());
+ /* TODO get rid of the blocking. */
+ BLI_ticket_mutex_lock(DST.gl_context_mutex);
+}
+
+void DRW_render_context_draw_end()
+{
+ // GPU_flush();
/* TODO get rid of the blocking. */
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
}
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index afdbbeedff4..204011fe46a 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -581,6 +581,24 @@ void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
const bool do_color_management,
struct GPUOffScreen *ofs,
struct GPUViewport *viewport);
+void ED_view3d_draw_offscreen_simple(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct View3DShading *shading_override,
+ int drawtype,
+ int winx,
+ int winy,
+ unsigned int draw_flags,
+ float viewmat[4][4],
+ float winmat[4][4],
+ float clip_start,
+ float clip_end,
+ float lens,
+ bool do_sky,
+ bool is_persp,
+ const char *viewname,
+ const bool do_color_management,
+ struct GPUOffScreen *ofs,
+ struct GPUViewport *viewport);
void ED_view3d_draw_setup_view(struct wmWindow *win,
struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 6ea4e832b58..31d00942e8c 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1593,6 +1593,85 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
G.f &= ~G_FLAG_RENDER_VIEWPORT;
}
+void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
+ Scene *scene,
+ View3DShading *shading_override,
+ int drawtype,
+ int winx,
+ int winy,
+ uint draw_flags,
+ float viewmat[4][4],
+ float winmat[4][4],
+ float clip_start,
+ float clip_end,
+ float lens,
+ bool do_sky,
+ bool is_persp,
+ const char *viewname,
+ const bool do_color_management,
+ GPUOffScreen *ofs,
+ GPUViewport *viewport)
+{
+ View3D v3d = {NULL};
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+
+ /* connect data */
+ v3d.regionbase.first = v3d.regionbase.last = &ar;
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+
+ View3DShading *source_shading_settings = &scene->display.shading;
+ if (draw_flags & V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS && shading_override != NULL) {
+ source_shading_settings = shading_override;
+ }
+ memcpy(&v3d.shading, source_shading_settings, sizeof(View3DShading));
+ v3d.shading.type = drawtype;
+
+ if (drawtype == OB_MATERIAL) {
+ v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS;
+ }
+
+ if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) {
+ v3d.flag2 |= V3D_SHOW_ANNOTATION;
+ }
+ if (draw_flags & V3D_OFSDRAW_SHOW_GRIDFLOOR) {
+ v3d.gridflag |= V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y;
+ v3d.grid = 1.0f;
+ v3d.gridlines = 16;
+ v3d.gridsubdiv = 10;
+
+ /* Show grid, disable other overlays (set all available _HIDE_ flags). */
+ v3d.overlay.flag |= V3D_OVERLAY_HIDE_CURSOR | V3D_OVERLAY_HIDE_TEXT |
+ V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_BONES |
+ V3D_OVERLAY_HIDE_OBJECT_XTRAS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
+ }
+ else {
+ v3d.flag2 = V3D_HIDE_OVERLAYS;
+ }
+
+ rv3d.persp = RV3D_PERSP;
+ v3d.clip_start = clip_start;
+ v3d.clip_end = clip_end;
+ v3d.lens = lens;
+
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ &v3d,
+ &ar,
+ winx,
+ winy,
+ viewmat,
+ winmat,
+ do_sky,
+ is_persp,
+ viewname,
+ do_color_management,
+ ofs,
+ viewport);
+}
+
/**
* Utility func for ED_view3d_draw_offscreen
*
@@ -1786,6 +1865,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) {
v3d.flag2 |= V3D_SHOW_ANNOTATION;
}
+ if (draw_flags & V3D_OFSDRAW_SHOW_GRIDFLOOR) {
+ v3d.gridflag |= V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y;
+ }
v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index c620644a5f8..fb7d3c1ace8 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -116,6 +116,7 @@ set(SRC
intern/gpu_batch_private.h
intern/gpu_codegen.h
intern/gpu_context_private.h
+ intern/gpu_matrix_private.h
intern/gpu_primitive_private.h
intern/gpu_private.h
intern/gpu_select_private.h
diff --git a/source/blender/gpu/intern/gpu_context.cpp b/source/blender/gpu/intern/gpu_context.cpp
index a0e03e61d5d..12a5748b198 100644
--- a/source/blender/gpu/intern/gpu_context.cpp
+++ b/source/blender/gpu/intern/gpu_context.cpp
@@ -36,6 +36,7 @@
#include "gpu_batch_private.h"
#include "gpu_context_private.h"
+#include "gpu_matrix_private.h"
#include <vector>
#include <string.h>
@@ -71,6 +72,7 @@ struct GPUContext {
std::unordered_set<GPUFrameBuffer *>
framebuffers; /* Framebuffers that have FBO from this context */
#endif
+ struct GPUMatrixState *matrix_state;
std::vector<GLuint> orphaned_vertarray_ids;
std::vector<GLuint> orphaned_framebuffer_ids;
std::mutex orphans_mutex; /* todo: try spinlock instead */
@@ -144,6 +146,7 @@ GPUContext *GPU_context_create(GLuint default_framebuffer)
GPUContext *ctx = new GPUContext;
glGenVertexArrays(1, &ctx->default_vao);
ctx->default_framebuffer = default_framebuffer;
+ ctx->matrix_state = GPU_matrix_state_create();
GPU_context_active_set(ctx);
return ctx;
}
@@ -164,6 +167,7 @@ void GPU_context_discard(GPUContext *ctx)
/* this removes the array entry */
GPU_batch_vao_cache_clear(*ctx->batches.begin());
}
+ GPU_matrix_state_discard(ctx->matrix_state);
glDeleteVertexArrays(1, &ctx->default_vao);
delete ctx;
active_ctx = NULL;
@@ -338,3 +342,9 @@ GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx)
{
return ctx->current_fbo;
}
+
+struct GPUMatrixState *gpu_context_active_matrix_state_get()
+{
+ BLI_assert(active_ctx);
+ return active_ctx->matrix_state;
+}
diff --git a/source/blender/gpu/intern/gpu_context_private.h b/source/blender/gpu/intern/gpu_context_private.h
index 6825b67d2c8..09248e45502 100644
--- a/source/blender/gpu/intern/gpu_context_private.h
+++ b/source/blender/gpu/intern/gpu_context_private.h
@@ -59,6 +59,8 @@ void gpu_context_remove_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb);
void gpu_context_active_framebuffer_set(GPUContext *ctx, struct GPUFrameBuffer *fb);
struct GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx);
+struct GPUMatrixState *gpu_context_active_matrix_state_get();
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 58ca800a92c..fb0dffb58d1 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -23,6 +23,9 @@
#include "GPU_shader_interface.h"
+#include "gpu_context_private.h"
+#include "gpu_matrix_private.h"
+
#define SUPPRESS_GENERIC_MATRIX_API
#define USE_GPU_PY_MATRIX_API /* only so values are declared */
#include "GPU_matrix.h"
@@ -32,6 +35,8 @@
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
+#include "MEM_guardedalloc.h"
+
#define DEBUG_MATRIX_BIND 0
#define MATRIX_STACK_DEPTH 32
@@ -44,7 +49,7 @@ typedef struct MatrixStack {
uint top;
} MatrixStack;
-typedef struct {
+typedef struct GPUMatrixState {
MatrixStack model_view_stack;
MatrixStack projection_stack;
@@ -56,8 +61,16 @@ typedef struct {
* TODO: separate Model from View transform? Batches/objects have model,
* camera/eye has view & projection
*/
-} MatrixState;
+} GPUMatrixState;
+
+#define ModelViewStack gpu_context_active_matrix_state_get()->model_view_stack
+#define ModelView ModelViewStack.stack[ModelViewStack.top]
+#define ProjectionStack gpu_context_active_matrix_state_get()->projection_stack
+#define Projection ProjectionStack.stack[ProjectionStack.top]
+
+GPUMatrixState *GPU_matrix_state_create(void)
+{
#define MATRIX_4X4_IDENTITY \
{ \
{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, \
@@ -66,27 +79,36 @@ typedef struct {
} \
}
-static MatrixState state = {
- .model_view_stack = {{MATRIX_4X4_IDENTITY}, 0},
- .projection_stack = {{MATRIX_4X4_IDENTITY}, 0},
- .dirty = true,
-};
+ GPUMatrixState *state = MEM_mallocN(sizeof(*state), __func__);
+ const MatrixStack identity_stack = {{MATRIX_4X4_IDENTITY}, 0};
+
+ state->model_view_stack = state->projection_stack = identity_stack;
+ state->dirty = true;
#undef MATRIX_4X4_IDENTITY
-#define ModelViewStack state.model_view_stack
-#define ModelView ModelViewStack.stack[ModelViewStack.top]
+ return state;
+}
-#define ProjectionStack state.projection_stack
-#define Projection ProjectionStack.stack[ProjectionStack.top]
+void GPU_matrix_state_discard(GPUMatrixState *state)
+{
+ MEM_freeN(state);
+}
+
+static void gpu_matrix_state_active_set_dirty(bool value)
+{
+ GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ state->dirty = value;
+}
void GPU_matrix_reset(void)
{
- state.model_view_stack.top = 0;
- state.projection_stack.top = 0;
+ GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ state->model_view_stack.top = 0;
+ state->projection_stack.top = 0;
unit_m4(ModelView);
unit_m4(Projection);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
#ifdef WITH_GPU_SAFETY
@@ -123,7 +145,7 @@ void GPU_matrix_pop(void)
{
BLI_assert(ModelViewStack.top > 0);
ModelViewStack.top--;
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_push_projection(void)
@@ -137,34 +159,34 @@ void GPU_matrix_pop_projection(void)
{
BLI_assert(ProjectionStack.top > 0);
ProjectionStack.top--;
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_set(const float m[4][4])
{
copy_m4_m4(ModelView, m);
CHECKMAT(ModelView3D);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_identity_projection_set(void)
{
unit_m4(Projection);
CHECKMAT(Projection3D);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_projection_set(const float m[4][4])
{
copy_m4_m4(Projection, m);
CHECKMAT(Projection3D);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_identity_set(void)
{
unit_m4(ModelView);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_translate_2f(float x, float y)
@@ -194,7 +216,7 @@ void GPU_matrix_translate_3f(float x, float y, float z)
m[3][2] = z;
GPU_matrix_mul(m);
#endif
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_translate_3fv(const float vec[3])
@@ -243,7 +265,7 @@ void GPU_matrix_mul(const float m[4][4])
{
mul_m4_m4_post(ModelView, m);
CHECKMAT(ModelView);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_rotate_2d(float deg)
@@ -272,7 +294,7 @@ void GPU_matrix_rotate_axis(float deg, char axis)
/* rotate_m4 works in place */
rotate_m4(ModelView, axis, DEG2RADF(deg));
CHECKMAT(ModelView);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
static void mat4_ortho_set(
@@ -298,7 +320,7 @@ static void mat4_ortho_set(
m[2][3] = 0.0f;
m[3][3] = 1.0f;
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
static void mat4_frustum_set(
@@ -324,7 +346,7 @@ static void mat4_frustum_set(
m[2][3] = -1.0f;
m[3][3] = 0.0f;
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3])
@@ -389,14 +411,14 @@ static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3
m[2][3] = 0.0f;
m[3][3] = 1.0f;
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far)
{
mat4_ortho_set(Projection, left, right, bottom, top, near, far);
CHECKMAT(Projection);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top)
@@ -404,7 +426,7 @@ void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top)
Mat4 m;
mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f);
CHECKMAT(Projection2D);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_frustum_set(
@@ -412,7 +434,7 @@ void GPU_matrix_frustum_set(
{
mat4_frustum_set(Projection, left, right, bottom, top, near, far);
CHECKMAT(Projection);
- state.dirty = true;
+ gpu_matrix_state_active_set_dirty(true);
}
void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far)
@@ -678,12 +700,13 @@ void GPU_matrix_bind(const GPUShaderInterface *shaderface)
glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m);
}
- state.dirty = false;
+ gpu_matrix_state_active_set_dirty(false);
}
bool GPU_matrix_dirty_get(void)
{
- return state.dirty;
+ GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ return state->dirty;
}
/* -------------------------------------------------------------------- */
@@ -695,12 +718,14 @@ BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mis
int GPU_matrix_stack_level_get_model_view(void)
{
- return (int)state.model_view_stack.top;
+ GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ return (int)state->model_view_stack.top;
}
int GPU_matrix_stack_level_get_projection(void)
{
- return (int)state.projection_stack.top;
+ GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ return (int)state->projection_stack.top;
}
/** \} */
diff --git a/source/blender/gpu/intern/gpu_matrix_private.h b/source/blender/gpu/intern/gpu_matrix_private.h
new file mode 100644
index 00000000000..862ef065481
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_matrix_private.h
@@ -0,0 +1,35 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_MATRIX_PRIVATE_H__
+#define __GPU_MATRIX_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct GPUMatrixState *GPU_matrix_state_create(void);
+void GPU_matrix_state_discard(struct GPUMatrixState *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_MATRIX_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index e3c13b0ec14..20e9b42ee05 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -467,8 +467,6 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
int rect_w = BLI_rcti_size_x(rect) + 1;
int rect_h = BLI_rcti_size_y(rect) + 1;
- DRW_opengl_context_enable();
-
if (dfbl->default_fb) {
if (rect_w != viewport->size[0] || rect_h != viewport->size[1] ||
U.ogl_multisamples != viewport->samples) {
@@ -553,7 +551,6 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
{
GPU_framebuffer_restore();
- DRW_opengl_context_disable();
}
GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport)
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index e7a4f9cbd4e..a22aeb4cedf 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -590,6 +590,7 @@ enum {
V3D_OFSDRAW_NONE = (0),
V3D_OFSDRAW_SHOW_ANNOTATION = (1 << 0),
V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS = (1 << 1),
+ V3D_OFSDRAW_SHOW_GRIDFLOOR = (1 << 2),
};
#define RV3D_CAMZOOM_MIN -30
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 8dcae41aaa2..ca7ceb048ae 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -42,6 +42,7 @@ struct wmKeyMap;
struct wmMsgBus;
struct wmOperator;
struct wmOperatorType;
+struct GHOST_XrContext;
/* forwards */
struct PointerRNA;
@@ -178,6 +179,9 @@ typedef struct wmWindowManager {
struct wmMsgBus *message_bus;
+ //#ifdef WITH_OPENXR
+ void *xr_context; /* GHOST_XrContextHandle */
+ //#endif
} wmWindowManager;
/* wmWindowManager.initialized */
@@ -201,6 +205,8 @@ typedef struct wmWindow {
/** Don't want to include ghost.h stuff. */
void *ghostwin;
+ /** Ghost context for rendering the window offscreen (usually unused). */
+ void *offscreen_context;
/** Don't want to include gpu stuff. */
void *gpuctx;
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 64f506f03a8..f05ea317832 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -71,11 +71,13 @@ set(SRC
intern/wm_playanim.c
intern/wm_stereo.c
intern/wm_subwindow.c
+ intern/wm_surface.c
intern/wm_toolsystem.c
intern/wm_tooltip.c
intern/wm_uilist_type.c
intern/wm_utils.c
intern/wm_window.c
+ intern/wm_xr.c
gizmo/intern/wm_gizmo.c
gizmo/intern/wm_gizmo_group.c
gizmo/intern/wm_gizmo_group_type.c
@@ -97,6 +99,7 @@ set(SRC
wm_event_system.h
wm_event_types.h
wm_files.h
+ wm_surface.h
wm_window.h
gizmo/WM_gizmo_api.h
gizmo/WM_gizmo_types.h
@@ -174,4 +177,8 @@ if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
+if(WITH_OPENXR)
+ add_definitions(-DWITH_OPENXR)
+endif()
+
blender_add_lib_nolist(bf_windowmanager "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 5d6e405dd5d..76ab06e0020 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -112,6 +112,7 @@ int WM_window_pixels_x(const struct wmWindow *win);
int WM_window_pixels_y(const struct wmWindow *win);
void WM_window_rect_calc(const struct wmWindow *win, struct rcti *r_rect);
void WM_window_screen_rect_calc(const struct wmWindow *win, struct rcti *r_rect);
+bool WM_window_is_non_opengl(const wmWindow *win);
bool WM_window_is_fullscreen(struct wmWindow *win);
void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATTR_NONNULL();
@@ -156,6 +157,10 @@ void *WM_opengl_context_create(void);
void WM_opengl_context_dispose(void *context);
void WM_opengl_context_activate(void *context);
void WM_opengl_context_release(void *context);
+#ifdef WIN32
+void *WM_directx_context_create(void);
+void WM_directx_context_dispose(void *context);
+#endif
/* defines for 'type' WM_window_open_temp */
enum {
@@ -168,6 +173,7 @@ enum {
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
struct wmWindow *WM_window_open_temp(
struct bContext *C, int x, int y, int sizex, int sizey, int type);
+struct wmWindow *WM_window_open_directx(struct bContext *C, const rcti *rect);
void WM_window_set_dpi(wmWindow *win);
bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 77e17ad4687..913b939bb87 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -52,6 +52,9 @@
#include "wm_event_system.h"
#include "wm_draw.h"
#include "wm.h"
+#ifdef WITH_OPENXR
+# include "GHOST_C-api.h"
+#endif
#include "ED_screen.h"
#include "BKE_undo_system.h"
@@ -374,6 +377,12 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
WM_msgbus_destroy(wm->message_bus);
}
+#ifdef WITH_OPENXR
+ if (wm->xr_context != NULL) {
+ GHOST_XrContextDestroy(wm->xr_context);
+ }
+#endif
+
BLI_freelistN(&wm->paintcursors);
WM_drag_free_list(&wm->drags);
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 3bcb955c2b2..4024fc628f0 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -48,6 +48,8 @@
#include "BKE_scene.h"
#include "BKE_workspace.h"
+#include "DRW_engine.h"
+
#include "GHOST_C-api.h"
#include "ED_node.h"
@@ -72,6 +74,7 @@
#include "wm_draw.h"
#include "wm_window.h"
#include "wm_event_system.h"
+#include "wm_surface.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_subsurf.h"
@@ -315,7 +318,7 @@ static void wm_draw_region_buffer_free(ARegion *ar)
}
}
-static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
+void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
{
/* Setup offscreen color texture for drawing. */
GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
@@ -399,6 +402,7 @@ static void wm_draw_region_bind(ARegion *ar, int view)
}
if (ar->draw_buffer->viewport[view]) {
+ DRW_opengl_context_enable();
GPU_viewport_bind(ar->draw_buffer->viewport[view], &ar->winrct);
}
else {
@@ -423,6 +427,7 @@ static void wm_draw_region_unbind(ARegion *ar, int view)
if (ar->draw_buffer->viewport[view]) {
GPU_viewport_unbind(ar->draw_buffer->viewport[view]);
+ DRW_opengl_context_disable();
}
else {
glDisable(GL_SCISSOR_TEST);
@@ -747,6 +752,60 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
}
}
+void wm_draw_upside_down(int sizex, int sizey)
+{
+ /* Don't use imm here, this is called from a separate thread with no imm available. */
+
+ /* wmOrtho for the screen has this same offset */
+ const float halfx = GLA_PIXEL_OFS / sizex;
+ const float halfy = GLA_PIXEL_OFS / sizey;
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
+
+ glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"),
+ halfx,
+ halfy,
+ 1.0f + halfx,
+ 1.0f + halfy);
+ glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), 0, sizey, sizex, 0);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
+
+ GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
+}
+
+static void wm_draw_window_upside_down_onscreen(bContext *C, wmWindow *win)
+{
+ const int width = WM_window_pixels_x(win);
+ const int height = WM_window_pixels_y(win);
+ GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL);
+
+ /* Upside down rendering only implemented for non-stereo. Easy to add but makes code messy. */
+ BLI_assert(
+ !(WM_stereo3d_enabled(win, false) && GHOST_isUpsideDownWindow(win->offscreen_context)));
+
+ if (offscreen) {
+ GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
+ wm_draw_offscreen_texture_parameters(offscreen);
+
+ /* Draw view into offscreen buffer. */
+ GPU_offscreen_bind(offscreen, false);
+ wm_draw_window_onscreen(C, win, -1);
+ GPU_offscreen_unbind(offscreen, false);
+
+ /* Draw offscreen buffer to screen. */
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
+
+ wm_draw_upside_down(win->sizex, win->sizey);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ GPU_offscreen_free(offscreen);
+ }
+}
+
static void wm_draw_window(bContext *C, wmWindow *win)
{
bScreen *screen = WM_window_get_active_screen(win);
@@ -758,8 +817,13 @@ static void wm_draw_window(bContext *C, wmWindow *win)
/* Now we draw into the window framebuffer, in full window coordinates. */
if (!stereo) {
- /* Regular mono drawing. */
- wm_draw_window_onscreen(C, win, -1);
+ if (GHOST_isUpsideDownWindow(win->ghostwin)) {
+ wm_draw_window_upside_down_onscreen(C, win);
+ }
+ else {
+ /* Regular mono drawing. */
+ wm_draw_window_onscreen(C, win, -1);
+ }
}
else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
/* For pageflip we simply draw to both back buffers. */
@@ -817,6 +881,22 @@ static void wm_draw_window(bContext *C, wmWindow *win)
screen->do_draw = false;
}
+/**
+ * Draw offscreen contexts not bound to a specific window.
+ */
+static void wm_draw_surface(bContext *C, wmSurface *surface)
+{
+ // wm_window_clear_drawable(CTX_wm_manager(C));
+ // wm_surface_make_drawable(surface);
+
+ surface->draw(C);
+
+ // wm_surface_present(surface);
+
+ /* Avoid interference with window drawable */
+ // wm_surface_clear_drawable();
+}
+
/****************** main update call **********************/
/* quick test to prevent changing window drawable */
@@ -939,11 +1019,14 @@ void wm_draw_update(bContext *C)
wm_draw_window(C, win);
wm_draw_update_clear_window(win);
- wm_window_swap_buffers(win);
+ wm_window_present(win);
CTX_wm_window_set(C, NULL);
}
}
+
+ /* Draw non-windows (surfaces) */
+ wm_surfaces_iter(C, wm_draw_surface);
}
void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(ar))
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 29cb02888ac..eb3f2125ee7 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -99,6 +99,7 @@
#include "wm_event_system.h"
#include "wm.h"
#include "wm_files.h"
+#include "wm_surface.h"
#include "wm_window.h"
#include "ED_anim_api.h"
@@ -129,6 +130,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "wm.h"
+
#include "DRW_engine.h"
#ifdef WITH_OPENSUBDIV
@@ -526,6 +529,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
BKE_keyconfig_pref_type_free();
wm_operatortype_free();
+ wm_surfaces_free();
wm_dropbox_free();
WM_menutype_free();
WM_uilisttype_free();
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index c984191076c..38600dcb018 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -75,6 +75,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h" /* BKE_ST_MAXNAME */
+#include "BKE_workspace.h"
#include "BKE_unit.h"
#include "BKE_idcode.h"
@@ -3514,6 +3515,35 @@ static void WM_OT_stereo3d_set(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+#ifdef WITH_OPENXR
+static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* Lazy-create xr context - tries to dynlink to the runtime, reading active_runtime.json. */
+ if (wm_xr_context_ensure(C, wm) == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ wm_xr_session_toggle(C, wm->xr_context);
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_xr_session_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Toggle VR Session";
+ ot->idname = "WM_OT_xr_session_toggle";
+ ot->description =
+ "Attempt to open a view for use with virtual reality headsets, or close it if already "
+ "opened";
+
+ /* callbacks */
+ ot->exec = wm_xr_session_toggle_exec;
+}
+#endif /* WITH_OPENXR */
+
void wm_operatortypes_register(void)
{
WM_operatortype_append(WM_OT_window_close);
@@ -3551,6 +3581,9 @@ void wm_operatortypes_register(void)
WM_operatortype_append(WM_OT_call_panel);
WM_operatortype_append(WM_OT_radial_control);
WM_operatortype_append(WM_OT_stereo3d_set);
+#ifdef WITH_OPENXR
+ WM_operatortype_append(WM_OT_xr_session_toggle);
+#endif
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif
diff --git a/source/blender/windowmanager/intern/wm_surface.c b/source/blender/windowmanager/intern/wm_surface.c
new file mode 100644
index 00000000000..38057370b92
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_surface.c
@@ -0,0 +1,128 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+
+#include "BKE_context.h"
+
+#include "BLF_api.h"
+
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "GHOST_C-api.h"
+
+#include "GPU_batch_presets.h"
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_context.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+#include "wm.h"
+
+#include "wm_surface.h"
+
+static ListBase global_surface_list = {NULL, NULL};
+static wmSurface *g_drawable = NULL;
+
+void wm_surfaces_iter(bContext *C, void (*cb)(bContext *C, wmSurface *))
+{
+ for (wmSurface *surf = global_surface_list.first; surf; surf = surf->next) {
+ cb(C, surf);
+ }
+}
+
+void wm_surface_clear_drawable(void)
+{
+#if 0
+ if (g_drawable) {
+ BLF_batch_reset();
+ gpu_batch_presets_reset();
+ immDeactivate();
+
+ g_drawable = NULL;
+ }
+#endif
+}
+
+void wm_surface_set_drawable(wmSurface *surface, bool activate)
+{
+ BLI_assert(ELEM(g_drawable, NULL, surface));
+
+ g_drawable = surface;
+ if (activate) {
+ // GHOST_ActivateOpenGLContext(surface->ghost_ctx);
+ }
+
+ // GPU_context_active_set(surface->gpu_ctx);
+ // immActivate();
+}
+
+void wm_surface_make_drawable(wmSurface *surface)
+{
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
+
+ if (surface != g_drawable) {
+ wm_surface_clear_drawable();
+ wm_surface_set_drawable(surface, true);
+ }
+}
+
+void wm_surface_reset_drawable(void)
+{
+ BLI_assert(BLI_thread_is_main());
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
+
+ if (g_drawable) {
+ wm_surface_clear_drawable();
+ wm_surface_set_drawable(g_drawable, true);
+ }
+}
+
+void wm_surface_present(wmSurface *surface)
+{
+ // GHOST_SwapContextBuffers(surface->ghost_ctx);
+ if (surface->secondary_ghost_ctx) {
+ // GHOST_SwapContextBuffers(surface->secondary_ghost_ctx);
+ }
+}
+
+void wm_surface_add(wmSurface *surface)
+{
+ BLI_addtail(&global_surface_list, surface);
+}
+
+void wm_surface_remove(wmSurface *surface)
+{
+ BLI_remlink(&global_surface_list, surface);
+ surface->free_data(surface);
+ MEM_freeN(surface);
+}
+
+void wm_surfaces_free(void)
+{
+ for (wmSurface *surf = global_surface_list.first, *surf_next; surf; surf = surf_next) {
+ surf_next = surf->next;
+ wm_surface_remove(surf);
+ }
+
+ BLI_assert(BLI_listbase_is_empty(&global_surface_list));
+}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index d17b8817691..42c372855ca 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -95,6 +95,12 @@
# include "BLI_threads.h"
#endif
+/* We may want to open non-OpenGL windows in certain cases and do all drawing into an offscreen
+ * OpenGL context then. This flag is useful for testing the blitting. It forces OpenGL windows
+ * only, but still does the offscreen rendering and blitting (if supported by GHOST context).
+ * See GHOST_BlitOpenGLOffscreenContext. */
+// #define USE_FORCE_OPENGL_FOR_NON_OPENGL_WIN
+
/* the global to talk to ghost */
static GHOST_SystemHandle g_system = NULL;
@@ -157,7 +163,7 @@ void wm_get_desktopsize(int *r_width, int *r_height)
/* keeps offset and size within monitor bounds */
/* XXX solve dual screen... */
-static void wm_window_check_position(rcti *rect)
+void wm_window_check_position(rcti *rect)
{
int width, height, d;
@@ -190,6 +196,17 @@ static void wm_window_check_position(rcti *rect)
}
}
+static void wm_window_drawing_context_activate(wmWindow *win)
+{
+ if (win->offscreen_context) {
+ /* In rare cases we may want to draw to an offscreen context. */
+ GHOST_ActivateOpenGLContext(win->offscreen_context);
+ }
+ else {
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ }
+}
+
static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
{
if (win->ghostwin) {
@@ -204,7 +221,7 @@ static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
}
/* We need this window's opengl context active to discard it. */
- GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ wm_window_drawing_context_activate(win);
GPU_context_active_set(win->gpuctx);
/* Delete local gpu context. */
@@ -550,7 +567,10 @@ static void wm_window_ensure_eventstate(wmWindow *win)
}
/* belongs to below */
-static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wmWindow *win)
+static void wm_window_ghostwindow_add(wmWindowManager *wm,
+ const char *title,
+ wmWindow *win,
+ GHOST_TDrawingContextType context_type)
{
GHOST_WindowHandle ghostwin;
GHOST_GLSettings glSettings = {0};
@@ -579,14 +599,29 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
win->sizex,
win->sizey,
(GHOST_TWindowState)win->windowstate,
+#ifdef USE_FORCE_OPENGL_FOR_NON_OPENGL_WIN
GHOST_kDrawingContextTypeOpenGL,
+#else
+ context_type,
+#endif
glSettings);
if (ghostwin) {
GHOST_RectangleHandle bounds;
+ GLuint default_fb;
- GLuint default_fb = GHOST_GetDefaultOpenGLFramebuffer(ghostwin);
- win->gpuctx = GPU_context_create(default_fb);
+ if (context_type == GHOST_kDrawingContextTypeOpenGL) {
+ default_fb = GHOST_GetDefaultOpenGLFramebuffer(ghostwin);
+ win->gpuctx = GPU_context_create(default_fb);
+ }
+ else {
+ /* Drawing into a non-OpenGL window -> create an offscreen OpenGL context to draw into. */
+ win->offscreen_context = WM_opengl_context_create();
+ WM_opengl_context_activate(win->offscreen_context);
+
+ default_fb = GHOST_GetContextDefaultOpenGLFramebuffer(win->offscreen_context);
+ win->gpuctx = GPU_context_create(default_fb);
+ }
/* needed so we can detect the graphics card below */
GPU_init();
@@ -626,7 +661,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
/* needed here, because it's used before it reads userdef */
WM_window_set_dpi(win);
- wm_window_swap_buffers(win);
+ wm_window_present(win);
// GHOST_SetWindowState(ghostwin, GHOST_kWindowStateModified);
@@ -638,23 +673,11 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
}
}
-/**
- * Initialize #wmWindow without ghostwin, open these and clear.
- *
- * window size is read from window, if 0 it uses prefsize
- * called in #WM_check, also inits stuff after file read.
- *
- * \warning
- * After running, 'win->ghostwin' can be NULL in rare cases
- * (where OpenGL driver fails to create a context for eg).
- * We could remove them with #wm_window_ghostwindows_remove_invalid
- * but better not since caller may continue to use.
- * Instead, caller needs to handle the error case and cleanup.
- */
-void wm_window_ghostwindows_ensure(wmWindowManager *wm)
+static void wm_window_ghostwindow_ensure(wmWindowManager *wm,
+ wmWindow *win,
+ GHOST_TDrawingContextType context_type)
{
wmKeyMap *keymap;
- wmWindow *win;
BLI_assert(G.background == false);
@@ -685,63 +708,83 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm)
#endif
}
- for (win = wm->windows.first; win; win = win->next) {
- if (win->ghostwin == NULL) {
- if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) {
- win->posx = wm_init_state.start_x;
- win->posy = wm_init_state.start_y;
- win->sizex = wm_init_state.size_x;
- win->sizey = wm_init_state.size_y;
-
- if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) {
- win->windowstate = GHOST_kWindowStateNormal;
- wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM;
- }
- else {
- win->windowstate = GHOST_WINDOW_STATE_DEFAULT;
- }
- }
+ if (win->ghostwin == NULL) {
+ if ((win->sizex == 0) || (wm_init_state.override_flag & WIN_OVERRIDE_GEOM)) {
+ win->posx = wm_init_state.start_x;
+ win->posy = wm_init_state.start_y;
+ win->sizex = wm_init_state.size_x;
+ win->sizey = wm_init_state.size_y;
- if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) {
- win->windowstate = wm_init_state.windowstate;
- wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE;
+ if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) {
+ win->windowstate = GHOST_kWindowStateNormal;
+ wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM;
}
-
- /* without this, cursor restore may fail, T45456 */
- if (win->cursor == 0) {
- win->cursor = CURSOR_STD;
+ else {
+ win->windowstate = GHOST_WINDOW_STATE_DEFAULT;
}
-
- wm_window_ghostwindow_add(wm, "Blender", win);
}
- if (win->ghostwin != NULL) {
- /* If we have no ghostwin this is a buggy window that should be removed.
- * However we still need to initialize it correctly so the screen doesn't hang. */
+ if (wm_init_state.override_flag & WIN_OVERRIDE_WINSTATE) {
+ win->windowstate = wm_init_state.windowstate;
+ wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE;
+ }
- /* happens after fileread */
- wm_window_ensure_eventstate(win);
+ /* without this, cursor restore may fail, T45456 */
+ if (win->cursor == 0) {
+ win->cursor = CURSOR_STD;
}
- /* add keymap handlers (1 handler for all keys in map!) */
- keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0);
- WM_event_add_keymap_handler(&win->handlers, keymap);
+ wm_window_ghostwindow_add(wm, "Blender", win, context_type);
+ }
- keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0);
- WM_event_add_keymap_handler(&win->handlers, keymap);
+ if (win->ghostwin != NULL) {
+ /* If we have no ghostwin this is a buggy window that should be removed.
+ * However we still need to initialize it correctly so the screen doesn't hang. */
- keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0);
- WM_event_add_keymap_handler(&win->modalhandlers, keymap);
+ /* happens after fileread */
+ wm_window_ensure_eventstate(win);
+ }
- /* add drop boxes */
- {
- ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
- WM_event_add_dropbox_handler(&win->handlers, lb);
- }
- wm_window_title(wm, win);
+ /* add keymap handlers (1 handler for all keys in map!) */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0);
+ WM_event_add_keymap_handler(&win->handlers, keymap);
- /* add topbar */
- ED_screen_global_areas_refresh(win);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Screen", 0, 0);
+ WM_event_add_keymap_handler(&win->handlers, keymap);
+
+ keymap = WM_keymap_ensure(wm->defaultconf, "Screen Editing", 0, 0);
+ WM_event_add_keymap_handler(&win->modalhandlers, keymap);
+
+ /* add drop boxes */
+ {
+ ListBase *lb = WM_dropboxmap_find("Window", 0, 0);
+ WM_event_add_dropbox_handler(&win->handlers, lb);
+ }
+ wm_window_title(wm, win);
+
+ /* add topbar */
+ ED_screen_global_areas_refresh(win);
+}
+
+/**
+ * Initialize #wmWindow without ghostwin, open these and clear.
+ *
+ * window size is read from window, if 0 it uses prefsize
+ * called in #WM_check, also inits stuff after file read.
+ *
+ * \warning
+ * After running, 'win->ghostwin' can be NULL in rare cases
+ * (where OpenGL driver fails to create a context for eg).
+ * We could remove them with #wm_window_ghostwindows_remove_invalid
+ * but better not since caller may continue to use.
+ * Instead, caller needs to handle the error case and cleanup.
+ */
+void wm_window_ghostwindows_ensure(wmWindowManager *wm)
+{
+ BLI_assert(G.background == false);
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ wm_window_ghostwindow_ensure(wm, win, GHOST_kDrawingContextTypeOpenGL);
}
}
@@ -769,8 +812,11 @@ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm)
* \note area-rip calls this.
* \return the window or NULL.
*/
-wmWindow *WM_window_open(bContext *C, const rcti *rect)
+static wmWindow *wm_window_open_ex(bContext *C,
+ const rcti *rect,
+ GHOST_TDrawingContextType context_type)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win = wm_window_new(C, win_prev);
@@ -779,18 +825,31 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
win->sizex = BLI_rcti_size_x(rect);
win->sizey = BLI_rcti_size_y(rect);
+ wm_window_ghostwindow_ensure(wm, win, context_type);
+
WM_check(C);
if (win->ghostwin) {
return win;
}
else {
- wm_window_close(C, CTX_wm_manager(C), win);
+ wm_window_close(C, wm, win);
CTX_wm_window_set(C, win_prev);
return NULL;
}
}
+wmWindow *WM_window_open(bContext *C, const rcti *rect)
+{
+ return wm_window_open_ex(C, rect, GHOST_kDrawingContextTypeOpenGL);
+}
+#ifdef WIN32
+wmWindow *WM_window_open_directx(bContext *C, const rcti *rect)
+{
+ return wm_window_open_ex(C, rect, GHOST_kDrawingContextTypeD3D);
+}
+#endif
+
/**
* Uses `screen->temp` tag to define what to do, currently it limits
* to only one "temp" window for render out, preferences, filewindow, etc...
@@ -1066,8 +1125,9 @@ static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool acti
wm->windrawable = win;
if (activate) {
- GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ wm_window_drawing_context_activate(win);
}
+
GPU_context_active_set(win->gpuctx);
immActivate();
}
@@ -1606,6 +1666,9 @@ void wm_window_process_events(const bContext *C)
GHOST_DispatchEvents(g_system);
}
hasevent |= wm_window_timer(C);
+#ifdef WITH_OPENXR
+ hasevent |= GHOST_XrEventsHandle(CTX_wm_manager(C)->xr_context);
+#endif
/* no event, we sleep 5 milliseconds */
if (hasevent == 0) {
@@ -1926,8 +1989,22 @@ void wm_window_raise(wmWindow *win)
/** \name Window Buffers
* \{ */
-void wm_window_swap_buffers(wmWindow *win)
+/**
+ * \brief Push rendered buffer to the screen.
+ * In most cases, just swaps the buffer. However a window offscreen context may have been used to
+ * inject a layer of control in-between the OpenGL context and the window. We use this to support
+ * drawing with OpenGL into a DirectX window for the rare cases we need this (Windows Mixed
+ * Reality OpenXR runtime, which doesn't support OpenGL).
+ */
+void wm_window_present(wmWindow *win)
{
+ if (win->offscreen_context) {
+ /* The window may be a non-OpenGL window (unlikely though). In that case it's given the
+ * chance to blit the offscreen buffer to its onscreen context. Just a simple interop
+ * layer. */
+ GHOST_BlitOpenGLOffscreenContext(win->ghostwin, win->offscreen_context);
+ GHOST_SwapContextBuffers(win->offscreen_context);
+ }
GHOST_SwapWindowBuffers(win->ghostwin);
}
@@ -2179,6 +2256,15 @@ void WM_window_screen_rect_calc(const wmWindow *win, rcti *r_rect)
*r_rect = screen_rect;
}
+/**
+ * For some specific use cases (VR views for DirectX only OpenXR runtime) non-OpenGL windows are
+ * supported. These are treated really specially though.
+ */
+bool WM_window_is_non_opengl(const wmWindow *win)
+{
+ return GHOST_GetDrawingContextType(win->ghostwin) != GHOST_kDrawingContextTypeOpenGL;
+}
+
bool WM_window_is_fullscreen(wmWindow *win)
{
return win->windowstate == GHOST_kWindowStateFullScreen;
@@ -2427,3 +2513,24 @@ void WM_opengl_context_release(void *context)
}
/** \} */
+
+#ifdef WIN32
+/* -------------------------------------------------------------------- */
+/** \name Direct DirectX Context Management
+ * \{ */
+
+void *WM_directx_context_create(void)
+{
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
+ return GHOST_CreateDirectXContext(g_system);
+}
+
+void WM_directx_context_dispose(void *context)
+{
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
+ GHOST_DisposeDirectXContext(g_system, context);
+}
+
+/** \} */
+
+#endif
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
new file mode 100644
index 00000000000..e20bc39ba1f
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -0,0 +1,567 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "BLI_math_geom.h"
+#include "BLI_math_matrix.h"
+#include "BLI_threads.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "DRW_engine.h"
+
+#include "ED_view3d.h"
+
+#include "GHOST_C-api.h"
+
+#include "GPU_context.h"
+#include "GPU_draw.h"
+#include "GPU_matrix.h"
+#include "GPU_viewport.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "wm.h"
+#include "wm_surface.h"
+#include "wm_window.h"
+
+#ifdef WIN32 /* Only WIN32 supported now */
+//# define USE_FORCE_WINDOWED_SESSION
+#endif
+
+#ifdef USE_FORCE_WINDOWED_SESSION
+static void xr_session_window_create(bContext *C);
+#endif
+
+static wmSurface *g_xr_surface = NULL;
+static Depsgraph *g_depsgraph = NULL;
+ListBase g_threadpool;
+
+typedef struct {
+ GHOST_TXrGraphicsBinding gpu_binding_type;
+ GPUOffScreen *offscreen;
+ GPUViewport *viewport;
+} wmXrSurfaceData;
+
+typedef struct {
+ wmWindowManager *wm;
+ bContext *evil_C;
+} wmXrErrorHandlerData;
+
+static void wm_xr_error_handler(const GHOST_XrError *error)
+{
+ wmXrErrorHandlerData *handler_data = error->customdata;
+ wmWindowManager *wm = handler_data->wm;
+
+ BKE_reports_clear(&wm->reports);
+ WM_report(RPT_ERROR, error->user_message);
+ WM_report_banner_show();
+ UI_popup_menu_reports(handler_data->evil_C, &wm->reports);
+
+ if (wm->xr_context) {
+ /* Just play safe and destroy the entire context. */
+ GHOST_XrContextDestroy(wm->xr_context);
+ wm->xr_context = NULL;
+ }
+}
+
+bool wm_xr_context_ensure(bContext *C, wmWindowManager *wm)
+{
+ if (wm->xr_context) {
+ return true;
+ }
+ static wmXrErrorHandlerData error_customdata;
+
+ /* Set up error handling */
+ error_customdata.wm = wm;
+ error_customdata.evil_C = C;
+ GHOST_XrErrorHandler(wm_xr_error_handler, &error_customdata);
+
+ {
+ const GHOST_TXrGraphicsBinding gpu_bindings_candidates[] = {
+ GHOST_kXrGraphicsOpenGL,
+#ifdef WIN32
+ GHOST_kXrGraphicsD3D11,
+#endif
+ };
+ GHOST_XrContextCreateInfo create_info = {
+ .gpu_binding_candidates = gpu_bindings_candidates,
+ .gpu_binding_candidates_count = ARRAY_SIZE(gpu_bindings_candidates)};
+
+ if (G.debug & G_DEBUG_XR) {
+ create_info.context_flag |= GHOST_kXrContextDebug;
+ }
+ if (G.debug & G_DEBUG_XR_TIME) {
+ create_info.context_flag |= GHOST_kXrContextDebugTime;
+ }
+
+ wm->xr_context = GHOST_XrContextCreate(&create_info);
+ }
+
+ return wm->xr_context != NULL;
+}
+
+static void wm_xr_session_surface_draw(bContext *C)
+{
+#if 0
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ if (!GHOST_XrSessionIsRunning(wm->xr_context)) {
+ return;
+ }
+ GHOST_XrSessionDrawViews(wm->xr_context, C);
+#endif
+}
+
+static void wm_xr_session_free_data(wmSurface *surface)
+{
+ wmXrSurfaceData *data = surface->customdata;
+
+ if (surface->secondary_ghost_ctx) {
+#ifdef WIN32
+ if (data->gpu_binding_type == GHOST_kXrGraphicsD3D11) {
+ WM_directx_context_dispose(surface->secondary_ghost_ctx);
+ }
+#endif
+ }
+ WM_opengl_context_activate(surface->ghost_ctx);
+ GPU_context_active_set(surface->gpu_ctx);
+
+ if (data->viewport) {
+ GPU_viewport_clear_from_offscreen(data->viewport);
+ GPU_viewport_free(data->viewport);
+ }
+ if (data->offscreen) {
+ GPU_offscreen_free(data->offscreen);
+ }
+ GPU_context_discard(g_xr_surface->gpu_ctx);
+ GPU_context_active_set(NULL);
+ WM_opengl_context_release(surface->ghost_ctx);
+ WM_opengl_context_dispose(surface->ghost_ctx);
+
+ DEG_graph_free(g_depsgraph);
+
+ MEM_freeN(surface->customdata);
+
+ g_xr_surface = NULL;
+}
+
+static wmSurface *wm_xr_session_surface_create(wmWindowManager *UNUSED(wm),
+ unsigned int gpu_binding_type)
+{
+ if (g_xr_surface) {
+ BLI_assert(false);
+ return g_xr_surface;
+ }
+
+ wmSurface *surface = MEM_callocN(sizeof(*surface), __func__);
+ wmXrSurfaceData *data = MEM_callocN(sizeof(*data), "XrSurfaceData");
+
+#ifndef WIN32
+ BLI_assert(gpu_binding_type == GHOST_kXrGraphicsOpenGL);
+#endif
+
+ surface->draw = wm_xr_session_surface_draw;
+ surface->free_data = wm_xr_session_free_data;
+
+ data->gpu_binding_type = gpu_binding_type;
+ surface->customdata = data;
+
+ surface->ghost_ctx = WM_opengl_context_create();
+ WM_opengl_context_activate(surface->ghost_ctx);
+
+ switch (gpu_binding_type) {
+ case GHOST_kXrGraphicsOpenGL:
+ break;
+#ifdef WIN32
+ case GHOST_kXrGraphicsD3D11:
+ surface->secondary_ghost_ctx = WM_directx_context_create();
+ break;
+#endif
+ }
+
+ WM_opengl_context_release(surface->ghost_ctx);
+ GPU_context_active_set(NULL);
+ wm_window_reset_drawable();
+
+ BLI_threadpool_end(&g_threadpool);
+
+ g_xr_surface = surface;
+
+ return surface;
+}
+
+static void wm_xr_draw_matrices_create(const Scene *scene,
+ const GHOST_XrDrawViewInfo *draw_view,
+ const float clip_start,
+ const float clip_end,
+ float r_view_mat[4][4],
+ float r_proj_mat[4][4])
+{
+ float scalemat[4][4], quat[4];
+ float temp[4][4];
+
+ perspective_m4_fov(r_proj_mat,
+ draw_view->fov.angle_left,
+ draw_view->fov.angle_right,
+ draw_view->fov.angle_up,
+ draw_view->fov.angle_down,
+ clip_start,
+ clip_end);
+
+ scale_m4_fl(scalemat, 1.0f);
+ invert_qt_qt_normalized(quat, draw_view->pose.orientation_quat);
+ quat_to_mat4(temp, quat);
+ translate_m4(temp,
+ -draw_view->pose.position[0],
+ -draw_view->pose.position[1],
+ -draw_view->pose.position[2]);
+
+ if (scene->camera) {
+ invert_m4_m4(scene->camera->imat, scene->camera->obmat);
+ mul_m4_m4m4(r_view_mat, temp, scene->camera->imat);
+ }
+ else {
+ copy_m4_m4(r_view_mat, temp);
+ }
+}
+
+static bool wm_xr_session_surface_offscreen_ensure(const GHOST_XrDrawViewInfo *draw_view)
+{
+ wmXrSurfaceData *surface_data = g_xr_surface->customdata;
+ char err_out[256] = "unknown";
+ bool failure = false;
+
+ if (surface_data->offscreen &&
+ (GPU_offscreen_width(surface_data->offscreen) == draw_view->width) &&
+ (GPU_offscreen_height(surface_data->offscreen) == draw_view->height)) {
+ BLI_assert(surface_data->viewport);
+ return true;
+ }
+
+ if (surface_data->offscreen) {
+ GPU_viewport_clear_from_offscreen(surface_data->viewport);
+ GPU_viewport_free(surface_data->viewport);
+ GPU_offscreen_free(surface_data->offscreen);
+ }
+
+ if (!(surface_data->offscreen = GPU_offscreen_create(
+ draw_view->width, draw_view->height, 0, true, false, err_out))) {
+ failure = true;
+ }
+ if ((failure == false) &&
+ !(surface_data->viewport = GPU_viewport_create_from_offscreen(surface_data->offscreen))) {
+ GPU_offscreen_free(surface_data->offscreen);
+ failure = true;
+ }
+
+ if (failure) {
+ fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
+ return false;
+ }
+
+ return true;
+}
+
+static GHOST_ContextHandle wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
+{
+ bContext *C = customdata;
+ wmXrSurfaceData *surface_data = g_xr_surface->customdata;
+ const float clip_start = 0.01, clip_end = 500.0f;
+ const float lens = 50.0f; /* TODO get from OpenXR */
+ const rcti rect = {
+ .xmin = 0, .ymin = 0, .xmax = draw_view->width - 1, .ymax = draw_view->height - 1};
+
+ GPUOffScreen *offscreen;
+ GPUViewport *viewport;
+ View3DShading shading;
+ float viewmat[4][4], winmat[4][4];
+
+ wm_xr_draw_matrices_create(CTX_data_scene(C), draw_view, clip_start, clip_end, viewmat, winmat);
+
+ BKE_scene_graph_evaluated_ensure(g_depsgraph, CTX_data_main(C));
+
+ DRW_render_context_draw_begin();
+
+ if (!wm_xr_session_surface_offscreen_ensure(draw_view)) {
+ // TODO disable correctly.
+ return NULL;
+ }
+
+ offscreen = surface_data->offscreen;
+ viewport = surface_data->viewport;
+ GPU_viewport_bind(viewport, &rect);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ BKE_screen_view3d_shading_init(&shading);
+ shading.flag |= V3D_SHADING_WORLD_ORIENTATION;
+ shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
+ ED_view3d_draw_offscreen_simple(g_depsgraph,
+ DEG_get_evaluated_scene(g_depsgraph),
+ &shading,
+ OB_SOLID,
+ draw_view->width,
+ draw_view->height,
+ /* Draw floor for better orientation */
+ V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS | V3D_OFSDRAW_SHOW_GRIDFLOOR,
+ viewmat,
+ winmat,
+ clip_start,
+ clip_end,
+ lens,
+ true,
+ true,
+ NULL,
+ false,
+ offscreen,
+ viewport);
+
+ GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
+
+ wm_draw_offscreen_texture_parameters(offscreen);
+
+ wmViewport(&rect);
+
+ if (g_xr_surface->secondary_ghost_ctx &&
+ GHOST_isUpsideDownContext(g_xr_surface->secondary_ghost_ctx)) {
+ GPU_texture_bind(texture, 0);
+ wm_draw_upside_down(draw_view->width, draw_view->height);
+ GPU_texture_unbind(texture);
+ }
+ else {
+ GPU_viewport_draw_to_screen(viewport, &rect);
+ }
+
+ GPU_viewport_unbind(viewport);
+
+ DRW_render_context_draw_end();
+
+ return g_xr_surface->ghost_ctx;
+}
+
+static void *wm_xr_session_gpu_binding_context_create(GHOST_TXrGraphicsBinding graphics_binding)
+{
+#ifndef USE_FORCE_WINDOWED_SESSION
+ wmSurface *surface = wm_xr_session_surface_create(G_MAIN->wm.first, graphics_binding);
+
+ wm_surface_add(surface);
+
+ return surface->secondary_ghost_ctx ? surface->secondary_ghost_ctx : surface->ghost_ctx;
+#else
+# ifdef WIN32
+ if (graphics_binding == GHOST_kXrGraphicsD3D11) {
+ wmWindowManager *wm = G_MAIN->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ /* TODO better lookup? For now only one D3D window possible, but later? */
+ if (GHOST_GetDrawingContextType(win->ghostwin) == GHOST_kDrawingContextTypeD3D) {
+ return GHOST_GetWindowContext(win->ghostwin);
+ }
+ }
+ }
+# endif
+ return NULL;
+#endif
+}
+
+static void wm_xr_session_gpu_binding_context_destroy(
+ GHOST_TXrGraphicsBinding UNUSED(graphics_lib), void *UNUSED(context))
+{
+#ifndef USE_FORCE_WINDOWED_SESSION
+ if (g_xr_surface) { /* Might have been freed already */
+ wm_surface_remove(g_xr_surface);
+ }
+#endif
+
+ wm_window_reset_drawable();
+}
+
+static Depsgraph *wm_xr_session_depsgraph_create(Main *bmain, Scene *scene, ViewLayer *viewlayer)
+{
+ Depsgraph *deg = DEG_graph_new(scene, viewlayer, DAG_EVAL_VIEWPORT);
+
+ DEG_debug_name_set(deg, "VR SESSION");
+ DEG_graph_build_from_view_layer(deg, bmain, scene, viewlayer);
+ BKE_scene_graph_evaluated_ensure(deg, bmain);
+ /* XXX Why do we have to call this? Depsgraph should handle. */
+ BKE_scene_base_flag_to_objects(DEG_get_evaluated_view_layer(deg));
+
+ return deg;
+}
+
+static void *wm_xr_session_drawthread_main(void *data)
+{
+ bContext *C = data;
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ g_depsgraph = wm_xr_session_depsgraph_create(
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C));
+
+ WM_opengl_context_activate(g_xr_surface->ghost_ctx);
+ g_xr_surface->gpu_ctx = GPU_context_create(
+ GHOST_GetContextDefaultOpenGLFramebuffer(g_xr_surface->ghost_ctx));
+ WM_opengl_context_release(g_xr_surface->ghost_ctx);
+
+ DRW_opengl_render_context_enable_ex(g_xr_surface->ghost_ctx);
+ DRW_gawain_render_context_enable(g_xr_surface->gpu_ctx);
+
+ /* Sort of the session's main loop. */
+ while (GHOST_XrHasSession(wm->xr_context)) {
+ if (!GHOST_XrSessionShouldRunDrawLoop(wm->xr_context)) {
+ continue;
+ }
+
+ GHOST_XrSessionDrawViews(wm->xr_context, C);
+ }
+
+ DRW_gawain_render_context_disable(g_xr_surface->gpu_ctx);
+ DRW_opengl_render_context_disable_ex(g_xr_surface->ghost_ctx);
+
+ return NULL;
+}
+
+static void wm_xr_session_drawthread_spawn(bContext *C)
+{
+ BLI_threadpool_init(&g_threadpool, wm_xr_session_drawthread_main, 1);
+ BLI_threadpool_insert(&g_threadpool, C);
+}
+
+static void wm_xr_session_begin_info_create(const Scene *scene,
+ GHOST_XrSessionBeginInfo *begin_info)
+{
+ if (scene->camera) {
+ copy_v3_v3(begin_info->base_pose.position, scene->camera->loc);
+ /* TODO will only work if rotmode is euler */
+ eul_to_quat(begin_info->base_pose.orientation_quat, scene->camera->rot);
+ }
+ else {
+ copy_v3_fl(begin_info->base_pose.position, 0.0f);
+ unit_qt(begin_info->base_pose.orientation_quat);
+ }
+}
+
+void wm_xr_session_toggle(bContext *C, void *xr_context_ptr)
+{
+ GHOST_XrContextHandle xr_context = xr_context_ptr;
+
+ if (xr_context && GHOST_XrHasSession(xr_context)) {
+ GHOST_XrSessionEnd(xr_context);
+ }
+ else {
+ GHOST_XrSessionBeginInfo begin_info;
+
+#if defined(USE_FORCE_WINDOWED_SESSION)
+ xr_session_window_create(C);
+#endif
+ wm_xr_session_begin_info_create(CTX_data_scene(C), &begin_info);
+
+ GHOST_XrGraphicsContextBindFuncs(xr_context,
+ wm_xr_session_gpu_binding_context_create,
+ wm_xr_session_gpu_binding_context_destroy);
+ GHOST_XrDrawViewFunc(xr_context, wm_xr_draw_view);
+
+ GHOST_XrSessionStart(xr_context, &begin_info);
+ wm_xr_session_drawthread_spawn(C);
+ }
+}
+
+#if defined(USE_FORCE_WINDOWED_SESSION)
+
+# include "BLI_rect.h"
+# include "DNA_workspace_types.h"
+# include "BKE_workspace.h"
+# include "ED_screen.h"
+# include "BLI_string.h"
+
+static void xr_session_window_create(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ wmWindow *win_prev = CTX_wm_window(C);
+
+ rcti rect;
+ wmWindow *win;
+ bScreen *screen;
+ ScrArea *sa;
+ int screen_size[2];
+
+ wm_get_screensize(&screen_size[0], &screen_size[1]);
+ BLI_rcti_init(&rect, 0, screen_size[0], 0, screen_size[1]);
+ BLI_rcti_scale(&rect, 0.8f);
+ wm_window_check_position(&rect);
+
+ win = WM_window_open_directx(C, &rect);
+
+ if (WM_window_get_active_workspace(win) == NULL) {
+ WorkSpace *workspace = WM_window_get_active_workspace(win_prev);
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+ }
+
+ /* add new screen layout */
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout = ED_workspace_layout_add(bmain, workspace, win, "VR Session");
+
+ screen = BKE_workspace_layout_screen_get(layout);
+ WM_window_set_active_layout(win, workspace, layout);
+
+ /* Set scene and view layer to match original window. */
+ STRNCPY(win->view_layer_name, view_layer->name);
+ if (WM_window_get_active_scene(win) != scene) {
+ ED_screen_scene_change(C, win, scene);
+ }
+
+ WM_check(C);
+
+ CTX_wm_window_set(C, win);
+ sa = screen->areabase.first;
+ CTX_wm_area_set(C, sa);
+ ED_area_newspace(C, sa, SPACE_VIEW3D, false);
+
+ ED_screen_change(C, screen);
+ ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
+
+ if (win->ghostwin) {
+ GHOST_SetTitle(win->ghostwin, "Blender VR Session View");
+ }
+ else {
+ /* very unlikely! but opening a new window can fail */
+ wm_window_close(C, CTX_wm_manager(C), win);
+ CTX_wm_window_set(C, win_prev);
+ }
+}
+#endif /* USE_FORCE_WINDOWED_SESSION */
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index fa375efb469..f28552916f2 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -95,4 +95,15 @@ void wm_stereo3d_set_cancel(bContext *C, wmOperator *op);
void wm_open_init_load_ui(wmOperator *op, bool use_prefs);
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs);
+/* wm_draw.c */
+struct GPUOffScreen;
+void wm_draw_offscreen_texture_parameters(struct GPUOffScreen *offscreen);
+void wm_draw_upside_down(int sizex, int sizey);
+
+#ifdef WITH_OPENXR
+/* wm_xr.c */
+bool wm_xr_context_ensure(bContext *C, wmWindowManager *wm);
+void wm_xr_session_toggle(bContext *C, void *xr_context);
+#endif
+
#endif /* __WM_H__ */
diff --git a/source/blender/windowmanager/wm_surface.h b/source/blender/windowmanager/wm_surface.h
new file mode 100644
index 00000000000..584e4c4f8b5
--- /dev/null
+++ b/source/blender/windowmanager/wm_surface.h
@@ -0,0 +1,57 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+
+#ifndef __WM_SURFACE_H__
+#define __WM_SURFACE_H__
+
+struct bContext;
+
+typedef struct wmSurface {
+ struct wmSurface *next, *prev;
+
+ GHOST_ContextHandle ghost_ctx;
+ /** Some surfaces may want to use a secondary context. E.g. a DirectX one to draw OpenGL
+ * resources using DirectX (compatibility layer using shared resources). */
+ GHOST_ContextHandle secondary_ghost_ctx;
+ struct GPUContext *gpu_ctx;
+
+ void *customdata;
+
+ void (*draw)(struct bContext *);
+ /** Free data, not the surface itself (done by wm_surface API) */
+ void (*free_data)(struct wmSurface *);
+} wmSurface;
+
+/* Create/Free */
+void wm_surface_add(wmSurface *surface);
+void wm_surface_remove(wmSurface *surface);
+void wm_surfaces_free(void);
+
+/* Utils */
+void wm_surfaces_iter(struct bContext *C, void (*cb)(bContext *, wmSurface *));
+
+/* Drawing */
+void wm_surface_make_drawable(wmSurface *surface);
+void wm_surface_clear_drawable(void);
+void wm_surface_set_drawable(wmSurface *surface, bool activate);
+void wm_surface_reset_drawable(void);
+void wm_surface_present(wmSurface *surface);
+
+#endif /* __WM_SURFACE_H__ */
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 90c580818c9..4d21dbf22e7 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -61,8 +61,9 @@ void wm_window_reset_drawable(void);
void wm_window_raise(wmWindow *win);
void wm_window_lower(wmWindow *win);
void wm_window_set_size(wmWindow *win, int width, int height);
+void wm_window_check_position(rcti *rect);
void wm_window_get_position(wmWindow *win, int *r_pos_x, int *r_pos_y);
-void wm_window_swap_buffers(wmWindow *win);
+void wm_window_present(wmWindow *win);
void wm_window_set_swap_interval(wmWindow *win, int interval);
bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index e911a591881..dcf5682099e 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -118,6 +118,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_OPENXR)
+ add_definitions(-DWITH_OPENXR)
+endif()
+
# Setup the exe sources and buildinfo
set(SRC
creator.c
@@ -858,6 +862,8 @@ elseif(WIN32)
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_gpu_glitchworkaround.cmd
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_log.cmd
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_factory_startup.cmd
+ ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_oculus.cmd
+ ${CMAKE_SOURCE_DIR}/release/windows/batch/oculus.json
DESTINATION "."
)
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index e175dbfbb96..c67af94e8f1 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -604,6 +604,10 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
BLI_argsPrintArgDoc(ba, "--debug-gpu-shaders");
BLI_argsPrintArgDoc(ba, "--debug-gpu-force-workarounds");
BLI_argsPrintArgDoc(ba, "--debug-wm");
+# ifdef WITH_OPENXR
+ BLI_argsPrintArgDoc(ba, "--debug-xr");
+ BLI_argsPrintArgDoc(ba, "--debug-xr-time");
+# endif
BLI_argsPrintArgDoc(ba, "--debug-all");
BLI_argsPrintArgDoc(ba, "--debug-io");
@@ -941,6 +945,16 @@ static const char arg_handle_debug_mode_generic_set_doc_wm[] =
"\n\t"
"Enable debug messages for the window manager, shows all operators in search, shows "
"keymap errors.";
+# ifdef WITH_OPENXR
+static const char arg_handle_debug_mode_generic_set_doc_xr[] =
+ "\n\t"
+ "Enable debug messages for virtual reality contexts.\n"
+ "\tEnables the OpenXR API validation layer, (OpenXR) debug messages and general information "
+ "prints.";
+static const char arg_handle_debug_mode_generic_set_doc_xr_time[] =
+ "\n\t"
+ "Enable debug messages for virtual reality frame rendering times.";
+# endif
static const char arg_handle_debug_mode_generic_set_doc_jobs[] =
"\n\t"
"Enable time profiling for background jobs.";
@@ -2081,6 +2095,16 @@ void main_args_setup(bContext *C, bArgs *ba)
(void *)G_DEBUG_HANDLERS);
BLI_argsAdd(
ba, 1, NULL, "--debug-wm", CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
+# ifdef WITH_OPENXR
+ BLI_argsAdd(
+ ba, 1, NULL, "--debug-xr", CB_EX(arg_handle_debug_mode_generic_set, xr), (void *)G_DEBUG_XR);
+ BLI_argsAdd(ba,
+ 1,
+ NULL,
+ "--debug-xr-time",
+ CB_EX(arg_handle_debug_mode_generic_set, xr_time),
+ (void *)G_DEBUG_XR_TIME);
+# endif
BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
BLI_argsAdd(ba, 1, NULL, "--debug-io", CB(arg_handle_debug_mode_io), NULL);