Copyright (c) 2017-2019 The Khronos Group Inc. All Rights reserved.
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 Specification has been created under the Khronos Intellectual Property Rights Policy, which is Attachment A of the Khronos Group Membership Agreement available at https://www.khronos.org/files/member_agreement.pdf, and which defines the terms 'Scope', 'Compliant Portion', and 'Necessary Patent Claims'. Parties desiring to implement the Specification and make use of Khronos trademarks in relation to that implementation, and receive reciprocal patent license protection under the Khronos Intellectual Property Rights Policy must become Adopters and confirm the implementation as conformant under the process defined by Khronos for this Specification; see https://www.khronos.org/adopters. 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.
Vulkan and Khronos are registered trademarks of The Khronos Group Inc. OpenGL and OpenGL ES are registered trademarks of Hewlett Packard Enterprise, all 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
The version number is used in several places in the OpenXR API. In each such use, the API major version number, minor version number, and patch version number are packed into a 32-bit integer 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.
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
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.
The following is a complete list of externally synchronized parameters in OpenXR:
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 can grow through the addition of new features. Similar to other Khronos APIs, extensions can be used to 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 must first query which extensions are available before enabling.
The application queries the available list of extensions using the 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.
API Logging Layer
Another example of an API layer is an API logging layer that simply serializes all the API calls to an output sink in a text format, including printing out argument values and structure contents.
API Trace Layer
A related API trace layer produces a trace file that contains all the information provided to the API so that the trace file can be played back by a replay program.
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 may determine the API layers that are available to them by calling the xrEnumerateApiLayerProperties function to obtain a list of available API layers. Applications then may 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.
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.7.5. 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 may need to provide a struct with a type that differs from the declared type.
For example, XrFrameEndInfo::layers
is an array of type
const
XrCompositionLayerBaseHeader *
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.
#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.7.6. 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 do not cover conditions where well-defined behavior (including returning an error code) exists.
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.7.7. 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.
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
.
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.
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.
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:
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:
-
OpenGL ⇒ _OPENGL
-
OpenGLES ⇒ _OPENGL_ES
-
D3D ⇒ _D3D
-
VULKAN ⇒ _VULKAN *
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
defined by an extension.
The extension structure must contain type
and next
member values
for that specific structure as described in the extension’s documentation.
The set of structures connected by next
pointers is referred to as a
next
chain.
In order to insert an extension structure into a next
chain, the
proper extension must have been previously enabled during
xrCreateInstance.
If the appropriate extension has not been enabled, then the structure must
be ignored.
Most extension structures 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: Extension 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:
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:
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 must 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.
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.8. Return Codes
While the core API is not designed to capture incorrect usage, some circumstances still require 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_VISIBILITY_UNAVAILABLE = 2,
XR_SESSION_LOSS_PENDING = 3,
XR_EVENT_UNAVAILABLE = 4,
XR_STATE_UNAVAILABLE = 5,
XR_STATE_TYPE_UNAVAILABLE = 6,
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_RUNTIME_VERSION_INCOMPATIBLE = -4,
XR_ERROR_DRIVER_INCOMPATIBLE = -5,
XR_ERROR_INITIALIZATION_FAILED = -6,
XR_ERROR_FUNCTION_UNSUPPORTED = -7,
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_LAYER_INVALID = -22,
XR_ERROR_LAYER_LIMIT_EXCEEDED = -23,
XR_ERROR_SWAPCHAIN_RECT_INVALID = -25,
XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26,
XR_ERROR_ACTION_TYPE_MISMATCH = -27,
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_BINDINGS_DUPLICATED = -43,
XR_ERROR_NAME_DUPLICATED = -44,
XR_ERROR_NAME_INVALID = -45,
XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR = -1000003000,
XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR = -1000003001,
XR_ERROR_DEBUG_UTILS_MESSENGER_INVALID_EXT = -1000019000,
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.
2.8.1. Success Codes
Enum | Description |
---|---|
|
Function successfully completed. |
|
The specified timeout time occurred before the operation could complete. |
|
The session has started but cannot be made visible at the moment. |
|
The session will be lost soon. |
|
No event was available. |
|
No state (of any type) is available for the provided handle. |
|
The state of the given type is not available for the provided handle. |
|
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. |
2.8.2. 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 version is incompatible with the requested or required version. |
|
The driver is incompatible with the runtime. |
|
Initialization of object could not be completed. |
|
The requested function was not found or is otherwise unsupported. |
|
A requested extension is not supported. |
|
The runtime supports no more of the requested resource. |
|
The supplied size was smaller than required. |
|
The supplied object handle was invalid. |
|
The XrInstance was lost or could not be found. It will need to be destroyed and optionally recreated. |
|
This session is already running. |
|
The operation requires this session to be in the running state. |
|
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 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 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 application specified bindings for an input form factor it had already suggested bindings for. |
|
The name provided was a duplicate of an already-existing resource. |
|
The name provided was invalid. |
2.8.3. Convenience Macros
#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
.
#define XR_FAILED(result) ((result) < 0)
A convenience macro that can be used to test if a function has failed in some way.
#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.8.4. Validation
Except as noted below or in individual API specifications, valid API usage
may be required by the runtime.
Invalid API usage may result in undefined behavior.
Runtimes may choose to validate some API usage and return
an XR_ERROR_*_INVALID
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.9. 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 are not required to detect invalid handles. Usage of an 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. To create an XrSwapchain handle, applications must call xrCreateSwapchain and pass an XrSession handle. Thus XrSwapchain is a child handle to XrSession.
2.10. 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.
typedef enum XrObjectType {
XR_OBJECT_TYPE_UNKNOWN = 0,
XR_OBJECT_TYPE_INSTANCE = 1,
XR_OBJECT_TYPE_SESSION = 2,
XR_OBJECT_TYPE_SWAPCHAIN = 3,
XR_OBJECT_TYPE_SPACE = 4,
XR_OBJECT_TYPE_ACTION_SET = 5,
XR_OBJECT_TYPE_ACTION = 6,
XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000019000,
XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrObjectType;
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.11. Buffer Size Parameters
Functions with input/output buffer parameters look like the following example, with the element type being float in this case:
XrResult xrFunction(uint32_t elementCapacityInput, uint32_t* elementCountOutput, float* elements);
A two-call idiom may be employed, first calling xrFunction
with a valid
elementCountOutput
pointer, 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 the value pointed to by
elementCountOutput
, a pointer to the allocated buffer should be passed
as elements
, along with the buffer’s length in the variable
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.
These functions have the below-listed behavior with respect to the buffer size parameters:
2.12. Time
Time is represented by a 64-bit signed integer representing nanoseconds
(XrTime
).
The passage of time is monotonic and not realtime (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.12.1. XrTime
typedef int64_t XrTime;
XrTime
is a base value type to represent time, as a 64 bit integer.
Unless specified otherwise, XrTime
denotes a time-point relative to
some runtime-determined constant epoch, rather than a duration, or a
time-point with some moving epoch such as function call time, vsync time, etc.
Time may be represented by the runtime with a standardized epoch (e.g. 12:00:00 January 1, 1970 as of runtime start), or an arbitrary epoch may be used (e.g. time since runtime start). Time overflows after 264 nanoseconds have occurred since the epoch. 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.
2.13. Duration
Duration refers to an elapsed period of time, as opposed to an absolute timepoint.
2.13.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
.
#define XR_NO_DURATION 0
For the case of timeout durations, XR_NO_DURATION may be used to indicate that the timeout is immediate.
#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.14. Colors
The XrColor4f structure is defined as:
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.
2.15. 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. When using XrPosef the rotation described by orientation
is always applied before the translation described by position
.
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:
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.
2.16. 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:
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:
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.
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.
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:
typedef struct XrRect2Df {
XrOffset2Df offset;
XrExtent2Df extent;
} XrRect2Df;
This structure is used for component values that may be fractional (floating-point).
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.
2.17. 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.
2.18. 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.19. 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:
2.20. Events
Events are messages sent from the runtime to the application.
2.20.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;
// Only the header needs to be initialized.
event.type = XR_TYPE_EVENT_DATA_BUFFER;
event.next = nullptr;
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
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
.
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 is defined as:
typedef struct XrEventDataBaseHeader {
XrStructureType type;
const void* XR_MAY_ALIAS 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* XR_MAY_ALIAS next;
uint8_t varying[4000];
} XrEventDataBuffer;
XR_MAX_EVENT_DATA_SIZE is the maximum size of an XrEventDataBuffer.
#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer)
XrEventDataEventsLost
The XrEventDataEventsLost is defined as:
typedef struct XrEventDataEventsLost {
XrStructureType type;
const void* XR_MAY_ALIAS 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.
3. API Initialization
Before using an OpenXR runtime, an application must initialize it by creating a 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.
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 returns XR_ERROR_HANDLE_INVALID
if instance
is
NULL
and name
is not one of the above strings.
xrGetInstanceProcAddr returns 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 dispatchable object (the first parameter) that is
instance
or a child ofinstance
.
typedef void (XRAPI_PTR *PFN_xrVoidFunction)(void);
PFN_xrVoidFunction is a dummy pointer 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:
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* XR_MAY_ALIAS next;
char layerName[XR_MAX_API_LAYER_NAME_SIZE];
uint32_t specVersion;
uint32_t implementationVersion;
char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];
} XrApiLayerProperties;
To enable a layer, the name of the layer should be added to the
enabledApiLayerNames
member of XrInstanceCreateInfo 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:
XrResult xrEnumerateInstanceExtensionProperties(
const char* layerName,
uint32_t propertyCapacityInput,
uint32_t* propertyCountOutput,
XrExtensionProperties* properties);
If properties
is NULL
, then the number of extensions properties
available is returned in propertyCountOutput
.
Otherwise, propertyCountInput
must point
to a variable set by the user to the number of elements in the properties
array.
If propertyCountInput
is less than the number of extension properties
available, the contents of properties
will be undefined.
If propertyCountInput
is smaller than the number of extensions available,
the failure code XR_ERROR_SIZE_INSUFFICIENT
and the contents of
properties
are undefined.
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* XR_MAY_ALIAS next;
char extensionName[XR_MAX_EXTENSION_NAME_SIZE];
uint32_t specVersion;
} XrExtensionProperties;
4.2. Instance Lifecycle
The xrCreateInstance function is defined as:
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 will 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 will return
XR_ERROR_LIMIT_REACHED
.
If the XrInstanceCreateInfo struct contains a platform-specific
extension for a platform other than the target platform,
XR_ERROR_INITIALIZATION_FAILED
will be returned.
The same is true if a mandatory platform-specific extension is defined for the
target platform but no matching extension struct is provided in
XrInstanceCreateInfo.
The XrInstanceCreateInfo structure is defined as:
typedef struct XrInstanceCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrInstanceCreateFlags createFlags;
XrApplicationInfo applicationInfo;
uint32_t enabledApiLayerCount;
const char* const* enabledApiLayerNames;
uint32_t enabledExtensionCount;
const char* const* enabledExtensionNames;
} XrInstanceCreateInfo;
The XrInstanceCreateFlags include:
// Flag bits for XrInstanceCreateFlags
There are currently no instance creation flags. 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;
uint32_t apiVersion;
} XrApplicationInfo;
The xrDestroyInstance function is defined as:
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. If the
instance
is invalid the runtime must return XR_ERROR_HANDLE_INVALID
.
4.3. Instance Information
The xrGetInstanceProperties function provides information about the instance and the associated runtime.
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* XR_MAY_ALIAS next;
uint32_t 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 extension structures. 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 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
typedef struct XrEventDataInstanceLossPending {
XrStructureType type;
const void* XR_MAY_ALIAS 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_INSTANCE_LOST
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.
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 follows:
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 app 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.
#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:
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 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;
void* XR_MAY_ALIAS 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;
memset(&system_get_info, 0, sizeof(system_get_info));
system_get_info.type = 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:
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* XR_MAY_ALIAS next;
XrSystemId systemId;
uint32_t vendorId;
char systemName[XR_MAX_SYSTEM_NAME_SIZE];
XrSystemGraphicsProperties graphicsProperties;
XrSystemTrackingProperties trackingProperties;
} XrSystemProperties;
The XrSystemGraphicsProperties structure is defined as:
typedef struct XrSystemGraphicsProperties {
uint32_t maxSwapchainImageHeight;
uint32_t maxSwapchainImageWidth;
uint32_t maxViewCount;
uint32_t maxLayerCount;
} XrSystemGraphicsProperties;
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 must not be shared 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.
#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 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:
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
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
will be returned.
6.3. Reserved Paths for Devices
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 devices 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 devices at all of these paths. For instance, in a system with no hand tracking, only /user/head would be provided a device. 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. Device 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.
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 - 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.
-
grip - 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.
Input sources whose orientation and/or position are tracked also expose pose identifiers.
Standard pose identifiers for tracked hands or motion controllers as represented by /user/hand/left and /user/hand/right are:
-
palm - A pose that allows applications to reliably render a virtual object in the user’s hand regardless of how a hand is tracked. The palm pose is defined as follows:
-
The palm position: The palm centroid when closing the fist. For handheld motion controllers, this position is adjusted left or right to center the position within the controller’s grip.
-
The palm orientation’s +X axis: When you completely open your hand to form a flat 5-finger pose, the ray that is normal to your palm (forward from left palm, backward from right palm)
-
The palm orientation’s -Z axis: When you close your hand partially (as if holding the controller), the ray that points "forward" through the tube formed by your non-thumb fingers.
-
The palm orientation’s +Y axis: The Up axis implied by the +X (Right) and -Z (Forward) definitions.
-
-
pointer - A pose positioned at the start of a motion controller’s natural pointing ray, with +Y up, +X to the right, and -Z forward. This pose is most useful for applications that are rendering a model matching the physical controller, as an application rendering a virtual object in the user’s hand likely prefers to point based on the geometry of that virtual object. The pointer ray chosen will be runtime-dependent, although this will often emerge from the frontmost tip of a motion controller.
Standard locations
When a single device contains multiple input sources that use the same identifier, a location suffix is added to create a unique identifier for that input source.
Standard locations are:
-
left
-
right
-
left_upper
-
left_lower
-
right_upper
-
right_lower
Standard components
Components are named for the specific boolean, scalar, or other value of the input source. Standard components are:
-
click - A physical switch has been pressed by the user. This is valid for all buttons, and is common for trackpads, thumbsticks, triggers, and dpads. "click" components are always boolean.
-
touch - The user has touched the input source. This is valid for all trackpads, and may be present for any other kind of input source if the device includes the necessary sensor. "touch" components are always boolean.
-
force - A 1D scalar value that represents the user applying force to the input. It varies from 0 to 1, with 0 being the rest state. This is present for any input source with a force sensor.
-
value - A 1D scalar value that varies from 0 to 1, with 0 being the rest state. This is present for triggers, throttles, and pedals. It may also be present for grips or other components.
-
x, y, z - 2D or 3D scalar values that vary from -1 to 1. These represent the 2D or 3D position of the input source with 0 being the rest state on each axis. x and y components are present for trackpads, thumbsticks, and joysticks.
-
twist - Some sources, such as flight sticks, have a sensor that allows the user to twist the input left or right. For this component -1 means all the way left and 1 means all the way right.
-
pose - The orientation and/or position of this input source. This component may exist for dedicated pose identifiers like palm and pointer, or may be defined on other identifiers such as trackpad to let applications reason about the surface of that part.
Output source paths
Many devices also have subpaths for output features such as haptics. The runtime must ignore output component paths that do not follow the pattern:
-
…/output/<output_identifier>[_<location>]
Standard output identifiers are:
-
haptic - A haptic element like an LRA (Linear Resonant Actuator) or vibration motor
Devices which contain multiple haptic elements with the same output identifier must use a location suffix as specified above.
6.3.3. Adding input sources via extensions
Extensions may enable input source path identifiers, output source path identifiers, and component names that are not included in the core specification, subject to the following conditions:
-
EXT extensions must include the _ext suffix on any identifier or component name. E.g. …/input/newidentifier_ext/newcomponent_ext
-
Vendor extensions must include the vendor’s tag as a suffix on any identifier or component name. E.g. …/input/newidentifier_vendor/newcomponent_vendor (where "vendor" is replaced with the vendor’s actual extension tag.)
-
Khronos (KHR) extensions may add undecorated identifier or component names.
These rules are in place to prevent extensions from adding first class undecorated names that become defacto standards. Runtimes must ignore input source paths that do not follow the restrictions above.
Extensions may also add new location suffixes, and may do so by adding a new identifier and location combination using the appropriate suffix. E.g. …/input/newidentifier_newlocation_ext
6.4. Interaction Profile Paths
An interaction profile path identifies a collection of buttons and other input sources in a physical arrangement to allow applications and runtimes to coordinate action bindings.
Interaction profile paths are of the form:
-
/interaction_profiles/<vendor_name>/<type_name>
6.4.1. Khronos Simple Controller Profile
Path: /interaction_profiles/khr/simple_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile provides basic pose, button, and haptic support for applications with simple input needs. There is no hardware associated with the profile, and runtimes which support this profile should map the input paths provided to whatever the appropriate paths are on the actual hardware.
Supported input sources:
-
…/input/select/click
-
…/input/menu/click
-
…/output/haptic
-
…/input/pointer/pose
-
…/input/palm/pose
6.4.2. Google Daydream Controller Profile
Path: /interaction_profiles/google/daydream_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Google Daydream Controller.
Supported input sources:
-
…/input/select/click
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/palm/pose
-
…/input/pointer/pose
6.4.3. HTC Vive Controller Profile
Path: /interaction_profiles/htc/vive_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Vive Controller.
Supported input sources:
-
…/input/system/click (may not be available for application use)
-
…/input/grip/click
-
…/input/menu/click
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/palm/pose
-
…/input/pointer/pose
-
…/output/haptic
6.4.4. HTC Vive Pro Profile
Path: /interaction_profiles/htc/vive_pro
Valid for user paths:
-
/user/head
This interaction profile represents the input sources on the Vive Pro headset.
Supported input sources:
-
…/input/system/click (may not be available for application use)
-
…/input/volume_up/click
-
…/input/volume_down/click
-
…/input/mute_mic/click
6.4.5. Microsoft Mixed Reality Motion Controller Profile
Path: /interaction_profiles/microsoft/motion_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Microsoft Mixed Reality Controller.
Supported input sources:
-
…/input/menu/click
-
…/input/grip/click
-
…/input/trigger/value
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/palm/pose
-
…/input/pointer/pose
-
…/output/haptic
6.4.6. Microsoft Xbox Controller Profile
Path: /interaction_profiles/microsoft/xbox_controller
Valid for user paths:
-
/user/gamepad
This interaction profile represents the input sources and haptics on the Microsoft Xbox Controller.
Supported input sources:
-
…/input/menu/click
-
…/input/view/click
-
…/input/a/click
-
…/input/b/click
-
…/input/x/click
-
…/input/y/click
-
…/input/dpad_down/click
-
…/input/dpad_right/click
-
…/input/dpad_up/click
-
…/input/dpad_left/click
-
…/input/shoulder_left/click
-
…/input/shoulder_right/click
-
…/input/thumbstick_left/click
-
…/input/thumbstick_right/click
-
…/input/trigger_left/value
-
…/input/trigger_right/value
-
…/input/thumbstick_left/x
-
…/input/thumbstick_left/y
-
…/input/thumbstick_right/x
-
…/input/thumbstick_right/y
-
…/output/haptic_left
-
…/output/haptic_right
-
…/output/haptic_left_trigger
-
…/output/haptic_right_trigger
6.4.7. Oculus Go Controller Profile
Path: /interaction_profiles/oculus/go_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Oculus Go controller.
Supported input sources:
-
…/input/system/click (may not be available for application use)
-
…/input/trigger/click
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/palm/pose
-
…/input/pointer/pose
6.4.8. Oculus Touch Controller Profile
Path: /interaction_profiles/oculus/touch_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Oculus Touch controller.
Supported input sources:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
…/input/system/click (may not be available for application use)
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
-
…/input/grip/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/palm/pose
-
…/input/pointer/pose
-
…/output/haptic
6.4.9. Valve Knuckles Controller Profile
Path: /interaction_profiles/valve/knuckles_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Valve Knuckles controller.
Supported input sources:
-
…/input/system/click (may not be available for application use)
-
…/input/system/touch (may not be available for application use)
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/grip/value
-
…/input/grip/force
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/force
-
…/input/trackpad/touch
-
…/input/palm/pose
-
…/input/pointer/pose
-
…/output/haptic
7. Spaces
Across both virtual reality and augmented reality, XR applications have a core need to map the location of virtual objects to the corresponding real-world locations where they will be rendered. Spaces allow applications to explicitly create and specify the frames of reference in which they choose to track the real world, and then determine how those frames of reference move relative to one another over time.
XR_DEFINE_HANDLE(XrSpace)
Spaces are represented by XrSpace handles, which the application creates and then uses in API calls. Whenever an application calls a function that returns coordinates, it provides an XrSpace to specify the frame of reference in which those coordinates will be expressed. Similarly, when providing coordinates to a function, the application specifies which XrSpace the runtime should use to interpret those coordinates.
OpenXR defines a set of well-known reference spaces that applications use to bootstrap their spatial reasoning.
These reference spaces are: VIEW
, LOCAL
and STAGE
.
Each reference space has a well-defined meaning, which establishes where its origin is positioned and how
its axes are oriented.
Runtimes whose tracking systems improve their understanding of the world over time may track spaces
independently. For example, even though a LOCAL
space and a STAGE
space each map their origin to a static position
in the world, a runtime with an inside-out tracking system may introduce slight adjustments to the origin of each space
on a continuous basis to keep each origin in place.
Spaces like the STAGE
space may be reconfigured by the user, causing their origin to jump instantaneously.
When a discontinuity in the origin of a space occurs, runtimes should delay representing these changes to the application
until the next call to xrPollEvent. This allows applications to cleanly detect the change in key poses before
and after the discontinuity.
Beyond well-known reference spaces, runtimes expose other independently-tracked spaces, such as a pose action space that tracks the pose of a motion controller over time.
When one or both spaces are tracking a dynamic object, passing in an updated time to xrLocateSpace each frame
will result in an updated relative pose. For example, the relationship of the left hand’s pose action space to the STAGE
reference space will
change each frame as the user’s hand moves relative to the stage’s predefined origin on the floor.
In other XR APIs, it is common to report the "pose" of an object relative to some presumed underlying
global space.
This API is careful to not explicitly define such an underlying global space, because it does not apply
to all systems. Some systems will support no STAGE
space, while others may support a STAGE
space that switches between various
physical stages with dynamic availability. To satisfy this wide variability, "poses" are always described as the relationship between two spaces.
Some devices improve their understanding of the world as the device is used. The relation returned by xrLocateSpace in later frames may change over time, even for spaces that track static objects, as either the target space or base space adjusts its origin.
Composition layers submitted by the application include an XrSpace for the runtime to use to position that layer over time.
Composition layers whose XrSpace is relative to the VIEW
reference space are implicitly "head-locked", even if they may not be "display-locked" for non-head-mounted form factors.
7.1. Reference Spaces
An XrSpace handle for a reference space is created using xrCreateReferenceSpace, by specifying the chosen reference space type and a pose within the natural reference frame defined for that reference space type.
Runtimes implement well-known reference spaces from XrReferenceSpaceType if they support tracking of that kind:
typedef enum XrReferenceSpaceType {
XR_REFERENCE_SPACE_TYPE_VIEW = 1,
XR_REFERENCE_SPACE_TYPE_LOCAL = 2,
XR_REFERENCE_SPACE_TYPE_STAGE = 3,
XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrReferenceSpaceType;
Available reference space types are indicated by xrEnumerateReferenceSpaces. Note that other spaces can be created as well, such as pose action spaces created by xrCreateActionSpace, which are not enumerated by that API.
XR systems may have limited real world spatial ranges in which users can freely move around while remaining tracked. Applications may wish to query these boundaries and alter application behavior or content placement to ensure the user can complete the experience while remaining within the boundary. Applications can query this information using xrGetReferenceSpaceBoundsRect.
When called, xrGetReferenceSpaceBoundsRect should return the extents of a rectangle that is clear of obstacles down to the floor, allowing where the user can freely move while remaining tracked, if available for that reference space. The returned extent represents the dimensions of an axis-aligned bounding box where the XrExtent2Df::width
and XrExtent2Df::height
fields correspond to the X and Z axes of the provided space, with the extents centered at the origin of the space.
Not all systems or spaces may support boundaries. If a runtime is unable to provide bounds for a given space, XR_SPACE_BOUNDS_UNAVAILABLE
will be returned and all fields of bounds
will be set to 0.
The returned extents are expressed relative to the natural origin of the provided XrReferenceSpaceType and must not incorporate any origin offsets specified by the app during calls to xrCreateReferenceSpace.
The runtime must return XR_ERROR_REFERENCE_SPACE_UNSUPPORTED
if the XrReferenceSpaceType passed in createInfo
is not supported by this session
.
When a runtime will begin operating with updated space bounds, the runtime must queue a corresponding XrEventDataReferenceSpaceChangePending event.
XrResult xrGetReferenceSpaceBoundsRect(
XrSession session,
XrReferenceSpaceType referenceSpaceType,
XrExtent2Df* bounds);
The XrEventDataReferenceSpaceChangePending event is sent to the application to notify it that the origin (and perhaps the bounds) of a reference space is changing. This may occur due to the user recentering the space explicitly, or the runtime otherwise switching to a different space definition.
The reference space change must only take effect for xrLocateSpace or xrLocateViews calls whose XrTime
parameter is greater than or equal to the changeTime
provided in that event. Runtimes should provide a changeTime
to apps that allows for a deep render pipeline to present frames that are already in flight using the previous definition of the space. Runtimes should choose a changeTime
that is midway between the displayTime
of future frames to avoid threshold issues with apps that calculate future frame times using displayPeriod
.
The pose
provided here must only describe the change in the natural origin of the reference space and must not incorporate any origin offsets specified by the app during calls to xrCreateReferenceSpace. If the runtime does not know the relationship between the new and the previous space, poseValid
must be false, and the position and orientation of the pose
are undefined.
typedef struct XrEventDataReferenceSpaceChangePending {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrReferenceSpaceType referenceSpaceType;
XrTime changeTime;
XrBool32 poseValid;
XrPosef poseInPreviousSpace;
} XrEventDataReferenceSpaceChangePending;
7.2. Action Spaces
An XrSpace handle for a pose action is created using xrCreateActionSpace, by specifying the chosen pose action and a pose within the action’s natural reference frame.
Runtimes support suggested pose action bindings to well-known user paths with …/pose subpaths if they support tracking for that particular identifier.
Some example well-known pose action paths:
For definitions of these well-known pose device paths, see the discussion of device input subpaths in the Semantic Paths chapter.
7.2.1. Action Spaces Lifetime
XrSpace handles created for a pose action must initially be unlocatable until the corresponding pose action has been synchronized and calls to xrGetActionStatePose report that the action is active.
If the underlying device that is active for the action changes, the device this space is tracking must only change to track the new device when xrSyncActionData is called.
If xrLocateSpace is called with an inactive action space, it will return no position or orientation and both XR_SPACE_RELATION_POSITION_VALID_BIT
and XR_SPACE_RELATION_ORIENTATION_VALID_BIT
will be unset.
If xrLocateViews is called with an inactive action space (although calling xrLocateViews with an action space is not generally useful), it will return no position or orientation and both XR_VIEW_STATE_POSITION_VALID_BIT
and XR_VIEW_STATE_ORIENTATION_VALID_BIT
will be unset.
If xrDestroyAction is called and an XrAction is destroyed, any XrSpace handles created from this XrAction using xrCreateActionSpace, will also be destroyed.
7.3. Space API
There are a small set of core APIs that allow applications to reason about reference spaces, action spaces, and the relationships between them all.
7.3.1. xrEnumerateReferenceSpaces
The xrEnumerateReferenceSpaces function is defined as:
XrResult xrEnumerateReferenceSpaces(
XrSession session,
uint32_t spaceCapacityInput,
uint32_t* spaceCountOutput,
XrReferenceSpaceType* spaces);
Enumerates the set of reference space types that this runtime supports for a given session. Runtimes must always return the same values from this enumeration for the lifetime of the session.
If a session enumerates support for a given reference space type, calls to xrCreateReferenceSpace must succeed for that session, with any transient unavailability of poses expressed later during calls to xrLocateSpace.
7.3.2. xrCreateReferenceSpace
The xrCreateReferenceSpace function is defined as:
XrResult xrCreateReferenceSpace(
XrSession session,
const XrReferenceSpaceCreateInfo* createInfo,
XrSpace* space);
Creates an XrSpace handle based on a chosen reference space. Application can provide an XrPosef to define the position and orientation of the new space’s origin within the natural reference frame of the reference space.
Multiple XrSpace handles may exist simultaneously, up to some limit imposed by the runtime. The XrSpace handle must be eventually freed via the xrDestroySpace function.
The runtime must return XR_ERROR_REFERENCE_SPACE_UNSUPPORTED
if the given reference space type is not
supported by this session
.
The runtime must return XR_ERROR_POSE_INVALID
if the pose
passed in createInfo.poseInReferenceSpace
contains non-unit quaternions.
The XrReferenceSpaceCreateInfo structure is defined as:
typedef struct XrReferenceSpaceCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrReferenceSpaceType referenceSpaceType;
XrPosef poseInReferenceSpace;
} XrReferenceSpaceCreateInfo;
7.3.3. xrCreateActionSpace
The xrCreateActionSpace function is defined as:
XrResult xrCreateActionSpace(
XrAction action,
const XrActionSpaceCreateInfo* createInfo,
XrSpace* space);
Creates an XrSpace handle based on a chosen pose action. Application can provide an XrPosef to define the position and orientation of the new space’s origin within the natural reference frame of the action space.
Multiple XrSpace handles may exist simultaneously, up to some limit imposed by the runtime. The XrSpace handle must be eventually freed via the xrDestroySpace function or by destroying the parent XrAction handle.
The runtime must return XR_ERROR_HANDLE_INVALID
if the action provided in
action
is not a valid action.
The runtime must return XR_ERROR_POSE_INVALID
if the pose
passed in createInfo.poseInActionSpace
contains non-unit quaternions.
The XrActionSpaceCreateInfo structure is defined as:
typedef struct XrActionSpaceCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrPath subactionPath;
XrPosef poseInActionSpace;
} XrActionSpaceCreateInfo;
7.3.4. xrDestroySpace
The xrDestroySpace function is defined as:
XrResult xrDestroySpace(
XrSpace space);
XrSpace handles are destroyed using xrDestroySpace. If the
XrSpace is invalid the runtime must return XR_ERROR_HANDLE_INVALID
.
The runtime may still use this space if there are active dependencies (e.g,
compositions in progress).
7.3.5. xrLocateSpace
xrLocateSpace provides the physical relationship of a space relative to a base space at a specified time, if currently known by the runtime.
XrResult xrLocateSpace(
XrSpace space,
XrSpace baseSpace,
XrTime time,
XrSpaceRelation* relation);
For a time
in the past, the runtime should relate the spaces based on the runtime’s most accurate
current understanding of how the world was at that historical time.
For a time
in the future, the runtime should relate the spaces based on the runtime’s most
up-to-date prediction of how the world will be at that future time.
The minimum valid range of values for time
are described in Prediction Time Limits. For values of time
outside this
range, xrLocateSpace may return a relation with no position and XR_SPACE_RELATION_POSITION_VALID_BIT
unset.
Some devices improve their understanding of the world as the device is used. The relation returned by
xrLocateSpace for a given space
, baseSpace
and time
may change over time,
even for spaces that track static objects, as one or both spaces adjust their origins.
During tracking loss of space
relative to baseSpace
, runtimes should continue to provide inferred or last-known position
and orientation
values.
These inferred poses can, for example, be based on neck model updates, inertial dead reckoning, or a last-known position, so long as it is still reasonable for the application to use that pose.
While a runtime is providing position data, it must continue to set XR_SPACE_RELATION_POSITION_VALID_BIT
but it can clear XR_SPACE_RELATION_POSITION_TRACKED_BIT
to indicate that the position is inferred or last-known in this way.
If the runtime has not yet observed even a last-known pose for how space
and baseSpace
relate (e.g. one space is an action space bound to a motion controller that has not yet been detected, or the two spaces are in disconnected fragments
of the runtime’s tracked volume), the runtime should return a relation with no position and XR_SPACE_RELATION_POSITION_VALID_BIT
unset.
The runtime must return a relation with both XR_SPACE_RELATION_POSITION_VALID_BIT
and XR_SPACE_RELATION_POSITION_TRACKED_BIT
set when relating space
and baseSpace
if both spaces were created relative to the same entity (e.g. two action spaces for the same action), even if the entity is currently untracked.
The relation in this case is the difference in the two spaces' application-specified transforms relative to that common entity.
The runtime should return a relation with XR_SPACE_RELATION_POSITION_VALID_BIT
set and XR_SPACE_RELATION_POSITION_TRACKED_BIT
unset
for spaces tracking two static entities in the world when their relative pose is known to the runtime.
This enables applications to make use of the runtime’s latest knowledge of the world, even during tracking loss.
The XrSpaceRelation structure is defined as:
typedef struct XrSpaceRelation {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrSpaceRelationFlags relationFlags;
XrTime time;
XrPosef pose;
XrVector3f linearVelocity;
XrVector3f angularVelocity;
XrVector3f linearAcceleration;
XrVector3f angularAcceleration;
} XrSpaceRelation;
The relationFlags
member is a bitwise-OR of zero or more of the following flags:
// Flag bits for XrSpaceRelationFlags
static const XrSpaceRelationFlags XR_SPACE_RELATION_ORIENTATION_VALID_BIT = 0x00000001;
static const XrSpaceRelationFlags XR_SPACE_RELATION_POSITION_VALID_BIT = 0x00000002;
static const XrSpaceRelationFlags XR_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT = 0x00000004;
static const XrSpaceRelationFlags XR_SPACE_RELATION_ANGULAR_VELOCITY_VALID_BIT = 0x00000008;
static const XrSpaceRelationFlags XR_SPACE_RELATION_LINEAR_ACCELERATION_VALID_BIT = 0x00000010;
static const XrSpaceRelationFlags XR_SPACE_RELATION_ANGULAR_ACCELERATION_VALID_BIT = 0x00000020;
static const XrSpaceRelationFlags XR_SPACE_RELATION_ORIENTATION_TRACKED_BIT = 0x00000040;
static const XrSpaceRelationFlags XR_SPACE_RELATION_POSITION_TRACKED_BIT = 0x00000080;
where the flags have the following meaning:
8. View Configurations
A view configuration is a semantically meaningful set of one or more views for which an application can render images. A primary view configuration is a view configuration intended to be presented to the viewer interacting with the XR application. This distinction allows the later addition of additional views, for example views which are intended for spectators.
A typical head-mounted VR system has a view configuration with two views, while a typical phone-based AR system has a view configuration with a single view. A simple multi-wall projection-based (CAVE-like) VR system may have a view configuration with at least one view for each display surface (wall, floor, ceiling) in the room.
For any supported form factor, a system will support one or more primary view configurations. Supporting more than one primary view configuration can be useful if a system supports a special view configuration optimized for the hardware but also supports a more broadly used view configuration as a compatibility fallback.
View configurations are identified with an XrViewConfigurationType.
8.1. Primary View Configurations
typedef enum XrViewConfigurationType {
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO = 1,
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO = 2,
XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrViewConfigurationType;
The application selects its primary view configuration type when calling xrBeginSession, and that configuration remains constant for the lifetime of the session, until xrEndSession is called.
The number of views and the semantic meaning of each view index within a given view configuration is well-defined, specified below for all core view configurations. The predefined primary view configuration types are:
8.2. View Configuration API
First an application needs to select which primary view configuration it wants to use. If it supports multiple configurations, an application can call xrEnumerateViewConfigurations before creating an XrSession to get a list of the view configuration types supported for a given system.
The application can then call xrGetViewConfigurationProperties and xrEnumerateViewConfigurationViews to get detailed information about each view configuration type and its individual views.
8.2.1. xrEnumerateViewConfigurations
The xrEnumerateViewConfigurations is defined as follows:
XrResult xrEnumerateViewConfigurations(
XrInstance instance,
XrSystemId systemId,
uint32_t viewConfigurationTypeCapacityInput,
uint32_t* viewConfigurationTypeCountOutput,
XrViewConfigurationType* viewConfigurationTypes);
xrEnumerateViewConfigurations enumerates the view configuration types supported by the XrSystemId
.
The supported set for that system must not change during the lifetime of its XrInstance.
The returned list of primary view configurations should be in order from what the runtime considered highest to lowest user preference.
Thus the first enumerated view configuration type should be the one the runtime prefers the application to use if possible.
8.2.2. xrGetViewConfigurationProperties
The xrGetViewConfigurationProperties function is defined as:
XrResult xrGetViewConfigurationProperties(
XrInstance instance,
XrSystemId systemId,
XrViewConfigurationType viewConfigurationType,
XrViewConfigurationProperties* configurationProperties);
xrGetViewConfigurationProperties queries properties of an individual view configuration.
Applications must use one of the supported view configuration types returned by xrEnumerateViewConfigurations.
If viewConfigurationType
is not supported by this XrInstance the runtime must return XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED
.
8.2.3. XrViewConfigurationProperties
The XrViewConfigurationProperties structure is defined as:
typedef struct XrViewConfigurationProperties {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrViewConfigurationType viewConfigurationType;
XrBool32 fovMutable;
} XrViewConfigurationProperties;
8.2.4. xrEnumerateViewConfigurationViews
The function xrEnumerateViewConfigurationViews is defined as:
XrResult xrEnumerateViewConfigurationViews(
XrInstance instance,
XrSystemId systemId,
XrViewConfigurationType viewConfigurationType,
uint32_t viewCapacityInput,
uint32_t* viewCountOutput,
XrViewConfigurationView* views);
Each XrViewConfigurationType defines the number of views associated with it.
Applications can query more details of each view element using xrEnumerateViewConfigurationViews.
If the supplied viewConfigurationType
is not supported by this
XrInstance and XrSystemId
, the
runtime must return XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED
.
8.2.5. XrViewConfigurationView
Each XrViewConfigurationView specifies properties related to rendering of an individual view within a view configuration.
The XrViewConfigurationView structure is defined as:
typedef struct XrViewConfigurationView {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t recommendedImageRectWidth;
uint32_t maxImageRectWidth;
uint32_t recommendedImageRectHeight;
uint32_t maxImageRectHeight;
uint32_t recommendedSwapchainSampleCount;
uint32_t maxSwapchainSampleCount;
} XrViewConfigurationView;
See XrSwapchainSubImage for more information about imageRect
values, and XrSwapchainCreateInfo for more information about creating swapchains appropriately sized to support those imageRect
values.
The array of XrViewConfigurationView returned by the runtime must adhere to the rules defined in XrViewConfigurationType, such as the count and association to the left and right eyes.
8.3. Example View Configuration Code
XrInstance instance; // previously initialized
XrSystemId system; // previously initialized
XrSession session; // previously initialized
// Enumerate the view configurations paths.
uint32_t configurationCount;
CHK_XR(xrEnumerateViewConfigurations(instance, system, 0, &configurationCount, nullptr));
std::vector<XrViewConfigurationType> configurationTypes(configurationCount);
CHK_XR(xrEnumerateViewConfigurations(instance, system, configurationCount, &configurationCount, configurationTypes.data()));
bool configFound = false;
for(uint32_t i = 0; i < configurationCount; ++i)
{
if (configurationTypes[i] == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO)
{
configFound = true;
break; // Pick the first supported, i.e. preferred, view configuration.
}
}
if (!configFound)
return; // Cannot support any view configuration of this system.
// Get detailed information of each view element.
uint32_t viewCount;
CHK_XR(xrEnumerateViewConfigurationViews(instance, system,
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
0,
&viewCount,
nullptr));
std::vector<XrViewConfigurationView> configViews(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW});
CHK_XR(xrEnumerateViewConfigurationViews(instance, system,
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
viewCount,
&viewCount,
configViews.data()));
// Set the primary view configuration for the session.
XrSessionBeginInfo beginInfo = {XR_TYPE_SESSION_BEGIN_INFO, nullptr, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO };
CHK_XR(xrBeginSession(session, &beginInfo));
XrCompositionLayerFlags layerFlags; // previously initialized
// Allocate a buffer according to viewCount.
std::vector<XrView> views(viewCount, {XR_TYPE_VIEW});
// Get views
XrTime displayTime; // previously initialized
XrSpace space; // previously initialized
// Run a per-frame loop.
while (!quit)
{
XrViewLocateInfo viewLocateInfo{XR_TYPE_VIEW_LOCATE_INFO};
viewLocateInfo.displayTime = displayTime;
viewLocateInfo.space = space;
XrViewState viewState{};
uint32_t viewCountOutput;
CHK_XR(xrLocateViews(session, &viewLocateInfo, &viewState, configViews.size(), &viewCountOutput, views.data()));
// Wait for beginning the next frame.
XrFrameWaitInfo frameWaitInfo{XR_TYPE_FRAME_WAIT_INFO};
XrFrameState frameState{XR_TYPE_FRAME_STATE};
CHK_XR(xrWaitFrame(session, &frameWaitInfo, &frameState));
// Begin frame
XrFrameBeginInfo frameBeginInfo { XR_TYPE_FRAME_BEGIN_INFO };
CHK_XR(xrBeginFrame(session, &frameBeginInfo));
// ...
// Use view and frameState for scene render.
// End frame
XrCompositionLayerProjectionView views[2] = { /*...*/ };
XrCompositionLayerProjection layerProj{ XR_TYPE_COMPOSITION_LAYER_PROJECTION, nullptr, layerFlags, space, 2, views };
XrCompositionLayerBaseHeader* layers[1] = { reinterpret_cast<XrCompositionLayerBaseHeader*>(&layerProj) };
XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO, nullptr, displayTime, XR_ENVIRONMENT_BLEND_MODE_OPAQUE, 1, layers };
CHK_XR(xrEndFrame(session, &frameEndInfo));
}
9. Session
XR_DEFINE_HANDLE(XrSession)
A session represents an application’s intention to display XR content to the user. An application makes its XR content eligible to be displayed by beginning a session with xrBeginSession, causing it to enter the running state. It may then hide its XR content for some period by ending its session with xrEndSession, causing it to leave the running state.
Only running sessions may become focused sessions that receive XR input. When a session is not running, the application must not submit frames. This is important because without a running session, the runtime no longer has to spend resources on sub-systems (tracking etc.) that are no longer needed by the application.
A session may be running but not currently visible, as another running session may take precedence. The XrEventDataSessionStateChanged event indicates changes to visibility or input focus states. Runtimes each establish their own policy for when an application has the right to make its running session visible in the XR display.
An application must set the current view configuration and supported view configurations before calling xrBeginSession.
9.1. Session Lifecycle
To present graphical content on an output device, OpenXR applications need to pick a graphics API which is supported by the runtime. Unextended OpenXR does not support any graphics APIs natively but provides a number of extensions of which each runtime can support any subset. These extensions can be activated during XrInstance create time.
During XrSession creation the application must provide information about which graphics API it intends to use by adding a struct of one (and only one) of the enabled graphics API extensions to the next chain of XrSessionCreateInfo. Unless specified differently in the graphics API extension, the application is responsible for creating a valid graphics device binding (for details refer to the extension specification of the graphics API).
The xrCreateSession function is defined as:
XrResult xrCreateSession(
XrInstance instance,
const XrSessionCreateInfo* createInfo,
XrSession* session);
Creates a session using the provided createInfo
and returns a handle to that session.
This session is created in the XR_SESSION_STATE_IDLE
state.
The XrSessionCreateInfo structure is defined as:
typedef struct XrSessionCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSessionCreateFlags createFlags;
XrSystemId systemId;
} XrSessionCreateInfo;
The XrSessionCreateFlags include:
// Flag bits for XrSessionCreateFlags
There are currently no session creation flags. This is reserved for future use.
The xrDestroySession function is defined as.
XrResult xrDestroySession(
XrSession session);
XrSession handles are destroyed using xrDestroySession.
When an XrSession is destroyed, all handles that are children of that XrSession are also destroyed.
If the session is invalid the runtime must return XR_ERROR_HANDLE_INVALID
.
The application is responsible for ensuring that it has no calls using session
in progress when the
session is destroyed.
9.2. Session Initialization
The xrBeginSession function is defined as:
XrResult xrBeginSession(
XrSession session,
const XrSessionBeginInfo* beginInfo);
When an app begins a session, it is requesting that the runtime show its rendered output to the user.
Note that a runtime may decide not to show a given session’s output to the user at any time,
for example if the user has switched to a different app’s running session.
If the session is
running but the runtime does not make the session visible, XR_SESSION_VISIBILITY_UNAVAILABLE
must be returned.
The app should use the XrEventDataSessionStateChanged event to determine
when this session is visible to the user and is focused to receive input.
If primaryViewConfigurationType
in beginInfo
is not supported by the XrInstance that created session
the runtime must return XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED
.
If a session was already begun for session
, then the runtime must return XR_ERROR_SESSION_RUNNING
.
The XrSessionBeginInfo structure is defined as:
typedef struct XrSessionBeginInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrViewConfigurationType primaryViewConfigurationType;
} XrSessionBeginInfo;
The xrEndSession function is defined as:
XrResult xrEndSession(
XrSession session);
The application calls xrEndSession to end a running session.
This function signals to the runtime that the application no longer wishes to display rendered output, read input state,
or control haptic events.
If this session
was not running, then XR_ERROR_SESSION_NOT_RUNNING
will be returned.
9.3. Session Lifecycle States
While events can be expanded upon, there are a minimum set of lifecycle events which can occur which all OpenXR applications must be aware of. These events are detailed below.
9.3.1. XrEventDataSessionStateChanged
The XrEventDataSessionStateChanged structure is defined as:
typedef struct XrEventDataSessionStateChanged {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSession session;
XrSessionState state;
XrTime time;
} XrEventDataSessionStateChanged;
Receiving the XrEventDataSessionStateChanged event structure indicates that the application has changed lifecycle state.
The XrSessionState enumerates the possible session lifecycle states:
typedef enum XrSessionState {
XR_SESSION_STATE_UNKNOWN = 0,
XR_SESSION_STATE_IDLE = 1,
XR_SESSION_STATE_READY = 2,
XR_SESSION_STATE_RUNNING = 3,
XR_SESSION_STATE_VISIBLE = 4,
XR_SESSION_STATE_FOCUSED = 5,
XR_SESSION_STATE_STOPPING = 6,
XR_SESSION_STATE_LOSS_PENDING = 7,
XR_SESSION_STATE_EXITING = 8,
XR_SESSION_STATE_MAX_ENUM = 0x7FFFFFFF
} XrSessionState;
The XR_SESSION_STATE_UNKNOWN
state must not be returned by the runtime,
and is only defined to avoid 0
being a valid state.
Receiving the XR_SESSION_STATE_IDLE
state
indicates that the runtime considers the session is idle. Applications in
this state should minimize resource consumption but continue to call xrPollEvent
at some reasonable cadence.
Receiving the XR_SESSION_STATE_READY
state
indicates that the runtime desires the application to prepare rendering resources,
call xrBeginSession, and start its rendering loop.
The rendering loop should consist of some sequence of
xrWaitFrame/xrBeginFrame/xrEndFrame calls. An application
should avoid heavy GPU work until reaching the XR_SESSION_STATE_VISIBLE
state
to avoid contention with other applications which may still possibly be running.
Receiving the XR_SESSION_STATE_RUNNING
state
indicates that the runtime has detected the applications rendering loop and properly
synchronized it with the display’s refresh cycle. Achieving synchronization prior
to entering the XR_SESSION_STATE_VISIBLE
state facilitates switching between
applications on a display frame boundary.
Receiving the XR_SESSION_STATE_VISIBLE
state
indicates that the session is visible.
This can occur in many cases, one typical example is when a user switches
from one OpenXR application to the current one.
Applications that become visible should respond by simulating and
submitting frames.
Applications that lose visibility should stop submitting frames in
order to give CPU and GPU precedence to any other applications that need it.
This is a temporary event and usually indicates that either the user or
the runtime process has determine the session should be placed on the
back burner but may be brought back into visibility shortly.
Receiving the XR_SESSION_STATE_FOCUSED
state
indicates the application is able to receive user input.
If a session is focused it receives all input from a user.
On the other hand, if a session does not have focus, it may receive no user
input.
The runtime must guarantee that at most one application has input
focus at any given time.
An application may be visible but not have focus, for example when the
runtime is composing a modal pop-up on top of the application’s rendered frames.
It is important for apps to continue rendering when visible even when they
do not have focus.
Applications should only render input avatars (depictions of hands or other
tracked objects controlled by the user) when in the XR_SESSION_STATE_FOCUSED
state.
The runtime must not render input avatars when an application is focused.
Receiving the XR_SESSION_STATE_STOPPING
state
indicates that the runtime has determined that the application should halt
its rendering loop. A possible reason for this would be to minimize contention
between multiple applications.
Applications should exit their rendering loop and
call xrEndSession when in this state.
Receiving the XR_SESSION_STATE_EXITING
state
indicates the runtime wishes the application to terminate its XR experience, typically
due to a user request via a runtime user interface.
Applications should gracefully end their process when in this state.
Receiving the XR_SESSION_STATE_LOSS_PENDING
state
indicates the runtime is no longer able to operate with the current session,
for example due to the loss of a display hardware connection.
An application should call xrDestroySession and may end its process
or decide to poll xrGetSystem at some reasonable cadence to
get a new XrSystemId
, and re-initialize all graphics resources related to the new system,
and then create a new session using xrCreateSession.
After the event is queued, subsequent calls to functions that accept XrSession parameters
must no longer return any success code other than XR_SESSION_LOSS_PENDING
for the given XrSession handle.
The XR_SESSION_LOSS_PENDING
success result is returned for an unspecified grace period of
time, and the functions that return it simulate success in their behavior.
If the runtime has no reasonable way to successfully complete a given function
(e.g. xrCreateSwapchain) when a lost session is pending, or if the runtime is not able to
provide the app a grace period, the runtime may return XR_ERROR_SESSION_LOST
.
Thereafter, functions which accept XrSession parameters for the lost session may return
XR_ERROR_SESSION_LOST
to indicate that the function failed and the given session was lost.
The XrSession handle and child handles are henceforth unusable and should be destroyed by
the application in order to immediately free up resources associated with those handles.
10. Rendering
10.1. Swapchain Image Management
XR_DEFINE_HANDLE(XrSwapchain)
Normal XR applications will want to present rendered images to the user. To allow this, the runtime provides images organized in swapchains for the application to render into. The runtime must allow applications to create multiple swapchains.
Swapchain image format support by the runtime is specified by the
xrEnumerateSwapchainFormats function. Runtimes should support R8G8B8A8
and R8G8B8A8
sRGB
formats if possible.
Swapchain images can be 2D or 2D Array.
Rendering operations involving composition of submitted layers should be
assumed to be internally performed by the runtime in linear color space.
Images submitted in sRGB color space must be created using an API-specific sRGB
format (e.g. DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, GL_SRGBA
,
VK_FORMAT_R8G8B8A8_SRGB
) to apply automatic sRGB-to-linear conversion
when read by the runtime. All other formats will be treated as linear values.
Note
DXGI resources will be created with their associated TYPELESS format, but the runtime will use the application-specified format for reading the data. |
The xrEnumerateSwapchainFormats is defined as:
XrResult xrEnumerateSwapchainFormats(
XrSession session,
uint32_t formatCapacityInput,
uint32_t* formatCountOutput,
int64_t* formats);
xrEnumerateSwapchainFormats enumerates the texture formats supported by the
current session.
The type of formats returned are dependent on the graphics
API specified in xrCreateSession.
For example, if a DirectX graphics API
was specified, then the enumerated formats correspond to the DXGI formats, such
as DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
.
With an OpenGL-based graphics API, the texture formats correspond to OpenGL internal formats.
With a Direct3D-based graphics API, xrEnumerateSwapchainFormats
never returns typeless formats (e.g. DXGI_FORMAT_R8G8B8A8_TYPELESS
).
Only concrete formats are returned, and only concrete formats may be
specified by applications for swapchain creation.
XrSwapchainUsageFlags Specify the intended usage of the swapchain images. When images are created, the runtime needs to know how the images are used in a way that requires more information than simply the image format. The XrSwapchainCreateInfo passed to xrCreateSwapchain should match the intended usage or else undefined behavior may result when the application works with the images.
Flags include:
// Flag bits for XrSwapchainUsageFlags
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT = 0x00000001;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000002;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT = 0x00000004;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT = 0x00000008;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT = 0x00000010;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_SAMPLED_BIT = 0x00000020;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT = 0x00000040;
The xrCreateSwapchain function is defined as:
XrResult xrCreateSwapchain(
XrSession session,
const XrSwapchainCreateInfo* createInfo,
XrSwapchain* swapchain);
Creates an XrSwapchain handle.
The returned swapchain handle may be subsequently used in API calls.
Multiple XrSwapchain handles may exist simultaneously, up to some limit imposed by the runtime.
The XrSwapchain handle must be eventually freed via the xrDestroySwapchain function.
The runtime must return XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED
if the image format specified
in the XrSwapchainCreateInfo is unsupported.
The XrSwapchainCreateInfo structure is defined as:
typedef struct XrSwapchainCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSwapchainCreateFlags createFlags;
XrSwapchainUsageFlags usageFlags;
int64_t format;
uint32_t sampleCount;
uint32_t width;
uint32_t height;
uint32_t faceCount;
uint32_t arraySize;
uint32_t mipCount;
} XrSwapchainCreateInfo;
The createFlags
are a combination of the following:
// Flag bits for XrSwapchainCreateFlags
static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT = 0x00000001;
static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT = 0x00000002;
A runtime may implement any of these, but is not required to.
The number of images in each swapchain is implementation-defined. To obtain the number of images actually allocated, call xrEnumerateSwapchainImages.
With a Direct3D-based graphics API, the swapchain returned by xrCreateSwapchain will be a typeless format if the requested format has a typeless analogue. Applications are required to reinterpret the swapchain as a compatible non-typeless type. Upon submitting such swapchains to the runtime, they are interpreted as the format specified by the application in the XrSwapchainCreateInfo.
Swapchains will be created with graphics API-specific flags appropriate to the type of underlying image and its usage. Extensions may exist to further assist the runtime in choosing how to create swapchains.
xrEnumerateSwapchainFormats never returns
typeless formats (e.g. DXGI_FORMAT_R8G8B8A8_TYPELESS
).
Only concrete formats
are returned, and only concrete formats may be specified by applications for
swapchain creation.
The xrDestroySwapchain function is defined as:
XrResult xrDestroySwapchain(
XrSwapchain swapchain);
All submitted graphics API commands that refer to swapchain
must have completed execution.
Runtimes may continue to utilize swapchain images after xrDestroySwapchain is called.
Swapchain images are acquired, waited on, and released by index, but the number of images in a swapchain is implementation-defined. Additionally, rendering to images requires access to the underlying image primitive of the graphics API being used. Applications may query and cache the images at any time after swapchain creation.
The xrEnumerateSwapchainImages function is defined as:
XrResult xrEnumerateSwapchainImages(
XrSwapchain swapchain,
uint32_t imageCapacityInput,
uint32_t* imageCountOutput,
XrSwapchainImageBaseHeader* images);
Fills an array of graphics API-specific XrSwapchainImage
structures.
The resources must be constant and valid for the lifetime of the XrSwapchain.
Note: images
is a pointer to an array of structures of graphics API-specific type, not an array of structure pointers.
The XrSwapchainImageBaseHeader structure is defined as follows:
typedef struct XrSwapchainImageBaseHeader {
XrStructureType type;
void* XR_MAY_ALIAS next;
} XrSwapchainImageBaseHeader;
The XrSwapchainImageBaseHeader is a base structure that can be overridden
by a graphics API-specific XrSwapchainImage*
child structure.
Before an application can start building graphics API command buffers that refer to an image in a swapchain, it must acquire the image from the swapchain. The acquire operation determines the index of the next image that will be used in the swapchain. The order in which images are acquired is undefined. The runtime must allow the application to acquire more than one image from a single swapchain at a time, for example if the application implements a multiple frame deep rendering pipeline.
The xrAcquireSwapchainImage function is defined as:
XrResult xrAcquireSwapchainImage(
XrSwapchain swapchain,
const XrSwapchainImageAcquireInfo* acquireInfo,
uint32_t* index);
Acquires the image corresponding to the index
position in the array
returned by xrEnumerateSwapchainImages.
The runtime must return XR_ERROR_CALL_ORDER_INVALID
if
index
has already been acquired and
not yet released with xrReleaseSwapchainImage.
If the swapchain
was created with the
XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT
set in
XrSwapchainCreateInfo::createFlags
, this function must not have
been previously called for this swapchain.
The XrSwapchainImageAcquireInfo structure is available for extensibility purposes. It is defined as:
typedef struct XrSwapchainImageAcquireInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrSwapchainImageAcquireInfo;
The xrWaitSwapchainImage function is defined as:
XrResult xrWaitSwapchainImage(
XrSwapchain swapchain,
const XrSwapchainImageWaitInfo* waitInfo);
Before an application can begin writing to a swapchain image, it must first wait on the image to avoid writing to it before the compositor has finished reading from it. xrWaitSwapchainImage will implicitly wait on the oldest acquired swapchain image which has not yet been successfully waited on. Once a swapchain image has been successfully waited on, it must be released before waiting on the next acquired swapchain image.
This function may block for longer than the timeout specified in XrSwapchainImageWaitInfo due to scheduling or contention.
If the timeout expires without the image becoming available for writing,
XR_TIMEOUT_EXPIRED
is returned.
If xrWaitSwapchainImage returns XR_TIMEOUT_EXPIRED
, the next call
to xrWaitSwapchainImage will wait on the same image index again until the
function succeeds with XR_SUCCESS
.
Note that this is not an error code; XR_SUCCEEDED(
is XR_TIMEOUT_EXPIRED
)true
.
The runtime must return XR_ERROR_CALL_ORDER_INVALID
if no image has
been acquired by calling xrAcquireSwapchainImage.
The XrSwapchainImageWaitInfo structure describes a swapchain image wait operation. It is defined as:
typedef struct XrSwapchainImageWaitInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrDuration timeout;
} XrSwapchainImageWaitInfo;
Once an application is done writing to a swapchain image, it is released. xrReleaseSwapchainImage will implicitly release the oldest swapchain image which has been acquired. The swapchain image must have been successfully waited on before it is released. xrEndFrame will use the most recently released swapchain image. In each frame submitted to the compositor only one image index from each swapchain will be used. Note that in case the swapchain contains 2D image arrays, one array is referenced per swapchain index and thus the whole image array can be used in one frame.
The xrReleaseSwapchainImage function is defined as:
XrResult xrReleaseSwapchainImage(
XrSwapchain swapchain,
const XrSwapchainImageReleaseInfo* releaseInfo);
If the swapchain
was created with the XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT
set in XrSwapchainCreateInfo::createFlags
structure,
this function must not have been previously called for this swapchain.
The runtime must return XR_ERROR_CALL_ORDER_INVALID
if no image has
been waited on by calling xrWaitSwapchainImage.
The XrSwapchainImageReleaseInfo structure is intended for extensibility purposes. It is defined as as:
typedef struct XrSwapchainImageReleaseInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrSwapchainImageReleaseInfo;
10.2. View and Projection State
An application uses xrLocateViews to retrieve the viewer pose and projection parameters needed to render each composition view returned by xrEnumerateViewConfigurationViews.
The xrLocateViews function is defined as:
XrResult xrLocateViews(
XrSession session,
const XrViewLocateInfo* viewLocateInfo,
XrViewState* viewState,
uint32_t viewCapacityInput,
uint32_t* viewCountOutput,
XrView* views);
The function xrLocateViews returns the view and projection info for a particular display time.
This time is typically the XrFrameState::predictedDisplayTime
for a given frame.
Repeatedly calling xrLocateViews with the same time may not necessarily return the same result.
Instead the prediction gets increasingly accurate as the function is called closer to the given time for which a prediction is made.
This allows an application to get the predicted views as late as possible in its pipeline to get the least amount of latency and prediction error.
xrLocateViews returns an array of XrView elements, one for each view of the running session’s active view configuration, along with an XrViewState containing additional state data shared across all views for the primary viewer. The eye each view corresponds to is statically defined in XrViewConfigurationType in case the application wants to apply eye-specific rendering traits. The XrViewState and XrView member data may change on subsequent calls to xrLocateViews, and so applications must not assume it to be constant.
The XrViewLocateInfo structure is defined as:
typedef struct XrViewLocateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrTime displayTime;
XrSpace space;
} XrViewLocateInfo;
The XrViewLocateInfo structure contains the display time and space used to locate the view XrView structures.
The XrViewState structure is defined as:
typedef struct XrViewState {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrViewStateFlags viewStateFlags;
} XrViewState;
The XrViewState contains additional view state from xrLocateViews common to all views of the active view configuration.
The XrViewStateFlags specifies the validity and quality of the corresponding XrView array returned by xrLocateViews.
Flags include:
// Flag bits for XrViewStateFlags
static const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_VALID_BIT = 0x00000001;
static const XrViewStateFlags XR_VIEW_STATE_POSITION_VALID_BIT = 0x00000002;
static const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_TRACKED_BIT = 0x00000004;
static const XrViewStateFlags XR_VIEW_STATE_POSITION_TRACKED_BIT = 0x00000008;
10.2.1. IPD / IAD / ER
The Inter Pupillary Distance (IPD), the distance between the user’s eyes, the Inter Axial Distance (IAD), the distance between the lenses, and the Eye Relief (ER), the distance from the pupil of the eye to the nearest surface of the lens, are all properties of the user and/or a typical VR headset.
On some headsets the IAD and/or the ER can be dynamically adjusted at run-time. The application, however, is not explicitly exposed to these values. CAVE-like VR systems do not use lenses and are not concerned with the IAD and ER, in which case exposing these values to the application makes no sense.
Instead, with a predicted head pose, the application gets a view pose for each eye, the direction in which each eye is looking, and the suggested FOV for each eye from which the application can trivially derive a projection matrix. It is important to get all this data as an atomic package with the same prediction for the same time, in particular when using a VR headset that allows the IAD and/or ER to be adjusted at run-time.
10.3. Display Timing
Instead of just using the latest tracking data, an application uses predicted tracking data for the middle of the time period during which the new swapchains will be displayed. The function xrWaitFrame returns a predicted display time for the time that the runtime predicts the swapchain images will be displayed. The application should use the predicted display time when requesting space relationships and view poses for rendering.
xrEndFrame may return immediately to the application, but xrWaitFrame will block for an amount of time that depends on throttling of the application by the runtime. There is no strong coupling between a specific call to xrWaitFrame, and a specific frame description in xrEndFrame. However, XrFrameEndInfo does include a display time, which should be computed using values returned by xrWaitFrame. The runtime may affect this computation by changing the return values of xrWaitFrame in response to feedback from frame submission and completion times in xrEndFrame. This results in a consistent predicted display time at every stage in the engine pipeline without being affected by oscillation in a deep threaded pipeline. Note that, if the application has multiple pipeline stages, the application must pass the predicted display time through its pipeline, as xrWaitFrame should not be called more than once per frame. However, the runtime should be robust against variations in the timing of calls to xrWaitFrame, since a pipelined system may call xrWaitFrame on a separate thread from xrBeginFrame and xrEndFrame without any synchronization guarantees.
An accurate predicted display time is very important to avoid black pull-in by reprojection and to reduce motion judder in case the runtime does not implement a translational reprojection. Reprojection should never display images before the display refresh period they were predicted for, even if they are completed early, because this will cause motion judder just the same. In other words, the better the predicted display time, the less latency experienced by the user. The engine simulation also needs to advance based on the time it will be displayed. Every stage in the engine pipeline should use the exact same predicted display time for one particular frame. An accurate and consistent predicted display time across all stages and threads in the engine pipeline is important to avoid object motion judder.
10.4. Frame Waiting
An application synchronizes its rendering loop to the compositor by calling xrWaitFrame.
The xrWaitFrame function is defined as:
XrResult xrWaitFrame(
XrSession session,
const XrFrameWaitInfo* frameWaitInfo,
XrFrameState* frameState);
If a frame submitted to xrEndFrame is consumed by the compositor before its target display time, a subsequent call to xrWaitFrame must block the caller until the start of the next rendering interval after the frame’s target display time as determined by the runtime.
If a frame submitted to xrEndFrame misses its target display time, a subsequent call to xrWaitFrame must block the caller until that frame is consumed by the compositor, at which point it must return immediately.
If no frame has been submitted to xrEndFrame since any prior call to xrWaitFrame, a subsequent call to xrWaitFrame must block the caller until the start of the next rendering interval time as determined by the runtime.
The runtime may dynamically adjust the start time of the rendering interval relative to the display hardware’s refresh cycle to minimize graphics processor contention between the application and the compositor.
xrWaitFrame must be callable from any thread, including a different thread than xrBeginFrame/xrEndFrame are being called from.
Calling xrWaitFrame must be externally synchronized by the application, concurrent calls may result in undefined behavior.
The runtime must return XR_ERROR_SESSION_NOT_RUNNING
if session
is not in the XR_SESSION_STATE_RUNNING
,
XR_SESSION_STATE_VISIBLE
or XR_SESSION_STATE_FOCUSED
XrSessionState.
The XrFrameWaitInfo structure is defined as:
typedef struct XrFrameWaitInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrFrameWaitInfo;
Because this structure only exists to support extension-specific structures,
xrWaitFrame will accept a NULL
argument for
frameWaitInfo
for applications that are not using any relevant
extensions.
The XrFrameState structure is defined as:
typedef struct XrFrameState {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrTime predictedDisplayTime;
XrDuration predictedDisplayPeriod;
} XrFrameState;
XrFrameState describes the time at which the next frame submitted to xrEndFrame will be displayed to the user.
predictedDisplayTime
must refer to the midpoint of the interval during which the frame is displayed.
The runtime may report a different predictedDisplayPeriod
from the hardware’s refresh cycle when interpolating
submitted frames.
10.5. Frame Submission
Every application must call xrBeginFrame before calling xrEndFrame, and should call xrEndFrame before calling xrBeginFrame again.
Calling xrEndFrame again without a prior call toxrBeginFrame will result in XR_ERROR_CALL_ORDER_INVALID
being returned by xrEndFrame.
An application may call xrBeginFrame again if the prior xrEndFrame fails or if the application wishes to discard an in-progress frame.
Calling xrBeginFrame again with no intervening xrEndFrame call will result in the success code XR_FRAME_DISCARDED
being returned from xrBeginFrame.
In this case it is assumed that the xrBeginFrame refers to the next frame and the previously begun frame is forfeited by the application.
Applications should call xrBeginFrame right before executing any graphics device work for a given frame, as opposed to calling it afterwards.
The runtime must only compose frames whose xrBeginFrame and xrEndFrame both return success codes.
While xrBeginFrame and xrEndFrame do not need to be called on the
same thread, the application must handle synchronization if they are called on
separate threads.
The xrBeginFrame function is defined as:
XrResult xrBeginFrame(
XrSession session,
const XrFrameBeginInfo* frameBeginInfo);
xrBeginFrame is called prior to the the start of frame rendering.
The runtime must return the success code XR_FRAME_DISCARDED
if a prior xrBeginFrame has been called without an
intervening call to xrEndFrame.
The runtime may return the success code XR_SESSION_VISIBILITY_UNAVAILABLE
if it determines that the current frame
will not be visible. In this case the application may elect to omit rendering work for the frame, but should still call xrEndFrame.
The runtime must consider the frame in-progress and ready for an xrEndFrame call if a success code is returned.
The runtime must return XR_ERROR_SESSION_NOT_RUNNING
if session
is not in the XR_SESSION_STATE_RUNNING
,
XR_SESSION_STATE_VISIBLE
or XR_SESSION_STATE_FOCUSED
XrSessionState.
The XrFrameBeginInfo structure is defined as:
typedef struct XrFrameBeginInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrFrameBeginInfo;
Because this structure only exists to support extension-specific structures,
xrBeginFrame will accept a NULL
argument for
frameBeginInfo
for applications that are not using any relevant
extensions.
The xrEndFrame function is defined as:
XrResult xrEndFrame(
XrSession session,
const XrFrameEndInfo* frameEndInfo);
Every call to xrEndFrame must be preceded by a successful call to xrBeginFrame.
Failure to do so will result in XR_ERROR_CALL_ORDER_INVALID
being returned by xrEndFrame.
XrFrameEndInfo may reference swapchains into which the application has rendered for this frame.
From each XrSwapchain only one image index is implicitly referenced per frame, the one corresponding to the last call to xrReleaseSwapchainImage.
However, a specific swapchain (and by extension a specific swapchain image index) may be referenced in XrFrameEndInfo multiple times.
This can be used for example to render a side by side image into a single swapchain image and referencing it twice with differing image rectangles in different layers.
XR_ERROR_LAYER_INVALID
will be returned if an unknown or unsupported layer type is passed as one of the XrFrameEndInfo::layers.
XR_ERROR_LAYER_LIMIT_EXCEEDED
will be returned if XrFrameEndInfo::layerCount exceeds XrSystemGraphicsProperties::maxLayerCount
or if the runtime is unable to composite the specified layers due to resource constraints.
XR_ERROR_SWAPCHAIN_RECT_INVALID
will be returned if XrFrameEndInfo::layers contains a composition layer which references pixels outside
of the associated swapchain image.
XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED
will be returned if XrFrameEndInfo::environmentBlendMode is not supported.
The runtime must return XR_ERROR_SESSION_NOT_RUNNING
if session
is not in the XR_SESSION_STATE_RUNNING
,
XR_SESSION_STATE_VISIBLE
or XR_SESSION_STATE_FOCUSED
XrSessionState.
The runtime must return XR_ERROR_POSE_INVALID
if any pose
passed in XrFrameEndInfo contains non-unit quaternions.
The XrFrameEndInfo structure is defined as:
typedef struct XrFrameEndInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrTime displayTime;
XrEnvironmentBlendMode environmentBlendMode;
uint32_t layerCount;
const XrCompositionLayerBaseHeader* const* layers;
} XrFrameEndInfo;
All layers submitted to xrEndFrame will be presented to the primary view configuration of the running session unless otherwise specified by extension functionality.
10.5.1. Frame Rate
For every application-generated frame, the application may call xrEndFrame to submit the application-generated composition layers. In addition, the application must call xrWaitFrame when the application is ready to begin preparing the next set of frame layers. xrEndFrame may return immediately to the application, but xrWaitFrame will block for an amount of time that depends on throttling of the application by the runtime. The earliest the runtime will return from xrWaitFrame is when it determines that the application should start drawing the next frame.
10.5.2. Compositing
Composition layers are submitted by the application via the xrEndFrame call.
All composition layers to be drawn must be submitted with every xrEndFrame call.
A layer that is omitted in this call will not be drawn by the runtime layer compositor.
All views associated with projection layers must be supplied or
XR_ERROR_VALIDATION_FAILURE
will be returned by xrEndFrame.
Composition layers are drawn in the same order as they are specified in via XrFrameEndInfo, with the 0th layer drawn first. Layers are drawn with a "painter’s algorithm," with each successive layer potentially overwriting the destination layers whether or not the new layers are virtually closer to the viewer.
10.5.3. Composition Layer Flags
The XrCompositionLayerFlagBits bitfield is specified as:
// Flag bits for XrCompositionLayerFlags
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001;
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002;
XrCompositionLayerFlags specify options for individual composition layers.
10.5.4. Composition Layer Blending
All types of composition layers are subject to blending with other layers.
Blending of layers can be controlled by layer per-texel source alpha.
Destination alpha is not supported.
Layer swapchain textures may contain an alpha channel, depending on the image format.
If a submitted swapchain’s texture format includes an alpha channel, and if the
XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT
is enabled, then the layer composition uses
the alpha channel to modulate the blending of the swapchain texture against the destination.
Swapchain texture color channels must be encoded with premultiplied alpha.
If the XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT
is enabled and the swapchain texture
has no alpha channel then the bit is effectively ignored and the texture is treated as if it is
opaque (has alpha channel values of one).
If the XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT
is not enabled, then the swapchain
texture is treated as if each texel has an alpha value of 1, regardless of the presence of a texture
swapchain alpha.
Texture color and alpha channels are clamped to a range of [0.0, 1.0] as input to the blending operation.
The blending operation between the source and destination is an addition. The blending factor for the source texture color and alpha channels is one (1, 1, 1, 1). The blending factor for the destination texture color and alpha channels is one minus source alpha (1-SRC_ALPHA). The result is:
Destination red = (source red + (destination red * (1 - source alpha))
Destination green = (source green + (destination green * (1 - source alpha))
Destination blue = (source blue + (destination blue * (1 - source alpha))
Textures that use color encoding other than RGB (e.g. YUV) are blended in a way equivalent to if the encoding was converted to RGB.
10.5.5. Composition Layer Behavior
The behavior of xrEndFrame with respect to layers includes the following behavior, evaluated in the order given:
-
xrEndFrame with a layer count of 0 results in a return of
XR_SUCCESS
and the VR display cleared. -
xrEndFrame with a layer count greater than XrSystemGraphicsProperties::maxLayerCount results in a return of
XR_ERROR_LAYER_LIMIT_EXCEEDED
. -
xrEndFrame with any
NULL
pointer to XrCompositionLayerBaseHeader layer entries is invalid and results in a return ofXR_ERROR_LAYER_INVALID
. -
xrEndFrame with any
NULL
image is invalid and results in a return ofXR_ERROR_HANDLE_INVALID
. -
xrEndFrame with an empty layer
imageRect
results inXR_SUCCESS
but nothing drawn. -
xrEndFrame with a negatively sized
imageRect
results inXR_ERROR_SWAPCHAIN_RECT_INVALID
.
10.5.6. Composition Layer Types
Composition layers allow an application to offload the composition of the final image to a runtime-supplied compositor. This reduces the application’s rendering complexity since details such as frame-rate interpolation and distortion correction can be performed by the runtime. The core specification defines XrCompositionLayerProjection and XrCompositionLayerQuad layer types.
The projection layer type represents planar projected images rendered from the eye point of each eye using a perspective projection. This layer type is typically use to render the virtual world from the user’s perspective.
The quad layer type describes a posable planar rectangle in the virtual world for displaying two-dimensional content. Quad layers can subtend a smaller portion of the display’s field of view, allowing a better match between the resolutions of the XrSwapchain image and footprint of that image in the final composition. This improves legibility for user interface elements or heads-up displays and allows optimal sampling during any composition distortion corrections the runtime might employ.
The classes below describe the layer types in the layer composition system.
The XrCompositionLayerBaseHeader structure is defined as:
typedef struct XrCompositionLayerBaseHeader {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
} XrCompositionLayerBaseHeader;
All composition layer structures begin with the elements described in the XrCompositionLayerBaseHeader. The XrCompositionLayerBaseHeader struct is not intended to be directly used, but forms a basis for defining current and future structures containing composition layer information. The XrFrameEndInfo structure contains an array of pointers to these polymorphic header structures. All composition layer type pointers must be type-castable as an XrCompositionLayerBaseHeader pointer.
Many composition layer structures also contain one or more references to generic layer data stored in an XrSwapchainSubImage structure.
The XrSwapchainSubImage structure is defined as:
typedef struct XrSwapchainSubImage {
XrSwapchain swapchain;
XrRect2Di imageRect;
uint32_t imageArrayIndex;
} XrSwapchainSubImage;
Projection Composition
The XrCompositionLayerProjection layer represents planar projected images rendered from the eye point of each eye using a standard perspective projection.
The XrCompositionLayerProjection structure is defined as:
typedef struct XrCompositionLayerProjection {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
uint32_t viewCount;
const XrCompositionLayerProjectionView* views;
} XrCompositionLayerProjection;
Note
Because a runtime may reproject the layer over time, a projection layer should specify an XrSpace in which to maximize stability
of the layer content.
For example, a projection layer containing world-locked content should use a XrSpace which is also world-locked, such as the |
The XrCompositionLayerProjectionView structure is defined as:
typedef struct XrCompositionLayerProjectionView {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrPosef pose;
XrFovf fov;
XrSwapchainSubImage subImage;
} XrCompositionLayerProjectionView;
The count and order of view poses submitted with XrCompositionLayerProjection
must be the same order as that returned by xrLocateViews.
The XrCompositionLayerProjectionView::pose
and
XrCompositionLayerProjectionView::fov
should almost always derive from XrView::pose
and
XrView::fov
as found in the
xrLocateViews::views
array.
However, applications may submit an XrCompositionLayerProjectionView
which has a different view or FOV than that from xrLocateViews.
In this case, the runtime will map the view and FOV to the system display appropriately.
In the case that two submitted views within a single layer overlap, they are composited in view array order.
In the case that submitted projection layers overlap, they are composited in layer array order.
Quad Layer Composition
The XrCompositionLayerQuad structure defined as:
typedef struct XrCompositionLayerQuad {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
XrEyeVisibility eyeVisibility;
XrSwapchainSubImage subImage;
XrPosef pose;
XrVector2f size;
} XrCompositionLayerQuad;
The XrCompositionLayerQuad layer is useful for user interface elements or 2D content rendered into the virtual world. The layer’s XrSwapchainSubImage::swapchain image is applied to a quad in the virtual world space. Only front face of the quad surface is visible; the back face is not visible and must not be drawn by the runtime. A quad layer has no thickness; it is a two-dimensional object positioned and oriented in 3D space. The position of a quad refers to the center of the quad within the given XrSpace. The orientation of the quad refers to the orientation of the normal vector from the front face. The size of a quad refers to the quad’s size in the x-y plane of the given XrSpace’s coordinate system. A quad with a position of {0,0,0}, rotation of {0,0,0,1} (no rotation), and a size of {1,1} refers to a 1 meter x 1 meter quad centered at {0,0,0} with its front face normal vector coinciding with the +z axis.
The XrEyeVisibility enum selects which of the viewer’s eyes to display a layer to:
typedef enum XrEyeVisibility {
XR_EYE_VISIBILITY_BOTH = 0,
XR_EYE_VISIBILITY_LEFT = 1,
XR_EYE_VISIBILITY_RIGHT = 2,
XR_EYE_VISIBILITY_MAX_ENUM = 0x7FFFFFFF
} XrEyeVisibility;
10.5.7. Environment Blend Mode
After the compositor has blended and flattened all layers (including any layers added by the runtime itself), it will then present this image to the system’s display.
The composited image will then blend with the user’s view of the physical world behind the displays in one of three modes,
based on the application’s chosen environment blend mode.
VR applications will generally choose the XR_ENVIRONMENT_BLEND_MODE_OPAQUE
blend mode,
while AR applications will generally choose either the XR_ENVIRONMENT_BLEND_MODE_ADDITIVE
or XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
mode.
Applications select their environment blend mode each frame as part of their call to xrEndFrame.
The application can inspect the set of supported environment blend modes for
a given system using xrEnumerateEnvironmentBlendModes, and prepare their assets and rendering techniques differently based on the blend mode they choose. For example, a
black shadow rendered using the XR_ENVIRONMENT_BLEND_MODE_ADDITIVE
blend mode will appear transparent, and so an app in that mode may render a glow as a grounding effect
around the black shadow to ensure the shadow can be seen.
Similarly, an app designed for XR_ENVIRONMENT_BLEND_MODE_ADDITIVE
rendering may choose to leave garbage in their
alpha channel as a side effect of a rendering optimization, but this garbage would appear as visible display artifacts if the environment blend mode was instead
XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
.
Not all systems will support all environment blend modes.
For example, a VR headset may not support the XR_ENVIRONMENT_BLEND_MODE_ADDITIVE
or
XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
modes unless it has video passthrough, while an AR headset with an additive display may not support the the
XR_ENVIRONMENT_BLEND_MODE_OPAQUE
or XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
modes.
For devices that can support multiple environment blend modes, such as AR phones with video passthrough, the runtime may optimize power consumption on the device in response to the
environment blend mode that the app chooses each frame.
For example, if an app on a video passthrough phone knows that it is currently rendering a 360-degree background covering all
screen pixels, it can submit frames with an environment blend mode of XR_ENVIRONMENT_BLEND_MODE_OPAQUE
, saving the runtime the cost of compositing a camera-based underlay of
the physical world behind the app’s layers.
The xrEnumerateEnvironmentBlendModes function is defined as follows.
XrResult xrEnumerateEnvironmentBlendModes(
XrInstance instance,
XrSystemId systemId,
uint32_t environmentBlendModeCapacityInput,
uint32_t* environmentBlendModeCountOutput,
XrEnvironmentBlendMode* environmentBlendModes);
Enumerates the set of environment blend modes that this runtime supports for a given system.
The possible blend modes are specified by the XrEnvironmentBlendMode enumeration:
typedef enum XrEnvironmentBlendMode {
XR_ENVIRONMENT_BLEND_MODE_OPAQUE = 1,
XR_ENVIRONMENT_BLEND_MODE_ADDITIVE = 2,
XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND = 3,
XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM = 0x7FFFFFFF
} XrEnvironmentBlendMode;
11. Input and Haptics
11.1. Action Overview
OpenXR applications communicate with input devices using XrActions.
Actions are created at initialization time and later used to request input device state, create action spaces, or control haptic events.
Input action handles represent 'actions' that the game is interested in obtaining the state of, not direct input device hardware.
For example, instead of the application directly querying the state of the A button when interacting with a menu, an OpenXR application instead creates a menu_select
action at startup then asks OpenXR for the state of the action.
The application recommends that the action be assigned to a specific input source on the input device for a known interaction profile, but runtimes have the ability to choose a different control depending on user preference, input device availability, or any other reason. This abstraction ensures that applications can run on a wide variety of input hardware and maximize user accessibility.
Example usage:
XrInstance instance; // previously initialized
XrSession session; // previously initialized
// Create an action set
XrActionSetCreateInfo actionSetInfo = {0};
actionSetInfo.type = XR_TYPE_ACTION_SET_CREATE_INFO;
strcpy(actionSetInfo.actionSetName, "gameplay" );
strcpy(actionSetInfo.localizedActionSetName, "Gameplay" );
XrActionSet inGameActionSet;
CHK_XR(xrCreateActionSet( session, &actionSetInfo, &inGameActionSet ));
// create a "teleport" input action
XrActionCreateInfo actioninfo = {0};
actioninfo.type = XR_TYPE_ACTION_CREATE_INFO;
strcpy(actioninfo.actionName, "teleport" );
actioninfo.actionType = XR_INPUT_ACTION_TYPE_BOOLEAN;
strcpy(actioninfo.localizedActionName, "Teleport" );
XrAction teleportAction;
CHK_XR(xrCreateAction( inGameActionSet, &actioninfo, &teleportAction ));
// create a "player_hit" output action
XrActionCreateInfo hapticsactioninfo = {0};
hapticsactioninfo.type = XR_TYPE_ACTION_CREATE_INFO;
strcpy(hapticsactioninfo.actionName, "player_hit" );
hapticsactioninfo.actionType = XR_OUTPUT_ACTION_TYPE_VIBRATION;
strcpy(hapticsactioninfo.localizedActionName, "Player hit" );
XrAction hapticsAction;
CHK_XR(xrCreateAction( inGameActionSet, &hapticsactioninfo, &hapticsAction ));
XrPath triggerClickPath, hapticPath;
CHK_XR(xrStringToPath( instance, "/user/hand/right/input/trigger/click", &triggerClickPath ));
CHK_XR(xrStringToPath( instance, "/user/hand/right/output/haptic", &hapticPath ))
XrPath interactionProfilePath;
CHK_XR(xrStringToPath( instance, "/interaction_profiles/vendor_x/profile_x", &interactionProfilePath ));
XrActionSuggestedBinding bindings[2];
bindings[0].action = teleportAction;
bindings[0].binding = triggerClickPath;
bindings[1].action = hapticsAction;
bindings[1].binding = hapticPath;
XrInteractionProfileSuggestedBinding suggestedBindings = {0};
suggestedBindings.type = XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING;
suggestedBindings.interactionProfile = interactionProfilePath;
suggestedBindings.suggestedBindings = bindings;
suggestedBindings.countSuggestedBindings = 2;
CHK_XR(xrSetInteractionProfileSuggestedBindings( session, &suggestedBindings ));
// application main loop
while( 1 )
{
// sync action data
XrActiveActionSet activeActionSet = {0};
activeActionSet.type = XR_TYPE_ACTIVE_ACTION_SET;
activeActionSet.actionSet = inGameActionSet;
activeActionSet.subactionPath = XR_NULL_PATH;
CHK_XR(xrSyncActionData( session, 1, &activeActionSet) );
// query input action state
XrActionStateBoolean teleportState;
CHK_XR(xrGetActionStateBoolean( teleportAction, 0, NULL, &teleportState ));
if ( teleportState.changedSinceLastSync && teleportState.currentState )
{
// fire haptics using output action
XrHapticVibration vibration = {0};
vibration.type = XR_TYPE_HAPTIC_VIBRATION;
vibration.amplitude = 0.5;
vibration.duration = 300;
vibration.frequency = 3000;
CHK_XR(xrApplyHapticFeedback( hapticsAction, 0, NULL, (const XrHapticBaseHeader*)&vibration ));
}
}
11.2. Action Sets
XR_DEFINE_HANDLE(XrActionSet)
Action sets are application-defined collections of actions. They are enabled or disabled by the application via xrSyncActionData depending on the current application context. For example, a game may have one set of actions that apply to controlling a character and another set for navigating a menu system. When these actions are grouped into two XrActionSet handles they can be selectively enabled and disabled using a single function call.
Actions are passed a handle to their XrActionSet when they are created.
Action sets are created by calling xrCreateActionSet:
The xrCreateActionSet function is defined as:
XrResult xrCreateActionSet(
XrSession session,
const XrActionSetCreateInfo* createInfo,
XrActionSet* actionSet);
The xrCreateActionSet function creates an action set and returns a handle to the created action set.
If session
is running when this call is made, the runtime must return XR_ERROR_SESSION_RUNNING
.
Additional error codes are described with XrActionSetCreateInfo.
The XrActionSetCreateInfo is defined as:
typedef struct XrActionSetCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE];
char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE];
uint32_t priority;
} XrActionSetCreateInfo;
When multiple actions are bound to the same input source, the priority
of each action set determines which
bindings are suppressed.
Runtimes must ignore bindings from action sets with a lower priority number if those specific bindings are
also present in active actions within a higher priority action set.
If multiple action sets with the same priority are bound to the same input source and that is the highest priority
number, runtimes must process all those bindings at the same time.
Two actions are considered to be bound to the same input source if they use the same identifier and optional location path segments, even if they have different component segments.
When runtimes are ignoring bindings because of priority, they must treat the binding to that input source as
though they do not exist.
That means the isActive
field must be false when retrieving action data, and that the runtime must
not provide any visual, haptic, or other feedback related to the binding of that action to that input source.
Other actions in the same action set which are bound to input sources that do not collide are not affected and are
processed as normal.
If actionSetName
or localizedActionSetName
are empty strings, the runtime must return XR_ERROR_NAME_INVALID
.
If actionSetName
or localizedActionSetName
are duplicates of the corresponding field for any existing action set in the specified session, the runtime must return XR_ERROR_NAME_DUPLICATED
.
If actionSetName
contains characters which are not allowed in a single level of a well-formed path string, the runtime must return XR_ERROR_PATH_FORMAT_INVALID
.
The xrDestroyActionSet function is defined as:
XrResult xrDestroyActionSet(
XrActionSet actionSet);
Action sets can be destroyed by calling xrDestroyActionSet.
When an action set is destroyed, all actions of that action set are also destroyed.
If the application subsequently attempts to destroy one of these actions via xrDestroyAction then XR_ERROR_HANDLE_INVALID
is returned.
11.3. Creating Actions
XR_DEFINE_HANDLE(XrAction)
Action handles are used to refer to individual actions when retrieving action data, creating action spaces, or sending haptic events.
The xrCreateAction function is defined as:
XrResult xrCreateAction(
XrActionSet actionSet,
const XrActionCreateInfo* createInfo,
XrAction* action);
xrCreateAction creates an action and returns its handle.
If the session containing actionSet
is running when this call is made, the runtime must return XR_ERROR_SESSION_RUNNING
.
The XrActionCreateInfo structure is defined as:
typedef struct XrActionCreateInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
char actionName[XR_MAX_ACTION_NAME_SIZE];
XrActionType actionType;
uint32_t countSubactionPaths;
const XrPath* subactionPaths;
char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE];
} XrActionCreateInfo;
Subaction paths are a mechanism that enables applications to use the same action name and handle on multiple devices.
Applications can query action state using subaction paths that differentiate data coming from each device.
This allows the runtime to group logically equivalent actions together in system UI.
For instance, an application could create a single pick_up
action
with the /user/hand/left and /user/hand/right subaction paths
and use the subaction paths to independently query the state of
pick_up_with_left_hand
and pick_up_with_right_hand
.
Applications can create actions with or without the subactionPaths
set to a list of paths.
If this list of paths is omitted (i.e. subactionPaths
is set to NULL
, and countSubactionPaths
is set to 0), the application is opting out of filtering action results by subaction paths and any call to get action data must also omit subaction paths.
If subactionPaths
is specified and any of the following conditions are not satisfied, the runtime must return XR_ERROR_PATH_INVALID
:
-
Each path provided is one of:
-
/user/head
-
/user/hand/left
-
/user/hand/right
-
/user/gamepad
-
/user
-
-
No path appears in the list more than once
Including /user in the list of subaction paths creates an 'other' bucket for action data to be filtered into.
When /user is included in the list passed to xrGetActionState*
the runtime must include data for all devices which are not included in the other subaction paths into the /user bucket.
Extensions may append additional top level user paths to the above list.
The runtime must return XR_ERROR_PATH_INVALID
in the following circumstances:
-
The application specified subaction paths at action creation and the application called
xrGetActionState*
or a haptic function with an empty subaction path array. -
The application called
xrGetActionState*
or a haptic function with a subaction path that was not specified when the action was created.
If actionName
or localizedActionName
are empty strings, the runtime must return XR_ERROR_NAME_INVALID
.
If actionName
or localizedActionName
are duplicates of the corresponding field for any existing action in the specified action set, the runtime must return XR_ERROR_NAME_DUPLICATED
.
If actionName
contains characters which are not allowed in a single level of a well-formed path string, the runtime must return XR_ERROR_PATH_FORMAT_INVALID
.
The XrActionType parameter takes one of the following values:
typedef enum XrActionType {
XR_INPUT_ACTION_TYPE_BOOLEAN = 1,
XR_INPUT_ACTION_TYPE_VECTOR1F = 2,
XR_INPUT_ACTION_TYPE_VECTOR2F = 3,
XR_INPUT_ACTION_TYPE_POSE = 4,
XR_OUTPUT_ACTION_TYPE_VIBRATION = 100,
XR_ACTION_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrActionType;
The xrDestroyAction function is defined as:
XrResult xrDestroyAction(
XrAction action);
Actions can be destroyed by calling xrDestroyAction. When an action is destroyed, it is removed from its associated action set. Alternatively, actions that are part of an action set are automatically destroyed when the action set is destroyed.
The runtime must ignore destroyed actions in action sets.
11.3.1. Input Actions & Output Actions
Input actions are used to read sensors like buttons or joysticks while output actions are used for triggering haptics or motion platforms. The type of action created by xrCreateAction depends on the value of the XrActionType argument.
A given action can either be used for either input or output, but not both. Input actions are queried using one of the xrGetActionState*
function calls, while output actions are set using the haptics calls.
If either call is used with an action of the wrong type XR_ERROR_ACTION_TYPE_MISMATCH
must be returned.
11.4. Suggested Bindings
Applications usually need to provide default bindings for their actions to runtimes so that input data can be mapped appropriately to the application’s actions.
Applications can do this by calling xrSetInteractionProfileSuggestedBindings for each interaction profile that the applications has default bindings for.
If bindings are provided for an appropriate interaction profile, the runtime will select one and input will begin to flow.
Applications can call xrGetCurrentInteractionProfile during on a running session to learn what the active interaction profile are for a top level user path.
If this value ever changes, the runtime must send an XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED
event to the application to indicate that the value should be queried again.
The bindings suggested by this system are only a hint to the runtime. Some runtimes may choose to use a different device binding depending on user preference, accessibility settings, or for any other reason. If the runtime is using the values provided by suggested bindings, it must make a best effort to convert the input value to the created action and apply certain rules to that use so that suggested bindings function in the same way across runtimes.
For actions created with XR_INPUT_ACTION_TYPE_BOOLEAN
when the runtime is obeying suggested bindings: Boolean input sources are bound directly to the action.
If the path is to a scalar value, a threshold must be applied to the value
and values over that threshold will be true.
The threshold may vary from device to device or component to
component and is left as an implementation detail.
If the path refers to the parent of input values instead of
to an input value itself, the runtime must use …/example/path/value instead of …/example/path if it
is available and apply the same thresholding that would be applied to any scalar input. If a parent path does not have
a …/value subpath, the runtime must use …/click.
In any other situation the runtime would need
to provide an alternate binding for the action or it will be unbound.
For actions created with XR_INPUT_ACTION_TYPE_VECTOR1F
when the runtime is obeying suggested
bindings: If the input value specified by the path is scalar, the input value is bound directly to the
vector.
If the path refers to the parent of input values instead of to an input value itself, the runtime must
use /example/path/value instead of …/example/path as the source of the value. If the input value is
boolean, the runtime must supply 0.0 or 1.0 as a conversion of the boolean value. In any other
situation, the runtime would need to provide an alternate binding for the action or it will be unbound.
For actions created with XR_INPUT_ACTION_TYPE_VECTOR2F
when the runtime is obeying suggested
bindings: The suggested binding path must refer to the parent of input values instead of to the input values
themselves, and that parent path must contain subpaths …/x and …/y. …/x
and …/y must be bound to 'x' and 'y' of the vector, respectively.
In any other situation, the runtime would need to provide an alternate binding for the action or it will
be unbound.
For actions created with XR_INPUT_ACTION_TYPE_POSE
when the runtime is obeying suggested
bindings: Pose input sources are bound directly to the action. If the path refers to the parent of input values instead of
to an input value itself, the runtime must; use …/example/path/pose instead of /example/path if it
is available. In any other situation the runtime would need to provide an alternate binding for the action or it will be unbound.
The XrEventDataInteractionProfileChanged structure is defined as:
typedef struct XrEventDataInteractionProfileChanged {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrEventDataInteractionProfileChanged;
The XrEventDataInteractionProfileChanged event is sent to the application to notify it that the active input form factor for one or more top level user paths has changed. This event must only be sent for interaction profiles that the application indicated its support for via xrSetInteractionProfileSuggestedBindings. This event must only be sent for running sessions.
The application can call xrGetCurrentInteractionProfile if it wants to change its own behavior based on the active hardware.
The function xrSetInteractionProfileSuggestedBindings is defined as:
XrResult xrSetInteractionProfileSuggestedBindings(
XrSession session,
const XrInteractionProfileSuggestedBinding* suggestedBindings);
xrSetInteractionProfileSuggestedBindings sets an interaction profile for which the application can provide default bindings. The application can call xrSetInteractionProfileSuggestedBindings once per interaction profile that it supports.
The application can provide any number of bindings for each action.
If the provided session is running, the runtime must return XR_ERROR_SESSION_RUNNING
.
If the application has already called xrSetInteractionProfileSuggestedBindings on this session for this interaction profile, the runtime must return XR_ERROR_BINDINGS_DUPLICATED
.
See suggested bindings for more details.
The XrInteractionProfileSuggestedBinding structure is defined as:
typedef struct XrInteractionProfileSuggestedBinding {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrPath interactionProfile;
uint32_t countSuggestedBindings;
const XrActionSuggestedBinding* suggestedBindings;
} XrInteractionProfileSuggestedBinding;
The XrActionSuggestedBinding structure is defined as:
typedef struct XrActionSuggestedBinding {
XrAction action;
XrPath binding;
} XrActionSuggestedBinding;
The xrGetCurrentInteractionProfile is defined as:
XrResult xrGetCurrentInteractionProfile(
XrSession session,
XrPath topLevelUserPath,
XrInteractionProfileInfo* interactionProfile);
xrGetCurrentInteractionProfile asks the runtime for the active interaction profiles for a top level user path.
The runtime must return only interaction profiles for which the application has provided bindings with xrSetInteractionProfileSuggestedBindings. The runtime may return interaction profiles that do not represent physically present hardware, for example if the runtime is using a known interaction profile to bind to hardware that the application is not aware of.
If the provided session is not running, the runtime must return XR_ERROR_SESSION_NOT_RUNNING
.
The XrInteractionProfileInfo structure is defined as:
typedef struct XrInteractionProfileInfo {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrPath interactionProfile;
} XrInteractionProfileInfo;
The runtime must only include interaction profiles that the application has provided bindings for via xrSetInteractionProfileSuggestedBindings or XR_PATH_NULL
.
If the runtime is rebinding an interaction profile provided by the application to a device that the application did not provide bindings for, it must return the interaction profile path that it is emulating.
If the runtime is unable to provide input because it cannot emulate any of the application-provided interaction profiles, it must return XR_PATH_NULL
.
11.5. Reading Input Action State
The current state of an input action can be obtained by calling the xrGetActionState*
function call that matches the XrActionType provided when the action was created.
If a mismatched call is used to retrieve the state XR_ERROR_ACTION_TYPE_MISMATCH
must be returned.
The results of calls to xrGetActionState*
for an XrAction and set of subaction paths generally
does not change between calls to xrSyncActionData.
When the combination of the parent XrActionSet and subaction path for an action is passed to
xrSyncActionData, the runtime must update the results from xrGetActionState*
after
this call with any changes to the state of the underlying hardware.
When the parent action set and subaction path for an action is removed from or added to the list of active
action sets passed to xrSyncActionData, the runtime must update isActive
to reflect the new
active state after this call.
In all cases the runtime must not change the results of xrGetActionState*
calls between calls
to xrSyncActionData.
For any call to xrGetActionState*
or haptics functions, if the parent session of the supplied XrAction is not running, the runtime must return XR_ERROR_SESSION_NOT_RUNNING
.
When retrieving action state, lastChangeTime
must be set to the runtime’s best estimate of when the
physical state of the part of the device bound to that action last changed.
The changedSinceLastSync
value is calculated based on the state at the previous sync and the state of the current sync. If there is no previous sync, the changedSinceLastSync
value must be set to false.
The isActive
value must be true whenever an action is bound and a source is providing state data for the
current sync. If the action is unbound or no source is present, the isActive
value must be false.
For any action which is inactive, the runtime must return zero (or false) for state, false for
changedSinceLastSync
, and 0 for lastChangeTime
.
11.5.1. Resolving a single action bound to multiple inputs or outputs
It is often the case that a single action will be bound to multiple physical inputs simultaneously. In these circumstances, the runtime must resolve the ambiguity in that multiple binding as follows:
The current state value is selected based on the type of the action:
-
Boolean actions - The current state must be the result of a boolean Or of all bound inputs
-
Vector1 and Vector2 actions - The current state must be the state of the input with the longest length
-
Pose actions - The runtime must select a single pose source when the action is created or bound and use that value consistently. The runtime should use subaction paths specified by the application to make this choice where possible.
-
Haptic actions - The runtime must send output events to all bound haptic devices
11.5.2. Boolean Actions
The xrGetActionStateBoolean function is defined as:
XrResult xrGetActionStateBoolean(
XrAction action,
uint32_t countSubactionPaths,
const XrPath* subactionPaths,
XrActionStateBoolean* data);
xrGetActionStateBoolean retrieves the current state of a boolean action. See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
The XrActionStateBoolean structure is defined as:
typedef struct XrActionStateBoolean {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrBool32 currentState;
XrBool32 changedSinceLastSync;
XrTime lastChangeTime;
XrBool32 isActive;
} XrActionStateBoolean;
See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
11.5.3. Vector Actions
The xrGetActionStateVector1f function is defined as:
XrResult xrGetActionStateVector1f(
XrAction action,
uint32_t countSubactionPaths,
const XrPath* subactionPaths,
XrActionStateVector1f* data);
xrGetActionStateVector1f retrieves the current state of a one-dimensional vector action. See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
The XrActionStateVector1f structure is defined as:
typedef struct XrActionStateVector1f {
XrStructureType type;
void* XR_MAY_ALIAS next;
float currentState;
XrBool32 changedSinceLastSync;
XrTime lastChangeTime;
XrBool32 isActive;
} XrActionStateVector1f;
The xrGetActionStateVector2f function is defined as:
XrResult xrGetActionStateVector2f(
XrAction action,
uint32_t countSubactionPaths,
const XrPath* subactionPaths,
XrActionStateVector2f* data);
xrGetActionStateVector2f retrieves the current state of a two-dimensional vector action. See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
The XrActionStateVector2f structure is defined as:
typedef struct XrActionStateVector2f {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrVector2f currentState;
XrBool32 changedSinceLastSync;
XrTime lastChangeTime;
XrBool32 isActive;
} XrActionStateVector2f;
11.5.4. Pose Actions
The xrGetActionStatePose function is defined as:
XrResult xrGetActionStatePose(
XrAction action,
XrPath subactionPath,
XrActionStatePose* data);
xrGetActionStatePose returns information about the binding and active state for the specified action. To determine the pose of this action at a historical or predicted time, create an action space using xrCreateActionSpace. Then, after each sync, get the pose of this action space within your base space using xrLocateSpace.
See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use. xrGetActionStatePose only accepts a single subaction path to require that the application choose which subaction to use for actions that are intended to be bound to multiple devices at the same time.
The XrActionStatePose structure is defined as:
typedef struct XrActionStatePose {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrBool32 isActive;
} XrActionStatePose;
11.6. Output Actions and Haptics
Haptic feedback is sent to a device using the xrApplyHapticFeedback
function. The hapticEvent
points to a supported event structure. All
event structures have in common that the first element is an XrHapticBaseHeader
which can be used to determine the type of the haptic event.
Haptic feedback may be immediately halted for a haptic action using the xrStopHapticFeedback function.
Output action requests activate immediately and must not wait for the next call to xrSyncActionData.
If a haptic event is sent to an action before a previous haptic event completes, the latest event will take precedence and the runtime must cancel all preceding incomplete haptic events on that action.
Output action requests must be discarded and have no effect on hardware if the application’s session is not active.
The only haptics type supported by unextended OpenXR is XrHapticVibration.
The xrApplyHapticFeedback function is defined as:
XrResult xrApplyHapticFeedback(
XrAction hapticAction,
uint32_t countSubactionPaths,
const XrPath* subactionPaths,
const XrHapticBaseHeader* hapticEvent);
Triggers a haptic event through the specified action of type XR_TYPE_ACTION_STATE_POSE
.
The runtime should deliver this request to the appropriate device, but exactly which device, if any, this event is sent to is up to the runtime to decide.
If an appropriate device is unavailable the runtime may ignore this request for haptic feedback.
If another haptic event from this session is currently happening on the device bound to this action, the runtime must interrupt that other event and replace it with the new one.
See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
The XrHapticBaseHeader structure is defined as:
typedef struct XrHapticBaseHeader {
XrStructureType type;
const void* XR_MAY_ALIAS next;
} XrHapticBaseHeader;
The XrHapticVibration structure is defined as:
typedef struct XrHapticVibration {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrDuration duration;
float frequency;
float amplitude;
} XrHapticVibration;
The XrHapticVibration is used in calls to xrApplyHapticFeedback that trigger vibration
output actions.
The duration
, and frequency
parameters may be clamped to implementation-dependent ranges.
XR_MIN_HAPTIC_DURATION is used to indicate to the runtime that a short haptic pulse of the minimal supported duration for the haptic device.
#define XR_MIN_HAPTIC_DURATION -1
XR_FREQUENCY_UNSPECIFIED is used to indicate that the application wants the runtime to decide what the optimal frequency is for the haptic pulse.
#define XR_FREQUENCY_UNSPECIFIED 0
The xrStopHapticFeedback function is defined as:
XrResult xrStopHapticFeedback(
XrAction hapticAction,
uint32_t countSubactionPaths,
const XrPath* subactionPaths);
If a haptic event from this XrAction is in progress, when this function is called the runtime must stop that event. See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
11.7. Input Action State Synchronization
The xrSyncActionData function is defined as:
XrResult xrSyncActionData(
XrSession session,
uint32_t countActionSets,
const XrActiveActionSet* actionSets);
xrSyncActionData updates the current state of input actions. Repeated input action state queries between subsequent synchronization calls must return the same values. This call must be called with an array containing the XrActiveActionSet structures, that reference action sets which belong to a single, running session, that should be updated during this synchronization. Any XrActionSet that has been created in this session but was not passed to xrSyncActionData will not be updated and all action state queries will return that the action is inactive.
If session
is not running, the runtime must return XR_ERROR_SESSION_NOT_RUNNING
.
If session
is not focused, the runtime must return XR_SESSION_NOT_FOCUSED
, and all actions in the session
will be inactive.
The XrActiveActionSet structure is defined as:
typedef struct XrActiveActionSet {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrActionSet actionSet;
XrPath subactionPath;
} XrActiveActionSet;
This structure defines a single active action set and subaction path combination. Applications provide a list of these structures via the xrSyncActionData function.
11.8. Action Sources
The xrGetBoundSourcesForAction function is defined as:
XrResult xrGetBoundSourcesForAction(
XrAction action,
uint32_t sourceCapacityInput,
uint32_t* sourceCountOutput,
XrPath* sources);
An application can use the xrGetBoundSourcesForAction and
xrGetInputSourceLocalizedName calls to prompt the user which physical inputs
to use in order to perform an action.
A source is the physical control that the action is bound to.
An action may be bound to multiple sources at one time, for example an action
named hold
could be bound to both the X and A buttons.
If an action is unbound, xrGetBoundSourcesForAction will assign 0 to the
value pointed-to by sourceCountOutput
and not modify the array.
Once the semantic paths for the action’s source are obtained, the application can gather additional information about the source. xrGetInputSourceLocalizedName returns a localized human-readable string describing the source, e.g. 'A Button'.
If the parent session of action
is not running, the runtime must return XR_ERROR_SESSION_NOT_RUNNING
.
The xrGetInputSourceLocalizedName function is defined as:
XrResult xrGetInputSourceLocalizedName(
XrSession session,
XrPath source,
XrInputSourceLocalizedNameFlags whichComponents,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer);
xrGetInputSourceLocalizedName returns a string for the input source in the current system locale. This string is appropriate for showing to users.
The xrGetInputSourceLocalizedName::whichComponents
parameter takes bitwise-OR of any of the following values:
// Flag bits for XrInputSourceLocalizedNameFlags
static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT = 0x00000001;
static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT = 0x00000002;
static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT = 0x00000004;
12. List of Extensions
12.1. XR_KHR_android_create_instance
- Name String
-
XR_KHR_android_create_instance
- Extension Type
-
Instance extension
- Registered Extension Number
-
9
- Revision
-
2
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Robert Menzel, NVIDIA
Martin Renschler, Qualcomm
Overview
When the application creates an XrInstance object on Android systems, additional information from the application has to be provided to the XR runtime.
The Android XR runtime must return error XR_ERROR_VALIDATION_FAILURE
if the additional information is not provided by the application or if the additional parameters are invalid.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR
New Enums
New Structures
The XrInstanceCreateInfoAndroidKHR structure is defined as:
typedef struct XrInstanceCreateInfoAndroidKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
void* XR_MAY_ALIAS applicationVM;
void* XR_MAY_ALIAS applicationActivity;
} XrInstanceCreateInfoAndroidKHR;
XrInstanceCreateInfoAndroidKHR contains additional Android specific information needed when calling xrCreateInstance.
The XrInstanceCreateInfoAndroidKHR struct must be provided as the next
pointer in the XrInstanceCreateInfo struct when calling xrCreateInstance.
New Functions
Issues
Version History
-
Revision 1, 2017-05-26 (Robert Menzel)
-
Initial draft
-
-
Revision 2, 2019-01-24 (Martin Renschler)
-
Added error code, reformatted
-
12.2. XR_KHR_android_surface_swapchain
- Name String
-
XR_KHR_android_surface_swapchain
- Extension Type
-
Instance extension
- Registered Extension Number
-
5
- Revision
-
4
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Krzysztof Kosiński
Johannes van Waveren, Oculus
Martin Renschler, Qualcomm - Contacts
-
Krzysztof Kosiński
Overview
A common activity in XR is to view an image stream.
Image streams are often the result of camera previews or decoded video streams.
On Android, the basic primitive representing the producer end of an image queue is the class android.view.Surface
.
This extension provides a special swapchain that uses an android.view.Surface
as its producer end.
New Object Types
New Flag Types
New Enum Constants
New Enums
New Structures
New Functions
To create an XrSwapchain object and an Android Surface object call:
XrResult xrCreateSwapchainAndroidSurfaceKHR(
XrSession session,
const XrSwapchainCreateInfo* info,
XrSwapchain* swapchain,
jobject* surface);
xrCreateSwapchainAndroidSurfaceKHR creates an XrSwapchain object returned in swapchain
and an Android Surface jobject
returned in surface
.
The jobject
must be valid to be passed back to Java code using JNI and must be valid to be used
with ordinary Android APIs for submitting images to Surfaces.
The returned XrSwapchain must be valid to be referenced in XrSwapchainSubImage structures to show content on the screen.
The width and height passed in XrSwapchainCreateInfo may not be persistent throughout the life cycle of the created swapchain, since on Android,
the size of the images is controlled by the producer and possibly changes at any time.
The only function that is allowed to be called on the XrSwapchain returned from this function is xrDestroySwapchain. For example calling any of the functions xrEnumerateSwapchainImages, xrAcquireSwapchainImage, xrWaitSwapchainImage or xrReleaseSwapchainImage is invalid.
The XR runtime must destroy the provided Surface on calling xrDestroySwapchain. Applications writing frames to the Surface thereafter leads to undefined behavior.
xrCreateSwapchainAndroidSurfaceKHR must return the same set of error codes as xrCreateSwapchain under same circumstances plus XR_ERROR_FUNCTION_UNSUPPORTED
in case the function is not supported.
Issues
Version History
-
Revision 1, 2017-01-17 (Johannes van Waveren)
-
Initial draft
-
-
Revision 2, 2017-10-30 (Kaye Mason)
-
Changed images to swapchains, used snippet includes. Added issue for Surfaces.
-
-
Revision 3, 2018-05-16 (Krzysztof Kosiński)
-
Refactored to use Surface instead of SurfaceTexture.
-
-
Revision 4, 2019-01-24 (Martin Renschler)
-
Refined the specification of the extension
-
12.3. XR_KHR_android_thread_settings
- Name String
-
XR_KHR_android_thread_settings
- Extension Type
-
Instance extension
- Registered Extension Number
-
4
- Revision
-
4
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Cass Everitt, Oculus
Johannes van Waveren, Oculus
Martin Renschler, Qualcomm
Overview
For XR to be comfortable, it is important for applications to deliver frames quickly and consistently. In order to make sure the important application threads get their full share of time, these threads must be identified to the system, which will adjust their scheduling priority accordingly.
New Object Types
New Flag Types
New Enum Constants
XrResult enumeration is extended with:
-
XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR
-
XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR
New Enums
The possible thread types are specified by the XrAndroidThreadTypeKHR enumeration:
typedef enum XrAndroidThreadTypeKHR {
XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
} XrAndroidThreadTypeKHR;
New Structures
New Functions
To declare a thread to be of a certain XrAndroidThreadTypeKHR type call:
XrResult xrSetAndroidApplicationThreadKHR(
XrSession session,
XrAndroidThreadTypeKHR threadType,
uint32_t threadId);
xrSetAndroidApplicationThreadKHR allows to declare an XR-critical thread and to classify it.
Version History
-
Revision 1, 2017-01-17 (Johannes van Waveren)
-
Initial draft.
-
-
Revision 2, 2017-10-31 (Armelle Laine)
-
Move the performance settings to EXT extension.
-
-
Revision 3, 2018-12-20 (Paul Pedriana)
-
Revised the error code naming to use KHR and renamed xrSetApplicationThreadKHR → xrSetAndroidApplicationThreadKHR.
-
-
Revision 4, 2019-01-24 (Martin Renschler)
-
Added enum specification, reformatting
-
12.4. XR_KHR_composition_layer_cube
- Name String
-
XR_KHR_composition_layer_cube
- Extension Type
-
Instance extension
- Registered Extension Number
-
7
- Revision
-
8
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Johannes van Waveren, Oculus
Cass Everitt, Oculus
Paul Pedriana, Oculus
Gloria Kennickell, Oculus
Sam Martin, ARM
Kaye Mason, Google, Inc.
Martin Renschler, Qualcomm - Contacts
-
Cass Everitt, Oculus
Paul Pedriana, Oculus
Overview
This extension adds an additional layer type that enables direct sampling from cubemaps.
The cube layer is the natural layer type for hardware accelerated environment maps. Without updating the image source, the user can look all around, and the compositor can display what they are looking at without intervention from the application.
The offset parameter in this layer type allows for an off-center projection of samples in the cubemap, which allows the distribution to be biased in a favored direction. This is useful for having a cubemap have very high quality in one direction, but whose quality fades as you look away from the interesting direction. A typical use case is video playback or high resolution forward image viewing.
The magnitude of the offset vector determines the magnitude of the directional bias. The offset vector must be added to the normalized direction vector before sampling the texture, and thus forms a modified direction vector. An example is shown below in which a Z offset results in greater sampling density in the -Z direction, but lower in the +Z direction. A cubemap used with this offset would typically be generated by the inverse of this offset mapping.
-Z +-----------------------------+ +-----------------------------+ | \ | | | | \ | | \ | | \ | | \ | | \ | | \ | | \ | offset { 0, 0, 0.2 } | \ | | + | --------------------> | + | | | | | | | | | | | | | | | | | | | | | +-----------------------------+ +-----------------------------+ +Z
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_COMPOSITION_LAYER_CUBE_KHR
New Enums
New Structures
The XrCompositionLayerCubeKHR structure is defined as:
typedef struct XrCompositionLayerCubeKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
XrEyeVisibility eyeVisibility;
XrSwapchain swapchain;
uint32_t imageArrayIndex;
XrQuaternionf orientation;
XrVector3f offset;
} XrCompositionLayerCubeKHR;
XrCompositionLayerCubeKHR contains the information needed to render a cube map when calling xrEndFrame. XrCompositionLayerCubeKHR is an alias type for the base struct XrCompositionLayerBaseHeader used in XrFrameEndInfo.
New Functions
Issues
Version History
-
Revision 0, 2017-02-01 (Johannes van Waveren)
-
Initial draft.
-
-
Revision 1, 2017-05-19 (Sam Martin)
-
Initial draft, moving the 3 layer types to an extension.
-
-
Revision 2, 2017-08-30 (Paul Pedriana)
-
Updated the specification.
-
-
Revision 3, 2017-10-12 (Cass Everitt)
-
Updated to reflect per-eye structs and the change to swapchains
-
-
Revision 4, 2017-10-18 (Kaye Mason)
-
Update to flatten structs to remove per-eye arrays.
-
-
Revision 5, 2017-12-05 (Paul Pedriana)
-
Updated to break out the cylinder and equirect features into separate extensions.
-
-
Revision 6, 2017-12-07 (Paul Pedriana)
-
Updated to use transform components instead of transform matrices.
-
-
Revision 7, 2017-12-07 (Paul Pedriana)
-
Updated to convert XrPosef to XrQuaternionf (there’s no position component).
-
-
Revision 8, 2019-01-24 (Martin Renschler)
-
Updated struct to use XrSwapchainSubImage, reformat and spec language changes, eye parameter description update
-
12.5. XR_KHR_composition_layer_cylinder
- Name String
-
XR_KHR_composition_layer_cylinder
- Extension Type
-
Instance extension
- Registered Extension Number
-
18
- Revision
-
4
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
James Hughes, Oculus
Paul Pedriana, Oculus
Martin Renschler, Qualcomm - Contacts
-
Paul Pedriana, Oculus
Cass Everitt, Oculus
Overview
This extension adds an additional layer type where the XR runtime must map a texture stemming from a swapchain onto the inside of a cylinder section. It can be imagined much the same way a curved television display looks to a viewer. This is not a projection type of layer but rather an object-in-world type of layer, similar to XrCompositionLayerQuad. Only the interior of the cylinder surface must be visible; the exterior of the cylinder is not visible and must not be drawn by the runtime.
The cylinder characteristics are specified by the following parameters:
XrPosef pose;
float radius;
float centralAngle;
float aspectRatio;
These can be understood via the following diagram, which is a top-down view of a horizontally oriented cylinder. The aspect ratio drives how tall the cylinder will appear based on the other parameters. Typically the aspectRatio would be set to be the aspect ratio of the texture being used, so that it looks the same within the cylinder as it does in 2D.
-z +y U=0 +--+--+ U=1 +-----------------+ - V=0 +---+ | +---+ | | | +--+ \ | / +--+ | | | +-+ \ / +-+ | | | ++ \ a / ++ | | | ++ \---/ ++ | -x +x | | | \ / | +--------p--------+ | +-------------p------r------+ +x | | | (+y is out of screen) | | | | | | r = Radius | | | a = Central Angle (0,2*Pi) | | | p = Pose Transform +-----------------+ - V=1 U/V = UV Coordinates -y
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR
New Enums
New Structures
The XrCompositionLayerCylinderKHR structure is defined as:
typedef struct XrCompositionLayerCylinderKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
XrEyeVisibility eyeVisibility;
XrSwapchainSubImage subImage;
XrPosef pose;
float radius;
float centralAngle;
float aspectRatio;
} XrCompositionLayerCylinderKHR;
XrCompositionLayerCylinderKHR contains the information needed to render a texture onto a cylinder when calling xrEndFrame. XrCompositionLayerCylinderKHR is an alias type for the base struct XrCompositionLayerBaseHeader used in XrFrameEndInfo.
New Functions
Issues
Version History
-
Revision 1, 2017-05-19 (Paul Pedriana)
-
Initial version. This was originally part of a single extension which supported multiple such extension layer types.
-
-
Revision 2, 2017-12-07 (Paul Pedriana)
-
Updated to use transform components instead of transform matrices.
-
-
Revision 3, 2018-03-05 (Paul Pedriana)
-
Added improved documentation and brought the documentation in line with the existing core spec.
-
-
Revision 4, 2019-01-24 (Martin Renschler)
-
Reformatted, spec language changes, eye parameter description update
-
12.6. XR_KHR_composition_layer_depth
- Name String
-
XR_KHR_composition_layer_depth
- Extension Type
-
Instance extension
- Registered Extension Number
-
11
- Revision
-
5
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Paul Pedriana, Oculus
Bryce Hutchings, Microsoft
Andreas Loeve Selvik, Arm
Martin Renschler, Qualcomm
Overview This extension defines an extra layer type which allows applications to submit valid depth buffers along with images submitted in projection layers, i.e. XrCompositionLayerProjection.
The XR runtime may use this information to perform more accurate reprojections taking depth into account.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR
New Enums
New Structures
When submitting depth buffers along with projection layers, add the XrCompositionLayerDepthInfoKHR to the next
chain
for all XrCompositionLayerProjectionView structures in the given layer.
The XrCompositionLayerDepthInfoKHR structure is defined as:
typedef struct XrCompositionLayerDepthInfoKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrSwapchainSubImage subImage;
float minDepth;
float maxDepth;
float nearZ;
float farZ;
} XrCompositionLayerDepthInfoKHR;
XrCompositionLayerDepthInfoKHR contains the information needed to specify an extra layer with depth information. When submitting depth buffers along with projection layers, add the XrCompositionLayerDepthInfoKHR to the next
chain
for all XrCompositionLayerProjectionView structures in the given layer.
New Functions
Issues
Version History
-
Revision 1, 2017-08-18 (Paul Pedriana)
-
Initial proposal.
-
-
Revision 2, 2017-10-30 (Kaye Mason)
-
Migration from Images to Swapchains.
-
-
Revision 3, 2018-07-20 (Bryce Hutchings)
-
Support for swapchain texture arrays
-
-
Revision 4, 2018-12-17 (Andreas Loeve Selvik)
-
depthImageRect in pixels instead of UVs
-
-
Revision 5, 2019-01-24 (Martin Renschler)
-
changed depthSwapchain/depthImageRect/depthImageArrayIndex
to XrSwapchainSubImage -
reformat and spec language changes
-
removed vendor specific terminology
-
12.7. XR_KHR_composition_layer_equirect
- Name String
-
XR_KHR_composition_layer_equirect
- Extension Type
-
Instance extension
- Registered Extension Number
-
19
- Revision
-
3
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Johannes van Waveren, Oculus
Cass Everitt, Oculus
Paul Pedriana, Oculus
Gloria Kennickell, Oculus
Martin Renschler, Qualcomm - Contacts
-
Cass Everitt, Oculus
Paul Pedriana, Oculus
Overview
This extension adds an additional layer type where the XR runtime must map an equirectangular coded image stemming from a swapchain onto the inside of a sphere.
The equirect layer type provides most of the same benefits as a cubemap, but from an equirect 2D image source. This image source is appealing mostly because equirect environment maps are very common, and the highest quality you can get from them is by sampling them directly in the compositor.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR
New Enums
New Structures
The XrCompositionLayerEquirectKHR structure is defined as:
typedef struct XrCompositionLayerEquirectKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
XrEyeVisibility eyeVisibility;
XrSwapchainSubImage subImage;
XrPosef pose;
XrVector3f offset;
XrVector2f scale;
XrVector2f bias;
} XrCompositionLayerEquirectKHR;
XrCompositionLayerEquirectKHR contains the information needed to render an equirectangular image onto a sphere when calling xrEndFrame. XrCompositionLayerEquirectKHR is an alias type for the base struct XrCompositionLayerBaseHeader used in XrFrameEndInfo.
New Functions
Issues
Version History
-
Revision 1, 2017-05-19 (Paul Pedriana)
-
Initial version. This was originally part of a single extension which supported multiple such extension layer types.
-
-
Revision 2, 2017-12-07 (Paul Pedriana)
-
Updated to use transform components instead of transform matrices.
-
-
Revision 3, 2019-01-24 (Martin Renschler)
-
Reformatted, spec language changes, eye parameter description update
-
12.8. XR_KHR_convert_timespec_time
- Name String
-
XR_KHR_convert_timespec_time
- Extension Type
-
Instance extension
- Registered Extension Number
-
37
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Paul Pedriana, Oculus
Overview
This extension provides two functions for converting between timespec monotonic time and XrTime
.
The xrConvertTimespecTimeToTimeKHR function converts from timespec time to XrTime
, while the xrConvertTimeToTimespecTimeKHR function converts XrTime
to timespec monotonic time.
The primary use case for this functionality is to be able to synchronize events between the local system and the OpenXR system.
New Object Types
New Flag Types
New Enum Constants
New Enums
New Structures
New Functions
To convert from timespec monotonic time to basetype::XrTime, call:
XrResult xrConvertTimespecTimeToTimeKHR(
XrInstance instance,
const struct timespec* timespecTime,
XrTime* time);
The xrConvertTimespecTimeToTimeKHR function converts a time obtained by the clock_gettime
function to the equivalent basetype::XrTime.
To convert from basetype::XrTime to timespec monotonic time, call:
XrResult xrConvertTimeToTimespecTimeKHR(
XrInstance instance,
XrTime time,
struct timespec* timespecTime);
The xrConvertTimeToTimespecTimeKHR function converts an basetype::XrTime to time as if generated by clock_gettime
.
Issues
Version History
-
Revision 1, 2019-01-24 (Paul Pedriana)
-
Initial draft
-
12.9. XR_KHR_D3D10_enable
- Name String
-
XR_KHR_D3D10_enable
- Extension Type
-
Instance extension
- Registered Extension Number
-
27
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2018-11-16
- IP Status
-
No known IP claims.
- Contributors
-
Paul Pedriana, Oculus
Bryce Hutchings, Microsoft
Mark Young, LunarG
Minmin Gong, Microsoft
Overview
This extension enables the use of the D3D10 graphics API in an OpenXR runtime. Without this extension, the OpenXR runtime may not be able to use any D3D10 swapchain images.
This extension provides the mechanisms necessary for an application to generate a valid XrGraphicsBindingD3D10KHR structure in order to create a D3D10-based XrSession. Note that during this process the application is responsible for creating all the required D3D10 objects, including a graphics device to be used for rendering.
This extension also provides mechanisms for the application to interact with images acquired by calling xrEnumerateSwapchainImages.
In order to expose the structures, types, and functions of this extension,
you must define
XR_USE_GRAPHICS_API_D3D10
before including the OpenXR platform header openxr_platform.h
,
in all portions of your library or application that include it.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D10_KHR
-
XR_TYPE_GRAPHICS_BINDING_D3D10_KHR
-
XR_TYPE_SWAPCHAIN_IMAGE_D3D10_KHR
New Enums
New Structures
The following structures are provided to supply supporting runtimes the necessary information required to work with the D3D10 API executing on certain operating systems.
The XrGraphicsBindingD3D10KHR structure is defined as:
typedef struct XrGraphicsBindingD3D10KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
ID3D10Device* device;
} XrGraphicsBindingD3D10KHR;
When creating a D3D10-backed XrSession, the application will provide
a pointer to an XrGraphicsBindingD3D10KHR in the next
chain of the
XrSessionCreateInfo.
The XrSwapchainImageD3D10KHR structure is defined as:
typedef struct XrSwapchainImageD3D10KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
ID3D10Texture2D* texture;
} XrSwapchainImageD3D10KHR;
If a given session was created with XrGraphicsBindingD3D10KHR, the following conditions must apply.
-
Calls to xrEnumerateSwapchainImages on an XrSwapchain in that session must return an array of XrSwapchainImageD3D10KHR structures.
-
Whenever an OpenXR function accepts an XrSwapchainImageBaseHeader pointer as a parameter in that session, the runtime must also accept a pointer to an XrSwapchainImageD3D10KHR.
The OpenXR runtime must interpret the top-left corner of the swapchain image as the coordinate origin unless specified otherwise by extension functionality.
The OpenXR runtime must interpret the swapchain images in a clip space of positive Y pointing up, near Z plane at 0, and far Z plane at 1.
The XrGraphicsRequirementsD3D10KHR structure is defined as:
typedef struct XrGraphicsRequirementsD3D10KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
LUID adapterLuid;
D3D10_FEATURE_LEVEL1 minFeatureLevel;
} XrGraphicsRequirementsD3D10KHR;
XrGraphicsRequirementsD3D10KHR is populated by xrGetD3D10GraphicsRequirementsKHR.
New Functions
Some computer systems may have multiple graphics devices, each of which may have independent external display outputs. XR systems that connect to such graphics devices are typically connected to a single device. Applications need to know what graphics device the XR system is connected to so that they can use that graphics device to generate XR images.
To retrieve the D3D10 feature level and graphics device for an instance and system, call:
XrResult xrGetD3D10GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D10KHR* graphicsRequirements);
The xrGetD3D10GraphicsRequirementsKHR function identifies to the application what graphics device
(Windows LUID) needs to be used and the minimum feature level to use.
xrGetD3D10GraphicsRequirementsKHR has to be called prior to calling xrCreateSession,
and the LUID and feature level that xrGetD3D10GraphicsRequirementsKHR returns should be used
to create the ID3D10Device
that the application passes to
xrCreateSession in the XrGraphicsBindingD3D10KHR.
Issues
Version History
-
Revision 1, 2018-05-07 (Mark Young)
-
Initial draft
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Split
XR_KHR_D3D_enable
intoXR_KHR_D3D10_enable
-
Rename and expand
xrGetD3DGraphicsDeviceKHR
functionality toxrGetD3D10GraphicsRequirementsKHR
-
-
Revision 3, 2018-11-15 (Paul Pedriana)
-
Specified the swapchain texture coordinate origin.
-
-
Revision 4, 2018-11-16 (Minmin Gong)
-
Specified Y direction and Z range in clip space
-
12.10. XR_KHR_D3D11_enable
- Name String
-
XR_KHR_D3D11_enable
- Extension Type
-
Instance extension
- Registered Extension Number
-
28
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2018-11-16
- IP Status
-
No known IP claims.
- Contributors
-
Bryce Hutchings, Microsoft
Paul Pedriana, Oculus
Mark Young, LunarG
Minmin Gong, Microsoft
Overview
This extension enables the use of the D3D11 graphics API in an OpenXR runtime. Without this extension, the OpenXR runtime may not be able to use any D3D11 swapchain images.
This extension provides the mechanisms necessary for an application to generate a valid XrGraphicsBindingD3D11KHR structure in order to create a D3D11-based XrSession. Note that during this process the application is responsible for creating all the required D3D11 objects, including a graphics device to be used for rendering.
This extension also provides mechanisms for the application to interact with images acquired by calling xrEnumerateSwapchainImages.
In order to expose the structures, types, and functions of this extension,
you must define
XR_USE_GRAPHICS_API_D3D11
before including the OpenXR platform header openxr_platform.h
,
in all portions of your library or application that include it.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR
-
XR_TYPE_GRAPHICS_BINDING_D3D11_KHR
-
XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR
New Enums
New Structures
The following structures are provided to supply supporting runtimes the necessary information required to work with the D3D11 API executing on certain operating systems.
The XrGraphicsBindingD3D11KHR structure is defined as:
typedef struct XrGraphicsBindingD3D11KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
ID3D11Device* device;
} XrGraphicsBindingD3D11KHR;
When creating a D3D11-backed XrSession, the application will provide
a pointer to an XrGraphicsBindingD3D11KHR in the next
chain of the
XrSessionCreateInfo.
The XrSwapchainImageD3D11KHR structure is defined as:
typedef struct XrSwapchainImageD3D11KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
ID3D11Texture2D* texture;
} XrSwapchainImageD3D11KHR;
If a given session was created with XrGraphicsBindingD3D11KHR, the following conditions must apply.
-
Calls to xrEnumerateSwapchainImages on an XrSwapchain in that session must return an array of XrSwapchainImageD3D11KHR structures.
-
Whenever an OpenXR function accepts an XrSwapchainImageBaseHeader pointer as a parameter in that session, the runtime must also accept a pointer to an XrSwapchainImageD3D11KHR.
The OpenXR runtime must interpret the top-left corner of the swapchain image as the coordinate origin unless specified otherwise by extension functionality.
The OpenXR runtime must interpret the swapchain images in a clip space of positive Y pointing up, near Z plane at 0, and far Z plane at 1.
The XrGraphicsRequirementsD3D11KHR structure is defined as:
typedef struct XrGraphicsRequirementsD3D11KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
LUID adapterLuid;
D3D_FEATURE_LEVEL minFeatureLevel;
} XrGraphicsRequirementsD3D11KHR;
XrGraphicsRequirementsD3D11KHR is populated by xrGetD3D11GraphicsRequirementsKHR.
New Functions
Some computer systems may have multiple graphics devices, each of which may have independent external display outputs. XR systems that connect to such graphics devices are typically connected to a single device. Applications need to know what graphics device the XR system is connected to so that they can use that graphics device to generate XR images.
To retrieve the D3D11 feature level and graphics device for an instance and system, call:
XrResult xrGetD3D11GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
The xrGetD3D11GraphicsRequirementsKHR function identifies to the application what graphics device
(Windows LUID) needs to be used and the minimum feature level to use.
xrGetD3D11GraphicsRequirementsKHR has to be called prior to calling xrCreateSession,
and the LUID and feature level that xrGetD3D11GraphicsRequirementsKHR returns should be used
to create the ID3D11Device
that the application passes to
xrCreateSession in the XrGraphicsBindingD3D11KHR.
Issues
Version History
-
Revision 1, 2018-05-07 (Mark Young)
-
Initial draft
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Split
XR_KHR_D3D_enable
intoXR_KHR_D3D11_enable
-
Rename and expand
xrGetD3DGraphicsDeviceKHR
functionality toxrGetD3D11GraphicsRequirementsKHR
-
-
Revision 3, 2018-11-15 (Paul Pedriana)
-
Specified the swapchain texture coordinate origin.
-
-
Revision 4, 2018-11-16 (Minmin Gong)
-
Specified Y direction and Z range in clip space
-
12.11. XR_KHR_D3D12_enable
- Name String
-
XR_KHR_D3D12_enable
- Extension Type
-
Instance extension
- Registered Extension Number
-
29
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-29
- IP Status
-
No known IP claims.
- Contributors
-
Bryce Hutchings, Microsoft
Paul Pedriana, Oculus
Mark Young, LunarG
Minmin Gong, Microsoft
Dan Ginsburg, Valve
Overview
This extension enables the use of the D3D12 graphics API in an OpenXR runtime. Without this extension, the OpenXR runtime may not be able to use any D3D12 swapchain images.
This extension provides the mechanisms necessary for an application to generate a valid XrGraphicsBindingD3D12KHR structure in order to create a D3D12-based XrSession. Note that during this process the application is responsible for creating all the required D3D12 objects, including a graphics device and queue to be used for rendering.
This extension also provides mechanisms for the application to interact with images acquired by calling xrEnumerateSwapchainImages.
In order to expose the structures, types, and functions of this extension,
you must define
XR_USE_GRAPHICS_API_D3D12
before including the OpenXR platform header openxr_platform.h
,
in all portions of your library or application that include it.
Swapchain Image Layout
When an application acquires a swapchain image by calling xrAcquireSwapchainImage in a session create using XrGraphicsBindingD3D12KHR, the OpenXR runtime must guarantee that:
-
The image has a memory layout compatible with
D3D12_RESOURCE_STATE_RENDER_TARGET
-
The
ID3D12CommandQueue
specified in XrGraphicsBindingD3D12KHR can write to the image.
When an application releases a swapchain image by calling xrReleaseSwapchainImage, in a session create using XrGraphicsBindingD3D12KHR, the OpenXR runtime must interpret the image as:
-
Having a memory layout compatible with
D3D12_RESOURCE_STATE_RENDER_TARGET
-
Being available for read/write on the
ID3D12CommandQueue
specified in XrGraphicsBindingD3D12KHR.
The application is responsible for transitioning the swapchain image back to the image layout and queue availability that the OpenXR runtime requires. If the image is not in a layout compatible with the above specifications the runtime may exhibit undefined behaviour.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR
-
XR_TYPE_GRAPHICS_BINDING_D3D12_KHR
-
XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR
New Enums
New Structures
The following structures are provided to supply supporting runtimes the necessary information required to work with the D3D12 API executing on certain operating systems.
The XrGraphicsBindingD3D12KHR structure is defined as:
typedef struct XrGraphicsBindingD3D12KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
ID3D12Device* device;
ID3D12CommandQueue* queue;
} XrGraphicsBindingD3D12KHR;
When creating a D3D12-backed XrSession, the application will provide
a pointer to an XrGraphicsBindingD3D12KHR in the next
chain of the
XrSessionCreateInfo.
The XrSwapchainImageD3D12KHR structure is defined as:
typedef struct XrSwapchainImageD3D12KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
ID3D12Resource* texture;
} XrSwapchainImageD3D12KHR;
If a given session was created with XrGraphicsBindingD3D12KHR, the following conditions must apply.
-
Calls to xrEnumerateSwapchainImages on an XrSwapchain in that session must return an array of XrSwapchainImageD3D12KHR structures.
-
Whenever an OpenXR function accepts an XrSwapchainImageBaseHeader pointer as a parameter in that session, the runtime must also accept a pointer to an XrSwapchainImageD3D12KHR.
The OpenXR runtime must interpret the top-left corner of the swapchain image as the coordinate origin unless specified otherwise by extension functionality.
The OpenXR runtime must interpret the swapchain images in a clip space of positive Y pointing up, near Z plane at 0, and far Z plane at 1.
The XrGraphicsRequirementsD3D12KHR structure is defined as:
typedef struct XrGraphicsRequirementsD3D12KHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
LUID adapterLuid;
D3D_FEATURE_LEVEL minFeatureLevel;
} XrGraphicsRequirementsD3D12KHR;
XrGraphicsRequirementsD3D12KHR is populated by xrGetD3D12GraphicsRequirementsKHR.
New Functions
Some computer systems may have multiple graphics devices, each of which may have independent external display outputs. XR systems that connect to such graphics devices are typically connected to a single device. Applications need to know what graphics device the XR system is connected to so that they can use that graphics device to generate XR images.
To retrieve the D3D12 feature level and graphics device for an instance and system, call:
XrResult xrGetD3D12GraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
The xrGetD3D12GraphicsRequirementsKHR function identifies to the application what graphics device
(Windows LUID) needs to be used and the minimum feature level to use.
xrGetD3D12GraphicsRequirementsKHR has to be called prior to calling xrCreateSession,
and the LUID and feature level that xrGetD3D12GraphicsRequirementsKHR returns should be used
to create the ID3D12Device
that the application passes to
xrCreateSession in the XrGraphicsBindingD3D12KHR.
Issues
Version History
-
Revision 1, 2018-05-07 (Mark Young)
-
Initial draft
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Split
XR_KHR_D3D_enable
intoXR_KHR_D3D12_enable
-
Rename and expand
xrGetD3DGraphicsDeviceKHR
functionality toxrGetD3D12GraphicsRequirementsKHR
-
-
Revision 3, 2018-11-15 (Paul Pedriana)
-
Specified the swapchain texture coordinate origin.
-
-
Revision 4, 2018-11-16 (Minmin Gong)
-
Specified Y direction and Z range in clip space
-
-
Revision 5, 2019-01-29 (Dan Ginsburg)
-
Added swapchain image resource state details.
-
12.12. XR_KHR_headless
- Name String
-
XR_KHR_headless
- Extension Type
-
Instance extension
- Registered Extension Number
-
14
- Revision
-
2
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2018-06-21
- IP Status
-
No known IP claims.
- Contributors
-
Krzysztof Kosiński, Google
Mark Young, LunarG
Ryan Pavlik, Collabora
Bryce Hutchings, Microsoft
Lachlan Ford, Microsoft
Overview
This extension enables headless operation, i.e., without interacting with any display devices or initializing the OpenXR compositor. It is intended to facilitate novel uses of OpenXR devices not covered by this specification.
Note that the term "headless" is used here as a term of art referring to not outputting to a display. It does not refer to the presence or absence of a head tracker, head-mounted display, or anything else related to a human head.
When this extension is enabled, the behavior of existing functions that interact with the graphics subsystem is altered. When calling the function xrCreateSession with no graphics binding structure, the session will be created as headless.
When operating with a headless session, the function xrEnumerateSwapchainFormats must return an empty list of formats. Calls to functions xrCreateSwapchain, xrDestroySwapchain, xrAcquireSwapchainImage, xrWaitFrame are invalid. All other functions, including those related to tracking, input and haptics, are unaffected.
In addition to this application-facing behavior, the runtime must not interact with any display devices on behalf of a headless session. The runtime should avoid performing any initialization or resource acquisition related to graphics or composition.
If the runtime supports transitions between multiple sessions, then the runtime should prevent users from transitioning to a headless session from a regular session and vice versa. The latter is assumed to be trivial, since the runtime is not allowed to interact with display devices and therefore prohibited from displaying any sort of user interface. If the runtime supports multiple concurrent sessions running at the same time, it should allow headless sessions to run concurrently with regular sessions.
New Object Types
New Flag Types
New Enum Constants
New Enums
New Structures
New Functions
Issues
Version History
-
Revision 1, 2017-09-30 (Krzysztof Kosiński)
-
Initial version.
-
-
Revision 2, 2018-05-07 (Mark Young)
-
Remove
XR_GRAPHICS_API_NONE_KHR
and replace it with a mention of the newXrGraphicsApi
value ofXR_GRAPHICS_API_UNKNOWN
-
-
Revision 3, 2018-06-21 (Bryce Hutchings)
-
Remove
XR_GRAPHICS_API_UNKNOWN
and replace it with a mention of the newXrGraphicsBindingHeadlessKHR
structure.
-
-
Revision 3, 2019-01-04 (Bryce Hutchings)
-
Change from headless applications to headless sessions.
-
12.13. XR_KHR_opengl_enable
- Name String
-
XR_KHR_opengl_enable
- Extension Type
-
Instance extension
- Registered Extension Number
-
24
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-25
- IP Status
-
No known IP claims.
- Contributors
-
Mark Young, LunarG
Bryce Hutchings, Microsoft
Paul Pedriana, Oculus
Minmin Gong, Microsoft
Robert Menzel, NVIDIA
Overview
This extension enables the use of the OpenGL graphics API in an OpenXR runtime. Without this extension, the OpenXR runtime may not be able to use any OpenGL swapchain images.
This extension provides the mechanisms necessary for an application to generate a
valid XrGraphicsBindingOpenGL*KHR
structure in order to create a
OpenGL-based XrSession.
Note that during this process the application is responsible for creating all
the required OpenGL objects,
including an OpenGL context to be used for rendering.
This extension also provides mechanisms for the application to interact with images acquired by calling xrEnumerateSwapchainImages.
In order to expose the structures, types, and functions of this extension,
you must define
XR_USE_GRAPHICS_API_OPENGL, as well as an appropriate
window system define supported by this extension,
before including the OpenXR platform header openxr_platform.h
,
in all portions of your library or application that include it.
The window system defines currently supported by this extension are:
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR
-
XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR
-
XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR
-
XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR
-
XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR
-
XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR
New Enums
New Structures
The following structures are provided to supply supporting runtimes the necessary information required to work with the OpenGL API executing on certain operating systems.
These structures are only available when the corresponding
XR_USE_PLATFORM_
macro is defined before including openxr_platform.h
.
The XrGraphicsBindingOpenGLWin32KHR structure is defined as:
typedef struct XrGraphicsBindingOpenGLWin32KHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
HDC hDC;
HGLRC hGLRC;
} XrGraphicsBindingOpenGLWin32KHR;
When creating an OpenGL-backed XrSession
on Microsoft Windows,
the application will provide
a pointer to an XrGraphicsBindingOpenGLWin32KHR in the next
chain of the
XrSessionCreateInfo.
The required window system configuration define to expose this structure type is XR_USE_PLATFORM_WIN32.
The XrGraphicsBindingOpenGLXlibKHR structure is defined as:
typedef struct XrGraphicsBindingOpenGLXlibKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
Display* xDisplay;
uint32_t visualid;
GLXFBConfig glxFBConfig;
GLXDrawable glxDrawable;
GLXContext glxContext;
} XrGraphicsBindingOpenGLXlibKHR;
When creating an OpenGL-backed XrSession
on any Linux/Unix platform that utilizes X11 and GLX, via the Xlib library,
the application will provide
a pointer to an XrGraphicsBindingOpenGLXlibKHR in the next
chain of the
XrSessionCreateInfo.
The required window system configuration define to expose this structure type is XR_USE_PLATFORM_XLIB.
The XrGraphicsBindingOpenGLXcbKHR structure is defined as:
typedef struct XrGraphicsBindingOpenGLXcbKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
xcb_connection_t* connection;
uint32_t screen_number;
xcb_glx_fbconfig_t fbconfigid;
xcb_visualid_t visualid;
xcb_glx_drawable_t glxDrawable;
xcb_glx_context_t glxContext;
} XrGraphicsBindingOpenGLXcbKHR;
When creating an OpenGL-backed XrSession
on any Linux/Unix platform that utilizes X11 and GLX, via the Xlib library,
the application will provide
a pointer to an XrGraphicsBindingOpenGLXcbKHR in the next
chain of the
XrSessionCreateInfo.
The required window system configuration define to expose this structure type is XR_USE_PLATFORM_XCB.
The XrGraphicsBindingOpenGLWaylandKHR structure is defined as:
typedef struct XrGraphicsBindingOpenGLWaylandKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
struct wl_display* display;
} XrGraphicsBindingOpenGLWaylandKHR;
When creating an OpenGL-backed XrSession
on any Linux/Unix platform that utilizes the Wayland protocol with its compositor,
the application will provide
a pointer to an XrGraphicsBindingOpenGLWin32KHR in the next
chain of the
XrSessionCreateInfo.
The required window system configuration define to expose this structure type is XR_USE_PLATFORM_WAYLAND.
The XrSwapchainImageOpenGLKHR structure is defined as:
typedef struct XrSwapchainImageOpenGLKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t image;
} XrSwapchainImageOpenGLKHR;
If a given session was created with a XrGraphicsBindingOpenGL*KHR
,
the following conditions must apply.
-
Calls to xrEnumerateSwapchainImages on an XrSwapchain in that session must return an array of XrSwapchainImageOpenGLKHR structures.
-
Whenever an OpenXR function accepts an XrSwapchainImageBaseHeader pointer as a parameter in that session, the runtime must also accept a pointer to an XrSwapchainImageOpenGLKHR.
The OpenXR runtime must interpret the bottom-left corner of the swapchain image as the coordinate origin unless specified otherwise by extension functionality.
The OpenXR runtime must interpret the swapchain images in a clip space of positive Y pointing up, near Z plane at -1, and far Z plane at 1.
The XrGraphicsRequirementsOpenGLKHR structure is defined as:
typedef struct XrGraphicsRequirementsOpenGLKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t minApiVersionSupported;
uint32_t maxApiVersionSupported;
} XrGraphicsRequirementsOpenGLKHR;
XrGraphicsRequirementsOpenGLKHR is populated by xrGetOpenGLGraphicsRequirementsKHR with the runtime’s OpenGL API version requirements.
New Functions
To query OpenGL API version requirements for an instance and system, call:
XrResult xrGetOpenGLGraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
The xrGetOpenGLGraphicsRequirementsKHR function identifies to the application the minimum OpenGL version requirement and the highest known tested OpenGL version. xrGetOpenGLGraphicsRequirementsKHR has to be called prior to calling xrCreateSession.
Issues
Version History
-
Revision 1, 2018-05-07 (Mark Young)
-
Initial draft
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Add new
xrGetOpenGLGraphicsRequirementsKHR
-
-
Revision 3, 2018-11-15 (Paul Pedriana)
-
Specified the swapchain texture coordinate origin.
-
-
Revision 4, 2018-11-16 (Minmin Gong)
-
Specified Y direction and Z range in clip space
-
-
Revision 5, 2019-01-25 (Robert Menzel)
-
Description updated
-
12.14. XR_KHR_opengl_es_enable
- Name String
-
XR_KHR_opengl_es_enable
- Extension Type
-
Instance extension
- Registered Extension Number
-
25
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-25
- IP Status
-
No known IP claims.
- Contributors
-
Mark Young, LunarG
Bryce Hutchings, Microsoft
Paul Pedriana, Oculus
Minmin Gong, Microsoft
Robert Menzel, NVIDIA
Overview
This extension enables the use of the OpenGL ES graphics API in an OpenXR runtime. Without this extension, the OpenXR runtime may not be able to use any OpenGL ES swapchain images.
This extension provides the mechanisms necessary for an application to generate a
valid XrGraphicsBindingOpenGLES*KHR
structure in order to create a
OpenGL-based XrSession.
Note that during this process the application is responsible for creating all
the required OpenGL ES objects,
including an OpenGL ES context to be used for rendering.
This extension also provides mechanisms for the application to interact with images acquired by calling xrEnumerateSwapchainImages.
In order to expose the structures, types, and functions of this extension,
you must define
XR_USE_GRAPHICS_API_OPENGL_ES, as well as an appropriate
window system define supported by this extension,
before including the OpenXR platform header openxr_platform.h
,
in all portions of your library or application that include it.
The only window system define currently supported by this extension is:
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR
-
XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR
-
XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR
New Enums
New Structures
The following structures are provided to supply supporting runtimes the necessary information required to work with the OpenGL ES API executing on certain operating systems.
These structures are only available when the corresponding
XR_USE_PLATFORM_
macro is defined before including openxr_platform.h
.
The XrGraphicsBindingOpenGLESAndroidKHR structure is defined as:
typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
EGLDisplay display;
EGLConfig config;
EGLContext context;
} XrGraphicsBindingOpenGLESAndroidKHR;
When creating an OpenGL ES-backed XrSession
on Android,
the application will provide
a pointer to an XrGraphicsBindingOpenGLESAndroidKHR in the next
chain of the
XrSessionCreateInfo.
The required window system configuration define to expose this structure type is XR_USE_PLATFORM_ANDROID.
The XrSwapchainImageOpenGLESKHR structure is defined as:
typedef struct XrSwapchainImageOpenGLESKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t image;
} XrSwapchainImageOpenGLESKHR;
If a given session was created with a XrGraphicsBindingOpenGLES*KHR
,
the following conditions must apply.
-
Calls to xrEnumerateSwapchainImages on an XrSwapchain in that session must return an array of XrSwapchainImageOpenGLESKHR structures.
-
Whenever an OpenXR function accepts an XrSwapchainImageBaseHeader pointer as a parameter in that session, the runtime must also accept a pointer to an XrSwapchainImageOpenGLESKHR.
The OpenXR runtime must interpret the bottom-left corner of the swapchain image as the coordinate origin unless specified otherwise by extension functionality.
The OpenXR runtime must interpret the swapchain images in a clip space of positive Y pointing up, near Z plane at -1, and far Z plane at 1.
The XrGraphicsRequirementsOpenGLESKHR structure is defined as:
typedef struct XrGraphicsRequirementsOpenGLESKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t minApiVersionSupported;
uint32_t maxApiVersionSupported;
} XrGraphicsRequirementsOpenGLESKHR;
XrGraphicsRequirementsOpenGLESKHR is populated by xrGetOpenGLESGraphicsRequirementsKHR with the runtime’s OpenGL ES API version requirements.
New Functions
To query OpenGL ES API version requirements for an instance and system, call:
XrResult xrGetOpenGLESGraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
The xrGetOpenGLESGraphicsRequirementsKHR function identifies to the application the minimum OpenGL ES version requirement and the highest known tested OpenGL ES version. xrGetOpenGLESGraphicsRequirementsKHR has to be called prior to calling xrCreateSession.
Issues
Version History
-
Revision 1, 2018-05-07 (Mark Young)
-
Initial draft
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Add new
xrGetOpenGLESGraphicsRequirementsKHR
-
-
Revision 3, 2018-11-15 (Paul Pedriana)
-
Specified the swapchain texture coordinate origin.
-
-
Revision 4, 2018-11-16 (Minmin Gong)
-
Specified Y direction and Z range in clip space
-
-
Revision 5, 2019-01-25 (Robert Menzel)
-
Description updated
-
12.15. XR_KHR_visibility_mask
- Name String
-
XR_KHR_visibility_mask
- Extension Type
-
Instance extension
- Registered Extension Number
-
32
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2018-07-05
- IP Status
-
No known IP claims.
- Contributors
-
Paul Pedriana, Oculus
- Contacts
-
Paul Pedriana, Oculus
Overview
This extension support the providing of a per-view drawing mask for applications. The primary purpose of this is to enable performance improvements that result from avoiding drawing on areas that aren’t visible to the user. A common occurrence in head-mounted VR hardware is that the optical system’s frustum doesn’t intersect precisely with the rectangular display it is viewing. As a result, it may be that there are parts of the display that aren’t visible to the user, such as the corners of the display. In such cases it would be unnecessary for the application to draw into those parts.
New Object Types
New Flag Types
New Enum Constants
New Enums
XrVisibilityMaskTypeKHR identifies the different types of mask specification that is supported. The application may request a view mask in any of the formats identified by these types.
typedef enum XrVisibilityMaskTypeKHR {
XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR = 1,
XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR = 2,
XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR = 3,
XR_VISIBILITY_MASK_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
} XrVisibilityMaskTypeKHR;
New Structures
The XrVisibilityMaskKHR struct is an input/output struct which specifies the view mask.
Upon input to xrGetVisibilityMaskKHR, vertexCount
and indexCount
refer to the capacity of the vertices and indices members, respectively.
Upon return from xrGetVisibilityMaskKHR, vertexCount
and indexCount
refer to the required capacity of the vertices and indices parameters respectively.
typedef struct XrVisibilityMaskKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t vertexCount;
XrVector2f* vertices;
uint32_t indexCount;
uint32_t* indices;
} XrVisibilityMaskKHR;
The XrEventDataVisibilityMaskChangedKHR struct specifies an event which indicates that a given view mask has changed. The application should respond to the event by calling xrGetVisibilityMaskKHR to retrieve the updated mask. This event is per-view, so if the masks for multiple views in a configuration change then multiple instances of this event will be sent to the application, one per view.
typedef struct XrEventDataVisibilityMaskChangedKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrViewConfigurationType viewConfigurationType;
uint32_t viewIndex;
} XrEventDataVisibilityMaskChangedKHR;
New Functions
The function xrGetVisibilityMaskKHR is defined as:
XrResult xrGetVisibilityMaskKHR(
XrSession session,
XrViewConfigurationType viewConfigurationType,
uint32_t viewIndex,
XrVisibilityMaskTypeKHR visibilityMaskType,
XrVisibilityMaskKHR* visibilityMask);
xrGetVisibilityMaskKHR retrieves the view mask for a given view.
If a view mask for the specified view isn’t available, the returned vertex and index counts will be zero.
If the input vertex or index count are less than required, XR_ERROR_SIZE_INSUFFICIENT
is returned, the vertex and index count will be updated to reflect the required count, and the vertex and index array contents are undefined.
Issues
Version History
-
Revision 1, 2018-07-05 (Paul Pedriana)
-
Initial version.
-
12.16. XR_KHR_vulkan_enable
- Name String
-
XR_KHR_vulkan_enable
- Extension Type
-
Instance extension
- Registered Extension Number
-
26
- Revision
-
6
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-25
- IP Status
-
No known IP claims.
- Contributors
-
Mark Young, LunarG
Paul Pedriana, Oculus
Ed Hutchins, Oculus
Andres Rodriguez, Valve
Dan Ginsburg, Valve
Bryce Hutchings, Microsoft
Minmin Gong, Microsoft
Robert Menzel, NVIDIA
Overview
This extension enables the use of the Vulkan graphics API in an OpenXR runtime. Without this extension, the OpenXR runtime may not be able to use any Vulkan swapchain images.
This extension provides the mechanisms necessary for an application to generate a valid XrGraphicsBindingVulkanKHR structure in order to create a Vulkan-based XrSession. Note that during this process the application is responsible for creating all the required Vulkan objects.
This extension also provides mechanisms for the application to interact with images acquired by calling xrEnumerateSwapchainImages.
In order to expose the structures, types, and functions of this extension,
you must define
XR_USE_GRAPHICS_API_VULKAN
before including the OpenXR platform header openxr_platform.h
,
in all portions of your library or application that include it.
Initialization
Some of the requirements for creating a valid XrGraphicsBindingVulkanKHR
include correct initialization of a VkInstance
, VkPhysicalDevice
, and
VkDevice
.
A runtime may require that the VkInstance
be initialized to a specific
vulkan API version.
Additionally, the runtime may require a set of instance extensions to be
enabled in the VkInstance
.
These requirements can be queried by the application using
xrGetVulkanGraphicsRequirementsKHR and
xrGetVulkanInstanceExtensionsKHR, respectively.
Similarly, the runtime may require the VkDevice
to have a set of device
extensions enabled, which can be queried using
xrGetVulkanDeviceExtensionsKHR.
In order to satisfy the VkPhysicalDevice
requirements, the
application can query xrGetVulkanGraphicsDeviceKHR to identify the
correct VkPhysicalDevice
.
Populating an XrGraphicsBindingVulkanKHR with a VkInstance
,
VkDevice
, or VkPhysicalDevice
that does not meet the requirements
outlined by this extension may result in undefined behaviour by the OpenXR
runtime.
The API version, instance extension, device extension and
physical device requirements only apply to the VkInstance
,
VkDevice
, and VkPhysicalDevice
objects which the application wishes
to associate with an XrGraphicsBindingVulkanKHR.
Concurrency
Vulkan requires that concurrent access to a VkQueue
from multiple threads
be externally synchronized.
Therefore, OpenXR functions that may access the VkQueue
specified in the
XrGraphicsBindingVulkanKHR must also be externally synchronized.
The list of OpenXR functions where the OpenXR runtime may access the
VkQueue
are:
The runtime must not access the VkQueue
in any OpenXR function that is
not listed above or in an extension definition.
Swapchain Image Layout
When an application acquires a swapchain image by calling xrAcquireSwapchainImage in a session create using XrGraphicsBindingVulkanKHR, the OpenXR runtime must guarantee that:
-
The image has a memory layout compatible with
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
-
The
VkQueue
specified in XrGraphicsBindingVulkanKHR has ownership of the image.
When an application releases a swapchain image by calling xrReleaseSwapchainImage, in a session create using XrGraphicsBindingVulkanKHR, the OpenXR runtime must interpret the image as:
-
Having a memory layout compatible with
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
, -
Being owned by the
VkQueue
specified in XrGraphicsBindingVulkanKHR.
The application is responsible for transitioning the swapchain image back to the image layout and queue ownership that the OpenXR runtime requires. If the image is not in a layout compatible with the above specifications the runtime may exhibit undefined behaviour.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR
-
XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR
-
XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR
New Enums
New Structures
The following structures are provided to supply supporting runtimes the necessary information required to work with the Vulkan API executing on certain operating systems.
The XrGraphicsBindingVulkanKHR structure is defined as:
typedef struct XrGraphicsBindingVulkanKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
VkInstance instance;
VkPhysicalDevice physicalDevice;
VkDevice device;
uint32_t queueFamilyIndex;
uint32_t queueIndex;
} XrGraphicsBindingVulkanKHR;
When creating a Vulkan-backed XrSession, the application will provide
a pointer to an XrGraphicsBindingVulkanKHR in the next
chain of the
XrSessionCreateInfo.
The XrSwapchainImageVulkanKHR structure is defined as:
typedef struct XrSwapchainImageVulkanKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
VkImage image;
} XrSwapchainImageVulkanKHR;
If a given session was created with XrGraphicsBindingVulkanKHR, the following conditions must apply.
-
Calls to xrEnumerateSwapchainImages on an XrSwapchain in that session must return an array of XrSwapchainImageVulkanKHR structures.
-
Whenever an OpenXR function accepts an XrSwapchainImageBaseHeader pointer as a parameter in that session, the runtime must also accept a pointer to an XrSwapchainImageVulkanKHR.
The OpenXR runtime must interpret the top-left corner of the swapchain image as the coordinate origin unless specified otherwise by extension functionality.
The OpenXR runtime must interpret the swapchain images in a clip space of positive Y pointing down, near Z plane at 0, and far Z plane at 1.
The XrGraphicsRequirementsVulkanKHR structure is defined as:
typedef struct XrGraphicsRequirementsVulkanKHR {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t minApiVersionSupported;
uint32_t maxApiVersionSupported;
} XrGraphicsRequirementsVulkanKHR;
XrGraphicsRequirementsVulkanKHR is populated by xrGetVulkanGraphicsRequirementsKHR with the runtime’s Vulkan API version requirements.
New Functions
To query Vulkan API version requirements, call:
XrResult xrGetVulkanGraphicsRequirementsKHR(
XrInstance instance,
XrSystemId systemId,
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
The xrGetVulkanGraphicsRequirementsKHR function identifies to the application the minimum Vulkan version requirement and the highest known tested Vulkan version. xrGetVulkanGraphicsRequirementsKHR has to be called prior to calling xrCreateSession.
Some computer systems may have multiple graphics devices, each of which may have independent external display outputs. XR systems that connect to such graphics devices are typically connected to a single device. Applications need to know what graphics device the XR system is connected to so that they can use that graphics device to generate XR images.
To identify what graphics device needs to be used for an instance and system, call:
XrResult xrGetVulkanGraphicsDeviceKHR(
XrInstance instance,
XrSystemId systemId,
VkInstance vkInstance,
VkPhysicalDevice* vkPhysicalDevice);
xrGetVulkanGraphicsDeviceKHR function identifies to the application what graphics device
(Vulkan VkPhysicalDevice
) needs to be used.
xrGetVulkanGraphicsDeviceKHR has to be called prior to calling xrCreateSession,
and the VkPhysicalDevice
that xrGetVulkanGraphicsDeviceKHR returns should be passed to
xrCreateSession in the XrGraphicsBindingVulkanKHR.
XrResult xrGetVulkanInstanceExtensionsKHR(
XrInstance instance,
XrSystemId systemId,
uint32_t namesCapacityInput,
uint32_t* namesCountOutput,
char* namesString);
The xrGetVulkanGraphicsDeviceKHR function identifies to the application
what graphics device (Vulkan VkPhysicalDevice
) needs to be used.
xrGetVulkanGraphicsDeviceKHR must be called
prior to calling xrCreateSession, and the VkPhysicalDevice
that
xrGetVulkanGraphicsDeviceKHR returns should be passed to
xrCreateSession.
XrResult xrGetVulkanDeviceExtensionsKHR(
XrInstance instance,
XrSystemId systemId,
uint32_t namesCapacityInput,
uint32_t* namesCountOutput,
char* namesString);
Issues
Version History
-
Revision 1, 2018-05-07 (Mark Young)
-
Initial draft
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Replace
session
parameter withinstance
andsystemId
parameters. -
Move
xrGetVulkanDeviceExtensionsKHR
,xrGetVulkanInstanceExtensionsKHR
andxrGetVulkanGraphicsDeviceKHR
functions into this extension -
Add new
XrGraphicsRequirementsVulkanKHR
function.
-
-
Revision 3, 2018-11-15 (Paul Pedriana)
-
Specified the swapchain texture coordinate origin.
-
-
Revision 4, 2018-11-16 (Minmin Gong)
-
Specified Y direction and Z range in clip space
-
-
Revision 5, 2019-01-24 (Robert Menzel)
-
Description updated
-
-
Revision 6, 2019-01-25 (Andres Rodriguez)
-
Reword sections of the spec to shift requirements on to the runtime instead of the app
-
12.17. XR_KHR_vulkan_swapchain_format_list
- Name String
-
XR_KHR_vulkan_swapchain_format_list
- Extension Type
-
Instance extension
- Registered Extension Number
-
15
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
Requires
XR_KHR_vulkan_enable
-
- Last Modified Date
-
2017-09-13
- IP Status
-
No known IP claims.
- Contributors
-
Paul Pedriana, Oculus
Dan Ginsburg, Valve
Overview
Vulkan has the VK_KHR_image_format_list
extension which allows applications
to tell the vkCreateImage
function which formats the application intends to use
when VK_IMAGE_USAGE_MUTABLE_FORMAT_BIT
is specified. This OpenXR extension
exposes that Vulkan extension to OpenXR applications. In the same way that a
Vulkan-based application can pass a VkImageFormatListCreateInfo
struct to the
vkCreateImage
function, an OpenXR application can pass an identically configured
XrVulkanSwapchainFormatListCreateInfoKHR struct to xrCreateSwapchain.
Applications using this extension to specify more than one swapchain format must
create OpenXR swapchains with the XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT
bit set.
Runtimes implementing this extension must support the XR_KHR_vulkan_enable
extension and add VK_KHR_image_format_list
to the list returned by xrGetVulkanDeviceExtensionsKHR,
as the runtime will need to use that Vulkan extension.
New Object Types
New Flag Types
New Enum Constants
XrStructureType enumeration is extended with:
XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR
New Enums
New Structures
typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
XrStructureType type;
const void* XR_MAY_ALIAS next;
uint32_t viewFormatCount;
const VkFormat* viewFormats;
} XrVulkanSwapchainFormatListCreateInfoKHR;
New Functions
Issues
Version History
-
Revision 1, 2017-09-13 (Paul Pedriana)
-
Initial proposal.
-
-
Revision 2, 2018-06-21 (Bryce Hutchings)
-
Update reference of
XR_KHR_vulkan_extension_requirements
toXR_KHR_vulkan_enable
-
12.18. XR_KHR_win32_convert_performance_counter_time
- Name String
-
XR_KHR_win32_convert_performance_counter_time
- Extension Type
-
Instance extension
- Registered Extension Number
-
36
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2019-01-24
- IP Status
-
No known IP claims.
- Contributors
-
Paul Pedriana, Oculus
Overview
This extension provides two functions for converting between Windows QueryPerformanceCounter
time and XrTime
.
The xrConvertWin32PerformanceCounterToTimeKHR function converts from Win32 QueryPerformanceCounter
time to XrTime
, while the xrConvertTimeToWin32PerformanceCounterKHR function converts XrTime
to Win32 QueryPerformanceCounter
time.
The primary use case for this functionality is to be able to synchronize events between the local system and the OpenXR system.
New Object Types
New Flag Types
New Enum Constants
New Enums
New Structures
New Functions
To convert from Win32 QueryPerformanceCounter
time to basetype::XrTime, call:
XrResult xrConvertWin32PerformanceCounterToTimeKHR(
XrInstance instance,
const LARGE_INTEGER* performanceCounter,
XrTime* time);
The xrConvertWin32PerformanceCounterToTimeKHR function converts a time obtained by the Win32 QueryPerformanceCounter
function to the equivalent basetype::XrTime.
To convert from basetype::XrTime to Win32 QueryPerformanceCounter
time, call:
XrResult xrConvertTimeToWin32PerformanceCounterKHR(
XrInstance instance,
XrTime time,
LARGE_INTEGER* performanceCounter);
The xrConvertTimeToWin32PerformanceCounterKHR function converts an basetype::XrTime to time as if generated by Win32 QueryPerformanceCounter
.
Issues
Version History
-
Revision 1, 2019-01-24 (Paul Pedriana)
-
Initial draft
-
12.19. XR_EXT_debug_utils
- Name String
-
XR_EXT_debug_utils
- Extension Type
-
Instance extension
- Registered Extension Number
-
20
- Revision
-
2
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2018-11-16
- IP Status
-
No known IP claims.
- Contributors
-
Mark Young, LunarG
Karl Schultz, LunarG
Overview
Due to the nature of the OpenXR interface, there is very little error information available to the developer and application. By using the XR_EXT_debug_utils extension, developers can obtain more information. When combined with validation layers, even more detailed feedback on the application’s use of OpenXR will be provided.
This extension provides the following capabilities:
-
The ability to create a debug messenger which will pass along debug messages to an application supplied callback.
-
The ability to identify specific OpenXR handles using a name to improve tracking.
12.19.1. Object Debug Annotation
It can be useful for an application to provide its own content relative to a specific OpenXR handle.
Object Naming
xrSetDebugUtilsObjectNameEXT allows application developers to associate user-defined information with OpenXR handles.
This is useful when paired with the callback that you register when creating an XrDebugUtilsMessengerEXT object. When properly used, debug messages will contain not only the corresponding object handle, but the associated object name as well.
An application can change the name associated with an object simply by calling xrSetDebugUtilsObjectNameEXT again with a new string. If the objectName member of the XrDebugUtilsObjectNameInfoEXT structure is an empty string, then any previously set name is removed.
12.19.2. Debug Messengers
OpenXR allows an application to register arbitrary number of callbacks with all the OpenXR components wishing to report debug information. Some callbacks can log the information to a file, others can cause a debug break point or any other behavior defined by the application. A primary producer of callback messages are the validation layers. If the extension is enabled, an application can register callbacks even when no validation layers are enabled. The OpenXR loader, other layers, and runtimes may also produce callback messages.
The debug messenger will provide detailed feedback on the application’s use of OpenXR when events of interest occur. When an event of interest does occur, the debug messenger will submit a debug message to the debug callback that was provided during its creation. Additionally, the debug messenger is responsible with filtering out debug messages that the callback isn’t interested in and will only provide desired debug messages.
12.19.3. Debug Message Categorization
Messages that are triggered by the debug messenger are categorized by their
message type and severity.
Additionally, each message has a string value identifying its messageId
.
These 3 bits of information can be used to filter out messages so you only
receive reports on the messages you desire.
In fact, during debug messenger creation, the severity and type flag values
are provided to indicate what messages should be allowed to trigger the
user’s callback.
Message Type
The message type indicates the general category the message falls under. Currently we have the following message types:
Enum | Description |
---|---|
|
Specifies a general purpose event type. This is typically a non-validation, non-performance event. |
|
Specifies an event caused during a validation against the OpenXR specification that may indicate invalid OpenXR usage. |
|
Specifies a potentially non-optimal use of OpenXR. |
A message may correspond to more than one type. For example, if a validation
warning also could impact performance, then the message might be identified
with both the XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
and
XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
flag bits.
Message Severity
The severity of a message is a flag that indicates how important the message is using standard logging naming. The severity flag bit values are shown in the following table.
Enum | Description |
---|---|
|
Specifies the most verbose output indicating all diagnostic messages from the OpenXR loader, layers, and drivers should be captured. |
|
Specifies an informational message such as resource details that might be handy when debugging an application. |
|
Specifies use of OpenXR that could be an application bug. Such cases may not be immediately harmful, such as providing too many swapchain images. Other cases may point to behavior that is almost certainly bad when unintended, such as using a swapchain image whose memory has not been filled. In general, if you see a warning but you know that the behavior is intended/desired, then simply ignore the warning. |
|
Specifies an error that may cause undefined behavior, including an application crash. |
Note
The values of XrDebugUtilsMessageSeverityFlagBitsEXT are sorted based on severity. The higher the flag value, the more severe the message. This allows for simple boolean operation comparisons when looking at XrDebugUtilsMessageSeverityFlagBitsEXT values. |
Message IDs
The XrDebugUtilsMessengerCallbackDataEXT structure contains a
messageId
that may be a string identifying the message ID for the
triggering debug message.
This may be blank, or it may simply contain the name of an OpenXR component
(like "OpenXR Loader").
However, when certain API layers or runtimes are used, especially the OpenXR
core_validation API layer, then this value is intended to uniquely identify
the message generated.
If a certain warning/error message constantly fires, a user can simply
look at the unique ID in their callback handler and manually filter it out.
For validation layers, this messageId
value actually can be used to
find the section of the OpenXR specification that the layer believes to have
been violated.
See the core_validation API Layer documentation for more information on how
this can be done.
12.19.4. Session Labels
All OpenXR work is performed inside of an XrSession. There are times that it helps to label areas in your OpenXR session to allow easier debugging. This can be especially true if your application creates more than one session. There are two kinds of labels provided in this extension:
-
Region labels
-
Individual labels
To begin identifying a region using a debug label inside a session, you may use the xrSessionBeginDebugUtilsLabelRegionEXT function. Calls to xrSessionBeginDebugUtilsLabelRegionEXT may be nested allowing you to identify smaller and smaller labeled regions within your code. Using this, you can build a "call-stack" of sorts with labels since any logging callback will contain the list of all active session label regions.
To end the last session label region that was begun, you must call xrSessionEndDebugUtilsLabelRegionEXT. Each xrSessionBeginDebugUtilsLabelRegionEXT must have a matching xrSessionEndDebugUtilsLabelRegionEXT. All of a session’s label region’s must be closed by the xrDestroySession function is called for the given XrSession.
An individual debug label may be inserted at any time using xrSessionInsertDebugUtilsLabelEXT. The xrSessionInsertDebugUtilsLabelEXT is used to indicate a particular location within the execution of the application’s session functions. The next call to xrSessionInsertDebugUtilsLabelEXT, xrSessionBeginDebugUtilsLabelRegionEXT, or xrSessionEndDebugUtilsLabelRegionEXT overrides this value.
New Object Types
XR_DEFINE_HANDLE(XrDebugUtilsMessengerEXT)
XrDebugUtilsMessengerEXT represents a callback function and associated filters registered with the runtime.
New Flag Types
typedef XrFlags64 XrDebugUtilsMessageSeverityFlagsEXT;
// Flag bits for XrDebugUtilsMessageSeverityFlagsEXT
static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001;
static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010;
static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100;
static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000;
typedef XrFlags64 XrDebugUtilsMessageTypeFlagsEXT;
// Flag bits for XrDebugUtilsMessageTypeFlagsEXT
static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001;
static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002;
static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004;
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT
-
XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT
-
XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
-
XR_TYPE_DEBUG_UTILS_LABEL_EXT
XrResult enumeration is extended with:
-
XR_ERROR_DEBUG_UTILS_MESSENGER_INVALID_EXT
New Enums
New Structures
typedef struct XrDebugUtilsObjectNameInfoEXT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrObjectType objectType;
uint64_t objectHandle;
const char* objectName;
} XrDebugUtilsObjectNameInfoEXT;
typedef struct XrDebugUtilsLabelEXT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
const char* labelName;
} XrDebugUtilsLabelEXT;
typedef struct XrDebugUtilsMessengerCallbackDataEXT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
const char* messageId;
const char* functionName;
const char* message;
uint32_t objectCount;
XrDebugUtilsObjectNameInfoEXT* objects;
uint32_t sessionLabelCount;
XrDebugUtilsLabelEXT* sessionLabels;
} XrDebugUtilsMessengerCallbackDataEXT;
An XrDebugUtilsMessengerCallbackDataEXT is a messenger object that handles passing along debug messages to a provided debug callback.
Note
This structure should only be considered valid during the lifetime of the triggered callback. |
The labels listed inside sessionLabels
are organized in time order, with
the most recently generated label appearing first, and the oldest label appearing
last.
typedef struct XrDebugUtilsMessengerCreateInfoEXT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrDebugUtilsMessageSeverityFlagsEXT messageSeverities;
XrDebugUtilsMessageTypeFlagsEXT messageTypes;
PFN_xrDebugUtilsMessengerCallbackEXT userCallback;
void* XR_MAY_ALIAS userData;
} XrDebugUtilsMessengerCreateInfoEXT;
For each XrDebugUtilsMessengerEXT that is created the
XrDebugUtilsMessengerCreateInfoEXT::messageSeverities
and
XrDebugUtilsMessengerCreateInfoEXT::messageTypes
determine when that
XrDebugUtilsMessengerCreateInfoEXT::userCallback
is called.
The process to determine if the user’s userCallback is triggered when
an event occurs is as follows:
-
The runtime will perform a bitwise AND of the event’s XrDebugUtilsMessageSeverityFlagBitsEXT with the XrDebugUtilsMessengerCreateInfoEXT::
messageSeverities
provided during creation of the XrDebugUtilsMessengerEXT object. -
If this results in 0, the message is skipped.
-
The runtime will perform bitwise AND of the event’s XrDebugUtilsMessageTypeFlagBitsEXT with the XrDebugUtilsMessengerCreateInfoEXT::
messageTypes
provided during the creation of the XrDebugUtilsMessengerEXT object. -
If this results in 0, the message is skipped.
-
If the message of the current event is not skipped, the callback will be called with the message.
The callback will come directly from the component that detected the event, unless some other layer intercepts the calls for its own purposes (filter them in a different way, log to a system error log, etc.).
An application can receive multiple callbacks if multiple XrDebugUtilsMessengerEXT objects are created. A callback will always be executed in the same thread as the originating OpenXR call.
Note
A callback can be called from multiple threads simultaneously if the application is making OpenXR calls from multiple threads. |
New Functions
XrResult xrSetDebugUtilsObjectNameEXT(
XrInstance instance,
const XrDebugUtilsObjectNameInfoEXT* nameInfo);
Applications may change the name associated with an object simply by
calling xrSetDebugUtilsObjectNameEXT again with a new string.
If XrDebugUtilsObjectNameInfoEXT::objectName
is an empty string,
then any previously set name is removed.
XrResult xrCreateDebugUtilsMessengerEXT(
XrInstance instance,
const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
XrDebugUtilsMessengerEXT* messenger);
The application must ensure that xrCreateDebugUtilsMessengerEXT is not
executed in parallel with any OpenXR function that is also called with
instance
or child of instance
as the dispatchable argument.
When an event of interest occurs a debug messenger calls its
createInfo
->userCallback
with a debug message from the producer
of the event. Additionally, the debug messenger must filter out any debug
messages that the application’s callback is not interested in based on
XrDebugUtilsMessengerCreateInfoEXT flags, as described below.
XrResult xrDestroyDebugUtilsMessengerEXT(
XrDebugUtilsMessengerEXT messenger);
The application must ensure that xrDestroyDebugUtilsMessengerEXT is not
executed in parallel with any OpenXR function that is also called with
instance
or child of instance
as the dispatchable argument.
XrResult xrSubmitDebugUtilsMessageEXT(
XrInstance instance,
XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
XrDebugUtilsMessageTypeFlagsEXT messageTypes,
const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
The application can also produce a debug message, and submit it into the OpenXR messaging system.
The call will propagate through the layers and generate callback(s) as indicated by the message’s flags. The parameters are passed on to the callback in addition to the userData value that was defined at the time the messenger was created.
XrResult xrSessionBeginDebugUtilsLabelRegionEXT(
XrSession session,
const XrDebugUtilsLabelEXT* labelInfo);
The xrSessionBeginDebugUtilsLabelRegionEXT function begins a label
region within session
.
XrResult xrSessionEndDebugUtilsLabelRegionEXT(
XrSession session);
This function ends the last label region begun with the
xrSessionBeginDebugUtilsLabelRegionEXT function within
the same session
.
XrResult xrSessionInsertDebugUtilsLabelEXT(
XrSession session,
const XrDebugUtilsLabelEXT* labelInfo);
The xrSessionInsertDebugUtilsLabelEXT function inserts an individual
label within session
.
The individual labels are useful for different reasons based on the type
of debugging scenario.
When used with something active like a profiler or debugger, it
identifies a single point of time.
When used with logging, the individual label identifies that a particular
location has been passed at the point the log message is triggered.
Because of this usage, individual labels only exist in a log until the
next call to any of the label functions:
New Function Pointers
typedef XrBool32 (XRAPI_PTR *PFN_xrDebugUtilsMessengerCallbackEXT)(
XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
XrDebugUtilsMessageTypeFlagsEXT messageTypes,
const XrDebugUtilsMessengerCallbackDataEXT* callbackData,
void* userData);
The callback must not call xrDestroyDebugUtilsMessengerEXT.
The callback returns an XrBool32
that indicates to the calling layer
the application’s desire to abort the call.
A value of XR_TRUE
indicates that the application wants to abort this
call.
If the application returns XR_FALSE
, the function must not be aborted.
Applications should always return XR_FALSE
so that they see the same
behavior with and without validation layers enabled.
If the application returns XR_TRUE
from its callback and the OpenXR
call being aborted returns an XrResult, the layer will return
XR_ERROR_VALIDATION_FAILURE
.
The object pointed to by callbackData
(and any pointers in it
recursively) must be valid during the lifetime of the triggered callback.
It may become invalid afterwards.
Examples
Example 1
XR_EXT_debug_utils allows an application to register multiple callbacks with any OpenXR component wishing to report debug information. Some callbacks may log the information to a file, others may cause a debug break point or other application defined behavior. An application can register callbacks even when no validation layers are enabled, but they will only be called for loader and, if implemented, driver events.
To capture events that occur while creating or destroying an instance an application can link an XrDebugUtilsMessengerCreateInfoEXT structure to the next element of the XrInstanceCreateInfo structure given to xrCreateInstance. This callback is only valid for the duration of the xrCreateInstance and the xrDestroyInstance call. Use xrCreateDebugUtilsMessengerEXT to create persistent callback objects.
Example uses: Create three callback objects.
One will log errors and warnings to the debug console using Windows
OutputDebugString
.
The second will cause the debugger to break at that callback when an error
happens and the third will log warnings to stdout.
XrInstance instance; // previously initialized
XrResult res;
XrDebugUtilsMessengerEXT messenger1, messenger2, messenger3;
// Must call extension functions through a function pointer:
PFN_xrCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT;
res = xrGetInstanceProcAddr(instance, "xrCreateDebugUtilsMessengerEXT", reinterpret_cast<PFN_xrVoidFunction*>(&pfnCreateDebugUtilsMessengerEXT));
PFN_xrDestroyDebugUtilsMessengerEXT pfnDestroyDebugUtilsMessengerEXT;
res = xrGetInstanceProcAddr(instance, "xrDestroyDebugUtilsMessengerEXT", reinterpret_cast<PFN_xrVoidFunction*>(&pfnDestroyDebugUtilsMessengerEXT));
XrDebugUtilsMessengerCreateInfoEXT callback1 = {
XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, // type
NULL, // next
XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | // messageSeverities
XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | // messageTypes
XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
myOutputDebugString, // userCallback
NULL // userData
};
res = pfnCreateDebugUtilsMessengerEXT(instance, &callback1, &messenger1);
if (res != XR_SUCCESS) {
// Do error handling
}
callback1.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
callback1.userCallback = myDebugBreak;
callback1.userData = NULL;
res = pfnCreateDebugUtilsMessengerEXT(instance, &callback1, &messenger2);
if (res != XR_SUCCESS) {
// Do error handling
}
XrDebugUtilsMessengerCreateInfoEXT callback3 = {
XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, // type
NULL, // next
XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, // messageSeverities
XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | // messageTypes
XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
myStdOutLogger, // userCallback
NULL // userData
};
res = pfnCreateDebugUtilsMessengerEXT(instance, &callback3, &messenger3);
if (res != XR_SUCCESS) {
// Do error handling
}
// ...
// Remove callbacks when cleaning up
pfnDestroyDebugUtilsMessengerEXT(messenger1);
pfnDestroyDebugUtilsMessengerEXT(messenger2);
pfnDestroyDebugUtilsMessengerEXT(messenger3);
Example 2
Associate a name with an XrSpace, for easier debugging in external tools or with validation layers that can print a friendly name when referring to objects in error messages.
extern XrInstance instance;
extern XrSpace space;
// Must call extension functions through a function pointer:
PFN_xrSetDebugUtilsObjectNameEXT pfnSetDebugUtilsObjectNameEXT;
xrGetInstanceProcAddr(instance, "xrSetDebugUtilsObjectNameEXT", reinterpret_cast<PFN_xrVoidFunction*>(&pfnSetDebugUtilsObjectNameEXT));
// Set a name on the space
const XrDebugUtilsObjectNameInfoEXT spaceNameInfo =
{
XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, // type
NULL, // next
XR_OBJECT_TYPE_SPACE, // objectType
(uint64_t)space, // objectHandle
"My Object-Specific Space", // objectName
};
pfnSetDebugUtilsObjectNameEXT(instance, &spaceNameInfo);
// A subsequent error might print:
// Space "My Object-Specific Space" (0xc0dec0dedeadbeef) is used
// with an XrSession that is not it's parent.
Example 3
Labeling the workload with naming information so that any form of analysis can display a more usable visualization of where actions occur in the lifetime of a session.
extern XrInstance instance;
extern XrSession session;
extern XrSessionBeginInfo session_begin_info;
extern XrFrameBeginInfo begin_frame_info;
extern XrFrameEndInfo end_frame_info;
extern XrFrameWaitInfo wait_frame_info;
extern XrFrameState frame_state;
// Must call extension functions through a function pointer:
PFN_xrSessionBeginDebugUtilsLabelRegionEXT pfn_xrSessionBeginDebugUtilsLabelRegionEXT = (PFN_xrSessionBeginDebugUtilsLabelRegionEXT)xrGetInstanceProcAddr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT");
PFN_xrSessionEndDebugUtilsLabelRegionEXT pfn_xrSessionEndDebugUtilsLabelRegionEXT = (PFN_xrSessionEndDebugUtilsLabelRegionEXT)xrGetInstanceProcAddr(instance, "xrSessionEndDebugUtilsLabelRegionEXT");
PFN_xrSessionInsertDebugUtilsLabelEXT pfn_xrSessionInsertDebugUtilsLabelEXT = (PFN_xrSessionInsertDebugUtilsLabelEXT)xrGetInstanceProcAddr(instance, "xrSessionInsertDebugUtilsLabelEXT");
const XrDebugUtilsLabelEXT session_active_region_label =
{
XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type
NULL, // next
"Session active", // labelName
};
xrSessionBegin(session, &session_begin_info);
// Start an annotated region of calls under the 'Session Active' name
pfn_xrSessionBeginDebugUtilsLabelRegionEXT(session, &session_active_region_label);
// Brackets added for clarity
{
XrDebugUtilsLabelEXT individual_label =
{
XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type
NULL, // next
"WaitFrame", // labelName
};
const char wait_frame_label[] = "WaitFrame";
individual_label.labelName = wait_frame_label;
pfn_xrSessionInsertDebugUtilsLabelEXT(session, individual_label);
xrWaitFrame(session, &wait_frame_info, &frame_state);
// Do stuff 1
const XrDebugUtilsLabelEXT session_frame_region_label =
{
XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type
NULL, // next
"Session Frame 123", // labelName
};
// Start an annotated region of calls under the 'Session Frame 123' name
pfn_xrSessionBeginDebugUtilsLabelRegionEXT(session, &session_frame_region_label);
// Brackets added for clarity
{
const char begin_frame_label[] = "BeginFrame";
individual_label.labelName = begin_frame_label;
pfn_xrSessionInsertDebugUtilsLabelEXT(session, individual_label);
xrBeginFrame(session, &begin_frame_info);
// Do stuff 2
const char end_frame_label[] = "EndFrame";
individual_label.labelName = end_frame_label;
pfn_xrSessionInsertDebugUtilsLabelEXT(session, individual_label);
xrEndFrame(session, &end_frame_info);
}
// End the session/begun region started above (in this case it's the "Session Frame 123" label)
pfn_xrSessionEndDebugUtilsLabelRegionEXT(session);
}
// End the session/begun region started above (in this case it's the "Session Active" label)
pfn_xrSessionEndDebugUtilsLabelRegionEXT(session);
vkEndSession(session);
In the above example, if an error occurred in the "// Do stuff 1" section,
then your debug utils callback would contain the following data in
its sessionLabels
array:
[0] = individual_label with labelName = "WaitFrame"
[1] = session_active_region_label with labelName = "Session active"
However, if an error occurred in the "// Do stuff 2" section,
then your debug utils callback would contain the following data in
its sessionLabels
array:
[0] = individual_label with labelName = "BeginFrame"
[1] = session_frame_region_label with labelName = "Session Frame 123"
[2] = session_active_region_label with labelName = "Session active"
You’ll notice that "WaitFrame" is no longer available as soon as the next call to another function like xrSessionBeginDebugUtilsLabelRegionEXT.
Issues
None
Version History
-
Revision 1, 2018-02-19 (Mark Young / Karl Schultz)
-
Initial draft, based on VK_EXT_debug_utils.
-
-
Revision 2, 2018-11-16 (Mark Young)
-
Clean up some language based on changes going into the Vulkan VK_EXT_debug_utils extension by Peter Kraus (aka @krOoze).
-
Added session labels
-
12.20. XR_EXT_performance_settings
- Name String
-
XR_EXT_performance_settings
- Extension Type
-
Instance extension
- Registered Extension Number
-
16
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2017-11-30
- IP Status
-
No known IP claims.
- Contributors
-
Armelle Laine, Qualcomm Technologies Inc, on behalf of Qualcomm Innovation Center, Inc
12.20.1. Overview
This extension defines an API for the application to give performance hints to the runtime and for the runtime to send performance related notifications back to the application. This allows both sides to dial in a suitable compromise between needed CPU and GPU performance, thermal sustainability and a consistent good user experience throughout the session.
The goal is to render frames consistently, in time, under varying system load without consuming more energy than necessary.
In summary, the APIs allow:
-
setting performance level hints
-
receiving performance related notifications
12.20.2. Setting Performance Levels Hints
Performance level hint definition
The XR performance level hints for a given hardware system are expressed as a level XrPerfSettingsLevelEXT for each of the XR-critical processing domains XrPerfSettingsDomainEXT (currently defined is a CPU and a GPU domain):
typedef enum XrPerfSettingsDomainEXT {
XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsDomainEXT;
typedef enum XrPerfSettingsLevelEXT {
XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT = 0,
XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT = 25,
XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT = 50,
XR_PERF_SETTINGS_LEVEL_BOOST_EXT = 75,
XR_PERF_SETTINGS_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsLevelEXT;
This extension defines platform-independent level hints:
-
XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT
is used by the application to indicate that it enters a non-XR section (head-locked / static screen), during which power savings are to be prioritized. Consistent XR compositing, consistent frame rendering, and low latency are not needed. -
XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT
is used by the application to indicate that it enters a low and stable complexity section, during which reducing power is more important than occasional late rendering frames. With such a hint, the XR Runtime still strives for consistent XR compositing (no tearing) within a thermally sustainable range(*), but is allowed to take measures to reduce power, such as increasing latencies or reducing headroom. -
XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT
is used by the application to indicate that it enters a high or dynamic complexity section, during which the XR Runtime strives for consistent XR compositing and frame rendering within a thermally sustainable range(*). -
XR_PERF_SETTINGS_LEVEL_BOOST_EXT
is used to indicate that the application enters a section with very high complexity, during which the XR Runtime is allowed to step up beyond the thermally sustainable range. As not thermally sustainable, this level is meant to be used for short-term durations (< 30 seconds).
(*) If the application chooses one of the two sustainable levels (XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT
or
XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT
), the device may still run into thermal limits under non-nominal
circumstances (high room temperature, additional background loads, extended device operation)
and therefore the application should also in the sustainable modes be prepared to react to performance
notifications (in particular XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
and
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
in the thermal sub-domain, see Notification level definition).
The XR Runtime shall select XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT
as the default hint if the application does not provide any.
The function to call for setting performance level hints is xrPerfSettingsSetPerformanceLevelEXT.
XrResult xrPerfSettingsSetPerformanceLevelEXT(
XrSession session,
XrPerfSettingsDomainEXT domain,
XrPerfSettingsLevelEXT level);
Example of using the short-term boost level hint
For a limited amount of time, both the Mobile and PC systems can provide a higher level of performance than is thermally sustainable. It is desirable to make this extra computational power available for short complex scenes, then go back to a sustainable lower level. This section describes means for the application developer to apply settings directing the runtime to boost performance for a short-term duration.
The application developer must pay attention to keep these boost periods very short and carefully monitor the side effects, which may vary a lot between different hardware systems.
extern XrSession session; (1)
// before entering the high complexity section
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, XR_PERF_SETTINGS_LEVEL_BOOST_EXT); (2)
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, XR_PERF_SETTINGS_LEVEL_BOOST_EXT);
// entering the high complexity section
// ... running
// end of the high complexity section
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT); (3)
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT);
1 | we assume that session is initialized and its handle is available |
2 | setting performance level to XR_PERF_SETTINGS_LEVEL_BOOST_EXT on both CPU and GPU domains |
3 | going back to the sustainable XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT |
Example of using the sustained low level hint for the CPU domain
extern XrSession session; (1)
// before entering a low CPU complexity section
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT);
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT); (2)
// entering the low complexity section
// ... running
// end of the low complexity section
xrPerfSettingsSetPerformanceLevelEXT(session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT); (3)
1 | we assume that session is initialized and its handle is available |
2 | the developer may choose to only reduce CPU domain and keep the GPU domain at XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT |
3 | going back to the sustainable XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT for CPU |
12.20.3. Receiving Performance Related Notifications
The XR runtime shall provide performance related notifications to the application in the following situations:
-
the compositing performance within the runtime has reached a new level, either improved or degraded from the previous one (
subDomain
is set toXR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT
) -
the application rendering performance has reached a new level, either improved or degraded from the previous one (
subDomain
is set toXR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT
) -
the temperature of the device has reached a new level, either improved or degraded from the previous one (
subDomain
is set toXR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT
).
When degradation is observed, the application should take measures reducing its workload,
helping the compositing or rendering subDomain
to meet their deadlines,
or the thermal subDomain
to avoid or stop throttling.
When improvement is observed, the application can potentially rollback some of its mitigations.
typedef struct XrEventDataPerfSettingsEXT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrPerfSettingsDomainEXT domain;
XrPerfSettingsSubDomainEXT subDomain;
XrPerfSettingsNotificationLevelEXT fromLevel;
XrPerfSettingsNotificationLevelEXT toLevel;
} XrEventDataPerfSettingsEXT;
typedef enum XrPerfSettingsSubDomainEXT {
XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT = 1,
XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT = 2,
XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT = 3,
XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsSubDomainEXT;
Compositing Sub-Domain
One of the major functions the runtime shall provide is the timely compositing of the submitted layers in
the background. The runtime has to share the CPU and GPU system resources for this operation with the application.
Since this is extremely time sensitive - the head room is only a few milliseconds - the runtime
may have to ask the application via notifications to cooperate and relinquish some usage of the
indicated resource (CPU or GPU domain).
Performance issues in this area
that the runtime notices are notified to the application with the subDomain
set to XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT
.
Rendering Sub-Domain
The application submits rendered layers to the runtime for compositing.
Performance issues in this area that the runtime notices (i.e. missing submission deadlines)
are notified to the application with the subDomain
set to XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT
.
Thermal Sub-Domain
XR applications run at a high-performance level during long periods of time, across a game or an entire movie session. As form factors shrink, especially on mobile solutions, the risk of reaching die thermal runaway or reaching the limits on skin and battery temperatures increases. When thermal limits are reached, the device mitigates the heat generation leading to severe performance reductions, which greatly affects user experience (dropped frames, high latency).
Better than dropping frames when it is too late, pro-active measures from the application should be encouraged.
The performance notification with the subDomain
set to XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT
provides an early
warning allowing the application to take mitigation actions.
Notification level definition
The levels are defined as follows:
typedef enum XrPerfSettingsNotificationLevelEXT {
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,
XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsNotificationLevelEXT;
-
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
notifies that the sub-domain has reached a level where no further actions other than currently applied are necessary. -
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
notifies that the sub-domain has reached an early warning level where the application should start proactive mitigation actions with the goal to return to theXR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
level. -
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
notifies that the sub-domain has reached a critical level with significant performance degradation. The application should take drastic mitigation action.
The above definitions summarize the broad interpretation of the notification levels, however sub-domain specific definitions of each level and their transitions are specified below:
-
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
-
For the compositing sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
indicates that the composition headroom is consistently being met with sufficient margin.
Getting intoXR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
fromXR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
indicates that the composition headroom was consistently met with sufficient margin during a sufficient time period. -
For the rendering sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
indicates that frames are being submitted in time to be used by the compositor.
Getting intoXR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
fromXR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
indicates that during a sufficient time period, none of the due layers was too late to be picked up by the compositor. -
For the thermal sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
indicates that the current load should be sustainable in the near future.
Getting intoXR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT
fromXR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
indicates that the runtime does not presuppose any further temperature mitigation action on the application side, other than the current ones.
-
-
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
-
For the compositing sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
indicates that the compositing headroom of the current frame was met but the margin is considered insufficient by the runtime, and the application should reduce its workload in the notified domain to solve this problem.
Getting intoXR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
fromXR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that the compositing deadline was not missed during a sufficient time period. -
For the rendering sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
indicates that at least one layer is regularly late to be picked up by the compositor, resulting in a degraded user experience, and that the application should take action to consistently provide frames in a more timely manner.
Getting intoXR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
fromXR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that the runtime has stopped any of its own independent actions which are tied to theXR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
level. -
For the thermal sub-domain, the
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
indicates that the runtime expects the device to overheat under the current load, and that the application should take mitigating action in order to prevent thermal throttling.
Getting intoXR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT
fromXR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that the underlying system thermal throttling has stopped.
-
-
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
-
For the compositing sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that composition can no longer be maintained under the current workload. The runtime may take independent action that will interfere with the application (e.g. limiting the framerate, ignoring submitted layers, or shutting down the application) in order to correct this problem. -
For the rendering sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that at least one layer is too often late to be picked up by the compositor, and consequently the runtime may take independent action that will interfere with the application (e.g. informing the user that the application is not responding, displaying a tracking environment in order to maintain user orientation). -
For the thermal sub-domain,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that the underlying system is taking measures, such as thermal throttling to reduce the temperature, impacting the XR experience.
-
Leaving XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT
indicates that any mitigating actions by the runtime
(e.g. down-clocking the device to stay within thermal limits) have ended.
Performance Settings API Reference
xrPerfSettingsSetPerformanceLevelEXT
XrResult xrPerfSettingsSetPerformanceLevelEXT(
XrSession session,
XrPerfSettingsDomainEXT domain,
XrPerfSettingsLevelEXT level);
Refer to Performance level hint definition for the definition of the level enumerations.
XrEventDataPerformanceSettingsEXT
typedef struct XrEventDataPerfSettingsEXT {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrPerfSettingsDomainEXT domain;
XrPerfSettingsSubDomainEXT subDomain;
XrPerfSettingsNotificationLevelEXT fromLevel;
XrPerfSettingsNotificationLevelEXT toLevel;
} XrEventDataPerfSettingsEXT;
typedef enum XrPerfSettingsDomainEXT {
XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsDomainEXT;
typedef enum XrPerfSettingsSubDomainEXT {
XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT = 1,
XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT = 2,
XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT = 3,
XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsSubDomainEXT;
typedef enum XrPerfSettingsNotificationLevelEXT {
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,
XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsNotificationLevelEXT;
Version History
-
Revision 1, 2017-11-30 (Armelle Laine)
12.21. XR_EXT_thermal_query
- Name String
-
XR_EXT_thermal_query
- Extension Type
-
Instance extension
- Registered Extension Number
-
17
- Revision
-
1
- Extension and Version Dependencies
-
-
Requires OpenXR 0.90
-
- Last Modified Date
-
2017-11-30
- IP Status
-
No known IP claims.
- Contributors
-
Armelle Laine, Qualcomm Technologies Inc, on behalf of Qualcomm Innovation Center, Inc
12.21.1. Overview
This extension provides an API to query a domain’s current thermal warning level and current thermal trend.
12.21.2. Querying the current thermal level and trend
This query allows to determine the extent and urgency of the needed workload reduction
and to verify that the mitigation measures efficiently reduce the temperature.
This query allows the application to retrieve the current notificationLevel
,
allowing to quickly verify whether the underlying system’s thermal throttling is still in effect.
It also provides the application with the remaining temperature headroom (tempHeadroom
) until
thermal throttling occurs, and the current rate of change (tempSlope
).
The most critical temperature of the domain is the one which is currently most likely to be
relevant for thermal throttling.
To query the status of a given domain:
XrResult xrThermalGetTemperatureTrendEXT(
XrSession session,
XrPerfSettingsDomainEXT domain,
XrPerfSettingsNotificationLevelEXT* notificationLevel,
float* tempHeadroom,
float* tempSlope);
typedef enum XrPerfSettingsDomainEXT {
XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsDomainEXT;
typedef enum XrPerfSettingsNotificationLevelEXT {
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,
XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsNotificationLevelEXT;
For the definition of the notification levels, see Notification level definition
Thermal Query API Reference
xrThermalGetTemperatureTrendEXT
XrResult xrThermalGetTemperatureTrendEXT(
XrSession session,
XrPerfSettingsDomainEXT domain,
XrPerfSettingsNotificationLevelEXT* notificationLevel,
float* tempHeadroom,
float* tempSlope);
Allows to query the current temperature warning level of a domain, the remaining headroom and the trend.
typedef enum XrPerfSettingsDomainEXT {
XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsDomainEXT;
typedef enum XrPerfSettingsNotificationLevelEXT {
XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,
XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,
XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,
XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
} XrPerfSettingsNotificationLevelEXT;
Version History
-
Revision 1, 2017-11-30 (Armelle Laine)
Appendix
Code Style Conventions
These are the code style conventions used in this specification to define the API.
Prefixes are used in the API to denote specific semantic meaning of names, or as a label to avoid name clashes, and are explained here:
Prefix | Description |
---|---|
|
Enumerants and defines are prefixed with these characters. |
|
Non-function-pointer types are prefixed with these characters. |
|
Functions are prefixed with these characters. |
|
Function pointer types are prefixed with these characters. |
Application Binary Interface
This section describes additional definitions and conventions that define the application binary interface.
Structure Types
typedef enum XrStructureType {
XR_TYPE_UNKNOWN = 0,
XR_TYPE_API_LAYER_PROPERTIES = 1,
XR_TYPE_EXTENSION_PROPERTIES = 2,
XR_TYPE_INSTANCE_CREATE_INFO = 3,
XR_TYPE_SYSTEM_GET_INFO = 4,
XR_TYPE_SYSTEM_PROPERTIES = 5,
XR_TYPE_VIEW_LOCATE_INFO = 6,
XR_TYPE_VIEW = 7,
XR_TYPE_SESSION_CREATE_INFO = 8,
XR_TYPE_SWAPCHAIN_CREATE_INFO = 9,
XR_TYPE_SESSION_BEGIN_INFO = 10,
XR_TYPE_VIEW_STATE = 11,
XR_TYPE_FRAME_END_INFO = 12,
XR_TYPE_HAPTIC_VIBRATION = 13,
XR_TYPE_EVENT_DATA_BUFFER = 16,
XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING = 17,
XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED = 18,
XR_TYPE_ACTION_STATE_BOOLEAN = 23,
XR_TYPE_ACTION_STATE_VECTOR1F = 24,
XR_TYPE_ACTION_STATE_VECTOR2F = 25,
XR_TYPE_ACTION_STATE_POSE = 27,
XR_TYPE_ACTION_SET_CREATE_INFO = 28,
XR_TYPE_ACTION_CREATE_INFO = 29,
XR_TYPE_INSTANCE_PROPERTIES = 32,
XR_TYPE_FRAME_WAIT_INFO = 33,
XR_TYPE_COMPOSITION_LAYER_PROJECTION = 35,
XR_TYPE_COMPOSITION_LAYER_QUAD = 36,
XR_TYPE_REFERENCE_SPACE_CREATE_INFO = 37,
XR_TYPE_ACTION_SPACE_CREATE_INFO = 38,
XR_TYPE_SPACE_RELATION = 39,
XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING = 40,
XR_TYPE_VIEW_CONFIGURATION_VIEW = 41,
XR_TYPE_FRAME_STATE = 44,
XR_TYPE_VIEW_CONFIGURATION_PROPERTIES = 45,
XR_TYPE_FRAME_BEGIN_INFO = 46,
XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW = 48,
XR_TYPE_EVENT_DATA_EVENTS_LOST = 49,
XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING = 51,
XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED = 52,
XR_TYPE_INTERACTION_PROFILE_INFO = 53,
XR_TYPE_ACTIVE_ACTION_SET = 54,
XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO = 55,
XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO = 56,
XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO = 57,
XR_TYPE_COMPOSITION_LAYER_CUBE_KHR = 1000006000,
XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR = 1000008000,
XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR = 1000010000,
XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR = 1000014000,
XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT = 1000015000,
XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR = 1000017000,
XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR = 1000018000,
XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000019000,
XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000019001,
XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000019002,
XR_TYPE_DEBUG_UTILS_LABEL_EXT = 1000019003,
XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR = 1000023000,
XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR = 1000023001,
XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR = 1000023002,
XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR = 1000023003,
XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR = 1000023004,
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR = 1000023005,
XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR = 1000024001,
XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR = 1000024002,
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR = 1000024003,
XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR = 1000025000,
XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR = 1000025001,
XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR = 1000025002,
XR_TYPE_GRAPHICS_BINDING_D3D10_KHR = 1000026000,
XR_TYPE_SWAPCHAIN_IMAGE_D3D10_KHR = 1000026001,
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D10_KHR = 1000026002,
XR_TYPE_GRAPHICS_BINDING_D3D11_KHR = 1000027000,
XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR = 1000027001,
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR = 1000027002,
XR_TYPE_GRAPHICS_BINDING_D3D12_KHR = 1000028000,
XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR = 1000028001,
XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR = 1000028002,
XR_TYPE_VISIBILITY_MASK_KHR = 1000031000,
XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001,
XR_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrStructureType;
Most structures containing type
members have a value of type
matching the type of the structure, as described more fully in
Valid Usage for Structure Types.
Note that all extension enums begin at the extension enum base of 110 (base 10). Each extension is assigned a block of 1000 enums, starting at the enum base and arranged by the extension’s index.
For example, if an extension with index 5 wants to use an enum value of 3, the final enum is computed by:
enum = enum_base + (enum_index - 1) * 1000 + enum_value 1000004003 = 1000000000 + 4 * 1000 + 3
Flag Types
Flag types are all bitmasks aliasing the base type XrFlags64
and with
corresponding bit flag types defining the valid bits for that flag, as
described in Valid Usage for Flags. Flag types supported by the API include:
typedef XrFlags64 XrCompositionLayerFlags;
typedef XrFlags64 XrInputSourceLocalizedNameFlags;
typedef XrFlags64 XrInstanceCreateFlags;
typedef XrFlags64 XrSessionCreateFlags;
typedef XrFlags64 XrSpaceRelationFlags;
typedef XrFlags64 XrSwapchainCreateFlags;
typedef XrFlags64 XrSwapchainUsageFlags;
typedef XrFlags64 XrViewStateFlags;
General Macro Definitions
This API is defined in C and uses "C" linkage.
The openxr.h
header file is opened with:
#ifdef __cplusplus
extern "C" {
#endif
and closed with:
#ifdef __cplusplus
}
#endif
The supplied openxr.h
header defines a
small number of C preprocessor macros that are described below.
Version Number Macros
Two version numbers are defined in openxr.h
.
Each is packed into a 32-bit integer as described in
API Version Number Function-like Macros.
// OpenXR current version number.
#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(0, 90, 1)
XR_CURRENT_API_VERSION is the current version of the OpenXR API.
// Version of this file
#define XR_HEADER_VERSION 43
XR_HEADER_VERSION is the version number of the openxr.h
header.
This value is currently kept synchronized with the release number of the
Specification. However, it is not guaranteed to remain synchronized,
since most Specification updates have no effect on openxr.h
.
API Version Number Function-like Macros
API Version Numbers are three components, packed into a single 32-bit integer. The following macros manipulate version components and packed version numbers.
#define XR_MAKE_VERSION(major, minor, patch) \
(((major) << 22) | ((minor) << 12) | (patch))
XR_MAKE_VERSION constructs a packed 32-bit integer API version number from three components. The format used is described in API Version Numbers and Semantics.
This macro can be used when constructing the
XrApplicationInfo::apiVersion
parameter passed to xrCreateInstance.
#define XR_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
XR_VERSION_MAJOR extracts the API major version number from a packed version number.
#define XR_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
XR_VERSION_MINOR extracts the API minor version number from a packed version number.
#define XR_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
XR_VERSION_PATCH extracts the API patch version number from a packed version number.
Handle and Atom Macros
#if !defined(XR_DEFINE_HANDLE)
#if (XR_PTR_SIZE == 8)
#define XR_DEFINE_HANDLE(object) typedef struct object##_T* object;
#else
#define XR_DEFINE_HANDLE(object) typedef uint64_t object;
#endif
#endif
XR_DEFINE_HANDLE defines a handle type, which is an opaque 64 bit value, which may be implemented as an opaque, distinct pointer type on platforms with 64 bit pointers.
For further details, see Handles.
#if !defined(XR_NULL_HANDLE)
#if (XR_PTR_SIZE == 8) && XR_CPP_NULLPTR_SUPPORTED
#define XR_NULL_HANDLE nullptr
#else
#define XR_NULL_HANDLE 0
#endif
#endif
XR_NULL_HANDLE is a reserved value representing a non-valid object handle. It may be passed to and returned from API functions only when specifically allowed.
#if !defined(XR_DEFINE_ATOM)
#define XR_DEFINE_ATOM(object) typedef uint64_t object;
#endif
XR_DEFINE_ATOM defines an atom type, which is an opaque 64 bit integer.
Platform-Specific Macro Definitions
Additional platform-specific macros and interfaces are defined using the
included openxr_platform.h
file. These macros are used to control
platform-dependent behavior, and their exact definitions are under the
control of specific platform implementations of the API.
Platform-Specific Calling Conventions
On many platforms the following macros are empty strings, causing platform- and compiler-specific default calling conventions to be used.
XRAPI_ATTR is a macro placed before the return type of an API function declaration. This macro controls calling conventions for C++11 and GCC/Clang-style compilers.
XRAPI_CALL is a macro placed after the return type of an API function declaration. This macro controls calling conventions for MSVC-style compilers.
XRAPI_PTR is a macro placed between the ( and * in API function pointer declarations. This macro also controls calling conventions, and typically has the same definition as XRAPI_ATTR or XRAPI_CALL, depending on the compiler.
Examples:
Function declaration:
XRAPI_ATTR <return_type> XRAPI_CALL <function_name>(<function_parameters>);
Function pointer type declaration:
typedef <return_type> (XRAPI_PTR *PFN_<function_name>(<function_parameters>);
Platform-Specific Header Control
If the XR_NO_STDINT_H macro is defined by the application
at compile time, before including any OpenXR header,
extended integer types normally found in <stdint.h>
and
used by the OpenXR headers, such as uint8_t
,
must also be defined (as typedef
or with the preprocessor)
before including any OpenXR header.
Otherwise, openxr.h
and related headers will not compile.
If XR_NO_STDINT_H is not defined,
the system-provided <stdint.h>
is used to define these types.
There is a fallback path for Microsoft Visual Studio version 2008
and earlier versions (which lack this header)
that is automatically activated as needed.
Graphics API Header Control
Compile Time Symbol | Graphics API Name |
---|---|
OpenGL |
|
OpenGL ES |
|
Vulkan |
|
Direct3D 10.x |
|
Direct3D 11 |
|
Direct3D 12 |
Glossary
The terms defined in this section are used throughout this Specification. Capitalization is not significant for these definitions.
Term | Description |
---|---|
Application |
The XR application which calls the OpenXR API to communicate with an OpenXR runtime. |
Deprecated |
A feature/extension is deprecated if it is no longer recommended as the correct or best way to achieve its intended purpose. Generally a newer feature/extension will have been created that solves the same problem - in cases where no newer alternative feature exists, justification should be provided. |
Handle |
An opaque integer or pointer value used to refer to an object. Each object type has a unique handle type. |
Haptic |
Haptic or kinesthetic communication recreates the sense of touch by applying forces, vibrations, or motions to the user. |
In-Process |
Something that executes in the application’s process. |
Instance |
The top-level object, which represents the application’s connection to the runtime. Represented by an XrInstance object. |
Normalized |
A value that is interpreted as being in the range [0,1], or a vector whose norm is in that range, as a result of being implicitly divided or scaled by some other value. |
Out-Of-Process |
Something that executes outside the application’s process. |
Promoted |
A feature is promoted if it is taken from an older extension and made available as part of a new core version of the API, or a newer extension that is considered to be either as widely supported or more so. A promoted feature may have minor differences from the original such as:
|
Required Extensions |
Extensions that must be enabled alongside extensions dependent on them, or that must be enabled to use given hardware. |
Runtime |
The software which implements the OpenXR API and allows applications to interact with XR hardware. |
Swapchain |
A resource that represents a chain of images in device memory. Represented by an XrSwapchain object. |
Swapchain Image |
Each element in a swapchain. Commonly these are simple formatted 2D images, but in other cases they may be array images. Represented by a structure related to XrSwapchainImageBaseHeader. |
Abbreviations
Abbreviations and acronyms are sometimes used in the API where they are considered clear and commonplace, and are defined here:
Abbreviation | Description |
---|---|
API |
Application Programming Interface |
AR |
Augmented Reality |
ER |
Eye Relief |
IAD |
Inter Axial Distance |
IPD |
Inter Pupillary Distance |
MR |
Mixed Reality |
OS |
Operating System |
TSG |
Technical Sub-Group. A specialized sub-group within a Khronos Working Group (WG). |
VR |
Virtual Reality |
WG |
Working Group. An organized group of people working to define/augment an API. |
XR |
VR + AR + MR |
Dedication (Informative)
In memory of Johannes van Waveren: a loving father, husband, son, brother, colleague, and dear friend.
Johannes, known to his friends as "JP", had a great sense of humor, fierce loyalty, intense drive, a love of rainbow unicorns, and deep disdain for processed American cheese. Perhaps most distinguishing of all, though, was his love of technology and his extraordinary technical ability.
JP’s love of technology started at an early age --- instead of working on his homework, he built train sets, hovercrafts, and complex erector sets from scratch; fashioned a tool for grabbing loose change out of street grates; and played computer games. The passion for computer games continued at Delft University of Technology, where, armed with a T1 internet connection and sheer talent, he regularly destroyed his foes in arena matches without being seen, earning him the moniker "MrElusive". During this time, he wrote the Gladiator-bot AI, which earned him acclaim in the community and led directly to a job at the iconic American computer game company, id Software. From there, he quickly became an expert in every system he touched, contributing significantly to every facet of the technology: AI, path navigation, networking, skeletal animation, virtual texturing, advanced rendering, and physics. He became a master of all. He famously owned more lines of code than anyone else, but he was also a generous mentor, helping junior developers hone their skills and make their own contributions.
When the chance to work in the VR industry arose, he saw it as an opportunity to help shape the future. Having never worked on VR hardware did not phase him; he quickly became a top expert in the field. Many of his contributions directly moved the industry forward, most recently his work on asynchronous timewarp and open-standards development.
Time was not on his side. Even in his final days, JP worked tirelessly on the initial proposal for this specification. The treatments he had undergone took a tremendous physical toll, but he continued to work because of his love of technology, his dedication to the craft, and his desire to get OpenXR started on a solid footing. His focus was unwavering.
His proposal was unofficially adopted several days before his passing - and upon hearing, he mustered the energy for a smile. While it was his great dream to see this process through, he would be proud of the spirit of cooperation, passion, and dedication of the industry peers who took up the torch to drive this specification to completion.
JP lived a life full of accomplishment, as evidenced by many publications, credits, awards, and nominations where you will find his name. A less obvious accomplishment --- but of equal importance --- is the influence he had on people through his passionate leadership. He strove for excellence in everything that he did. He was always excited to talk about technology and share the discoveries made while working through complex problems. He created excitement and interest around engineering and technical excellence. He was a mentor and teacher who inspired those who knew him and many continue to benefit from his hard work and generosity.
JP was a rare gem; fantastically brilliant intellectually, but also warm, compassionate, generous, humble, and funny. Those of us lucky enough to have crossed paths with him knew what a privilege and great honor it was to know him. He is certainly missed.
Contributors (Informative)
OpenXR is the result of contributions from many people and companies participating in the Khronos OpenXR Working Group. Members of the Working Group, including the company that they represented at the time of their most recent contribution, are listed below.
Contributors to OpenXR 0.90 Provisional
-
Adam Gousetis, Google
-
Alex Turner, Microsoft
-
Andreas Loeve Selvik, Arm
-
Andres Rodriguez, Valve Software
-
Armelle Laine, Qualcomm Technologies, Inc
-
Blake Taylor, Magic Leap
-
Brad Grantham, Google
-
Brandon Jones, Google
-
Brent E. Insko, Intel
-
Brent Wilson, Microsoft
-
Bryce Hutchings, Microsoft
-
Cass Everitt, Facebook
-
Charles Egenbacher, Epic Games
-
Christoph Haag, Collabora
-
Craig Donner, Google
-
Dan Ginsburg, Valve Software
-
Dave Houlton, LunarG
-
Dave Shreiner, Unity Technologies
-
Denny Rönngren, Tobii
-
Dmitriy Vasilev, Samsung
-
Doug Twileager, ZSpace
-
Ed Hutchins, Facebook
-
Gloria Kennickell, Facebook
-
Gregory Greeby, AMD
-
Guodong Chen, Huawei
-
Jakob Bornecrantz, Collabora
-
Jared Cheshier, PlutoVR
-
Javier Martinez, Intel
-
Jeff Bellinghausen, Valve Software
-
Jiehua Guo, Huawei
-
Joe Ludwig, Valve Software
-
Johannes van Waveren, Facebook
-
Jon Leech, Khronos
-
Jonathan Wright, Facebook
-
Juan Wee, Samsung
-
Jules Blok, Epic Games
-
Karl Schultz, LunarG
-
Kaye Mason, Google
-
Krzysztof Kosiński, Google
-
Lachlan Ford, Microsoft
-
Lubosz Sarnecki, Collabora
-
Mark Young, LunarG
-
Martin Renschler, Qualcomm Technologies, Inc.
-
Matias Koskela, Tampere University of Technology
-
Matt Wash, Arm
-
Mattias Brand, Tobii
-
Mattias O. Karlsson, Tobii
-
Michael Gatson, Dell
-
Minmin Gong, Microsoft
-
Mitch Singer, AMD
-
Nell Waliczek, Microsoft
-
Nick Whiting, Epic Games
-
Nigel Williams, Sony
-
Paul Pedriana, Facebook
-
Peter Kuhn, Unity Technologies
-
Peter Peterson, HP Inc.
-
Pierre-Loup Griffais, Valve Software
-
Rajeev Gupta, Sony
-
Remi Arnaud, Starbreeze
-
Remy Zimmerman, Logitech
-
River Gillis, Google
-
Robert Memmott, Facebook
-
Robert Menzel, NVIDIA
-
Robert Simpson, Qualcomm Technologies, Inc.
-
Robin Bourianes, Starbreeze
-
Ryan Pavlik, Collabora
-
Ryan Vance, Epic Games
-
Sam Martin, Arm
-
Satish Salian, NVIDIA
-
Scott Flynn, Unity Technologies
-
Sophia Baldonado, PlutoVR
-
Sungye Kim, Intel
-
Tom Flynn, Samsung
-
Trevor F. Smith, Mozilla
-
Vivek Viswanathan, Dell
-
Yin Li, Microsoft
-
Yuval Boger, Sensics