diff options
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_ = ¤tValue(); + } + + 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_ = ¤tValue(); + } + + 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 ®istry_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); |