Preamble
Copyright (c) 2017-2023, The Khronos Group Inc.
This Specification is protected by copyright laws and contains material proprietary to Khronos. Except as described by these terms, it or any components may not be reproduced, republished, distributed, transmitted, displayed, broadcast or otherwise exploited in any manner without the express prior written permission of Khronos.
Khronos grants a conditional copyright license to use and reproduce the unmodified Specification for any purpose, without fee or royalty, EXCEPT no licenses to any patent, trademark or other intellectual property rights are granted under these terms.
Khronos makes no, and expressly disclaims any, representations or warranties, express or implied, regarding this Specification, including, without limitation: merchantability, fitness for a particular purpose, non-infringement of any intellectual property, correctness, accuracy, completeness, timeliness, and reliability. Under no circumstances will Khronos, or any of its Promoters, Contributors or Members, or their respective partners, officers, directors, employees, agents or representatives be liable for any damages, whether direct, indirect, special or consequential damages for lost revenues, lost profits, or otherwise, arising from or in connection with these materials.
This document contains extensions which are not ratified by Khronos, and as such is not a ratified Specification, though it contains text from (and is a superset of) the ratified OpenXR Specification that can be found at https://registry.khronos.org/OpenXR/specs/1.0-khr/html/xrspec.html (core with KHR extensions).
The Khronos Intellectual Property Rights Policy defines the terms 'Scope', 'Compliant Portion', and 'Necessary Patent Claims'.
Some parts of this Specification are purely informative and so are EXCLUDED from the Scope of this Specification. The Document Conventions section of the Introduction defines how these parts of the Specification are identified.
Where this Specification uses technical terminology, defined in the Glossary or otherwise, that refer to enabling technologies that are not expressly set forth in this Specification, those enabling technologies are EXCLUDED from the Scope of this Specification. For clarity, enabling technologies not disclosed with particularity in this Specification (e.g. semiconductor manufacturing technology, hardware architecture, processor architecture or microarchitecture, memory architecture, compiler technology, object oriented technology, basic operating system technology, compression technology, algorithms, and so on) are NOT to be considered expressly set forth; only those application program interfaces and data structures disclosed with particularity are included in the Scope of this Specification.
For purposes of the Khronos Intellectual Property Rights Policy as it relates to the definition of Necessary Patent Claims, all recommended or optional features, behaviors and functionality set forth in this Specification, if implemented, are considered to be included as Compliant Portions.
Khronos® and Vulkan® are registered trademarks, and glTF™ is a trademark of The Khronos Group Inc. OpenXR™ is a trademark owned by The Khronos Group Inc. and is registered as a trademark in China, the European Union, Japan and the United Kingdom. OpenGL® is a registered trademark and the OpenGL ES™ and OpenGL SC™ logos are trademarks of Hewlett Packard Enterprise used under license by Khronos. All other product names, trademarks, and/or company names are used solely for identification and belong to their respective owners.
1. Introduction
This chapter is informative except for the section on Normative Terminology.
This document, referred to as the "OpenXR Specification" or just the "Specification" hereafter, describes OpenXR: what it is, how it acts, and what is required to implement it. We assume that the reader has a basic understanding of computer graphics and the technologies involved in virtual and augmented reality. This means familiarity with the essentials of computer graphics algorithms and terminology, modern GPUs (Graphic Processing Units), tracking technologies, head mounted devices, and input modalities.
The canonical version of the Specification is available in the official OpenXR Registry, located at URL
1.1. What is OpenXR?
OpenXR is an API (Application Programming Interface) for XR applications. XR refers to a continuum of real-and-virtual combined environments generated by computers through human-machine interaction and is inclusive of the technologies associated with virtual reality (VR), augmented reality (AR) and mixed reality (MR). OpenXR is the interface between an application and an in-process or out-of-process "XR runtime system", or just "runtime" hereafter. The runtime may handle such functionality as frame composition, peripheral management, and raw tracking information.
Optionally, a runtime may support device layer plugins which allow access to a variety of hardware across a commonly defined interface.
1.2. The Programmer’s View of OpenXR
To the application programmer, OpenXR is a set of functions that interface with a runtime to perform commonly required operations such as accessing controller/peripheral state, getting current and/or predicted tracking positions, and submitting rendered frames.
A typical OpenXR program begins with a call to create an instance which establishes a connection to a runtime. Then a call is made to create a system which selects for use a physical display and a subset of input, tracking, and graphics devices. Subsequently a call is made to create buffers into which the application will render one or more views using the appropriate graphics APIs for the platform. Finally calls are made to create a session and begin the application’s XR rendering loop.
1.3. The Implementor’s View of OpenXR
To the runtime implementor, OpenXR is a set of functions that control the operation of the XR system and establishes the lifecycle of a XR application.
The implementor’s task is to provide a software library on the host which implements the OpenXR API, while mapping the work for each OpenXR function to the graphics hardware as appropriate for the capabilities of the device.
1.4. Our View of OpenXR
We view OpenXR as a mechanism for interacting with VR/AR/MR systems in a platform-agnostic way.
We expect this model to result in a specification that satisfies the needs of both programmers and runtime implementors. It does not, however, necessarily provide a model for implementation. A runtime implementation must produce results conforming to those produced by the specified methods, but may carry out particular procedures in ways that are more efficient than the one specified.
1.5. Filing Bug Reports
Issues with and bug reports on the OpenXR Specification and the API Registry can be filed in the Khronos OpenXR GitHub repository, located at URL
Please tag issues with appropriate labels, such as “Specification”, “Ref Pages” or “Registry”, to help us triage and assign them appropriately. Unfortunately, GitHub does not currently let users who do not have write access to the repository set GitHub labels on issues. In the meantime, they can be added to the title line of the issue set in brackets, e.g. “[Specification]”.
1.6. Document Conventions
The OpenXR specification is intended for use by both implementors of the API and application developers seeking to make use of the API, forming a contract between these parties. Specification text may address either party; typically the intended audience can be inferred from context, though some sections are defined to address only one of these parties. (For example, Valid Usage sections only address application developers). Any requirements, prohibitions, recommendations or options defined by normative terminology are imposed only on the audience of that text.
1.6.1. Normative Terminology
The key words must, required, should, may, and optional in this document, when denoted as above, are to be interpreted as described in RFC 2119:
- must
-
When used alone, this word, or the term required, means that the definition is an absolute requirement of the specification. When followed by not (“must not” ), the phrase means that the definition is an absolute prohibition of the specification.
- should
-
When used alone, this word means that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course. When followed by not (“should not”), the phrase means that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label.
- may
-
This word, or the adjective optional, means that an item is truly optional. One vendor may choose to include the item because a particular marketplace requires it or because the vendor feels that it enhances the product while another vendor may omit the same item.
The additional terms can and cannot are to be interpreted as follows:
- can
-
This word means that the particular behavior described is a valid choice for an application, and is never used to refer to runtime behavior.
- cannot
-
This word means that the particular behavior described is not achievable by an application, for example, an entry point does not exist.
There is an important distinction between cannot and must not, as used in this Specification. Cannot means something the application literally is unable to express or accomplish through the API, while must not means something that the application is capable of expressing through the API, but that the consequences of doing so are undefined and potentially unrecoverable for the runtime. |
2. Fundamentals
2.1. API Version Numbers and Semantics
Multi-part version numbers are used in several places in the OpenXR API.
// Provided by XR_VERSION_1_0
typedef uint64_t XrVersion;
In each such use, the API major version number, minor version number, and
patch version number are packed into a 64-bit integer, referred to as
XrVersion
, as follows:
Differences in any of the version numbers indicate a change to the API, with each part of the version number indicating a different scope of change, as follows.
Note
The rules below apply to OpenXR versions 1.0 or later. Prerelease versions of OpenXR may use different rules for versioning. |
A difference in patch version numbers indicates that some usually small part of the specification or header has been modified, typically to fix a bug, and may have an impact on the behavior of existing functionality. Differences in the patch version number must affect neither full compatibility nor backwards compatibility between two versions, nor may it add additional interfaces to the API. Runtimes may use patch version number to determine whether to enable implementation changes, such as bug fixes, that impact functionality. Runtimes should document any changes that are tied to the patch version. Application developers should retest their application on all runtimes they support after compiling with a new version.
A difference in minor version numbers indicates that some amount of new functionality has been added. This will usually include new interfaces in the header, and may also include behavior changes and bug fixes. Functionality may be deprecated in a minor revision, but must not be removed. When a new minor version is introduced, the patch version is reset to 0, and each minor revision maintains its own set of patch versions. Differences in the minor version number should not affect backwards compatibility, but will affect full compatibility.
A difference in major version numbers indicates a large set of changes to the API, potentially including new functionality and header interfaces, behavioral changes, removal of deprecated features, modification or outright replacement of any feature, and is thus very likely to break compatibility. Differences in the major version number will typically require significant modification to application code in order for it to function properly.
The following table attempts to detail the changes that may occur versus when they must not be updated (indicating the next version number must be updated instead) during an update to any of the major, minor, or patch version numbers:
Reason |
Major Version |
Minor Version |
Patch Version |
Extensions Added/Removed* |
may |
may |
may |
Spec-Optional Behavior Changed* |
may |
may |
may |
Spec Required Behavior Changed* |
may |
may |
must not |
Core Interfaces Added* |
may |
may |
must not |
Weak Deprecation* |
may |
may |
must not |
Strong Deprecation* |
may |
must not |
must not |
Core Interfaces Changed/Removed* |
may |
must not |
must not |
In the above table, the following identify the various cases in detail:
Extensions Added/Removed |
An extension may be added or removed with a change at this patch level. |
Specification-Optional Behavior Changed |
Some optional behavior laid out in this specification has changed. Usually this will involve a change in behavior that is marked with the normatives should or may. For example, a runtime that previously did not validate a particular use case may now begin validating that use case. |
Specification-Required Behavior Changed |
A behavior of runtimes that is required by this specification may have changed. For example, a previously optional validation may now have become mandatory for runtimes. |
Core Interfaces Added |
New interfaces may have been added to this specification (and to the OpenXR header file) in revisions at this level. |
Weak Deprecation |
An interface may have been weakly deprecated at this level. This may happen if there is now a better way to accomplish the same thing. Applications making this call should behave the same as before the deprecation, but following the new path may be more performant, less latent, or otherwise yield better results. It is possible that some runtimes may choose to give run-time warnings that the feature has been weakly deprecated and will likely be strongly deprecated or removed in the future. |
Strong Deprecation |
An interface may have been strongly deprecated at this level. This means that the interface must still exist (so applications that are compiled against it will still run) but it may now be a no-op, or it may be that its behavior has been significantly changed. It may be that this functionality is no longer necessary, or that its functionality has been subsumed by another call. This should not break an application, but some behavior may be different or unanticipated. |
Interfaces Changed/Removed |
An interface may have been changed — with different parameters or return types — at this level. An interface or feature may also have been removed entirely. It is almost certain that rebuilding applications will be required. |
2.2. String Encoding
This API uses strings as input and output for some functions.
Unless otherwise specified, all such strings are NULL
terminated UTF-8
encoded case-sensitive character arrays.
2.3. Threading Behavior
The OpenXR API is intended to provide scalable performance when used on multiple host threads. All functions must support being called concurrently from multiple threads, but certain parameters, or components of parameters are defined to be externally synchronized. This means that the caller must guarantee that no more than one thread is using such a parameter at a given time.
More precisely, functions use simple stores to update software structures representing objects. A parameter declared as externally synchronized may have its software structures updated at any time during the host execution of the function. If two functions operate on the same object and at least one of the functions declares the object to be externally synchronized, then the caller must guarantee not only that the functions do not execute simultaneously, but also that the two functions are separated by an appropriate memory barrier if needed.
For all functions which destroy an object handle, the application must externally synchronize the object handle parameter and any child handles.
2.4. Multiprocessing Behavior
The OpenXR API does not explicitly recognize nor require support for multiple processes using the runtime simultaneously, nor does it prevent a runtime from providing such support.
2.5. Runtime
An OpenXR runtime is software which implements the OpenXR API. There may be more than one OpenXR runtime installed on a system, but only one runtime can be active at any given time.
2.6. Extensions
OpenXR is an extensible API that grows through the addition of new features. Similar to other Khronos APIs, extensions may expose new OpenXR functions or modify the behavior of existing OpenXR functions. Extensions are optional and therefore must be enabled by the application before the extended functionality is made available. Because extensions are optional, they may be implemented only on a subset of runtimes, graphics platforms, or operating systems. Therefore, an application should first query which extensions are available before enabling.
The application queries the available list of extensions using the xrEnumerateInstanceExtensionProperties function. Once an application determines which target extensions are supported, it can enable some subset of them during the call to xrCreateInstance.
OpenXR extensions have unique names that convey information about what functionality is provided. The names have the following format:
For example: XR_KHR_composition_layer_cube
is an OpenXR extension
created by the Khronos (KHR) OpenXR Working Group to support cube
composition layers.
The public list of available extensions known at the time of this specification being generated appears in the List of Extensions appendix at the end of this document.
2.7. API Layers
OpenXR is designed to be a layered API, which means that a user or application may insert API layers between the application and the runtime implementation. These API layers provide additional functionality by intercepting OpenXR functions from the layer above and then performing different operations than would otherwise be performed without the layer. In the simplest cases, the layer simply calls the next layer down with the same arguments, but a more complex layer may implement API functionality that is not present in the layers or runtime below it. This mechanism is essentially an architected "function shimming" or "intercept" feature that is designed into OpenXR and meant to replace more informal methods of "hooking" API calls.
2.7.1. Examples of API Layers
Validation Layer
The layered API approach employed by OpenXR allows for the expensive validation of correct API usage to be implemented in a "validation" layer. This layer allows the application developer to develop their application with the validation layer active to ensure that the application is using the API correctly. The validation layer confirms that the application has set up object state correctly, has provided the required data for each function, ensures that required resources are available, etc. If the validation layer detects a problem, it issues an error message that can be logged or captured by the application via a callback. After the developer has determined that the application is correct, they turn off the validation layer to allow the application to run in a production environment without repeatedly incurring the validation expense.
2.7.2. Naming API Layers
To organize API layer names and prevent collisions in the API layer name namespace, API layers must be named using the following convention:
XR_APILAYER_<VENDOR-TAG>_short_name
Vendors are responsible for registering a vendor tag with the OpenXR working group and just like for implementors, they must maintain their vendor namespace.
Example of an API layer name produced by the Acme company for the "check best practices" API layer:
XR_APILAYER_ACME_check_best_practices
2.7.3. Activating API Layers
Application Activation
Applications can determine the API layers that are available to them by calling the xrEnumerateApiLayerProperties function to obtain a list of available API layers. Applications then can select the desired API layers from this list and provide them to the xrCreateInstance function when creating an instance.
System Activation
Application users or users performing roles such as system integrator or system administrator may configure a system to activate API layers without involvement from the applications. These platform-dependent steps may include the installation of API layer-related files, setting environment variables, or other platform-specific operations. The options that are available for configuring the API layers in this manner are also dependent on the platform and/or runtime.
2.7.4. API Layer Extensions
API layers may implement OpenXR functions that may or may not be supported by the underlying runtime. In order to expose these new features, the API layer must expose this functionality in the form of an OpenXR extension. It must not expose new OpenXR functions without an associated extension.
For example, an OpenXR API-logging API layer might expose an API function to
allow the application to turn logging on for only a portion of its
execution.
Since new functions must be exposed through an extension, the vendor has
created an extension called XR_ACME_logging_on_off
to contain these new
functions.
The application should query if the API layer supports the extension and
then, only if it exists, enable both the extension and the API layer by name
during xrCreateInstance.
To find out what extensions an API layer supports, an application must first verify that the API layer exists on the current system by calling xrEnumerateApiLayerProperties. After verifying an API layer of interest exists, the application then should call xrEnumerateInstanceExtensionProperties and provide the API layer name as the first parameter. This will return the list of extensions implemented internally in that API layer.
2.8. Type Aliasing
Type aliasing refers to the situation in which the actual type of a element
does not match the declared type.
Some C and C++ compilers can be configured to assume that the actual type
matches the declared type, and may be so configured by default at common
optimization levels.
Without this, otherwise undefined behavior may occur.
This compiler feature is typically referred to as "strict aliasing," and it
can usually be enabled or disabled via compiler options.
The OpenXR specification does not support strict aliasing, as there are some
cases in which an application intentionally provides a struct with a type
that differs from the declared type.
For example, XrFrameEndInfo::layers
is an array of type
const
XrCompositionLayerBaseHeader code:* const
.
However, the array must be of one of the specific layer types, such as
XrCompositionLayerQuad.
Similarly, xrEnumerateSwapchainImages accepts an array of
XrSwapchainImageBaseHeader, whereas the actual type passed must be an
array of a type such as
XrSwapchainImageVulkanKHR.
For OpenXR to work correctly, the compiler must support the type aliasing described here.
// Provided by XR_VERSION_1_0
#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
As a convenience, some types and pointers that are known at specification time to alias values of different types have been annotated with the XR_MAY_ALIAS definition. If this macro is not defined before including OpenXR headers, and a new enough Clang or GCC compiler is used, it will be defined to the compiler-specific attribute annotation to inform these compilers that those pointers may alias. However, there is no guarantee that all aliasing types or pointers have been correctly marked with this macro, so thorough testing is still recommended if you choose (at your own risk) to permit your compiler to perform type-based aliasing analysis.
2.9. Valid Usage
Valid usage defines a set of conditions which must be met in order to achieve well-defined run-time behavior in an application. These conditions depend only on API state, and the parameters or objects whose usage is constrained by the condition.
Some valid usage conditions have dependencies on runtime limits or feature availability. It is possible to validate these conditions against the API’s minimum or maximum supported values for these limits and features, or some subset of other known values.
Valid usage conditions should apply to a function or structure where complete information about the condition would be known during execution of an application. This is such that a validation API layer or linter can be written directly against these statements at the point they are specified.
2.9.1. Implicit Valid Usage
Some valid usage conditions apply to all functions and structures in the API, unless explicitly denoted otherwise for a specific function or structure. These conditions are considered implicit. Implicit valid usage conditions are described in detail below.
2.9.2. Valid Usage for Object Handles
Any input parameter to a function that is an object handle must be a valid object handle, unless otherwise specified. An object handle is valid if and only if:
There are contexts in which an object handle is optional or otherwise
unspecified.
In those cases, the API uses XR_NULL_HANDLE, which has the integer
value 0
.
2.9.3. Valid Usage for Pointers
Any parameter that is a pointer must be a valid pointer when the specification indicates that the runtime uses the pointer. A pointer is valid if and only if it points at memory containing values of the number and type(s) expected by the function, and all fundamental types accessed through the pointer (e.g. as elements of an array or as members of a structure) satisfy the alignment requirements of the host processor.
2.9.4. Valid Usage for Enumerated Types
Any parameter of an enumerated type must be a valid enumerant for that type. An enumerant is valid if and only if the enumerant is defined as part of the enumerated type in question.
2.9.5. Valid Usage for Flags
A collection of flags is represented by a bitmask using the type
XrFlags64
:
typedef uint64_t XrFlags64;
Bitmasks are passed to many functions and structures to compactly represent
options and are stored in memory defined by the XrFlags64
type.
But the API does not use the XrFlags64
type directly.
Instead, a Xr*Flags
type is used which is an alias of the
XrFlags64
type.
The API also defines a set of constant bit definitions used to set the
bitmasks.
Any Xr*Flags
member or parameter used in the API must be a valid
combination of bit flags.
A valid combination is either zero or the bitwise OR
of valid bit
flags.
A bit flag is valid if and only if:
2.9.6. Valid Usage for Structure Types
Any parameter that is a structure containing a type
member must have
a value of type
which is a valid XrStructureType value matching
the type of the structure.
As a general rule, the name of this value is obtained by taking the
structure name, stripping the leading Xr
, prefixing each capital letter
with an underscore, converting the entire resulting string to upper case,
and prefixing it with XR_TYPE_
.
The only exceptions to this rule are API and Operating System names which are converted in a way that produces a more readable value:
2.9.7. Valid Usage for Structure Pointer Chains
Any structure containing a void*
next
member must have a value
of next
that is either NULL
, or points to a valid structure that
also contains type
and next
member values.
The set of structures connected by next
pointers is referred to as a
next
chain.
In order to use a structure type defined by an extension in a next
chain, the proper extension must have been previously enabled during
xrCreateInstance.
A runtime must ignore all unrecognized structures in a next
chain,
including those associated with an extension that has not been enabled.
Some structures for use in a chain are described in the core OpenXR specification and are mentioned in the Member Descriptions. Any structure described in this document intended for use in a chain is mentioned in a "See also" list in the implicit valid usage of the structure they chain to. Most chained structures are associated with extensions, and are described in the base OpenXR Specification under the List of Extensions. Vendor-specific extensions may be found there as well, or may only be available from the vendor’s website or internal document repositories.
Unless otherwise specified: Chained structs which are output structs may be modified by the runtime with the exception of the type and next fields. Upon return from any function, all type and next fields in the chain must be unmodified.
Useful Base Structures
As a convenience to runtimes and layers needing to iterate through a structure pointer chain, the OpenXR API provides the following base structures:
The XrBaseInStructure structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrBaseInStructure {
XrStructureType type;
const struct XrBaseInStructure* next;
} XrBaseInStructure;
XrBaseInStructure can be used to facilitate iterating through a read-only structure pointer chain.
The XrBaseOutStructure structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrBaseOutStructure {
XrStructureType type;
struct XrBaseOutStructure* next;
} XrBaseOutStructure;
XrBaseOutStructure can be used to facilitate iterating through a structure pointer chain that returns data back to the application.
These structures allow for some type safety and can be used by OpenXR API functions that operate on generic inputs and outputs.
Next Chain Structure Uniqueness
Applications should ensure that they create and insert no more than one
occurrence of each type of extension structure in a given next
chain.
Other components of OpenXR (such as the OpenXR loader or an API Layer) may
insert duplicate structures into this chain.
This provides those components the ability to update a structure that
appears in the next
chain by making a modified copy of that same
structure and placing the new version at the beginning of the chain.
The benefit of allowing this duplication is each component is no longer
required to create a copy of the entire next
chain just to update one
structure.
When duplication is present, all other OpenXR components must process only
the first instance of a structure of a given type, and then ignore all
instances of a structure of that same type.
If a component makes such a structure copy, and the original structure is also used to return content, then that component must copy the necessary content from the copied structure and into the original version of the structure upon completion of the function prior to proceeding back up the call stack. This is to ensure that OpenXR behavior is consistent whether or not that particular OpenXR component is present and/or enabled on the system.
2.9.8. Valid Usage for Nested Structures
The above conditions also apply recursively to members of structures provided as input to a function, either as a direct argument to the function, or themselves a member of another structure.
Specifics on valid usage of each function are covered in their individual sections.
2.10. Return Codes
The core API is designed to capture most, but not all, instances of incorrect usage. As such, most functions provide return codes. Functions in the API return their status via return codes that are in one of the two categories below.
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_GRAPHICS_REQUIREMENTS_CALL_MISSING = -50,
XR_ERROR_RUNTIME_UNAVAILABLE = -51,
// Provided by XR_KHR_android_thread_settings
XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR = -1000003000,
// Provided by XR_KHR_android_thread_settings
XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR = -1000003001,
XR_RESULT_MAX_ENUM = 0x7FFFFFFF
} XrResult;
All return codes in the API are reported via XrResult return values.
Some common suffixes shared across many of the return codes are defined below:
-
_INVALID
: The specified handle, atom or value is formatted incorrectly, or the specified handle was never created or has been destroyed. -
_UNSUPPORTED
: The specified handle, atom, enumerant or value is formatted correctly but cannot be used for the lifetime of this function’s parent handle. -
_UNAVAILABLE
: The specified handle, atom, enumerant or value is supported by this function’s parent handle but not at this moment.
Success Codes
Enum | Description |
---|---|
|
Function successfully completed. |
|
The specified timeout time occurred before the operation could complete. |
|
The session will be lost soon. |
|
No event was available. |
|
The space’s bounds are not known at the moment. |
|
The session is not in the focused state. |
|
A frame has been discarded from composition. |
Error Codes
Enum | Description |
---|---|
|
The function usage was invalid in some way. |
|
The runtime failed to handle the function in an unexpected way that is not covered by another error result. |
|
A memory allocation has failed. |
|
The runtime does not support the requested API version. |
|
Initialization of object could not be completed. |
|
The requested function was not found or is otherwise unsupported. |
|
The requested feature is not supported. |
|
A requested extension is not supported. |
|
The runtime supports no more of the requested resource. |
|
The supplied size was smaller than required. |
|
A supplied object handle was invalid. |
|
The XrInstance was lost or could not be found. It will need to be destroyed and optionally recreated. |
|
The session is already running. |
|
The session is not yet running. |
|
The XrSession was lost. It will need to be destroyed and optionally recreated. |
|
The provided |
|
The provided |
|
The maximum number of supported semantic paths has been reached. |
|
The semantic path character format is invalid. |
|
The semantic path is unsupported. |
|
The layer was NULL or otherwise invalid. |
|
The number of specified layers is greater than the supported number. |
|
The image rect was negatively sized or otherwise invalid. |
|
The image format is not supported by the runtime or platform. |
|
The API used to retrieve an action’s state does not match the action’s type. |
|
The session is not in the ready state. |
|
The session is not in the stopping state. |
|
The provided |
|
The specified reference space is not supported by the runtime or system. |
|
The file could not be accessed. |
|
The file’s contents were invalid. |
|
The specified form factor is not supported by the current runtime or platform. |
|
The specified form factor is supported, but the device is currently not available, e.g. not plugged in or powered off. |
|
A requested API layer is not present or could not be loaded. |
|
The call was made without having made a previously required call. |
|
The given graphics device is not in a valid state. The graphics device could be lost or initialized without meeting graphics requirements. |
|
The supplied pose was invalid with respect to the requirements. |
|
The supplied index was outside the range of valid indices. |
|
The specified view configuration type is not supported by the runtime or platform. |
|
The specified environment blend mode is not supported by the runtime or platform. |
|
The name provided was a duplicate of an already-existing resource. |
|
The name provided was invalid. |
|
A referenced action set is not attached to the session. |
|
The session already has attached action sets. |
|
The localized name provided was a duplicate of an already-existing resource. |
|
The localized name provided was invalid. |
|
The |
|
The loader was unable to find or load a runtime. |
|
xrSetAndroidApplicationThreadKHR failed as thread id is invalid. (Added by the |
|
xrSetAndroidApplicationThreadKHR failed setting the thread attributes/priority. (Added by the |
2.10.1. Convenience Macros
// Provided by XR_VERSION_1_0
#define XR_SUCCEEDED(result) ((result) >= 0)
A convenience macro that can be used to test if a function succeeded.
This may be a qualified success such as XR_FRAME_DISCARDED
.
// Provided by XR_VERSION_1_0
#define XR_FAILED(result) ((result) < 0)
A convenience macro that can be used to test if a function has failed in some way.
// Provided by XR_VERSION_1_0
#define XR_UNQUALIFIED_SUCCESS(result) ((result) == 0)
A convenience macro that can be used to test a function’s failure.
The XR_UNQUALIFIED_SUCCESS macro is a convenience macro which may be
used to compare an XrResult to 0
(XR_SUCCESS
) exclusively.
2.10.2. Validation
Except as noted below or in individual API specifications, valid API usage may be required by the runtime. Runtimes may choose to validate some API usage and return an appropriate error code.
Application developers should use validation layers to catch and eliminate errors during development. Once validated, applications should not enable validation layers by default.
If a function returns a run time error, unless otherwise specified any output parameters will have undefined contents, except that if the output parameter is a structure with type and next fields, those fields will be unmodified. Any output structures chained from next will also have undefined contents, except that the type and next will be unmodified.
Unless otherwise specified, errors do not affect existing OpenXR objects. Objects that have already been successfully created may still be used by the application.
XrResult code returns may be added to a given function in future versions of the specification. Runtimes must return only XrResult codes from the set documented for the given application API version.
Runtimes must ensure that incorrect usage by an application does not affect the integrity of the operating system, the API implementation, or other API client applications in the system, and does not allow one application to access data belonging to another application.
2.11. Handles
Objects which are allocated by the runtime on behalf of applications are
represented by handles.
Handles are opaque identifiers for objects whose lifetime is controlled by
applications via the create and destroy functions.
Example handle types include XrInstance, XrSession, and
XrSwapchain.
Handles which have not been destroyed are unique for a given application
process, but may be reused after being destroyed.
Unless otherwise specified, a successful handle creation function call
returns a new unique handle.
Unless otherwise specified, handles are implicitly destroyed when their
parent handle is destroyed.
Applications may destroy handles explicitly before the parent handle is
destroyed, and should do so if no longer needed, in order to conserve
resources.
Runtimes may detect XR_NULL_HANDLE and other invalid handles passed
where a valid handle is required and return XR_ERROR_HANDLE_INVALID
.
However, runtimes are not required to do so unless otherwise specified, and
so use of any invalid handle may result in undefined behavior.
When a function has an optional handle parameter, XR_NULL_HANDLE must
be used unless passing a valid handle.
All functions that take a handle parameter may return
XR_ERROR_HANDLE_INVALID
.
Handles form a hierarchy in which child handles fall under the validity and lifetime of parent handles. For example, to create an XrSwapchain handle, applications must call xrCreateSwapchain and pass an XrSession handle. Thus XrSwapchain is a child handle to XrSession.
2.12. Object Handle Types
The type of an object handle used in a function is usually determined by the specification of that function, as discussed in Valid Usage for Object Handles. However, some functions accept or return object handle parameters where the type of the object handle is unknown at execution time and is not specified in the description of the function itself. For these functions, the XrObjectType may be used to explicitly specify the type of a handle.
For example, an information-gathering or debugging mechanism implemented in a runtime extension or API layer extension may return a list of object handles that are generated by the mechanism’s operation. The same mechanism may also return a parallel list of object handle types that allow the recipient of this information to easily determine the types of the handles.
In general, anywhere an object handle of more than one type can occur, the object handle type may be provided to indicate its type.
// Provided by XR_VERSION_1_0
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_MAX_ENUM = 0x7FFFFFFF
} XrObjectType;
The XrObjectType enumeration defines values, each of which corresponds to a specific OpenXR handle type. These values can be used to associate debug information with a particular type of object through one or more extensions.
The following table defines XrObjectType and OpenXR Handle relationships:
XrObjectType | OpenXR Handle Type |
---|---|
|
Unknown/Undefined Handle |
|
|
|
|
|
|
|
|
|
|
|
2.13. Buffer Size Parameters
Functions with input/output buffer parameters take on either parameter form
or struct form, looking like one of the following examples, with the element
type being float
in this case:
Parameter form:
XrResult xrFunction(uint32_t elementCapacityInput, uint32_t* elementCountOutput, float* elements);
Struct form:
XrResult xrFunction(XrBuffer* buffer);
struct XrBuffer {
uint32_t elementCapacityInput;
uint32_t elementCountOutput;
float* elements;
};
A two-call idiom may be employed, first calling xrFunction
(with a
valid elementCountOutput
pointer if in parameter form), but passing
NULL
as elements
and 0
as elementCapacityInput
, to
retrieve the required buffer size as number of elements (number of floats in
this example).
After allocating a buffer at least as large as elementCountOutput
(in
a struct) or the value pointed to by elementCountOutput
(as
parameters), a pointer to the allocated buffer should be passed as
elements
, along with the buffer’s length in
elementCapacityInput
, to a second call to xrFunction
to perform
the retrieval of the data.
In case that elements
is a struct with type
and next
fields, the application must set the type
to the correct value as
well as next
either to NULL
or a struct with extension related
data in which type
and next
also need to be well defined.
In the following discussion, "set elementCountOutput
" should be
interpreted as "set the value pointed to by elementCountOutput
" in
parameter form and "set the value of elementCountOutput
" in struct
form.
These functions have the below-listed behavior with respect to the buffer
size parameters:
Some functions fill multiple buffers in one call.
For these functions, the elementCapacityInput
,
elementCountOutput
and elements
parameters or fields are
repeated, once per buffer, with different prefixes.
In that case, the semantics above still apply, with the additional behavior
that if any elementCapacityInput
parameter or field is set to 0 by the
application, the runtime must treat all elementCapacityInput
values
as if they were set to 0.
If any elementCapacityInput
value is too small to fit all elements of
the buffer, XR_ERROR_SIZE_INSUFFICIENT
must be returned, and the data
in all buffers is undefined.
2.14. Time
Time is represented by a 64-bit signed integer representing nanoseconds
(XrTime
).
The passage of time must be monotonic and not real-time (i.e. wall clock
time).
Thus the time is always increasing at a constant rate and is unaffected by
clock changes, time zones, daylight savings, etc.
2.14.1. XrTime
typedef int64_t XrTime;
XrTime
is a base value type that represents time as a signed 64-bit
integer, representing the monotonically-increasing count of nanoseconds that
have elapsed since a runtime-chosen epoch.
XrTime
always represents the time elapsed since that constant
epoch, rather than a duration or a time point relative to some moving epoch
such as vsync time, etc.
Durations are instead represented by XrDuration
.
A single runtime must use the same epoch for all simultaneous applications. Time must be represented the same regardless of multiple processors or threads present in the system.
The period precision of time reported by the runtime is runtime-dependent, and may change. One nanosecond is the finest possible period precision. A runtime may, for example, report time progression with only microsecond-level granularity.
Time must not be assumed to correspond to a system clock time.
Unless specified otherwise, zero or a negative value is not a valid
XrTime
, and related functions must return error
XR_ERROR_TIME_INVALID
.
Applications must not initialize such XrTime
fields to a zero
value.
Instead, applications should always assign XrTime
fields to the
meaningful point in time they are choosing to reason about, such as a
frame’s predicted display time, or an action’s last change time.
The behavior of a runtime is undefined when time overflows beyond the
maximum positive value that can be represented by an XrTime
.
Runtimes should choose an epoch that minimizes the chance of overflow.
Runtimes should also choose an epoch that minimizes the chance of underflow
below 0 for applications performing a reasonable amount of historical pose
lookback.
For example, if the runtime chooses an epoch relative to its startup time,
it should push the epoch into the past by enough time to avoid applications
performing reasonable pose lookback from reaching a negative XrTime
value.
An application cannot assume that the system’s clock and the runtime’s clock
will maintain a constant relationship across frames and should avoid
storing such an offset, as this may cause time drift.
Applications should instead always use time interop functions to convert a
relevant time point across the system’s clock and the runtime’s clock using
extensions, for example,
XR_KHR_win32_convert_performance_counter_time
or
XR_KHR_convert_timespec_time
.
2.15. Duration
Duration refers to an elapsed period of time, as opposed to an absolute timepoint.
2.15.1. XrDuration
typedef int64_t XrDuration;
The difference between two timepoints is a duration, and thus the difference
between two XrTime
values is an XrDuration
value.
Functions that refer to durations use XrDuration
as opposed to
XrTime
.
// Provided by XR_VERSION_1_0
#define XR_NO_DURATION 0
For the case of timeout durations, XR_NO_DURATION may be used to indicate that the timeout is immediate.
// Provided by XR_VERSION_1_0
#define XR_INFINITE_DURATION 0x7fffffffffffffffLL
XR_INFINITE_DURATION is a special value that may be used to indicate that the timeout never occurs. A timeout with a duration that refers to the past has the same effect as a timeout of XR_NO_DURATION.
2.16. Prediction Time Limits
Some functions involve prediction.
For example, xrLocateViews accepts a display time for which to return
the resulting data.
Prediction times provided by applications may refer to time in the past or
the future.
Times in the past may be interpolated historical data.
Runtimes have different practical limits with respect to how far forward or
backward prediction times can be accurate.
There is no prescribed forward limit the application can successfully
request predictions for, though predictions may become less accurate as they
get farther into the future.
With respect to backward prediction, the application can pass a prediction
time equivalent to the timestamp of the most recently received pose plus as
much as 50
milliseconds in the past to retrieve accurate historical
data.
Requested times predating this time window, or requested times predating the
earliest received pose, may result in a best effort data whose accuracy
reduced or unspecified.
2.17. Colors
The XrColor4f structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrColor4f {
float r;
float g;
float b;
float a;
} XrColor4f;
Unless otherwise specified, colors are encoded as linear (not with sRGB nor other gamma compression) values with individual components being in the range of 0.0 through 1.0, and without the RGB components being premultiplied by the alpha component.
If color encoding is specified as being premultiplied by the alpha component, the RGB components are set to zero if the alpha component is zero.
2.18. Coordinate System
This API uses a Cartesian right-handed coordinate system.
The conventions for mapping coordinate axes of any particular space to meaningful directions depend on and are documented with the description of the space.
The API uses 2D, 3D, and 4D floating-point vectors to describe points and directions in a space.
A two-dimensional vector is defined by the XrVector2f structure:
typedef struct XrVector2f {
float x;
float y;
} XrVector2f;
If used to represent physical distances (rather than e.g. normalized direction) and not otherwise specified, values must be in meters.
A three-dimensional vector is defined by the XrVector3f structure:
typedef struct XrVector3f {
float x;
float y;
float z;
} XrVector3f;
If used to represent physical distances (rather than e.g. velocity or angular velocity) and not otherwise specified, values must be in meters.
A four-dimensional or homogeneous vector is defined by the XrVector4f structure:
// Provided by XR_VERSION_1_0
typedef struct XrVector4f {
float x;
float y;
float z;
float w;
} XrVector4f;
If used to represent physical distances, x
, y
, and z
values must be in meters.
Rotation is represented by a unit quaternion defined by the XrQuaternionf structure:
typedef struct XrQuaternionf {
float x;
float y;
float z;
float w;
} XrQuaternionf;
A pose is defined by the XrPosef structure:
typedef struct XrPosef {
XrQuaternionf orientation;
XrVector3f position;
} XrPosef;
A construct representing a position and orientation within a space, with
position expressed in meters, and orientation represented as a unit
quaternion.
When using XrPosef the rotation described by orientation
is
always applied before the translation described by position
.
A runtime must return XR_ERROR_POSE_INVALID
if the orientation
norm deviates by more than 1% from unit length.
2.19. Common Object Types
Some types of OpenXR objects are used in multiple structures.
Those include the XrVector*f
and types specified above but also the
following structures: offset, extents and rectangle.
Offsets are used to describe the magnitude of an offset in two dimensions.
A floating-point offset is defined by the structure:
// Provided by XR_VERSION_1_0
typedef struct XrOffset2Df {
float x;
float y;
} XrOffset2Df;
This structure is used for component values that may be fractional (floating-point). If used to represent physical distances, values must be in meters.
An integer offset is defined by the structure:
typedef struct XrOffset2Di {
int32_t x;
int32_t y;
} XrOffset2Di;
This variant is for representing discrete values such as texels. For representing physical distances, the floating-point variant must be used instead.
Extents are used to describe the size of a rectangular region in two dimensions.
A two-dimensional floating-point extent is defined by the structure:
// Provided by XR_VERSION_1_0
typedef struct XrExtent2Df {
float width;
float height;
} XrExtent2Df;
This structure is used for component values that may be fractional (floating-point). If used to represent physical distances, values must be in meters.
The width
and height
value must be non-negative.
A two-dimensional integer extent is defined by the structure:
typedef struct XrExtent2Di {
int32_t width;
int32_t height;
} XrExtent2Di;
This variant is for representing discrete values such as texels. For representing physical distances, the floating-point variant must be used instead.
The width
and height
value must be non-negative.
Rectangles are used to describe a specific rectangular region in two dimensions. Rectangles must include both an offset and an extent defined in the same units. For instance, if a rectangle is in meters, both offset and extent must be in meters.
A rectangle with floating-point values is defined by the structure:
// Provided by XR_VERSION_1_0
typedef struct XrRect2Df {
XrOffset2Df offset;
XrExtent2Df extent;
} XrRect2Df;
This structure is used for component values that may be fractional (floating-point).
The offset
is the position of the rectangle corner with minimum value
coordinates.
The other three corners are computed by adding the
XrExtent2Di::width
to the x
offset,
XrExtent2Di::height
to the y
offset, or both.
A rectangle with integer values is defined by the structure:
typedef struct XrRect2Di {
XrOffset2Di offset;
XrExtent2Di extent;
} XrRect2Di;
This variant is for representing discrete values such as texels. For representing physical distances, the floating-point variant must be used instead.
The offset
is the position of the rectangle corner with minimum value
coordinates.
The other three corners are computed by adding the
XrExtent2Di::width
to the x
offset,
XrExtent2Di::height
to the y
offset, or both.
2.20. Angles
Where a value is provided as a function parameter or as a structure member and will be interpreted as an angle, the value is defined to be in radians.
Field of view (FoV) is defined by the structure:
typedef struct XrFovf {
float angleLeft;
float angleRight;
float angleUp;
float angleDown;
} XrFovf;
Angles to the right of the center and upwards from the center are positive,
and angles to the left of the center and down from the center are negative.
The total horizontal field of view is angleRight
minus
angleLeft
, and the total vertical field of view is angleUp
minus
angleDown
.
For a symmetric FoV, angleRight
and angleUp
will have positive
values, angleLeft
will be -angleRight
, and angleDown
will
be -angleUp
.
The angles must be specified in radians, and must be between -π/2 and π/2 exclusively.
When angleLeft
> angleRight
, the content of the view must be
flipped horizontally.
When angleDown
> angleUp
, the content of the view must be
flipped vertically.
2.21. Boolean Values
typedef uint32_t XrBool32;
Boolean values used by OpenXR are of type XrBool32
and are 32-bits
wide as suggested by the name.
The only valid values are the following:
#define XR_TRUE 1
#define XR_FALSE 0
2.22. Events
Events are messages sent from the runtime to the application.
2.22.1. Event Polling
These events are placed in a queue and the application must read from the queue with regularity. Events are read from the queue one at a time via xrPollEvent. Every event is identified by an individual struct, with each struct beginning with an XrEventDataBaseHeader.
XrInstance instance; // previously initialized
// Initialize an event buffer to hold the output.
XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
XrResult result = xrPollEvent(instance, &event);
if (result == XR_SUCCESS) {
switch (event.type) {
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
const XrEventDataSessionStateChanged& session_state_changed_event =
*reinterpret_cast<XrEventDataSessionStateChanged*>(&event);
// ...
break;
}
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
const XrEventDataInstanceLossPending& instance_loss_pending_event =
*reinterpret_cast<XrEventDataInstanceLossPending*>(&event);
// ...
break;
}
}
}
xrPollEvent
// Provided by XR_VERSION_1_0
XrResult xrPollEvent(
XrInstance instance,
XrEventDataBuffer* eventData);
xrPollEvent polls for the next event and returns an event if one is
available.
xrPollEvent returns immediately regardless of whether an event was
available.
The event (if present) is unilaterally removed from the queue if a valid
XrInstance is provided.
On return the eventData
parameter is filled with the event’s data and
the type field is changed to the event’s type.
Runtimes may create valid next chains depending on enabled extensions, but
they must guarantee that any such chains point only to objects which fit
completely within the original XrEventDataBuffer pointed to by
eventData
.
The runtime must discard queued events which contain destroyed or otherwise invalid handles.
Event | Description |
---|---|
event queue has overflowed and some events were lost |
|
application is about to lose the instance |
|
active input form factor for one or more top level user paths has changed |
|
runtime will begin operating with updated space bounds |
|
application has changed lifecycle state |
The XrEventDataBaseHeader structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataBaseHeader {
XrStructureType type;
const void* next;
} XrEventDataBaseHeader;
The XrEventDataBaseHeader is a generic structure used to identify the common event data elements.
Upon receipt, the XrEventDataBaseHeader pointer should be type-cast to
a pointer of the appropriate event data based on the type
parameter.
The XrEventDataBuffer is a structure passed to xrPollEvent large enough to contain any returned event data element. The maximum size is specified by XR_MAX_EVENT_DATA_SIZE.
It is sufficient to clear the type
and next
parameters of an
XrEventDataBuffer when passing it as an input to xrPollEvent.
An XrEventDataBuffer may be type-cast to an
XrEventDataBaseHeader pointer or a pointer to any other appropriate
event data based on the type
parameter.
typedef struct XrEventDataBuffer {
XrStructureType type;
const void* next;
uint8_t varying[4000];
} XrEventDataBuffer;
XR_MAX_EVENT_DATA_SIZE is the maximum size of an XrEventDataBuffer.
// Provided by XR_VERSION_1_0
#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer)
XrEventDataEventsLost
The XrEventDataEventsLost structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataEventsLost {
XrStructureType type;
const void* next;
uint32_t lostEventCount;
} XrEventDataEventsLost;
Receiving the XrEventDataEventsLost event structure indicates that the event queue overflowed and some events were removed at the position within the queue at which this event was found.
Other event structures are defined in later chapters in the context where their definition is most relevant.
2.23. System resource lifetime
The creator of an underlying system resource is responsible for ensuring the resource’s lifetime matches the lifetime of the associated OpenXR handle.
Resources passed as inputs from the application to the runtime when creating
an OpenXR handle should not be freed while that handle is valid.
A runtime must not free resources passed as inputs or decrease their
reference counts (if applicable) from the initial value.
For example, the graphics device handle (or pointer) passed in to
xrCreateSession in XrGraphicsBinding*
structure should be kept
alive when the corresponding XrSession handle is valid, and should be
freed by the application after the XrSession handle is destroyed.
Resources created by the runtime should not be freed by the application, and
the application should maintain the same reference count (if applicable) at
the destruction of the OpenXR handle as it had at its creation.
For example, the ID3D*Texture2D
objects in the XrSwapchainImageD3D*
are
created by the runtime and associated with the lifetime of the
XrSwapchain handle.
The application should not keep additional reference counts on any
ID3D*Texture2D
objects past the lifetime of the XrSwapchain handle,
or make extra reference count decrease after destroying the
XrSwapchain handle.
3. API Initialization
Before using an OpenXR runtime, an application must initialize it by creating an XrInstance object. The following functions are useful for gathering information about the API layers and extensions installed on the system and creating the instance.
xrEnumerateApiLayerProperties and xrEnumerateInstanceExtensionProperties can be called before calling xrCreateInstance.
3.1. Exported Functions
A dynamically linked library (.dll or .so) that implements the API loader must export all core OpenXR API functions. However, the application can gain access to extension functions by obtaining pointers to these functions through the use of xrGetInstanceProcAddr.
3.2. Function Pointers
Function pointers for all OpenXR functions can be obtained with the function xrGetInstanceProcAddr.
// Provided by XR_VERSION_1_0
XrResult xrGetInstanceProcAddr(
XrInstance instance,
const char* name,
PFN_xrVoidFunction* function);
xrGetInstanceProcAddr itself is obtained in a platform- and loader- specific manner. Typically, the loader library will export this function as a function symbol, so applications can link against the loader library, or load it dynamically and look up the symbol using platform-specific APIs. Loaders must export function symbols for all core OpenXR functions. Because of this, applications that use only the core OpenXR functions have no need to use xrGetInstanceProcAddr.
Because an application can call xrGetInstanceProcAddr before creating
an instance, xrGetInstanceProcAddr returns a valid function pointer
when the instance
parameter is XR_NULL_HANDLE and the name
parameter is one of the following strings:
xrGetInstanceProcAddr must return XR_ERROR_HANDLE_INVALID
if
name
is not one of the above strings and instance
is
XR_NULL_HANDLE.
xrGetInstanceProcAddr may return XR_ERROR_HANDLE_INVALID
if
name
is not one of the above strings and instance
is invalid but
not XR_NULL_HANDLE.
xrGetInstanceProcAddr must return XR_ERROR_FUNCTION_UNSUPPORTED
if instance
is a valid instance and the string specified in name
is not the name of an OpenXR core or enabled extension function.
If name
is the name of an extension function, then the result returned
by xrGetInstanceProcAddr will depend upon how the instance
was
created.
If instance
was created with the related extension’s name appearing in
the XrInstanceCreateInfo::enabledExtensionNames
array, then
xrGetInstanceProcAddr returns a valid function pointer.
If the related extension’s name did not appear in the
XrInstanceCreateInfo::enabledExtensionNames
array during the
creation of instance
, then xrGetInstanceProcAddr returns
XR_ERROR_FUNCTION_UNSUPPORTED
.
Because of this, function pointers returned by xrGetInstanceProcAddr
using one XrInstance may not be valid when used with objects related
to a different XrInstance.
The returned function pointer is of type PFN_xrVoidFunction, and must be cast to the type of the function being queried.
The table below defines the various use cases for xrGetInstanceProcAddr and return value (“fp” is “function pointer”) for each case.
instance parameter |
name parameter |
return value |
---|---|---|
* |
|
undefined |
invalid instance |
* |
undefined |
|
fp |
|
|
fp |
|
|
fp |
|
|
* (any |
|
instance |
core OpenXR function |
fp1 |
instance |
enabled extension function for |
fp1 |
instance |
* (any |
|
- 1
-
The returned function pointer must only be called with a handle (the first parameter) that is
instance
or a child ofinstance
.
typedef void (XRAPI_PTR *PFN_xrVoidFunction)(void);
PFN_xrVoidFunction is a generic function pointer type returned by queries, specifically those to xrGetInstanceProcAddr.
4. Instance
XR_DEFINE_HANDLE(XrInstance)
An OpenXR instance is an object that allows an OpenXR application to communicate with an OpenXR runtime. The application accomplishes this communication by calling xrCreateInstance and receiving a handle to the resulting XrInstance object.
The XrInstance object stores and tracks OpenXR-related application state, without storing any such state in the application’s global address space. This allows the application to create multiple instances as well as safely encapsulate the application’s OpenXR state since this object is opaque to the application. OpenXR runtimes may limit the number of simultaneous XrInstance objects that may be created and used, but they must support the creation and usage of at least one XrInstance object per process.
Physically, this state may be stored in any of the OpenXR loader, OpenXR API layers or the OpenXR runtime components. The exact storage and distribution of this saved state is implementation-dependent, except where indicated by this specification.
The tracking of OpenXR state in the instance allows the streamlining of the API, where the intended instance is inferred from the highest ascendant of an OpenXR function’s target object. For example, in:
myResult = xrEndFrame(mySession, &myEndFrameDescription);
the XrSession object was created from an XrInstance object. The OpenXR loader typically keeps track of the XrInstance that is the parent of the XrSession object in this example and directs the function to the runtime associated with that instance. This tracking of OpenXR objects eliminates the need to specify an XrInstance in every OpenXR function.
4.1. API Layers and Extensions
Additional functionality may be provided by API layers or extensions. An API layer must not add or modify the definition of OpenXR functions, while an extension may do so.
The set of API layers to enable is specified when creating an instance, and those API layers are able to intercept any functions dispatched to that instance or any of its child objects.
Example API layers may include (but are not limited to):
-
an API layer to dump out OpenXR API calls
-
an API layer to perform OpenXR validation
To determine what set of API layers are available, OpenXR provides the xrEnumerateApiLayerProperties function:
// Provided by XR_VERSION_1_0
XrResult xrEnumerateApiLayerProperties(
uint32_t propertyCapacityInput,
uint32_t* propertyCountOutput,
XrApiLayerProperties* properties);
The list of available layers may change at any time due to actions outside
of the OpenXR runtime, so two calls to xrEnumerateApiLayerProperties
with the same parameters may return different results, or retrieve
different propertyCountOutput
values or properties
contents.
Once an instance has been created, the layers enabled for that instance will continue to be enabled and valid for the lifetime of that instance, even if some of them become unavailable for future instances.
The XrApiLayerProperties structure is defined as:
typedef struct XrApiLayerProperties {
XrStructureType type;
void* next;
char layerName[XR_MAX_API_LAYER_NAME_SIZE];
XrVersion specVersion;
uint32_t layerVersion;
char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];
} XrApiLayerProperties;
To enable a layer, the name of the layer should be added to
XrInstanceCreateInfo::enabledApiLayerNames
when creating an
XrInstance.
Loader implementations may provide mechanisms outside this API for enabling
specific API layers.
API layers enabled through such a mechanism are implicitly enabled, while
API layers enabled by including the API layer name in
XrInstanceCreateInfo::enabledApiLayerNames
are explicitly
enabled.
Except where otherwise specified, implicitly enabled and explicitly enabled
API layers differ only in the way they are enabled.
Explicitly enabling an API layer that is implicitly enabled has no
additional effect.
Instance extensions are able to affect the operation of the instance and any of its child objects. As stated earlier, extensions can expand the OpenXR API and provide new functions or augment behavior.
Examples of extensions may be (but are not limited to):
The application can determine the available instance extensions by calling xrEnumerateInstanceExtensionProperties:
// Provided by XR_VERSION_1_0
XrResult xrEnumerateInstanceExtensionProperties(
const char* layerName,
uint32_t propertyCapacityInput,
uint32_t* propertyCountOutput,
XrExtensionProperties* properties);
Because the list of available layers may change externally between calls to
xrEnumerateInstanceExtensionProperties, two calls may retrieve
different results if a layerName
is available in one call but not in
another.
The extensions supported by a layer may also change between two calls, e.g.
if the layer implementation is replaced by a different version between those
calls.
The XrExtensionProperties structure is defined as:
typedef struct XrExtensionProperties {
XrStructureType type;
void* next;
char extensionName[XR_MAX_EXTENSION_NAME_SIZE];
uint32_t extensionVersion;
} XrExtensionProperties;
4.2. Instance Lifecycle
The xrCreateInstance function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrCreateInstance(
const XrInstanceCreateInfo* createInfo,
XrInstance* instance);
xrCreateInstance creates the XrInstance, then enables and
initializes global API layers and extensions requested by the application.
If an extension is provided by an API layer, both the API layer and
extension must be specified at xrCreateInstance time.
If a specified API layer cannot be found, no XrInstance will be
created and the function will return XR_ERROR_API_LAYER_NOT_PRESENT
.
Likewise, if a specified extension cannot be found, the call must return
XR_ERROR_EXTENSION_NOT_PRESENT
and no XrInstance will be
created.
Additionally, some runtimes may limit the number of concurrent instances
that may be in use.
If the application attempts to create more instances than a runtime can
simultaneously support, xrCreateInstance may return
XR_ERROR_LIMIT_REACHED
.
If the XrApplicationInfo::applicationName
is the empty string
the runtime must return XR_ERROR_NAME_INVALID
.
If the XrInstanceCreateInfo structure contains a platform-specific
extension for a platform other than the target platform,
XR_ERROR_INITIALIZATION_FAILED
may be returned.
If a mandatory platform-specific extension is defined for the target
platform but no matching extension struct is provided in
XrInstanceCreateInfo the runtime must return
XR_ERROR_INITIALIZATION_FAILED
.
The XrInstanceCreateInfo structure is defined as:
typedef struct XrInstanceCreateInfo {
XrStructureType type;
const void* next;
XrInstanceCreateFlags createFlags;
XrApplicationInfo applicationInfo;
uint32_t enabledApiLayerCount;
const char* const* enabledApiLayerNames;
uint32_t enabledExtensionCount;
const char* const* enabledExtensionNames;
} XrInstanceCreateInfo;
The XrInstanceCreateInfo::createFlags
member is of the following
type, and contains a bitwise-OR of zero or more of the bits defined in
XrInstanceCreateFlagBits.
typedef XrFlags64 XrInstanceCreateFlags;
Valid bits for XrInstanceCreateFlags are defined by XrInstanceCreateFlagBits.
// Flag bits for XrInstanceCreateFlags
There are currently no instance creation flag bits defined. This is reserved for future use.
The XrApplicationInfo structure is defined as:
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;
Note
When using the OpenXR API to implement a reusable engine that will be used
by many applications, When using the OpenXR API to implement an individual application without a
shared engine, the input |
The xrDestroyInstance function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrDestroyInstance(
XrInstance instance);
The xrDestroyInstance function is used to destroy an XrInstance.
XrInstance handles are destroyed using xrDestroyInstance. When an XrInstance is destroyed, all handles that are children of that XrInstance are also destroyed.
4.3. Instance Information
The xrGetInstanceProperties function provides information about the instance and the associated runtime.
// Provided by XR_VERSION_1_0
XrResult xrGetInstanceProperties(
XrInstance instance,
XrInstanceProperties* instanceProperties);
The instanceProperties
parameter must be filled out by the runtime in
response to this call, with information as defined in
XrInstanceProperties.
The XrInstanceProperties structure is defined as:
typedef struct XrInstanceProperties {
XrStructureType type;
void* next;
XrVersion runtimeVersion;
char runtimeName[XR_MAX_RUNTIME_NAME_SIZE];
} XrInstanceProperties;
4.4. Platform-Specific Instance Creation
Some amount of data required for instance creation is exposed through chained structures defined in extensions. These structures may be optional or even required for instance creation on specific platforms, but not on other platforms. Separating off platform-specific functionality into extension structures prevents the primary XrInstanceCreateInfo structure from becoming too bloated with unnecessary information.
See the
List of Extensions
appendix for the list of available extensions and their related structures.
These structures expand the XrInstanceCreateInfo parent struct using
the XrInstanceCreateInfo::next
member.
The specific list of structures that may be used for extending
XrInstanceCreateInfo::next
can be found in the "Valid Usage
(Implicit)" block immediately following the definition of the structure.
4.4.1. The Instance Lost Error
The XR_ERROR_INSTANCE_LOST
error indicates that the XrInstance
has become unusable.
This can happen if a critical runtime process aborts, if the connection to
the runtime is otherwise no longer available, or if the runtime encounters
an error during any function execution which prevents it from being able to
support further function execution.
Once XR_ERROR_INSTANCE_LOST
is first returned, it must henceforth be
returned by all non-destroy functions that involve an XrInstance or
child handle type until the instance is destroyed.
Applications must destroy the XrInstance.
Applications may then attempt to continue by recreating all relevant OpenXR
objects, starting with a new XrInstance.
A runtime may generate an XrEventDataInstanceLossPending event when
instance loss is detected.
4.4.2. XrEventDataInstanceLossPending
// Provided by XR_VERSION_1_0
typedef struct XrEventDataInstanceLossPending {
XrStructureType type;
const void* next;
XrTime lossTime;
} XrEventDataInstanceLossPending;
Receiving the XrEventDataInstanceLossPending event structure indicates
that the application is about to lose the indicated XrInstance at the
indicated lossTime
in the future.
The application should call xrDestroyInstance and relinquish any
instance-specific resources.
This typically occurs to make way for a replacement of the underlying
runtime, such as via a software update.
After the application has destroyed all of its instances and their children
and waited past the specified time, it may then re-try
xrCreateInstance in a loop waiting for whatever maintenance the
runtime is performing to complete.
The runtime will return XR_ERROR_RUNTIME_UNAVAILABLE
from
xrCreateInstance as long as it is unable to create the instance.
Once the runtime has returned and is able to continue, it must resume
returning XR_SUCCESS
from xrCreateInstance if valid data is
passed in.
4.5. Instance Enumerated Type String Functions
Applications often want to turn certain enum values from the runtime into strings for use in log messages, to be localized in UI, or for various other reasons. OpenXR provides functions that turn common enum types into UTF-8 strings for use in applications.
// Provided by XR_VERSION_1_0
XrResult xrResultToString(
XrInstance instance,
XrResult value,
char buffer[XR_MAX_RESULT_STRING_SIZE]);
Returns the text version of the provided XrResult value as a UTF-8 string.
In all cases the returned string must be one of:
The xrStructureTypeToString function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrStructureTypeToString(
XrInstance instance,
XrStructureType value,
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
Returns the text version of the provided XrStructureType value as a UTF-8 string.
In all cases the returned string must be one of:
5. System
This API separates the concept of physical systems of XR devices from the
logical objects that applications interact with directly.
A system represents a collection of related devices in the runtime, often
made up of several individual hardware components working together to enable
XR experiences.
An XrSystemId
is returned by xrGetSystem representing the
system of devices the runtime will use to support a given
form factor.
Each system may include: a VR/AR display, various forms of input (gamepad,
touchpad, motion controller), and other trackable objects.
The application uses the system to create a session, which can then be used to accept input from the user and output rendered frames. The application also provides a default set of bindings from its actions to any number of input sources. The runtime may use this action information to activate only a subset of devices and avoid wasting resources on devices that are not in use. Exactly which devices are active once an XR system is selected will depend on the features provided by the runtime, and may vary from runtime to runtime. For example, a runtime that is capable of mapping from one tracking system’s space to another’s may support devices from multiple tracking systems simultaneously.
5.1. Form Factors
The first step in selecting a system is for the application to request its desired form factor. The form factor defines how the display(s) moves in the environment relative to the user’s head and how the user will interact with the XR experience. A runtime may support multiple form factors, such as on a mobile phone that supports both slide-in VR headset experiences and handheld AR experiences.
While an application’s core XR rendering may span across form factors, its user interface will often be written to target a particular form factor, requiring explicit tailoring to function well on other form factors. For example, screen-space UI designed for a handheld phone will produce an uncomfortable experience for users if presented in screen-space on an AR headset.
typedef enum XrFormFactor {
XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1,
XR_FORM_FACTOR_HANDHELD_DISPLAY = 2,
XR_FORM_FACTOR_MAX_ENUM = 0x7FFFFFFF
} XrFormFactor;
The predefined form factors which may be supported by OpenXR runtimes are:
5.2. Getting the XrSystemId
XR_DEFINE_ATOM(XrSystemId)
An XrSystemId
is an opaque atom used by the runtime to identify a
system.
The value XR_NULL_SYSTEM_ID is considered an invalid system.
// Provided by XR_VERSION_1_0
#define XR_NULL_SYSTEM_ID 0
The only XrSystemId
value defined to be constant across all
instances is the invalid system XR_NULL_SYSTEM_ID.
No supported system is associated with XR_NULL_SYSTEM_ID.
Unless explicitly permitted, it should not be passed to API calls or used
as a structure attribute when a valid XrSystemId
is required.
The xrGetSystem function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetSystem(
XrInstance instance,
const XrSystemGetInfo* getInfo,
XrSystemId* systemId);
To get an XrSystemId
, an application specifies its desired
form factor to xrGetSystem and gets the
runtime’s XrSystemId
associated with that configuration.
If the form factor is supported but temporarily unavailable,
xrGetSystem must return XR_ERROR_FORM_FACTOR_UNAVAILABLE
.
A runtime may return XR_SUCCESS
on a subsequent call for a form
factor it previously returned XR_ERROR_FORM_FACTOR_UNAVAILABLE
.
For example, connecting or warming up hardware might cause an unavailable
form factor to become available.
The XrSystemGetInfo structure is defined as:
typedef struct XrSystemGetInfo {
XrStructureType type;
const void* next;
XrFormFactor formFactor;
} XrSystemGetInfo;
The XrSystemGetInfo structure specifies attributes about a system as desired by an application.
XrInstance instance; // previously initialized
XrSystemGetInfo system_get_info = {XR_TYPE_SYSTEM_GET_INFO};
system_get_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
XrSystemId systemId;
CHK_XR(xrGetSystem(instance, &system_get_info, &systemId));
// create session
// create swapchains
// begin session
// main loop
// end session
// destroy session
// no access to hardware after this point
5.3. System Properties
The xrGetSystemProperties function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetSystemProperties(
XrInstance instance,
XrSystemId systemId,
XrSystemProperties* properties);
An application can call xrGetSystemProperties to retrieve information about the system such as vendor ID, system name, and graphics and tracking properties.
The XrSystemProperties structure is defined as:
typedef struct XrSystemProperties {
XrStructureType type;
void* next;
XrSystemId systemId;
uint32_t vendorId;
char systemName[XR_MAX_SYSTEM_NAME_SIZE];
XrSystemGraphicsProperties graphicsProperties;
XrSystemTrackingProperties trackingProperties;
} XrSystemProperties;
The runtime must report a valid vendor ID for the system. The vendor ID must be either the USB vendor ID defined for the physical device or a Khronos vendor ID.
The XrSystemGraphicsProperties structure is defined as:
typedef struct XrSystemGraphicsProperties {
uint32_t maxSwapchainImageHeight;
uint32_t maxSwapchainImageWidth;
uint32_t maxLayerCount;
} XrSystemGraphicsProperties;
// Provided by XR_VERSION_1_0
#define XR_MIN_COMPOSITION_LAYERS_SUPPORTED 16
XR_MIN_COMPOSITION_LAYERS_SUPPORTED defines the minimum number of
composition layers that a conformant runtime must support.
A runtime must return the
XrSystemGraphicsProperties::maxLayerCount
at least the value of
XR_MIN_COMPOSITION_LAYERS_SUPPORTED.
The XrSystemTrackingProperties structure is defined as:
typedef struct XrSystemTrackingProperties {
XrBool32 orientationTracking;
XrBool32 positionTracking;
} XrSystemTrackingProperties;
6. Path Tree and Semantic Paths
OpenXR incorporates an internal semantic path tree model, also known as the path tree, with entities associated with nodes organized in a logical tree and referenced by path name strings structured like a filesystem path or URL. The path tree unifies a number of concepts used in this specification and a runtime may add additional nodes as implementation details. As a general design principle, the most application-facing paths should have semantic and hierarchical meaning in their name. Thus, these paths are often referred to as semantic paths. However, path names in the path tree model may not all have the same level or kind of semantic meaning.
In regular use in an application, path name strings are converted to
instance-specific XrPath
values which are used in place of path
strings.
The mapping between XrPath
values and their corresponding path name
strings may be considered to be tracked by the runtime in a one-to-one
mapping in addition to the natural tree structure of the referenced
entities.
Runtimes may use any internal implementation that satisfies the
requirements.
Formally, the runtime maintains an instance-specific bijective mapping
between well-formed path name strings and valid XrPath
(uint64_t
) values.
These XrPath
values are only valid within a single
XrInstance, and applications must not share these values between
instances.
Applications must instead use the string representation of a path in their
code and configuration, and obtain the correct corresponding XrPath
at runtime in each XrInstance.
The term path or semantic path may refer interchangeably to either the
path name string or its associated XrPath
value within an instance
when context makes it clear which type is being discussed.
Given that path trees are a unifying model in this specification, the
entities referenced by paths can be of diverse types.
For example, they may be used to represent physical device or sensor
components, which may be of various component types.
They may also be used to represent frames of reference that are understood
by the application and the runtime, as defined by an XrSpace.
Additionally, to permit runtime re-configuration and support
hardware-independent development, any syntactically-valid path string may
be used to retrieve a corresponding XrPath
without error given
sufficient resources, even if no logical or hardware entity currently
corresponds to that path at the time of the call.
Later retrieval of the associated path string of such an XrPath
using xrPathToString should succeed if the other requirements of that
call are met.
However, using such an XrPath
in a later call to any other API
function may result in an error if no entity of the type required by the
call is available at the path at that later time.
A runtime should permit the entity referenced by a path to vary over time
to naturally reflect varying system configuration and hardware availability.
6.1. Path Atom Type
XR_DEFINE_ATOM(XrPath)
The XrPath
is an atom that connects an application with a single
path, within the context of a single instance.
There is a bijective mapping between well-formed path strings and atoms in
use.
This atom is used — in place of the path name string it corresponds to — to retrieve state and perform other operations.
As an XrPath
is only shorthand for a well-formed path string, they
have no explicit life cycle.
Lifetime is implicitly managed by the XrInstance.
An XrPath
must not be used unless it is received at execution time
from the runtime in the context of a particular XrInstance.
Therefore, with the exception of XR_NULL_PATH, XrPath
values
must not be specified as constant values in applications: the corresponding
path string should be used instead.
During the lifetime of a given XrInstance, the XrPath
associated with that instance with any given well-formed path must not
vary, and similarly the well-formed path string that corresponds to a given
XrPath
in that instance must not vary.
An XrPath
that is received from one XrInstance may not be
used with another.
Such an invalid use may be detected and result in an error being returned,
or it may result in undefined behavior.
Well-written applications should typically use a small, bounded set of
paths in practice.
However, the runtime should support looking up the XrPath
for a
large number of path strings for maximum compatibility.
Runtime implementers should keep in mind that applications supporting
diverse systems may look up path strings in a quantity exceeding the number
of non-empty entities predicted or provided by any one runtime’s own path
tree model, and this is not inherently an error.
However, system resources are finite and thus runtimes may signal
exhaustion of resources dedicated to these associations under certain
conditions.
When discussing the behavior of runtimes at these limits, a new
XrPath
refers to an XrPath
value that, as of some point in
time, has neither been received by the application nor tracked internally by
the runtime.
In this case, since an application has not yet received the value of such an
XrPath
, the runtime has not yet made any assertions about its
association with any path string.
In this context, new only refers to the fact that the mapping has not
necessarily been made constant for a given value/path string pair for the
remaining life of the associated instance by being revealed to the
application.
It does not necessarily imply creation of the entity, if any, referred to by
such a path.
Similarly, it does not imply the absence of such an entity prior to that
point.
Entities in the path tree have varied lifetime that is independent from the
duration of the mapping from path string to XrPath
.
For flexibility, the runtime may internally track or otherwise make
constant, in instance or larger scope, any mapping of a path string to an
XrPath
value even before an application would otherwise receive
that value, thus making it no longer new by the above definition.
When the runtime’s resources to track the path string-XrPath
mapping are exhausted, and the application makes an API call that would have
otherwise retrieved a new XrPath
as defined above, the runtime
must return XR_ERROR_PATH_COUNT_EXCEEDED
.
This includes both explicit calls to xrStringToPath as well as other
calls that retrieve an XrPath
in any other way.
The runtime should support creating as many paths as memory will allow and
must return XR_ERROR_PATH_COUNT_EXCEEDED
from relevant functions when
no more can be created.
// Provided by XR_VERSION_1_0
#define XR_NULL_PATH 0
The only XrPath
value defined to be constant across all instances
is the invalid path XR_NULL_PATH.
No well-formed path string is associated with XR_NULL_PATH.
Unless explicitly permitted, it should not be passed to API calls or used
as a structure attribute when a valid XrPath
is required.
6.2. Well-Formed Path Strings
Even though they look similar, semantic paths are not file paths. To avoid confusion with file path directory traversal conventions, many file path conventions are explicitly disallowed from well-formed path name strings.
A well-formed path name string must conform to the following rules:
-
Path name strings must be constructed entirely from characters on the following list.
-
Lower case ASCII letters: a-z
-
Numeric digits: 0-9
-
Dash: -
-
Underscore: _
-
Period: .
-
Forward Slash: /
-
-
Path name strings must start with a single forward slash character.
-
Path name strings must not end with a forward slash character.
-
Path name strings must not contain two or more adjacent forward slash characters.
-
Path name strings must not contain two forward slash characters that are separated by only period characters.
-
Path name strings must not contain only period characters following the final forward slash character in the string.
-
The maximum string length for a path name string, including the terminating
\0
character, is defined byXR_MAX_PATH_LENGTH
.
6.2.1. xrStringToPath
The xrStringToPath function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrStringToPath(
XrInstance instance,
const char* pathString,
XrPath* path);
xrStringToPath retrieves the XrPath
value for a well-formed
path string.
If such a value had not yet been assigned by the runtime to the provided
path string in this XrInstance, one must be assigned at this point.
All calls to this function with the same XrInstance and path string
must retrieve the same XrPath
value.
Upon failure, xrStringToPath must return an appropriate
XrResult, and may set the output parameter to XR_NULL_PATH.
See Path Atom Type for the conditions under which an
error may be returned when this function is given a valid XrInstance
and a well-formed path string.
If the runtime’s resources are exhausted and it cannot create the path, a
return value of XR_ERROR_PATH_COUNT_EXCEEDED
must be returned.
If the application specifies a string that is not a well-formed path string,
XR_ERROR_PATH_FORMAT_INVALID
must be returned.
A return value of XR_SUCCESS from xrStringToPath may not
necessarily imply that the runtime has a component or other source of data
that will be accessible through that semantic path.
It only means that the path string supplied was well-formed and that the
retrieved XrPath maps to the given path string within and during
the lifetime of the XrInstance given.
|
6.2.2. xrPathToString
// Provided by XR_VERSION_1_0
XrResult xrPathToString(
XrInstance instance,
XrPath path,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer);
xrPathToString retrieves the path name string associated with an
XrPath
, in the context of a given XrInstance, in the form of
a NULL
terminated string placed into a caller-allocated buffer.
Since the mapping between a well-formed path name string and an
XrPath
is bijective, there will always be exactly one string for
each valid XrPath
value.
This can be useful if the calling application receives an XrPath
value that they had not previously retrieved via xrStringToPath.
During the lifetime of the given XrInstance, the path name string
retrieved by this function for a given valid XrPath
will not
change.
For invalid paths, including XR_NULL_PATH, XR_ERROR_PATH_INVALID
must be returned.
6.3. Reserved Paths
In order for some uses of semantic paths to work consistently across runtimes, it is necessary to standardize several paths and require each runtime to use the same paths or patterns of paths for certain classes of usage. Those paths are as follows.
6.3.1. /user paths
Some paths are used to refer to entities that are filling semantic roles in the system. These paths are all under the /user subtree.
The reserved user paths are:
Runtimes are not required to provide interaction at all of these paths. For instance, in a system with no hand tracking, only /user/head would be active for interaction. In a system with only one controller, the runtime may provide access to that controller via either /user/hand/left or /user/hand/right as it deems appropriate.
The runtime may change the devices referred to by /user/hand/left and /user/hand/right at any time.
If more than two hand-held controllers or devices are active, the runtime must determine which two are accessible as /user/hand/left and /user/hand/right.
6.3.2. Input subpaths
Devices on the source side of the input system need to define paths for each component that can be bound to an action. This section describes the naming conventions for those input components. Runtimes must ignore input source paths that use identifiers and component names that do not appear in this specification or otherwise do not follow the pattern specified below.
Each input source path must match the following pattern:
-
…/input/<identifier>[_<location>][/<component>]
Identifiers are often the label on the component or related to the type and location of the component.
When specifying a suggested binding there are several cases where the component part of the path can be determined automatically. See Suggested Bindings for more details.
See Interaction Profiles for examples of input subpaths.
Standard identifiers
-
trackpad - A 2D input source that usually includes click and touch component.
-
thumbstick - A small 2D joystick that is meant to be used with the user’s thumb. These sometimes include click and/or touch components.
-
joystick - A 2D joystick that is meant to be used with the user’s entire hand, such as a flight stick. These generally do not have click component, but might have touch components.
-
trigger - A 1D analog input component that returns to a rest state when the user stops interacting with it. These sometime include touch and/or click components.
-
throttle - A 1D analog input component that remains in position when the user stops interacting with it.
-
trackball - A 2D relative input source. These sometimes include click components.
-
pedal - A 1D analog input component that is similar to a trigger but meant to be operated by a foot
-
system - A button with the specialised meaning that it enables the user to access system-level functions and UI. Input data from system buttons is generally used internally by runtimes and may not be available to applications.
-
dpad_up, dpad_down, dpad_left, and dpad_right - A set of buttons arranged in a plus shape.
-
diamond_up, diamond_down, diamond_left, and diamond_right - Gamepads often have a set of four buttons arranged in a diamond shape. The labels on those buttons vary from gamepad to gamepad, but their arrangement is consistent. These names are used for the A/B/X/Y buttons on a Xbox controller, and the square/cross/circle/triangle button on a PlayStation controller.
-
a, b, x, y, start, home, end, select - Standalone buttons are named for their physical labels. These are the standard identifiers for such buttons. Extensions may add new identifiers as detailed in the next section. Groups of four buttons in a diamond shape should use the diamond-prefix names above instead of using the labels on the buttons themselves.
-
volume_up, volume_down, mute_mic, play_pause, menu, view, back - Some other standard controls are often identified by icons. These are their standard names.
-
thumbrest - Some controllers have a place for the user to rest their thumb.
-
shoulder - A button that is usually pressed with the index finger and is often positioned above a trigger.
-
squeeze - An input source that indicates that the user is squeezing their fist closed. This could be a simple button or act more like a trigger. Sources with this identifier should either follow button or trigger conventions for their components.
-
wheel - A steering wheel.