Preamble
Copyright (c) 2017-2025 The Khronos Group Inc.
This Specification is protected by copyright laws and contains material proprietary to Khronos. Except as described by these terms, it or any components may not be reproduced, republished, distributed, transmitted, displayed, broadcast or otherwise exploited in any manner without the express prior written permission of Khronos.
Khronos grants a conditional copyright license to use and reproduce the unmodified Specification for any purpose, without fee or royalty, EXCEPT no licenses to any patent, trademark or other intellectual property rights are granted under these terms.
Khronos makes no, and expressly disclaims any, representations or warranties, express or implied, regarding this Specification, including, without limitation: merchantability, fitness for a particular purpose, non-infringement of any intellectual property, correctness, accuracy, completeness, timeliness, and reliability. Under no circumstances will Khronos, or any of its Promoters, Contributors or Members, or their respective partners, officers, directors, employees, agents or representatives be liable for any damages, whether direct, indirect, special or consequential damages for lost revenues, lost profits, or otherwise, arising from or in connection with these materials.
This document contains extensions which are not ratified by Khronos, and as such is not a ratified Specification, though it contains text from (and is a superset of) the ratified OpenXR Specification that can be found at https://registry.khronos.org/OpenXR/specs/1.1-khr/html/xrspec.html (core with KHR extensions).
The Khronos Intellectual Property Rights Policy defines the terms 'Scope', 'Compliant Portion', and 'Necessary Patent Claims'.
Some parts of this Specification are purely informative and so are EXCLUDED from the Scope of this Specification. The Document Conventions section of the Introduction defines how these parts of the Specification are identified.
Where this Specification uses technical terminology, defined in the Glossary or otherwise, that refer to enabling technologies that are not expressly set forth in this Specification, those enabling technologies are EXCLUDED from the Scope of this Specification. For clarity, enabling technologies not disclosed with particularity in this Specification (e.g. semiconductor manufacturing technology, hardware architecture, processor architecture or microarchitecture, memory architecture, compiler technology, object oriented technology, basic operating system technology, compression technology, algorithms, and so on) are NOT to be considered expressly set forth; only those application program interfaces and data structures disclosed with particularity are included in the Scope of this Specification.
For purposes of the Khronos Intellectual Property Rights Policy as it relates to the definition of Necessary Patent Claims, all recommended or optional features, behaviors and functionality set forth in this Specification, if implemented, are considered to be included as Compliant Portions.
Khronos® and Vulkan® are registered trademarks, and glTF™ is a trademark of The Khronos Group Inc. OpenXR™ is a trademark owned by The Khronos Group Inc. and is registered as a trademark in China, the European Union, Japan and the United Kingdom. OpenGL® is a registered trademark and the OpenGL ES™ and OpenGL SC™ logos are trademarks of Hewlett Packard Enterprise used under license by Khronos. All other product names, trademarks, and/or company names are used solely for identification and belong to their respective owners.
1. Introduction
This chapter is informative except for the section on Normative Terminology.
This document, referred to as the "OpenXR Specification" or just the "Specification" hereafter, describes OpenXR: what it is, how it acts, and what is required to implement it. We assume that the reader has a basic understanding of computer graphics and the technologies involved in virtual and augmented reality. This means familiarity with the essentials of computer graphics algorithms and terminology, modern GPUs (Graphic Processing Units), tracking technologies, head mounted devices, and input modalities.
The canonical version of the Specification is available in the official OpenXR Registry, located at URL
1.1. What is OpenXR?
OpenXR is an API (Application Programming Interface) for XR applications. XR refers to a continuum of real-and-virtual combined environments generated by computers through human-machine interaction and is inclusive of the technologies associated with virtual reality (VR), augmented reality (AR) and mixed reality (MR). OpenXR is the interface between an application and an in-process or out-of-process "XR runtime system", or just "runtime" hereafter. The runtime may handle such functionality as frame composition, peripheral management, and raw tracking information.
Optionally, a runtime may support device layer plugins which allow access to a variety of hardware across a commonly defined interface.
1.2. The Programmer’s View of OpenXR
To the application programmer, OpenXR is a set of functions that interface with a runtime to perform commonly required operations such as accessing controller/peripheral state, getting current and/or predicted tracking positions, and submitting rendered frames.
A typical OpenXR program begins with a call to create an instance which establishes a connection to a runtime. Then a call is made to create a system which selects for use a physical display and a subset of input, tracking, and graphics devices. Subsequently a call is made to create buffers into which the application will render one or more views using the appropriate graphics APIs for the platform. Finally calls are made to create a session and begin the application’s XR rendering loop.
1.3. The Implementor’s View of OpenXR
To the runtime implementor, OpenXR is a set of functions that control the operation of the XR system and establishes the lifecycle of a XR application.
The implementor’s task is to provide a software library on the host which implements the OpenXR API, while mapping the work for each OpenXR function to the graphics hardware as appropriate for the capabilities of the device.
1.4. Our View of OpenXR
We view OpenXR as a mechanism for interacting with VR/AR/MR systems in a platform-agnostic way.
We expect this model to result in a specification that satisfies the needs of both programmers and runtime implementors. It does not, however, necessarily provide a model for implementation. A runtime implementation must produce results conforming to those produced by the specified methods, but may carry out particular procedures in ways that are more efficient than the one specified.
1.5. Filing Bug Reports
Issues with and bug reports on the OpenXR Specification and the API Registry can be filed in the Khronos OpenXR GitHub repository, located at URL
Please tag issues with appropriate labels, such as “Specification”, “Ref Pages” or “Registry”, to help us triage and assign them appropriately. Unfortunately, GitHub does not currently let users who do not have write access to the repository set GitHub labels on issues. In the meantime, they can be added to the title line of the issue set in brackets, e.g. “[Specification]”.
1.6. Document Conventions
The OpenXR specification is intended for use by both implementors of the API and application developers seeking to make use of the API, forming a contract between these parties. Specification text may address either party; typically the intended audience can be inferred from context, though some sections are defined to address only one of these parties. (For example, Valid Usage sections only address application developers). Any requirements, prohibitions, recommendations or options defined by normative terminology are imposed only on the audience of that text.
1.6.1. Normative Terminology
The key words must, required, should, may, and optional in this document, when denoted as above, are to be interpreted as described in RFC 2119:
- must
-
When used alone, this word, or the term required, means that the definition is an absolute requirement of the specification. When followed by not (“must not” ), the phrase means that the definition is an absolute prohibition of the specification.
- should
-
When used alone, this word means that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course. When followed by not (“should not”), the phrase means that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label.
- may
-
This word, or the adjective optional, means that an item is truly optional. One vendor may choose to include the item because a particular marketplace requires it or because the vendor feels that it enhances the product while another vendor may omit the same item.
The additional terms can and cannot are to be interpreted as follows:
- can
-
This word means that the particular behavior described is a valid choice for an application, and is never used to refer to runtime behavior.
- cannot
-
This word means that the particular behavior described is not achievable by an application, for example, an entry point does not exist.
There is an important distinction between cannot and must not, as used in this Specification. Cannot means something the application literally is unable to express or accomplish through the API, while must not means something that the application is capable of expressing through the API, but that the consequences of doing so are undefined and potentially unrecoverable for the runtime. |
2. Fundamentals
2.1. API Version Numbers and Semantics
Multi-part version numbers are used in several places in the OpenXR API.
// Provided by XR_VERSION_1_0
typedef uint64_t XrVersion;
In each such use, the API major version number, minor version number, and
patch version number are packed into a 64-bit integer, referred to as
XrVersion
, as follows:
Differences in any of the version numbers indicate a change to the API, with each part of the version number indicating a different scope of change, as follows.
Note
The rules below apply to OpenXR versions 1.0 or later. Prerelease versions of OpenXR may use different rules for versioning. |
A difference in patch version numbers indicates that some usually small part of the specification or header has been modified, typically to fix a bug, and may have an impact on the behavior of existing functionality. Differences in the patch version number must affect neither full compatibility nor backwards compatibility between two versions, nor may it add additional interfaces to the API. Runtimes may use patch version number to determine whether to enable implementation changes, such as bug fixes, that impact functionality. Runtimes should document any changes that are tied to the patch version. Application developers should retest their application on all runtimes they support after compiling with a new version.
A difference in minor version numbers indicates that some amount of new functionality has been added. This will usually include new interfaces in the header, and may also include behavior changes and bug fixes. Functionality may be deprecated in a minor revision, but must not be removed. When a new minor version is introduced, the patch version continues where the last minor version left off, making patch versions unique inside major 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 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 normative language 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, lower latency, or otherwise yield better results. It is possible that some runtimes may choose to give run-time warnings that the feature has been weakly deprecated and will likely be strongly deprecated or removed in the future. |
Strong Deprecation |
An interface may have been strongly deprecated at this level. This means that the interface must still exist (so applications that are compiled against it will still run) but it may now be a no-op, or it may be that its behavior has been significantly changed. It may be that this functionality is no longer necessary, or that its functionality has been subsumed by another call. This should not break an application, but some behavior may be different or unanticipated. |
Interfaces Changed/Removed |
An interface may have been changed — with different parameters or return types — at this level. An interface or feature may also have been removed entirely. It is almost certain that rebuilding applications will be required. |
2.2. String Encoding
This API uses strings as input and output for some functions.
Unless otherwise specified, all such strings are NULL
terminated UTF-8
encoded case-sensitive character arrays.
2.3. Threading Behavior
The OpenXR API is intended to provide scalable performance when used on multiple host threads. All functions must support being called concurrently from multiple threads, but certain parameters, or components of parameters are defined to be externally synchronized. This means that the caller must guarantee that no more than one thread is using such a parameter at a given time.
More precisely, functions use simple stores to update software structures representing objects. A parameter declared as externally synchronized may have its software structures updated at any time during the host execution of the function. If two functions operate on the same object and at least one of the functions declares the object to be externally synchronized, then the caller must guarantee not only that the functions do not execute simultaneously, but also that the two functions are separated by an appropriate memory barrier if needed.
For all functions which destroy an object handle, the application must externally synchronize the object handle parameter and any child handles.
2.4. Multiprocessing Behavior
The OpenXR API does not explicitly recognize nor require support for multiple processes using the runtime simultaneously, nor does it prevent a runtime from providing such support.
2.5. Runtime
An OpenXR runtime is software which implements the OpenXR API. There may be more than one OpenXR runtime installed on a system, but only one runtime can be active at any given time.
2.6. Extensions
OpenXR is an extensible API that grows through the addition of new features. Similar to other Khronos APIs, extensions may expose new OpenXR functions or modify the behavior of existing OpenXR functions. Extensions are optional, and therefore must be enabled by the application before the extended functionality is made available. Because extensions are optional, they may be implemented only on a subset of runtimes, graphics platforms, or operating systems. Therefore, an application should first query which extensions are available before enabling.
The application queries the available list of extensions using the xrEnumerateInstanceExtensionProperties function. Once an application determines which 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:
is an OpenXR extension
created by the Khronos (KHR) OpenXR Working Group to support cube
composition layers.XR_KHR_composition_layer_cube
The public list of available extensions known and configured for inclusion in this document 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 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 potentially expensive validation of correct API usage to be implemented in a "validation" layer. Such a layer allows the application developer to develop their application with a validation layer active to ensure that the application is using the API correctly. A 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 a 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 a validation layer to allow the application to run in a production environment without repeatedly incurring the validation expense. (Note that some validation of correct API usage is required to be implemented by the runtime.)
2.7.2. Naming API Layers
To organize API layer names and prevent collisions in the API layer name namespace, API layers must be named using the following convention:
XR_APILAYER_<VENDOR-TAG>_short_name
Vendors are responsible for registering a vendor tag with the OpenXR working group, and just like for implementors, they must maintain their vendor namespace.
Example of an API layer name produced by the Acme company for the "check best practices" API layer:
XR_APILAYER_ACME_check_best_practices
2.7.3. Activating API Layers
Application Activation
Applications can determine the API layers that are available to them by calling the xrEnumerateApiLayerProperties function to obtain a list of available API layers. Applications then can select the desired API layers from this list and provide them to the xrCreateInstance function when creating an instance.
System Activation
Application users or users performing roles such as system integrator or system administrator may configure a system to activate API layers without involvement from the applications. These platform-dependent steps may include the installation of API layer-related files, setting environment variables, or other platform-specific operations. The options that are available for configuring the API layers in this manner are also dependent on the platform and/or runtime.
2.7.4. API Layer Extensions
API layers may implement OpenXR functions that are not 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 by that API layer.
2.8. Type Aliasing
Type aliasing refers to the situation in which the actual type of a element
does not match the declared type.
Some C and C++ compilers assume that the actual type matches the declared
type in some configurations, and may be so configured by default at common
optimization levels.
In such a compiler configured with that assumption, violating the assumption
may produce undefined behavior.
This compiler feature is typically referred to as "strict aliasing," and it
can usually be enabled or disabled via compiler options.
The OpenXR specification does not support strict aliasing, as there are
some cases in which an application intentionally provides a struct with a
type that differs from the declared type.
For example, XrFrameEndInfo::layers
is an array of type
const
XrCompositionLayerBaseHeader code:* const
.
However, each element of the array must be of one of the specific layer
types, such as XrCompositionLayerQuad.
Similarly, xrEnumerateSwapchainImages accepts an array of
XrSwapchainImageBaseHeader, whereas the actual type passed must be an
array of a type such as
XrSwapchainImageVulkanKHR
.
For OpenXR to work correctly, the compiler must support the type aliasing described here.
// Provided by XR_VERSION_1_0
#if !defined(XR_MAY_ALIAS)
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4))
#define XR_MAY_ALIAS __attribute__((__may_alias__))
#else
#define XR_MAY_ALIAS
#endif
#endif
As a convenience, some types and pointers that are known at specification time to alias values of different types have been annotated with the XR_MAY_ALIAS definition. If this macro is not defined before including OpenXR headers, and a new enough Clang or GCC compiler is used, it is defined to a compiler-specific attribute annotation to inform these compilers that those pointers may alias. However, there is no guarantee that all aliasing types or pointers have been correctly marked with this macro, so thorough testing is still recommended if you choose (at your own risk) to permit your compiler to perform type-based aliasing analysis.
2.9. Valid Usage
Valid usage defines a set of conditions which must be met in order to achieve well-defined run-time behavior in an application. These conditions depend only on API state, and the parameters or objects whose usage is constrained by the condition.
Some valid usage conditions have dependencies on runtime limits or feature availability. It is possible to validate these conditions against the API’s minimum or maximum supported values for these limits and features, or some subset of other known values.
Valid usage conditions should apply to a function or structure where complete information about the condition would be known during execution of an application. This is such that a validation API layer or linter can be written directly against these statements at the point they are specified.
2.9.1. Implicit Valid Usage
Some valid usage conditions apply to all functions and structures in the API, unless explicitly denoted otherwise for a specific function or structure. These conditions are considered implicit. Implicit valid usage conditions are described in detail below.
2.9.2. Valid Usage for Object Handles
Any input parameter to a function that is an object handle must be a valid object handle, unless otherwise specified. An object handle is valid if and only if all of the following conditions hold:
There are contexts in which an object handle is optional or otherwise
unspecified.
In those cases, the API uses XR_NULL_HANDLE, which has the integer
value 0
.
2.9.3. Valid Usage for Pointers
Any parameter that is a pointer must be a valid pointer when the specification indicates that the runtime uses the pointer. A pointer is valid if and only if it points at memory containing values of the number and type(s) expected by the function, and all fundamental types accessed through the pointer (e.g. as elements of an array or as members of a structure) satisfy the alignment requirements of the host processor.
2.9.4. Valid Usage for Enumerated Types
Any parameter of an enumerated type must be a valid enumerant for that type. An enumerant is valid if and only if the enumerant is defined as part of the enumerated type in question.
2.9.5. Valid Usage for Flags
A collection of flags is represented by a bitmask using the type
XrFlags64
:
typedef uint64_t XrFlags64;
Bitmasks are passed to many functions and structures to compactly represent
options and are stored in memory defined by the XrFlags64
type.
But the API does not use the XrFlags64
type directly.
Instead, a Xr*Flags
type is used which is an alias of the
XrFlags64
type.
The API also defines a set of constant bit definitions used to set the
bitmasks.
Any Xr*Flags
member or parameter used in the API must be a valid
combination of bit flags.
A valid combination is either zero or the bitwise OR
of valid bit
flags.
A bit flag is valid if and only if:
2.9.6. Valid Usage for Structure Types
Any parameter that is a structure containing a type
member must have
a value of type
which is a valid XrStructureType value matching
the type of the structure.
As a general rule, the name of this value is obtained by taking the
structure name, stripping the leading Xr
, prefixing each capital letter
with an underscore, converting the entire resulting string to upper case,
and prefixing it with XR_TYPE_
.
The only exceptions to this rule are API and Operating System names which are converted in a way that produces a more readable value:
2.9.7. Valid Usage for Structure Pointer Chains
Any structure containing a void*
next
member must have a value
of next
that is either NULL
, or points to a valid structure that
also contains type
and next
member values.
The set of structures connected by next
pointers is referred to as a
next
chain.
In order to use a structure type defined by an extension in a next
chain, the proper extension must have been previously enabled during
xrCreateInstance.
A runtime must ignore all unrecognized structures in a next
chain,
including those associated with an extension that has not been enabled.
Some structures for use in a chain are described in the core OpenXR specification and are mentioned in the Member Descriptions. Any structure described in this document intended for use in a chain is mentioned in a "See also" list in the implicit valid usage of the structure they chain to. Most chained structures are associated with extensions, and are described in the base OpenXR Specification under the List of Extensions. Vendor-specific extensions may be found there as well, or may only be available from the vendor’s website or internal document repositories.
Unless otherwise specified: Chained structs which are output structs may be modified by the runtime with the exception of the type and next fields. Upon return from any function, all type and next fields in the chain must be unmodified.
Useful Base Structures
As a convenience to runtimes and layers needing to iterate through a structure pointer chain, the OpenXR API provides the following base structures:
The XrBaseInStructure structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrBaseInStructure {
XrStructureType type;
const struct XrBaseInStructure* next;
} XrBaseInStructure;
XrBaseInStructure can be used to facilitate iterating through a read-only structure pointer chain.
The XrBaseOutStructure structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrBaseOutStructure {
XrStructureType type;
struct XrBaseOutStructure* next;
} XrBaseOutStructure;
XrBaseOutStructure can be used to facilitate iterating through a structure pointer chain that returns data back to the application.
These structures allow for some type safety and can be used by OpenXR API functions that operate on generic inputs and outputs.
Next Chain Structure Uniqueness
Applications should ensure that they create and insert no more than one
occurrence of each type of extension structure in a given next
chain.
Other components of OpenXR (such as the OpenXR loader or an API Layer) may
insert duplicate structures into this chain.
This provides those components the ability to update a structure that
appears in the next
chain by making a modified copy of that same
structure and placing the new version at the beginning of the chain.
The benefit of allowing this duplication is each component is no longer
required to create a copy of the entire next
chain just to update one
structure.
When duplication is present, all other OpenXR components must process only
the first instance of a structure of a given type, and then ignore all
instances of a structure of that same type.
If a component makes such a structure copy, and the original structure is also used to return content, then that component must copy the necessary content from the copied structure and into the original version of the structure upon completion of the function prior to proceeding back up the call stack. This is to ensure that OpenXR behavior is consistent whether or not that particular OpenXR component is present and/or enabled on the system.
2.9.8. Valid Usage for Nested Structures
The above conditions also apply recursively to members of structures provided as input to a function, either as a direct argument to the function, or themselves a member of another structure.
Specifics on valid usage of each function are covered in their individual sections.
2.10. Return Codes
The core API is designed to capture most, but not all, instances of incorrect usage. As such, most functions provide return codes. Functions in the API return their status via return codes that are in one of the two categories below.
typedef enum XrResult {
XR_SUCCESS = 0,
XR_TIMEOUT_EXPIRED = 1,
XR_SESSION_LOSS_PENDING = 3,
XR_EVENT_UNAVAILABLE = 4,
XR_SPACE_BOUNDS_UNAVAILABLE = 7,
XR_SESSION_NOT_FOCUSED = 8,
XR_FRAME_DISCARDED = 9,
XR_ERROR_VALIDATION_FAILURE = -1,
XR_ERROR_RUNTIME_FAILURE = -2,
XR_ERROR_OUT_OF_MEMORY = -3,
XR_ERROR_API_VERSION_UNSUPPORTED = -4,
XR_ERROR_INITIALIZATION_FAILED = -6,
XR_ERROR_FUNCTION_UNSUPPORTED = -7,
XR_ERROR_FEATURE_UNSUPPORTED = -8,
XR_ERROR_EXTENSION_NOT_PRESENT = -9,
XR_ERROR_LIMIT_REACHED = -10,
XR_ERROR_SIZE_INSUFFICIENT = -11,
XR_ERROR_HANDLE_INVALID = -12,
XR_ERROR_INSTANCE_LOST = -13,
XR_ERROR_SESSION_RUNNING = -14,
XR_ERROR_SESSION_NOT_RUNNING = -16,
XR_ERROR_SESSION_LOST = -17,
XR_ERROR_SYSTEM_INVALID = -18,
XR_ERROR_PATH_INVALID = -19,
XR_ERROR_PATH_COUNT_EXCEEDED = -20,
XR_ERROR_PATH_FORMAT_INVALID = -21,
XR_ERROR_PATH_UNSUPPORTED = -22,
XR_ERROR_LAYER_INVALID = -23,
XR_ERROR_LAYER_LIMIT_EXCEEDED = -24,
XR_ERROR_SWAPCHAIN_RECT_INVALID = -25,
XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26,
XR_ERROR_ACTION_TYPE_MISMATCH = -27,
XR_ERROR_SESSION_NOT_READY = -28,
XR_ERROR_SESSION_NOT_STOPPING = -29,
XR_ERROR_TIME_INVALID = -30,
XR_ERROR_REFERENCE_SPACE_UNSUPPORTED = -31,
XR_ERROR_FILE_ACCESS_ERROR = -32,
XR_ERROR_FILE_CONTENTS_INVALID = -33,
XR_ERROR_FORM_FACTOR_UNSUPPORTED = -34,
XR_ERROR_FORM_FACTOR_UNAVAILABLE = -35,
XR_ERROR_API_LAYER_NOT_PRESENT = -36,
XR_ERROR_CALL_ORDER_INVALID = -37,
XR_ERROR_GRAPHICS_DEVICE_INVALID = -38,
XR_ERROR_POSE_INVALID = -39,
XR_ERROR_INDEX_OUT_OF_RANGE = -40,
XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED = -41,
XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED = -42,
XR_ERROR_NAME_DUPLICATED = -44,
XR_ERROR_NAME_INVALID = -45,
XR_ERROR_ACTIONSET_NOT_ATTACHED = -46,
XR_ERROR_ACTIONSETS_ALREADY_ATTACHED = -47,
XR_ERROR_LOCALIZED_NAME_DUPLICATED = -48,
XR_ERROR_LOCALIZED_NAME_INVALID = -49,
XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING = -50,
XR_ERROR_RUNTIME_UNAVAILABLE = -51,
// Provided by XR_VERSION_1_1
XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED = -1000710001,
// Provided by XR_VERSION_1_1
XR_ERROR_PERMISSION_INSUFFICIENT = -1000710000,
// Provided by XR_PICO_virtual_boundary
XR_ERROR_VIRTUAL_BOUNDARY_TRIGGER_NODE_TYPE_UNSUPPORTED_PICO = -1010001000,
// Provided by XR_PICO_motion_tracking
XR_ERROR_MOTION_TRACKER_TYPE_MISMATCH_PICO = -1010002000,
// Provided by XR_PICO_motion_tracking
XR_ERROR_MOTION_TRACKER_COUNT_EXCEEDED_PICO = -1010002001,
// Provided by XR_PICO_motion_tracking
XR_ERROR_MOTION_TRACKING_MODE_MISMATCH_PICO = -1010002002,
// Provided by XR_PICO_motion_tracking
XR_ERROR_MOTION_TRACKER_ID_INVALID_PICO = -1010002003,
// Provided by XR_PICO_secure_mixed_reality
XR_ERROR_SECURE_MR_UNREGISTERED_HANDLE_PICO = -1010007000,
// Provided by XR_PICO_secure_mixed_reality
XR_ERROR_SECURE_MR_INVALID_PARAM_PICO = -1010007001,
// Provided by XR_PICO_secure_mixed_reality
XR_ERROR_SECURE_MR_PIPELINE_LOCKED_PICO = -1010007002,
// Provided by XR_PICO_secure_mixed_reality
XR_ERROR_SECURE_MR_USAGE_BEFORE_INIT_PICO = -1010007003,
// Provided by XR_PICO_secure_mixed_reality
XR_ERROR_SECURE_MR_OTHER_INTERNAL_ERROR_PICO = -1010007004,
// Provided by XR_PICO_expand_device
XR_ERROR_EXPAND_TRACKER_ID_INVALID_PICO = -1010008000,
XR_RESULT_MAX_ENUM = 0x7FFFFFFF
} XrResult;
All return codes in the API are reported via XrResult return values.
The following are common suffixes shared across many of the return codes:
-
_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 the handle taken by this function, but is not usable at this moment.
Success Codes
Enum | Description |
---|---|
|
Function successfully completed. |
|
The specified timeout time occurred before the operation could complete. |
|
The session will be lost soon. |
|
No event was available. |
|
The space’s bounds are not known at the moment. |
|
The session is not in the focused state. |
|
A frame has been discarded from composition. |
Error Codes
Enum | Description |
---|---|
|
The function usage was invalid in some way. |
|
The runtime failed to handle the function in an unexpected way that is not covered by another error result. |
|
A memory allocation has failed. |
|
The runtime does not support the requested API version. |
|
Initialization of object could not be completed. |
|
The requested function was not found or is otherwise unsupported. |
|
The requested feature is not supported. |
|
A requested extension is not supported. |
|
The runtime supports no more of the requested resource. |
|
The supplied size was smaller than required. |
|
A supplied object handle was invalid. |
|
The XrInstance was lost or could not be found. It will need to be destroyed and optionally recreated. |
|
The session is already running. |
|
The session is not yet running. |
|
The XrSession was lost. It will need to be destroyed and optionally recreated. |
|
The provided |
|
The provided |
|
The maximum number of supported semantic paths has been reached. |
|
The semantic path character format is invalid. |
|
The semantic path is unsupported. |
|
The layer was NULL or otherwise invalid. |
|
The number of specified layers is greater than the supported number. |
|
The image rect was negatively sized or otherwise invalid. |
|
The image format is not supported by the runtime or platform. |
|
The API used to retrieve an action’s state does not match the action’s type. |
|
The session is not in the ready state. |
|
The session is not in the stopping state. |
|
The provided |
|
The specified reference space is not supported by the runtime or system. |
|
The file could not be accessed. |
|
The file’s contents were invalid. |
|
The specified form factor is not supported by the current runtime or platform. |
|
The specified form factor is supported, but the device is currently not available, e.g. not plugged in or powered off. |
|
A requested API layer is not present or could not be loaded. |
|
The call was made without having made a previously required call. |
|
The given graphics device is not in a valid state. The graphics device could be lost or initialized without meeting graphics requirements. |
|
The supplied pose was invalid with respect to the requirements. |
|
The supplied index was outside the range of valid indices. |
|
The specified view configuration type is not supported by the runtime or platform. |
|
The specified environment blend mode is not supported by the runtime or platform. |
|
The name provided was a duplicate of an already-existing resource. |
|
The name provided was invalid. |
|
A referenced action set is not attached to the session. |
|
The session already has attached action sets. |
|
The localized name provided was a duplicate of an already-existing resource. |
|
The localized name provided was invalid. |
|
The |
|
The loader was unable to find or load a runtime. |
|
One or more of the extensions being enabled has dependency on extensions that are not enabled. |
|
Insufficient permissions. This error is included for use by vendor extensions. The precise definition of |
|
The trigger node is not supported by the runtime. (Added by the |
|
The connected tracker type is not motion tracker. (Added by the |
|
The tracker num is exceeded. (Added by the |
|
The tracking mode is not motion tracking. (Added by the |
|
The tracker id is invalid. (Added by the |
|
cannot find the object being referred (Added by the |
|
parameters to the API is invalid (Added by the |
|
pipeline being locked, cannot perform the requested API calls (Added by the |
|
renderer or render assets not initialized (Added by the |
|
all other error types are converged here (Added by the |
|
The expand tracker id is invalid. (Added by the |
2.10.1. Convenience Macros
// Provided by XR_VERSION_1_0
#define XR_SUCCEEDED(result) ((result) >= 0)
A convenience macro that can be used to test if a function succeeded.
Note that this evaluates to true for all success codes, including a
qualified success such as XR_FRAME_DISCARDED
.
// Provided by XR_VERSION_1_0
#define XR_FAILED(result) ((result) < 0)
A convenience macro that can be used to test if a function has failed in some way. It evaluates to true for all failure codes.
// Provided by XR_VERSION_1_0
#define XR_UNQUALIFIED_SUCCESS(result) ((result) == 0)
A convenience macro that can be used to test a function’s failure.
The XR_UNQUALIFIED_SUCCESS macro evaluates to true exclusively when
the provided XrResult is equal to XR_SUCCESS
(0
).
2.10.2. Validation
Except as noted below or in individual API specifications, valid API usage may be required by the runtime. Runtimes may choose to validate some API usage and return an appropriate error code.
Application developers should use validation layers to catch and eliminate errors during development. Once validated, applications should not enable validation layers by default.
If a function returns a run time error, unless otherwise specified any
output parameters will have undefined contents, except that if the output
parameter is a structure with type
and next
fields, those fields will be
unmodified.
Any output structures chained from next
will also have undefined contents,
except that the type
and next
will be unmodified.
Unless otherwise specified, errors do not affect existing OpenXR objects. Objects that have already been successfully created may still be used by the application.
XrResult code returns may be added to a given function in future versions of the specification. Runtimes must return only XrResult codes from the set documented for the given application API version.
Runtimes must ensure that incorrect usage by an application does not affect the integrity of the operating system, the API implementation, or other API client applications in the system, and does not allow one application to access data belonging to another application.
2.11. Handles
Objects which are allocated by the runtime on behalf of applications are
represented by handles.
Handles are opaque identifiers for objects whose lifetime is controlled by
applications via the create and destroy functions.
Example handle types include XrInstance, XrSession, and
XrSwapchain.
Handles which have not been destroyed are unique for a given application
process, but may be reused after being destroyed.
Unless otherwise specified, a successful handle creation function call
returns a new unique handle.
Unless otherwise specified, handles are implicitly destroyed when their
parent handle is destroyed.
Applications may destroy handles explicitly before the parent handle is
destroyed, and should do so if no longer needed, in order to conserve
resources.
Runtimes may detect XR_NULL_HANDLE and other invalid handles passed
where a valid handle is required and return XR_ERROR_HANDLE_INVALID
.
However, runtimes are not required to do so unless otherwise specified, and
so use of any invalid handle may result in undefined behavior.
When a function has an optional handle parameter, XR_NULL_HANDLE
must be passed by the application if it does not pass a valid handle.
All functions that take a handle parameter may return
XR_ERROR_HANDLE_INVALID
.
Handles form a hierarchy in which child handles fall under the validity and lifetime of parent handles. For example, to create an XrSwapchain handle, applications must call xrCreateSwapchain and pass an XrSession handle. Thus XrSwapchain is a child handle of XrSession.
2.12. Object Handle Types
The type of an object handle used in a function is usually determined by the specification of that function, as discussed in Valid Usage for Object Handles. However, some functions accept or return object handle parameters where the type of the object handle is unknown at execution time and is not specified in the description of the function itself. For these functions, the XrObjectType may be used to explicitly specify the type of a handle.
For example, an information-gathering or debugging mechanism implemented in a runtime extension or API layer extension may return a list of object handles that are generated by the mechanism’s operation. The same mechanism may also return a parallel list of object handle types that allow the recipient of this information to easily determine the types of the handles.
In general, anywhere an object handle of more than one type can occur, the object handle type may be provided to indicate its type.
// Provided by XR_VERSION_1_0
typedef enum XrObjectType {
XR_OBJECT_TYPE_UNKNOWN = 0,
XR_OBJECT_TYPE_INSTANCE = 1,
XR_OBJECT_TYPE_SESSION = 2,
XR_OBJECT_TYPE_SWAPCHAIN = 3,
XR_OBJECT_TYPE_SPACE = 4,
XR_OBJECT_TYPE_ACTION_SET = 5,
XR_OBJECT_TYPE_ACTION = 6,
// Provided by XR_PICO_eye_tracker
XR_OBJECT_TYPE_EYE_TRACKER_PICO = 1010006000,
// Provided by XR_PICO_secure_mixed_reality
XR_OBJECT_TYPE_SECURE_MR_FRAMEWORK_PICO = 1010007000,
// Provided by XR_PICO_secure_mixed_reality
XR_OBJECT_TYPE_SECURE_MR_PIPELINE_PICO = 1010007001,
// Provided by XR_PICO_secure_mixed_reality
XR_OBJECT_TYPE_SECURE_MR_TENSOR_PICO = 1010007002,
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 in the core specification:
XrObjectType | OpenXR Handle Type |
---|---|
|
Unknown/Undefined Handle |
|
|
|
|
|
|
|
|
|
|
|
2.13. Buffer Size Parameters
Functions with input/output buffer parameters take on either parameter form
or structure form, as in one of the following examples, with the element
type being float
in this case:
Parameter form:
XrResult xrFunction(uint32_t elementCapacityInput, uint32_t* elementCountOutput, float* elements);
Structure form:
XrResult xrFunction(XrBuffer* buffer);
struct XrBuffer {
uint32_t elementCapacityInput;
uint32_t elementCountOutput;
float* elements;
};
A "two-call idiom" should be employed by the application, first calling
xrFunction
(with a valid elementCountOutput
pointer if in
parameter form), but passing NULL
as elements
and 0
as
elementCapacityInput
, to retrieve the required buffer size as number
of elements (number of floats in this example).
After allocating a buffer at least as large as elementCountOutput
(in
a structure) or the value pointed to by elementCountOutput
(as
parameters), a pointer to the allocated buffer should be passed as
elements
, along with the buffer’s length in
elementCapacityInput
, to a second call to xrFunction
to perform
the retrieval of the data.
If the element type of elements
is a structure with type
and
next
fields, the application must set the type
to the correct
value, and must set next
to a valid value.
A valid value for next
is generally either NULL
or another
structure with related data, in which type
and next
are also
valid, recursively.
(See Valid Usage for Structure Pointer Chains for details.)
In the following discussion, "set elementCountOutput
" should be
interpreted as "set the value pointed to by elementCountOutput
" in
parameter form and "set the value of elementCountOutput
" in struct
form.
These functions have the following behavior with respect to the array/buffer
and its size parameters:
Some functions have a given elementCapacityInput
and
elementCountOutput
associated with more than one element array (i.e.
parallel arrays).
In this case, the capacity/count and all its associated arrays will share a
common prefix.
All of the preceding general requirements continue to apply.
Some functions fill multiple element arrays of varying sizes in one call.
For these functions, the elementCapacityInput
,
elementCountOutput
, and elements
array parameters or fields are
repeated with different prefixes.
In this case, all of the preceding general requirements still apply, with
these additional requirements:
-
If the application sets any
elementCapacityInput
parameter or field to0
, the runtime must treat allelementCapacityInput
values as if they were set to0
. -
If all
elementCapacityInput
values are non-zero but any is insufficient to fit all elements of its corresponding array, the runtime must returnXR_ERROR_SIZE_INSUFFICIENT
. As in the case of the single array, the data in all arrays is undefined whenXR_ERROR_SIZE_INSUFFICIENT
is returned.
2.14. Time
Time is represented by a 64-bit signed integer representing nanoseconds
(XrTime
).
The passage of time must be monotonic and not real-time (i.e. wall clock
time).
Thus the time is always increasing at a constant rate and is unaffected by
clock changes, time zones, daylight savings, etc.
2.14.1. XrTime
typedef int64_t XrTime;
XrTime
is a base value type that represents time as a signed 64-bit
integer, representing the monotonically-increasing count of nanoseconds that
have elapsed since a runtime-chosen epoch.
XrTime
always represents the time elapsed since that constant
epoch, rather than a duration or a time point relative to some moving epoch
such as vsync time, etc.
Durations are instead represented by XrDuration
.
A single runtime must use the same epoch for all simultaneous applications. Time must be represented the same regardless of multiple processors or threads present in the system.
The period precision of time reported by the runtime is runtime-dependent, and may change. One nanosecond is the finest possible period precision. A runtime may, for example, report time progression with only microsecond-level granularity.
Time must not be assumed to correspond to a system clock time.
Unless specified otherwise, zero or a negative value is not a valid
XrTime
, and related functions must return error
XR_ERROR_TIME_INVALID
.
Applications must not initialize such XrTime
fields to a zero
value.
Instead, applications should always assign XrTime
fields to the
meaningful point in time they are choosing to reason about, such as a
frame’s predicted display time, or an action’s last change time.
The behavior of a runtime is undefined when time overflows beyond the
maximum positive value that can be represented by an XrTime
.
Runtimes should choose an epoch that minimizes the chance of overflow.
Runtimes should also choose an epoch that minimizes the chance of underflow
below 0 for applications performing a reasonable amount of historical pose
lookback.
For example, if the runtime chooses an epoch relative to its startup time,
it should push the epoch into the past by enough time to avoid applications
performing reasonable pose lookback from reaching a negative XrTime
value.
An application cannot assume that the system’s clock and the runtime’s clock
will maintain a constant relationship across frames and should avoid
storing such an offset, as this may cause time drift.
Applications should instead always use time interop functions to convert a
relevant time point across the system’s clock and the runtime’s clock using
extensions, for example,
or
XR_KHR_win32_convert_performance_counter_time
.XR_KHR_convert_timespec_time
2.15. Duration
Duration refers to an elapsed period of time, as opposed to an absolute timepoint.
2.15.1. XrDuration
typedef int64_t XrDuration;
The difference between two timepoints is a duration, and thus the difference
between two XrTime
values is an XrDuration
value.
XrDuration
is a base value type that represents duration as a
signed 64-bit integer, representing the signed number of nanoseconds between
two timepoints.
Functions that refer to durations use XrDuration
as opposed to
XrTime
.
When an XrDuration
is used as a timeout parameter, the constants
XR_NO_DURATION and XR_INFINITE_DURATION have special meaning.
A timeout with a duration that refers to the past (that is, a negative
duration) must be interpreted as a timeout of XR_NO_DURATION.
The interpretation of zero and negative durations in non-timeout uses is specified along with each such use.
// Provided by XR_VERSION_1_0
#define XR_NO_DURATION 0
For the case of timeout durations, XR_NO_DURATION can be used to indicate that the timeout is immediate.
// Provided by XR_VERSION_1_0
#define XR_INFINITE_DURATION 0x7fffffffffffffffLL
XR_INFINITE_DURATION is a special value that can be used to indicate that the timeout never occurs.
2.16. Prediction Time Limits
Some functions involve prediction or history retrieval for a supplied
XrTime
timepoint.
For example, xrLocateViews accepts a display time for which to return
the resulting data.
Timepoints 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 the accuracy
possible at varying past (historical or backwards prediction) and future
timepoints.
The runtime must treat as valid any future time requested by an
application, except when disqualified by size limitations of the underlying
types, 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.
The runtime must retain and return at least 50 milliseconds of historical
data, interpolating as required, preceding the most recently received pose.
Requested times predating this time window, or requested times predating the
earliest received pose, may result in a best effort data whose accuracy
reduced or unspecified.
2.17. Colors
The XrColor3f structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrColor3f {
float r;
float g;
float b;
} XrColor3f;
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.
The XrColor4f structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrColor4f {
float r;
float g;
float b;
float a;
} XrColor4f;
Unless otherwise specified, colors are encoded as linear (not with sRGB nor other gamma compression) values with individual components being in the range of 0.0 through 1.0, and without the RGB components being premultiplied by the alpha component.
If color encoding is specified as being premultiplied by the alpha component, the RGB components are set to zero if the alpha component is zero.
2.18. Coordinate System
This API uses a Cartesian right-handed coordinate system.
The conventions for mapping coordinate axes of any particular space to meaningful directions depend on and are documented with the description of the space.
The API uses 2D, 3D, and 4D floating-point vectors to describe points and directions in a space.
A two-dimensional vector is defined by the XrVector2f structure:
typedef struct XrVector2f {
float x;
float y;
} XrVector2f;
If used to represent physical distances (rather than e.g. normalized direction) and not otherwise specified, values must be in meters.
A three-dimensional vector is defined by the XrVector3f structure:
typedef struct XrVector3f {
float x;
float y;
float z;
} XrVector3f;
If used to represent physical distances (rather than e.g. velocity or angular velocity) and not otherwise specified, values must be in meters.
A four-dimensional or homogeneous vector is defined by the XrVector4f structure:
// Provided by XR_VERSION_1_0
typedef struct XrVector4f {
float x;
float y;
float z;
float w;
} XrVector4f;
If used to represent physical distances, x
, y
, and z
values must be in meters.
Rotation is represented by a unit quaternion defined by the XrQuaternionf structure:
typedef struct XrQuaternionf {
float x;
float y;
float z;
float w;
} XrQuaternionf;
A pose is defined by the XrPosef structure:
typedef struct XrPosef {
XrQuaternionf orientation;
XrVector3f position;
} XrPosef;
A construct representing a position and orientation within a space, with
position expressed in meters, and orientation represented as a unit
quaternion.
When using XrPosef the rotation described by orientation
is
always applied before the translation described by position
.
A runtime must return XR_ERROR_POSE_INVALID
if the orientation
norm deviates by more than 1% from unit length.
2.19. Common Data Types
Some OpenXR data types are used in multiple structures.
Those include the XrVector*f
family of types, the spatial types
specified above, and the following categories of structures:
-
offset
-
extents
-
rectangle
-
field of view
Offsets are used to describe the direction and distance of an offset in two dimensions.
A floating-point offset is defined by the structure:
// Provided by XR_VERSION_1_0
typedef struct XrOffset2Df {
float x;
float y;
} XrOffset2Df;
This structure is used for component values that may be real numbers, represented with single-precision floating point. For representing offsets in discrete values, such as texels, the integer variant XrOffset2Di is used instead.
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 XrOffset2Df is used instead.
Extents are used to describe the size of a rectangular region in two or three dimensions.
A two-dimensional floating-point extent is defined by the structure:
// Provided by XR_VERSION_1_0
typedef struct XrExtent2Df {
float width;
float height;
} XrExtent2Df;
This structure is used for component values that may be real numbers, represented with single-precision floating point. For representing extents in discrete values, such as texels, the integer variant XrExtent2Di is used instead.
If used to represent physical distances, values must be in meters.
The width
and height
value must be non-negative.
The XrExtent3Df structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrExtent3Df {
float width;
float height;
float depth;
} XrExtent3Df;
This structure is used for component values that may be real numbers, represented with single-precision floating point.
If used to represent physical distances, values must be in meters. The width, height, and depth values must be non-negative.
A two-dimensional integer extent is defined by the structure:
typedef struct XrExtent2Di {
int32_t width;
int32_t height;
} XrExtent2Di;
This variant is for representing discrete values such as texels. For representing physical distances, the floating-point variant XrExtent2Df is used instead.
The width
and height
value must be non-negative.
Rectangles are used to describe a specific rectangular region in two dimensions. Rectangles must include both an offset and an extent defined in the same units. For instance, if a rectangle is in meters, both offset and extent must be in meters.
A rectangle with floating-point values is defined by the structure:
// Provided by XR_VERSION_1_0
typedef struct XrRect2Df {
XrOffset2Df offset;
XrExtent2Df extent;
} XrRect2Df;
This structure is used for component values that may be real numbers, represented with single-precision floating point.
The offset
is the position of the rectangle corner with minimum value
coordinates.
The other three corners are computed by adding the
XrExtent2Df::width
to the x
offset,
XrExtent2Df::height
to the y
offset, or both.
A rectangle with integer values is defined by the structure:
typedef struct XrRect2Di {
XrOffset2Di offset;
XrExtent2Di extent;
} XrRect2Di;
This variant is for representing discrete values such as texels. For representing physical distances, the floating-point variant XrRect2Df is used instead.
The offset
is the position of the rectangle corner with minimum value
coordinates.
The other three corners are computed by adding the
XrExtent2Di::width
to the x
offset,
XrExtent2Di::height
to the y
offset, or both.
An XrSpheref structure describes the center and radius of a sphere bounds.
// Provided by XR_VERSION_1_1
typedef struct XrSpheref {
XrPosef center;
float radius;
} XrSpheref;
The runtime must return XR_ERROR_VALIDATION_FAILURE
if radius
is not a finite positive value.
An XrBoxf structure describes the pose and extents of an oriented box.
// Provided by XR_VERSION_1_1
typedef struct XrBoxf {
XrPosef center;
XrExtent3Df extents;
} XrBoxf;
The runtime must return XR_ERROR_VALIDATION_FAILURE
if width, height
or depth values are negative.
An XrFrustumf structure describes the pose, field of view, and far distance of a frustum.
// Provided by XR_VERSION_1_1
typedef struct XrFrustumf {
XrPosef pose;
XrFovf fov;
float nearZ;
float farZ;
} XrFrustumf;
The runtime must return XR_ERROR_VALIDATION_FAILURE
if farZ
is
less than or equal to zero.
The runtime must return XR_ERROR_VALIDATION_FAILURE
if nearZ
is
less than zero.
See XrFovf for validity requirements on fov
.
The XrUuid structure is a 128-bit Universally Unique Identifier and is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrUuid {
uint8_t data[XR_UUID_SIZE];
} XrUuid;
The structure is composed of 16 octets, with the size and order of the fields defined in RFC 4122 section 4.1.2.
2.20. Angles
Where a value is provided as a function parameter or as a structure member and will be interpreted as an angle, the value is defined to be in radians.
Field of view (FoV) is defined by the structure:
typedef struct XrFovf {
float angleLeft;
float angleRight;
float angleUp;
float angleDown;
} XrFovf;
Angles to the right of the center and upwards from the center are positive,
and angles to the left of the center and down from the center are negative.
The total horizontal field of view is angleRight
minus
angleLeft
, and the total vertical field of view is angleUp
minus
angleDown
.
For a symmetric FoV, angleRight
and angleUp
will have positive
values, angleLeft
will be -angleRight
, and angleDown
will
be -angleUp
.
The angles must be specified in radians, and must be between -π/2 and π/2 exclusively.
When angleLeft
> angleRight
, the content of the view must be
flipped horizontally.
When angleDown
> angleUp
, the content of the view must be
flipped vertically.
2.21. Boolean Values
typedef uint32_t XrBool32;
Boolean values used by OpenXR are of type XrBool32
and are 32-bits
wide as suggested by the name.
The only valid values are the following:
#define XR_TRUE 1
#define XR_FALSE 0
2.22. Events
Events are messages sent from the runtime to the application.
2.22.1. Event Polling
Events are placed in a queue within the runtime. The application must read from the queue with regularity. Events are read from the queue one at a time via xrPollEvent. Every type of event is identified by an individual structure type, with each such structure beginning with an XrEventDataBaseHeader.
XrInstance instance; // previously initialized
// Initialize an event buffer to hold the output.
XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
XrResult result = xrPollEvent(instance, &event);
if (result == XR_SUCCESS) {
switch (event.type) {
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
const XrEventDataSessionStateChanged& session_state_changed_event =
*reinterpret_cast<XrEventDataSessionStateChanged*>(&event);
// ...
break;
}
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
const XrEventDataInstanceLossPending& instance_loss_pending_event =
*reinterpret_cast<XrEventDataInstanceLossPending*>(&event);
// ...
break;
}
}
}
xrPollEvent
The xrPollEvent function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrPollEvent(
XrInstance instance,
XrEventDataBuffer* eventData);
xrPollEvent polls for the next event and returns an event if one is
available.
xrPollEvent returns immediately regardless of whether an event was
available.
The event (if present) is unilaterally removed from the queue if a valid
XrInstance is provided.
On return, the eventData
parameter is filled with the event’s data and
the type field is changed to the event’s type.
Runtimes may create valid next
chains depending on enabled extensions,
but they must guarantee that any such chains point only to objects which
fit completely within the original XrEventDataBuffer pointed to by
eventData
.
The runtime must discard queued events which contain destroyed or otherwise invalid handles. The runtime must not return events containing handles that have been destroyed or are otherwise invalid at the time of the call to xrPollEvent.
Event | Description |
---|---|
event queue has overflowed and some events were lost |
|
application is about to lose the instance |
|
current interaction profile for one or more top level user paths has changed |
|
runtime will begin operating with updated definitions or bounds for a reference space |
|
the application’s session has changed lifecycle state |
The XrEventDataBaseHeader structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataBaseHeader {
XrStructureType type;
const void* next;
} XrEventDataBaseHeader;
The XrEventDataBaseHeader is a generic structure used to identify the common event data elements.
Upon receipt, the XrEventDataBaseHeader pointer should be type-cast
to a pointer of the appropriate event data type based on the type
parameter.
typedef struct XrEventDataBuffer {
XrStructureType type;
const void* next;
uint8_t varying[4000];
} XrEventDataBuffer;
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.
An application can set (or reset) only the type
member and clear the
next
member of an XrEventDataBuffer before passing it as an
input to xrPollEvent.
The runtime must ignore the contents of the varying
field and
overwrite it without reading it.
A pointer to an XrEventDataBuffer may be type-cast to an
XrEventDataBaseHeader pointer, or a pointer to any other appropriate
event data based on the type
parameter.
// Provided by XR_VERSION_1_0
#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer)
XR_MAX_EVENT_DATA_SIZE is the size of XrEventDataBuffer,
including the size of the XrEventDataBuffer::type
and
XrEventDataBuffer::next
members.
XrEventDataEventsLost
The XrEventDataEventsLost structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataEventsLost {
XrStructureType type;
const void* next;
uint32_t lostEventCount;
} XrEventDataEventsLost;
Receiving the XrEventDataEventsLost event structure indicates that the event queue overflowed and some events were removed at the position within the queue at which this event was found.
Other event structures are defined in later chapters in the context where their definition is most relevant.
2.23. System resource lifetime
The creator of an underlying system resource is responsible for ensuring the resource’s lifetime matches the lifetime of the associated OpenXR handle.
Resources passed as inputs from the application to the runtime when creating
an OpenXR handle should not be freed while that handle is valid.
A runtime must not free resources passed as inputs or decrease their
reference counts (if applicable) from the initial value.
For example, the graphics device handle (or pointer) passed in to
xrCreateSession in XrGraphicsBinding*
structure should be kept
alive when the corresponding XrSession handle is valid, and should be
freed by the application after the XrSession handle is destroyed.
Resources created by the runtime should not be freed by the application, and
the application should maintain the same reference count (if applicable) at
the destruction of the OpenXR handle as it had at its creation.
For example, the ID3D*Texture2D
objects in the XrSwapchainImageD3D*
are
created by the runtime and associated with the lifetime of the
XrSwapchain handle.
The application should not keep additional reference counts on any
ID3D*Texture2D
objects past the lifetime of the XrSwapchain handle,
or make extra reference count decrease after destroying the
XrSwapchain handle.
3. API Initialization
Before using an OpenXR runtime, an application must initialize it by creating an XrInstance object. The following functions are useful for gathering information about the API layers and extensions installed on the system and creating the instance.
xrEnumerateApiLayerProperties and xrEnumerateInstanceExtensionProperties can be called before calling xrCreateInstance.
3.1. Exported Functions
A dynamically linked library (.dll
or .so
) that implements the API
loader must export all core OpenXR API functions.
The application can gain access to extension functions by obtaining
pointers to these functions through the use of xrGetInstanceProcAddr.
3.2. Function Pointers
Function pointers for all OpenXR functions can be obtained with the function xrGetInstanceProcAddr.
// Provided by XR_VERSION_1_0
XrResult xrGetInstanceProcAddr(
XrInstance instance,
const char* name,
PFN_xrVoidFunction* function);
xrGetInstanceProcAddr itself is obtained in a platform- and loader- specific manner. Typically, the loader library will export this function as a function symbol, so applications can link against the loader library, or load it dynamically and look up the symbol using platform-specific APIs. Loaders must export function symbols for all core OpenXR functions. Because of this, applications that use only the core OpenXR functions have no need to use xrGetInstanceProcAddr.
Because an application can call xrGetInstanceProcAddr before creating
an instance, xrGetInstanceProcAddr must return a valid function
pointer when the instance
parameter is XR_NULL_HANDLE and the
name
parameter is one of the following strings:
xrGetInstanceProcAddr must return XR_ERROR_HANDLE_INVALID
if
name
is not one of the above strings and instance
is
XR_NULL_HANDLE.
xrGetInstanceProcAddr may return XR_ERROR_HANDLE_INVALID
if
name
is not one of the above strings and instance
is invalid but
not XR_NULL_HANDLE.
xrGetInstanceProcAddr must return XR_ERROR_FUNCTION_UNSUPPORTED
if instance
is a valid instance and the string specified in name
is not the name of an OpenXR core or enabled extension function.
If name
is the name of an extension function, then the result returned
by xrGetInstanceProcAddr will depend upon how the instance
was
created.
If instance
was created with the related extension’s name appearing in
the XrInstanceCreateInfo::enabledExtensionNames
array, then
xrGetInstanceProcAddr returns a valid function pointer.
If the related extension’s name did not appear in the
XrInstanceCreateInfo::enabledExtensionNames
array during the
creation of instance
, then xrGetInstanceProcAddr returns
XR_ERROR_FUNCTION_UNSUPPORTED
.
Because of this, function pointers returned by xrGetInstanceProcAddr
using one XrInstance may not be valid when used with objects related
to a different XrInstance.
The returned function pointer is of type PFN_xrVoidFunction, and must be cast by the application to the type of the function being queried.
The table below defines the various use cases for xrGetInstanceProcAddr and return value (“fp” is “function pointer”) for each case.
instance parameter |
name parameter |
return value |
---|---|---|
* |
|
undefined |
invalid instance |
* |
undefined |
|
fp |
|
|
fp |
|
|
fp |
|
|
* (any |
|
instance |
core OpenXR function |
fp1 |
instance |
enabled extension function for |
fp1 |
instance |
* (any |
|
- 1
-
The returned function pointer must only be called with a handle (the first parameter) that is
instance
or a child ofinstance
.
typedef void (XRAPI_PTR *PFN_xrVoidFunction)(void);
PFN_xrVoidFunction is a generic function pointer type returned by queries, specifically those to xrGetInstanceProcAddr.
typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
PFN_xrGetInstanceProcAddr is a function pointer type for xrGetInstanceProcAddr.
typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo;
typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
const XrInstanceCreateInfo* info,
const XrApiLayerCreateInfo* apiLayerInfo,
XrInstance* instance);
PFN_xrCreateApiLayerInstance is a function pointer type for xrCreateApiLayerInstance.
Note: This function pointer type is only used by an OpenXR loader library, and never by an application.
3.3. Runtime Interface Negotiation
In order to negotiate the runtime interface version with the loader, the runtime must implement the xrNegotiateLoaderRuntimeInterface function.
Note
The API described in this section is solely intended for use between an OpenXR loader and a runtime (and/or an API layer, where noted). Applications use the appropriate loader library for their platform to load the active runtime and configured API layers, rather than making these calls directly. This section is included in the specification to ensure consistency between runtimes in their interactions with the loader. Be advised that as this is not application-facing API, some of the typical OpenXR API conventions are not followed in this section. |
The xrNegotiateLoaderRuntimeInterface function is defined as:
// Provided by XR_LOADER_VERSION_1_0
XrResult xrNegotiateLoaderRuntimeInterface(
const XrNegotiateLoaderInfo* loaderInfo,
XrNegotiateRuntimeRequest* runtimeRequest);
xrNegotiateLoaderRuntimeInterface should be directly exported by a
runtime so that using e.g. GetProcAddress
on Windows or dlsym
on POSIX
platforms returns a valid function pointer to it.
The runtime must return XR_ERROR_INITIALIZATION_FAILED
if any of the
following conditions on loaderInfo
are true:
-
XrNegotiateLoaderInfo::
structType
is notXR_LOADER_INTERFACE_STRUCT_LOADER_INFO
-
XrNegotiateLoaderInfo::
structVersion
is not XR_LOADER_INFO_STRUCT_VERSION -
XrNegotiateLoaderInfo::
structSize
is notsizeof(XrNegotiateLoaderInfo)
The runtime must also return XR_ERROR_INITIALIZATION_FAILED
if any of
the following conditions on runtimeRequest
are true:
-
XrNegotiateRuntimeRequest::
structType
is notXR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST
-
XrNegotiateRuntimeRequest::
structVersion
is not XR_RUNTIME_INFO_STRUCT_VERSION -
XrNegotiateRuntimeRequest::
structSize
is notsizeof(XrNegotiateRuntimeRequest)
The runtime must determine if it supports the loader’s request. The runtime does not support the loader’s request if either of the following is true:
-
the runtime does not support the interface versions supported by the loader as specified by the parameters XrNegotiateLoaderInfo::
minInterfaceVersion
and XrNegotiateLoaderInfo::maxInterfaceVersion
-
the runtime does not support the API versions supported by the loader as specified by the parameters XrNegotiateLoaderInfo::
minApiVersion
and XrNegotiateLoaderInfo::maxApiVersion
.
The runtime must return XR_ERROR_INITIALIZATION_FAILED
if it does not
support the loader’s request.
If the function succeeds, the runtime must set the
XrNegotiateRuntimeRequest::runtimeInterfaceVersion
with the
runtime interface version it desires to support.
The XrNegotiateRuntimeRequest::runtimeInterfaceVersion
set must
be between XrNegotiateLoaderInfo::minInterfaceVersion
and
XrNegotiateLoaderInfo::maxInterfaceVersion
.
If the function succeeds, the runtime must set the
XrNegotiateRuntimeRequest::runtimeApiVersion
with the API
version of OpenXR it will execute under.
The XrNegotiateRuntimeRequest::runtimeApiVersion
set must be
between XrNegotiateLoaderInfo::minApiVersion
and
XrNegotiateLoaderInfo::maxApiVersion
.
If the function succeeds, the runtime must set the
XrNegotiateRuntimeRequest::getInstanceProcAddr
with a valid
function pointer for the loader to use to query function pointers to the
remaining OpenXR functions supported by the runtime.
If the function succeeds, the runtime must return XR_SUCCESS
.
The XrNegotiateLoaderInfo structure is used to pass information about the loader to a runtime or an API layer.
The XrNegotiateLoaderInfo structure is defined as:
typedef struct XrNegotiateLoaderInfo {
XrLoaderInterfaceStructs structType;
uint32_t structVersion;
size_t structSize;
uint32_t minInterfaceVersion;
uint32_t maxInterfaceVersion;
XrVersion minApiVersion;
XrVersion maxApiVersion;
} XrNegotiateLoaderInfo;
This structure is an input from the loader to the runtime in an xrNegotiateLoaderRuntimeInterface call, as well as from the loader to an API layer in an xrNegotiateLoaderApiLayerInterface call.
The XrLoaderInterfaceStructs enumeration is defined as:
typedef enum XrLoaderInterfaceStructs {
XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0,
XR_LOADER_INTERFACE_STRUCT_LOADER_INFO = 1,
XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST = 2,
XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST = 3,
XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO = 4,
XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO = 5,
XR_LOADER_INTERFACE_STRUCTS_MAX_ENUM = 0x7FFFFFFF
} XrLoaderInterfaceStructs;
This enumeration serves a similar purpose in the runtime and API layer interface negotiation (loader) API as XrStructureType serves in the application-facing API.
// Provided by XR_LOADER_VERSION_1_0
#define XR_LOADER_INFO_STRUCT_VERSION 1
XR_LOADER_INFO_STRUCT_VERSION is the current version of the
XrNegotiateLoaderInfo structure.
It is used to populate the XrNegotiateLoaderInfo::structVersion
field.
// Provided by XR_LOADER_VERSION_1_0
#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
XR_CURRENT_LOADER_RUNTIME_VERSION is the current version of the overall OpenXR Loader Runtime interface. It is used to populate maximum and minimum interface version fields in XrNegotiateLoaderInfo when loading a runtime.
// Provided by XR_LOADER_VERSION_1_0
#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
XR_CURRENT_LOADER_API_LAYER_VERSION is the current version of the overall OpenXR Loader API Layer interface. It is used to populate maximum and minimum interface version fields in XrNegotiateLoaderInfo when loading an API layer.
The XrNegotiateRuntimeRequest structure is used to pass information about the runtime back to the loader.
The XrNegotiateRuntimeRequest structure is defined as:
typedef struct XrNegotiateRuntimeRequest {
XrLoaderInterfaceStructs structType;
uint32_t structVersion;
size_t structSize;
uint32_t runtimeInterfaceVersion;
XrVersion runtimeApiVersion;
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
} XrNegotiateRuntimeRequest;
This is an output structure from runtime negotiation.
The loader must populate structType
, structVersion
, and
structSize
to ensure correct interpretation by the runtime, while the
runtime populates the rest of the fields in a successful call to
xrNegotiateLoaderRuntimeInterface.
// Provided by XR_LOADER_VERSION_1_0
#define XR_RUNTIME_INFO_STRUCT_VERSION 1
XR_RUNTIME_INFO_STRUCT_VERSION is the current version of the
XrNegotiateRuntimeRequest structure.
It is used to populate the
XrNegotiateRuntimeRequest::structVersion
field.
3.4. API Layer Interface Negotiation
In order to negotiate the API layer interface version with the loader, an OpenXR API layer must implement the xrNegotiateLoaderApiLayerInterface function.
Note
The API described in this section is solely intended for use between an OpenXR loader and an API layer. Applications use the appropriate loader library for their platform to load the active runtime and configured API layers, rather than making these calls directly. This section is included in the specification to ensure consistency between runtimes in their interactions with the loader. Be advised that as this is not application-facing API, some of the typical OpenXR API conventions are not followed in this section. |
The xrNegotiateLoaderApiLayerInterface function is defined as:
// Provided by XR_LOADER_VERSION_1_0
XrResult xrNegotiateLoaderApiLayerInterface(
const XrNegotiateLoaderInfo* loaderInfo,
const char* layerName,
XrNegotiateApiLayerRequest* apiLayerRequest);
xrNegotiateLoaderApiLayerInterface should be directly exported by an
API layer so that using e.g. GetProcAddress
on Windows or dlsym
on POSIX
platforms returns a valid function pointer to it.
The API layer must return XR_ERROR_INITIALIZATION_FAILED
if any of
the following conditions on loaderInfo
are true:
-
XrNegotiateLoaderInfo::
structType
is notXR_LOADER_INTERFACE_STRUCT_LOADER_INFO
-
XrNegotiateLoaderInfo::
structVersion
is not XR_LOADER_INFO_STRUCT_VERSION -
XrNegotiateLoaderInfo::
structSize
is notsizeof(XrNegotiateLoaderInfo)
The API layer must also return XR_ERROR_INITIALIZATION_FAILED
if any
of the following conditions on apiLayerRequest
are true:
-
XrNegotiateApiLayerRequest::
structType
is notXR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST
-
XrNegotiateApiLayerRequest::
structVersion
is not XR_API_LAYER_INFO_STRUCT_VERSION -
XrNegotiateApiLayerRequest::
structSize
is notsizeof(XrNegotiateApiLayerRequest)
The API layer must determine if it supports the loader’s request. The API layer does not support the loader’s request if either of the following is true:
-
the API layer does not support the interface versions supported by the loader as specified by the parameters XrNegotiateLoaderInfo::
minInterfaceVersion
and XrNegotiateLoaderInfo::maxInterfaceVersion
-
the API layer does not support the API versions supported by the loader as specified by the parameters XrNegotiateLoaderInfo::
minApiVersion
and XrNegotiateLoaderInfo::maxApiVersion
.
The API layer must return XR_ERROR_INITIALIZATION_FAILED
if it does
not support the loader’s request.
If the function succeeds, the API layer must set the
XrNegotiateApiLayerRequest::layerInterfaceVersion
with the API
layer interface version it desires to support.
The XrNegotiateApiLayerRequest::layerInterfaceVersion
set must
be between XrNegotiateLoaderInfo::minInterfaceVersion
and
XrNegotiateLoaderInfo::maxInterfaceVersion
.
If the function succeeds, the API layer must set the
XrNegotiateApiLayerRequest::layerApiVersion
with the API version
of OpenXR it will execute under.
The XrNegotiateApiLayerRequest::layerApiVersion
set must be
between XrNegotiateLoaderInfo::minApiVersion
and
XrNegotiateLoaderInfo::maxApiVersion
.
If the function succeeds, the API layer must set the
XrNegotiateApiLayerRequest::getInstanceProcAddr
with a valid
function pointer for the loader to use to query function pointers to the
remaining OpenXR functions supported by the API layer.
If the function succeeds, the API layer must set the
XrNegotiateApiLayerRequest::createApiLayerInstance
with a valid
function pointer to an implementation of xrCreateApiLayerInstance for
the loader to use to create the instance through the API layer call chain.
If the function succeeds, the API layer must return XR_SUCCESS
.
The API layer must not call into another API layer from its implementation of the xrNegotiateLoaderApiLayerInterface function. The loader must handle all API layer negotiations with each API layer individually.
The XrNegotiateApiLayerRequest structure is used to pass information about the API layer back to the loader.
The XrNegotiateApiLayerRequest structure is defined as:
typedef struct XrNegotiateApiLayerRequest {
XrLoaderInterfaceStructs structType;
uint32_t structVersion;
size_t structSize;
uint32_t layerInterfaceVersion;
XrVersion layerApiVersion;
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
PFN_xrCreateApiLayerInstance createApiLayerInstance;
} XrNegotiateApiLayerRequest;
This is an output structure from API layer negotiation.
The loader must populate structType
, structVersion
, and
structSize
before calling to ensure correct interpretation by the API
layer, while the API layer populates the rest of the fields in a successful
call to xrNegotiateLoaderApiLayerInterface.
// Provided by XR_LOADER_VERSION_1_0
#define XR_API_LAYER_INFO_STRUCT_VERSION 1
XR_API_LAYER_INFO_STRUCT_VERSION is the current version of the
XrNegotiateApiLayerRequest structure.
It is used to populate the
XrNegotiateApiLayerRequest::structVersion
field.
The xrCreateApiLayerInstance function is defined as:
// Provided by XR_LOADER_VERSION_1_0
XrResult xrCreateApiLayerInstance(
const XrInstanceCreateInfo* info,
const XrApiLayerCreateInfo* layerInfo,
XrInstance* instance);
An API layer’s implementation of the xrCreateApiLayerInstance function is invoked during the loader’s implementation of xrCreateInstance, if the layer in question is enabled.
An API layer needs additional information during xrCreateInstance calls, so each API layer must implement the xrCreateApiLayerInstance function, which is a special API layer function.
An API layer must not implement xrCreateInstance.
xrCreateApiLayerInstance must be called by the loader during its implementation of the xrCreateInstance function.
The loader must call the first API layer’s xrCreateApiLayerInstance function passing in the pointer to the created XrApiLayerCreateInfo.
The XrApiLayerCreateInfo::nextInfo
must be a linked-list of
XrApiLayerNextInfo structures with information about each of the API
layers that are to be enabled.
Note that this does not operate like a next
chain in the OpenXR
application API, but instead describes the enabled API layers from outermost
to innermost.
The API layer may validate that it is getting the correct next information
by checking that the XrApiLayerNextInfo::layerName
matches the
expected value.
The API layer must use the information in its XrApiLayerNextInfo to call down the call chain to the next xrCreateApiLayerInstance:
-
The API layer must copy the XrApiLayerCreateInfo structure into its own structure.
-
The API layer must then update its copy of the XrApiLayerCreateInfo structure, setting XrApiLayerCreateInfo::
nextInfo
to point to the XrApiLayerNextInfo for the next API layer (e.g.layerInfoCopy→nextInfo = layerInfo→nextInfo→next;
). -
The API layer must then use the pointer to its XrApiLayerCreateInfo structure (instead of the one that was passed in) when it makes a call to the xrCreateApiLayerInstance function.
-
If the nested xrCreateApiLayerInstance call succeeds, the API layer may choose to setup its own dispatch table to the next API layer’s functions using the returned XrInstance and the next API layer’s xrGetInstanceProcAddr.
-
The API layer must return the XrResult returned from the next API layer.
The XrApiLayerCreateInfo structure contains special information required by a API layer during its create instance process.
The XrApiLayerCreateInfo structure is defined as:
typedef struct XrApiLayerCreateInfo {
XrLoaderInterfaceStructs structType;
uint32_t structVersion;
size_t structSize;
void* loaderInstance;
char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE];
XrApiLayerNextInfo* nextInfo;
} XrApiLayerCreateInfo;
// Provided by XR_LOADER_VERSION_1_0
#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
XR_API_LAYER_CREATE_INFO_STRUCT_VERSION is the current version of the
XrApiLayerCreateInfo structure.
It is used to populate the XrApiLayerCreateInfo::structVersion
field.
// Provided by XR_LOADER_VERSION_1_0
#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
XR_API_LAYER_MAX_SETTINGS_PATH_SIZE is the size of the
XrApiLayerCreateInfo::settings_file_location
field.
The XrApiLayerNextInfo structure:
The XrApiLayerNextInfo structure is defined as:
typedef struct XrApiLayerNextInfo {
XrLoaderInterfaceStructs structType;
uint32_t structVersion;
size_t structSize;
char layerName[XR_MAX_API_LAYER_NAME_SIZE];
PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr;
PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance;
struct XrApiLayerNextInfo* next;
} XrApiLayerNextInfo;
// Provided by XR_LOADER_VERSION_1_0
#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
XR_API_LAYER_NEXT_INFO_STRUCT_VERSION is the current version of the
XrApiLayerNextInfo structure.
It is used to populate the XrApiLayerNextInfo::structVersion
field.
4. Instance
XR_DEFINE_HANDLE(XrInstance)
An OpenXR instance is an object that allows an OpenXR application to communicate with an OpenXR runtime. The application accomplishes this communication by calling xrCreateInstance and receiving a handle to the resulting XrInstance object.
The XrInstance object stores and tracks OpenXR-related application state, without storing any such state in the application’s global address space. This allows the application to create multiple instances as well as safely encapsulate the application’s OpenXR state since this object is opaque to the application. OpenXR runtimes may limit the number of simultaneous XrInstance objects that may be created and used, but they must support the creation and usage of at least one XrInstance object per process.
Physically, this state may be stored in any of the OpenXR loader, OpenXR API layers or the OpenXR runtime components. The exact storage and distribution of this saved state is implementation-dependent, except where indicated by this specification.
The tracking of OpenXR state in the instance allows the streamlining of the API, where the intended instance is inferred from the highest ascendant of an OpenXR function’s target object. For example, in:
myResult = xrEndFrame(mySession, &myEndFrameDescription);
the XrSession object was created from an XrInstance object. The OpenXR loader typically keeps track of the XrInstance that is the parent of the XrSession object in this example and directs the function to the runtime associated with that instance. This tracking of OpenXR objects eliminates the need to specify an XrInstance in every OpenXR function.
4.1. API Layers and Extensions
Additional functionality may be provided by API layers or extensions. An API layer must not add or modify the definition of OpenXR functions, while an extension may do so.
The set of API layers to enable is specified when creating an instance, and those API layers are able to intercept any functions dispatched to that instance or any of its child objects.
Example API layers may include (but are not limited to):
-
an API layer to dump out OpenXR API calls
-
an API layer to perform OpenXR validation
To determine what set of API layers are available, OpenXR provides the xrEnumerateApiLayerProperties function:
// Provided by XR_VERSION_1_0
XrResult xrEnumerateApiLayerProperties(
uint32_t propertyCapacityInput,
uint32_t* propertyCountOutput,
XrApiLayerProperties* properties);
The list of available layers may change at any time due to actions outside
of the OpenXR runtime, so two calls to xrEnumerateApiLayerProperties
with the same parameters may return different results, or retrieve
different propertyCountOutput
values or properties
contents.
Once an instance has been created, the layers enabled for that instance will continue to be enabled and valid for the lifetime of that instance, even if some of them become unavailable for future instances.
The XrApiLayerProperties structure is defined as:
typedef struct XrApiLayerProperties {
XrStructureType type;
void* next;
char layerName[XR_MAX_API_LAYER_NAME_SIZE];
XrVersion specVersion;
uint32_t layerVersion;
char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];
} XrApiLayerProperties;
To enable a layer, the name of the layer should be added to
XrInstanceCreateInfo::enabledApiLayerNames
when creating an
XrInstance.
Loader implementations may provide mechanisms outside this API for enabling
specific API layers.
API layers enabled through such a mechanism are implicitly enabled, while
API layers enabled by including the API layer name in
XrInstanceCreateInfo::enabledApiLayerNames
are explicitly
enabled.
Except where otherwise specified, implicitly enabled and explicitly enabled
API layers differ only in the way they are enabled.
Explicitly enabling an API layer that is implicitly enabled has no
additional effect.
Instance extensions are able to affect the operation of the instance and any of its child objects. As stated earlier, extensions can expand the OpenXR API and provide new functions or augment behavior.
Examples of extensions may be (but are not limited to):
The application can determine the available instance extensions by calling xrEnumerateInstanceExtensionProperties:
// Provided by XR_VERSION_1_0
XrResult xrEnumerateInstanceExtensionProperties(
const char* layerName,
uint32_t propertyCapacityInput,
uint32_t* propertyCountOutput,
XrExtensionProperties* properties);
Because the list of available layers may change externally between calls to
xrEnumerateInstanceExtensionProperties, two calls may retrieve
different results if a layerName
is available in one call but not in
another.
The extensions supported by a layer may also change between two calls, e.g.
if the layer implementation is replaced by a different version between those
calls.
The XrExtensionProperties structure is defined as:
typedef struct XrExtensionProperties {
XrStructureType type;
void* next;
char extensionName[XR_MAX_EXTENSION_NAME_SIZE];
uint32_t extensionVersion;
} XrExtensionProperties;
4.2. Instance Lifecycle
The xrCreateInstance function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrCreateInstance(
const XrInstanceCreateInfo* createInfo,
XrInstance* instance);
xrCreateInstance creates the XrInstance, then enables and
initializes global API layers and extensions requested by the application.
If an extension is provided by an API layer, both the API layer and
extension must be specified at xrCreateInstance time.
If a specified API layer cannot be found, no XrInstance will be
created and the function will return XR_ERROR_API_LAYER_NOT_PRESENT
.
Likewise, if a specified extension cannot be found, the call must return
XR_ERROR_EXTENSION_NOT_PRESENT
and no XrInstance will be
created.
Additionally, some runtimes may limit the number of concurrent instances
that may be in use.
If the application attempts to create more instances than a runtime can
simultaneously support, xrCreateInstance may return
XR_ERROR_LIMIT_REACHED
.
If the XrApplicationInfo::applicationName
is the empty string
the runtime must return XR_ERROR_NAME_INVALID
.
If the XrInstanceCreateInfo structure contains a platform-specific
extension for a platform other than the target platform,
XR_ERROR_INITIALIZATION_FAILED
may be returned.
If a mandatory platform-specific extension is defined for the target
platform but no matching extension struct is provided in
XrInstanceCreateInfo the runtime must return
XR_ERROR_INITIALIZATION_FAILED
.
The XrInstanceCreateInfo structure is defined as:
typedef struct XrInstanceCreateInfo {
XrStructureType type;
const void* next;
XrInstanceCreateFlags createFlags;
XrApplicationInfo applicationInfo;
uint32_t enabledApiLayerCount;
const char* const* enabledApiLayerNames;
uint32_t enabledExtensionCount;
const char* const* enabledExtensionNames;
} XrInstanceCreateInfo;
The XrInstanceCreateInfo::createFlags
member is of the following
type, and contains a bitwise-OR of zero or more of the bits defined in
XrInstanceCreateFlagBits.
typedef XrFlags64 XrInstanceCreateFlags;
Valid bits for XrInstanceCreateFlags are defined by XrInstanceCreateFlagBits.
// Flag bits for XrInstanceCreateFlags
There are currently no instance creation flag bits defined. This is reserved for future use.
The XrApplicationInfo structure is defined as:
typedef struct XrApplicationInfo {
char applicationName[XR_MAX_APPLICATION_NAME_SIZE];
uint32_t applicationVersion;
char engineName[XR_MAX_ENGINE_NAME_SIZE];
uint32_t engineVersion;
XrVersion apiVersion;
} XrApplicationInfo;
Useful values for apiVersion
include XR_API_VERSION_1_0 and
XR_API_VERSION_1_1.
Note
When using the OpenXR API to implement a reusable engine that will be used
by many applications, When using the OpenXR API to implement an individual application without a
shared engine, the input |
The xrDestroyInstance function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrDestroyInstance(
XrInstance instance);
The xrDestroyInstance function is used to destroy an XrInstance.
XrInstance handles are destroyed using xrDestroyInstance. When an XrInstance is destroyed, all handles that are children of that XrInstance are also destroyed.
4.3. Instance Information
The xrGetInstanceProperties function provides information about the instance and the associated runtime.
// Provided by XR_VERSION_1_0
XrResult xrGetInstanceProperties(
XrInstance instance,
XrInstanceProperties* instanceProperties);
The instanceProperties
parameter must be filled out by the runtime in
response to this call, with information as defined in
XrInstanceProperties.
The XrInstanceProperties structure is defined as:
typedef struct XrInstanceProperties {
XrStructureType type;
void* next;
XrVersion runtimeVersion;
char runtimeName[XR_MAX_RUNTIME_NAME_SIZE];
} XrInstanceProperties;
4.4. Platform-Specific Instance Creation
Some amount of data required for instance creation is exposed through chained structures defined in extensions. These structures may be optional or even required for instance creation on specific platforms, but not on other platforms. Separating off platform-specific functionality into extension structures prevents the primary XrInstanceCreateInfo structure from becoming too bloated with unnecessary information.
See the
List of Extensions
appendix for the list of available extensions and their related structures.
These structures expand the XrInstanceCreateInfo parent struct using
the XrInstanceCreateInfo::next
member.
The specific list of structures that may be used for extending
XrInstanceCreateInfo::next
can be found in the "Valid Usage
(Implicit)" block immediately following the definition of the structure.
4.4.1. The Instance Lost Error
The XR_ERROR_INSTANCE_LOST
error indicates that the XrInstance
has become unusable.
This can happen if a critical runtime process aborts, if the connection to
the runtime is otherwise no longer available, or if the runtime encounters
an error during any function execution which prevents it from being able to
support further function execution.
Once XR_ERROR_INSTANCE_LOST
is first returned, it must henceforth be
returned by all non-destroy functions that involve an XrInstance or
child handle type until the instance is destroyed.
Applications must destroy the XrInstance.
Applications may then attempt to continue by recreating all relevant OpenXR
objects, starting with a new XrInstance.
A runtime may generate an XrEventDataInstanceLossPending event when
instance loss is detected.
4.4.2. XrEventDataInstanceLossPending
The XrEventDataInstanceLossPending structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataInstanceLossPending {
XrStructureType type;
const void* next;
XrTime lossTime;
} XrEventDataInstanceLossPending;
Receiving the XrEventDataInstanceLossPending event structure indicates
that the application is about to lose the indicated XrInstance at the
indicated lossTime
in the future.
The application should call xrDestroyInstance and relinquish any
instance-specific resources.
This typically occurs to make way for a replacement of the underlying
runtime, such as via a software update.
After the application has destroyed all of its instances and their children
and waited past the specified time, it may then re-try
xrCreateInstance in a loop waiting for whatever maintenance the
runtime is performing to complete.
The runtime will return XR_ERROR_RUNTIME_UNAVAILABLE
from
xrCreateInstance as long as it is unable to create the instance.
Once the runtime has returned and is able to continue, it must resume
returning XR_SUCCESS
from xrCreateInstance if valid data is
passed in.
4.5. Instance Enumerated Type String Functions
Applications often want to turn certain enum values from the runtime into strings for use in log messages, to be localized in UI, or for various other reasons. OpenXR provides functions that turn common enum types into UTF-8 strings for use in applications.
// Provided by XR_VERSION_1_0
XrResult xrResultToString(
XrInstance instance,
XrResult value,
char buffer[XR_MAX_RESULT_STRING_SIZE]);
Returns the text version of the provided XrResult value as a UTF-8 string.
In all cases the returned string must be one of:
The xrStructureTypeToString function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrStructureTypeToString(
XrInstance instance,
XrStructureType value,
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
Returns the text version of the provided XrStructureType value as a UTF-8 string.
In all cases the returned string must be one of:
5. System
This API separates the concept of physical systems of XR devices from the
logical objects that applications interact with directly.
A system represents a collection of related devices in the runtime, often
made up of several individual hardware components working together to enable
XR experiences.
An XrSystemId
is returned by xrGetSystem representing the
system of devices the runtime will use to support a given
form factor.
Each system may include: a VR/AR display, various forms of input (gamepad,
touchpad, motion controller), and other trackable objects.
The application uses the system to create a session, which can then be used to accept input from the user and output rendered frames. The application also provides suggested bindings from its actions to any number of input sources. The runtime may use this action information to activate only a subset of devices and avoid wasting resources on devices that are not in use. Exactly which devices are active once an XR system is selected will depend on the features provided by the runtime, and may vary from runtime to runtime. For example, a runtime that is capable of mapping from one tracking system’s space to another’s may support devices from multiple tracking systems simultaneously.
5.1. Form Factors
The first step in selecting a system is for the application to request its desired form factor. The form factor defines how the display(s) moves in the environment relative to the user’s head and how the user will interact with the XR experience. A runtime may support multiple form factors, such as on a mobile phone that supports both slide-in VR headset experiences and handheld AR experiences.
While an application’s core XR rendering may span across form factors, its user interface will often be written to target a particular form factor, requiring explicit tailoring to function well on other form factors. For example, screen-space UI designed for a handheld phone will produce an uncomfortable experience for users if presented in screen-space on an AR headset.
typedef enum XrFormFactor {
XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1,
XR_FORM_FACTOR_HANDHELD_DISPLAY = 2,
XR_FORM_FACTOR_MAX_ENUM = 0x7FFFFFFF
} XrFormFactor;
The predefined form factors which may be supported by OpenXR runtimes are:
5.2. Getting the XrSystemId
XR_DEFINE_ATOM(XrSystemId)
An XrSystemId
is an opaque atom used by the runtime to identify a
system.
The value XR_NULL_SYSTEM_ID is considered an invalid system.
// Provided by XR_VERSION_1_0
#define XR_NULL_SYSTEM_ID 0
The only XrSystemId
value defined to be constant across all
instances is the invalid system XR_NULL_SYSTEM_ID.
No supported system is associated with XR_NULL_SYSTEM_ID.
Unless explicitly permitted, it should not be passed to API calls or used
as a structure attribute when a valid XrSystemId
is required.
The xrGetSystem function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetSystem(
XrInstance instance,
const XrSystemGetInfo* getInfo,
XrSystemId* systemId);
To get an XrSystemId
, an application specifies its desired
form factor to xrGetSystem and gets
the runtime’s XrSystemId
associated with that configuration.
If the form factor is supported but temporarily unavailable,
xrGetSystem must return XR_ERROR_FORM_FACTOR_UNAVAILABLE
.
A runtime may return XR_SUCCESS
on a subsequent call for a form
factor it previously returned XR_ERROR_FORM_FACTOR_UNAVAILABLE
.
For example, connecting or warming up hardware might cause an unavailable
form factor to become available.
The XrSystemGetInfo structure is defined as:
typedef struct XrSystemGetInfo {
XrStructureType type;
const void* next;
XrFormFactor formFactor;
} XrSystemGetInfo;
The XrSystemGetInfo structure specifies attributes about a system as desired by an application.
XrInstance instance; // previously initialized
XrSystemGetInfo system_get_info = {XR_TYPE_SYSTEM_GET_INFO};
system_get_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
XrSystemId systemId;
CHK_XR(xrGetSystem(instance, &system_get_info, &systemId));
// create session
// create swapchains
// begin session
// main loop
// end session
// destroy session
// no access to hardware after this point
5.3. System Properties
The xrGetSystemProperties function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetSystemProperties(
XrInstance instance,
XrSystemId systemId,
XrSystemProperties* properties);
An application can call xrGetSystemProperties to retrieve information about the system such as vendor ID, system name, and graphics and tracking properties.
The XrSystemProperties structure is defined as:
typedef struct XrSystemProperties {
XrStructureType type;
void* next;
XrSystemId systemId;
uint32_t vendorId;
char systemName[XR_MAX_SYSTEM_NAME_SIZE];
XrSystemGraphicsProperties graphicsProperties;
XrSystemTrackingProperties trackingProperties;
} XrSystemProperties;
The runtime must report a valid vendor ID for the system. The vendor ID must be either the USB vendor ID defined for the physical device or a Khronos vendor ID.
The XrSystemGraphicsProperties structure is defined as:
typedef struct XrSystemGraphicsProperties {
uint32_t maxSwapchainImageHeight;
uint32_t maxSwapchainImageWidth;
uint32_t maxLayerCount;
} XrSystemGraphicsProperties;
// Provided by XR_VERSION_1_0
#define XR_MIN_COMPOSITION_LAYERS_SUPPORTED 16
XR_MIN_COMPOSITION_LAYERS_SUPPORTED defines the minimum number of
composition layers that a conformant runtime must support.
A runtime must return the
XrSystemGraphicsProperties::maxLayerCount
at least the value of
XR_MIN_COMPOSITION_LAYERS_SUPPORTED.
The XrSystemTrackingProperties structure is defined as:
typedef struct XrSystemTrackingProperties {
XrBool32 orientationTracking;
XrBool32 positionTracking;
} XrSystemTrackingProperties;
6. Path Tree and Semantic Paths
OpenXR incorporates an internal semantic path tree model, also known as the path tree, with entities associated with nodes organized in a logical tree and referenced by path name strings structured like a filesystem path or URL. The path tree unifies a number of concepts used in this specification and a runtime may add additional nodes as implementation details. As a general design principle, the most application-facing paths should have semantic and hierarchical meaning in their name. Thus, these paths are often referred to as semantic paths. However, path names in the path tree model may not all have the same level or kind of semantic meaning.
In regular use in an application, path name strings are converted to
instance-specific XrPath
values which are used in place of path
strings.
The mapping between XrPath
values and their corresponding path name
strings may be considered to be tracked by the runtime in a one-to-one
mapping in addition to the natural tree structure of the referenced
entities.
Runtimes may use any internal implementation that satisfies the
requirements.
Formally, the runtime maintains an instance-specific bijective mapping
between well-formed path name strings and valid XrPath
(uint64_t
) values.
These XrPath
values are only valid within a single
XrInstance, and applications must not share these values between
instances.
Applications must instead use the string representation of a path in their
code and configuration, and obtain the correct corresponding XrPath
at runtime in each XrInstance.
The term path or semantic path may refer interchangeably to either the
path name string or its associated XrPath
value within an instance
when context makes it clear which type is being discussed.
Given that path trees are a unifying model in this specification, the
entities referenced by paths can be of diverse types.
For example, they may be used to represent physical device or sensor
components, which may be of various component types.
They may also be used to represent frames of reference that are understood
by the application and the runtime, as defined by an XrSpace.
Additionally, to permit runtime re-configuration and support
hardware-independent development, any syntactically-valid path string may
be used to retrieve a corresponding XrPath
without error given
sufficient resources, even if no logical or hardware entity currently
corresponds to that path at the time of the call.
Later retrieval of the associated path string of such an XrPath
using xrPathToString should succeed if the other requirements of that
call are met.
However, using such an XrPath
in a later call to any other API
function may result in an error if no entity of the type required by the
call is available at the path at that later time.
A runtime should permit the entity referenced by a path to vary over time
to naturally reflect varying system configuration and hardware availability.
6.1. Path Atom Type
XR_DEFINE_ATOM(XrPath)
The XrPath
is an atom that connects an application with a single
path, within the context of a single instance.
There is a bijective mapping between well-formed path strings and atoms in
use.
This atom is used — in place of the path name string it corresponds to — to retrieve state and perform other operations.
As an XrPath
is only shorthand for a well-formed path string, they
have no explicit life cycle.
Lifetime is implicitly managed by the XrInstance.
An XrPath
must not be used unless it is received at execution time
from the runtime in the context of a particular XrInstance.
Therefore, with the exception of XR_NULL_PATH, XrPath
values
must not be specified as constant values in applications: the corresponding
path string should be used instead.
During the lifetime of a given XrInstance, the XrPath
associated with that instance with any given well-formed path must not
vary, and similarly the well-formed path string that corresponds to a given
XrPath
in that instance must not vary.
An XrPath
that is received from one XrInstance may not be
used with another.
Such an invalid use may be detected and result in an error being returned,
or it may result in undefined behavior.
Well-written applications should typically use a small, bounded set of
paths in practice.
However, the runtime should support looking up the XrPath
for a
large number of path strings for maximum compatibility.
Runtime implementers should keep in mind that applications supporting
diverse systems may look up path strings in a quantity exceeding the number
of non-empty entities predicted or provided by any one runtime’s own path
tree model, and this is not inherently an error.
However, system resources are finite and thus runtimes may signal
exhaustion of resources dedicated to these associations under certain
conditions.
When discussing the behavior of runtimes at these limits, a new
XrPath
refers to an XrPath
value that, as of some point in
time, has neither been received by the application nor tracked internally by
the runtime.
In this case, since an application has not yet received the value of such an
XrPath
, the runtime has not yet made any assertions about its
association with any path string.
In this context, new only refers to the fact that the mapping has not
necessarily been made constant for a given value/path string pair for the
remaining life of the associated instance by being revealed to the
application.
It does not necessarily imply creation of the entity, if any, referred to by
such a path.
Similarly, it does not imply the absence of such an entity prior to that
point.
Entities in the path tree have varied lifetime that is independent from the
duration of the mapping from path string to XrPath
.
For flexibility, the runtime may internally track or otherwise make
constant, in instance or larger scope, any mapping of a path string to an
XrPath
value even before an application would otherwise receive
that value, thus making it no longer new by the above definition.
When the runtime’s resources to track the path string-XrPath
mapping are exhausted, and the application makes an API call that would have
otherwise retrieved a new XrPath
as defined above, the runtime
must return XR_ERROR_PATH_COUNT_EXCEEDED
.
This includes both explicit calls to xrStringToPath as well as other
calls that retrieve an XrPath
in any other way.
The runtime should support creating as many paths as memory will allow and
must return XR_ERROR_PATH_COUNT_EXCEEDED
from relevant functions when
no more can be created.
// Provided by XR_VERSION_1_0
#define XR_NULL_PATH 0
The only XrPath
value defined to be constant across all instances
is the invalid path XR_NULL_PATH.
No well-formed path string is associated with XR_NULL_PATH.
Unless explicitly permitted, it should not be passed to API calls or used
as a structure attribute when a valid XrPath
is required.
6.2. Well-Formed Path Strings
Even though they look similar, semantic paths are not file paths. To avoid confusion with file path directory traversal conventions, many file path conventions are explicitly disallowed from well-formed path name strings.
A well-formed path name string must conform to the following rules:
-
Path name strings must be constructed entirely from characters on the following list.
-
Lower case ASCII letters: a-z
-
Numeric digits: 0-9
-
Dash: -
-
Underscore: _
-
Period: .
-
Forward Slash: /
-
-
Path name strings must start with a single forward slash character.
-
Path name strings must not end with a forward slash character.
-
Path name strings must not contain two or more adjacent forward slash characters.
-
Path name strings must not contain two forward slash characters that are separated by only period characters.
-
Path name strings must not contain only period characters following the final forward slash character in the string.
-
The maximum string length for a path name string, including the terminating
\0
character, is defined byXR_MAX_PATH_LENGTH
.
6.2.1. xrStringToPath
The xrStringToPath function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrStringToPath(
XrInstance instance,
const char* pathString,
XrPath* path);
xrStringToPath retrieves the XrPath
value for a well-formed
path string.
If such a value had not yet been assigned by the runtime to the provided
path string in this XrInstance, one must be assigned at this point.
All calls to this function with the same XrInstance and path string
must retrieve the same XrPath
value.
Upon failure, xrStringToPath must return an appropriate
XrResult, and may set the output parameter to XR_NULL_PATH.
See Path Atom Type for the conditions under which an
error may be returned when this function is given a valid XrInstance
and a well-formed path string.
If the runtime’s resources are exhausted and it cannot create the path, a
return value of XR_ERROR_PATH_COUNT_EXCEEDED
must be returned.
If the application specifies a string that is not a well-formed path string,
XR_ERROR_PATH_FORMAT_INVALID
must be returned.
A return value of XR_SUCCESS from xrStringToPath may not
necessarily imply that the runtime has a component or other source of data
that will be accessible through that semantic path.
It only means that the path string supplied was well-formed and that the
retrieved XrPath maps to the given path string within and during
the lifetime of the XrInstance given.
|
6.2.2. xrPathToString
// Provided by XR_VERSION_1_0
XrResult xrPathToString(
XrInstance instance,
XrPath path,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer);
xrPathToString retrieves the path name string associated with an
XrPath
, in the context of a given XrInstance, in the form of
a NULL
terminated string placed into a caller-allocated buffer.
Since the mapping between a well-formed path name string and an
XrPath
is bijective, there will always be exactly one string for
each valid XrPath
value.
This can be useful if the calling application receives an XrPath
value that they had not previously retrieved via xrStringToPath.
During the lifetime of the given XrInstance, the path name string
retrieved by this function for a given valid XrPath
will not
change.
For invalid paths, including XR_NULL_PATH, XR_ERROR_PATH_INVALID
must be returned.
6.3. Reserved Paths
In order for some uses of semantic paths to work consistently across runtimes, it is necessary to standardize several paths and require each runtime to use the same paths or patterns of paths for certain classes of usage. Those paths are as follows.
6.3.1. Top level /user paths
Some paths are used to refer to entities that are filling semantic roles in the system. These paths are all under the /user subtree.
The reserved user paths are:
Runtimes are not required to provide interaction at all of these paths. For instance, in a system with no hand tracking, only /user/head would be active for interaction. In a system with only one controller, the runtime may provide access to that controller via either /user/hand/left or /user/hand/right as it deems appropriate.
The runtime may change the devices referred to by /user/hand/left and /user/hand/right at any time.
If more than two hand-held controllers or devices are active, the runtime must determine which two are accessible as /user/hand/left and /user/hand/right.
6.3.2. Input subpaths
Interaction profiles 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 subpaths that use identifiers and component
names that do not appear in this specification or otherwise do not follow
the pattern specified below.
Input subpaths further qualify top-level /user paths to form
binding paths.
For this reason, they are often shown starting with …
or omitting path components before /input
or /output
entirely.
The input subpaths considered valid when combined with any given top-level
/user path vary by interaction profile.
Each input subpath must match the following pattern:
-
…/input/<identifier>[_<location>][/<component>]
Identifiers are often the label on the component or related to the type and location of the component.
When specifying a suggested binding there are several cases where the component part of the path can be determined automatically. See Suggested Bindings for more details.
See Interaction Profiles for examples of input subpaths.
Standard identifiers
-
trackpad - A 2D input source that usually includes click and touch component.
-
thumbstick - A small 2D joystick that is meant to be used with the user’s thumb. These sometimes include click and/or touch components.
-
joystick - A 2D joystick that is meant to be used with the user’s entire hand, such as a flight stick. These generally do not have click component, but might have touch components.
-
trigger - A 1D analog input component that returns to a rest state when the user stops interacting with it. These sometime include touch and/or click components.
-
throttle - A 1D analog input component that remains in position when the user stops interacting with it.
-
trackball - A 2D relative input source. These sometimes include click components.
-
pedal - A 1D analog input component that is similar to a trigger but meant to be operated by a foot
-
system - A button with the specialised meaning that it enables the user to access system-level functions and UI. Input data from system buttons is generally used internally by runtimes and may not be available to applications.
-
dpad_up, dpad_down, dpad_left, and dpad_right - A set of buttons arranged in a plus shape.
-
diamond_up, diamond_down, diamond_left, and diamond_right - Gamepads often have a set of four buttons arranged in a diamond shape. The labels on those buttons vary from gamepad to gamepad, but their arrangement is consistent. These names are used for the A/B/X/Y buttons on a Xbox controller, and the square/cross/circle/triangle button on a PlayStation controller.
-
a, b, x, y, start, home, end, select - Standalone buttons are named for their physical labels. These are the standard identifiers for such buttons. Extensions may add new identifiers as detailed in the next section. Groups of four buttons in a diamond shape should use the diamond-prefix names above instead of using the labels on the buttons themselves.
-
volume_up, volume_down, mute_mic, play_pause, menu, view, back - Some other standard controls are often identified by icons. These are their standard names.
-
thumbrest - Some controllers have a place for the user to rest their thumb.
-
shoulder - A button that is usually pressed with the index finger and is often positioned above a trigger.
-
squeeze - An input source that indicates that the user is squeezing their fist closed. This could be a simple button or act more like a trigger. Sources with this identifier should either follow button or trigger conventions for their components.
-
wheel - A steering wheel.
-
thumb_resting_surfaces - Any surfaces that a thumb may naturally rest on. This may include, but is not limited to, face buttons, thumbstick, and thumbrest (Provided by
XR_VERSION_1_1
) -
stylus - Tip that can be used for writing or drawing. May be able to detect various pressure levels (Provided by
XR_VERSION_1_1
) -
trigger_curl - This sensor detects how pointed or curled the user’s finger is on the trigger: 0 = fully pointed, 1 = finger flat on surface (Provided by
XR_VERSION_1_1
) -
trigger_slide - This sensor represents how far the user is sliding their index finger along the surface of the trigger: 0 = finger flat on the surface, 1 = finger fully drawn back (Provided by
XR_VERSION_1_1
)
Standard pose identifiers
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:
-
grip - A pose that allows applications to reliably render a virtual object held in the user’s hand, whether it is tracked directly or by a motion controller. The grip pose is defined as follows:
-
The grip position:
-
For tracked hands: The user’s palm centroid when closing the fist, at the surface of the palm.
-
For handheld motion controllers: A fixed position within the controller that generally lines up with the palm centroid when held by a hand in a neutral position. This position should be adjusted left or right to center the position within the controller’s grip.
-
-
The grip orientation’s +X axis: When you completely open your hand to form a flat 5-finger pose, the ray that is normal to the user’s palm (away from the palm in the left hand, into the palm in the right hand).
-
The grip orientation’s -Z axis: When you close your hand partially (as if holding the controller), the ray that goes through the center of the tube formed by your non-thumb fingers, in the direction of little finger to thumb.
-
The grip orientation’s +Y axis: orthogonal to +Z and +X using the right-hand rule.
-
-
aim - A pose that allows applications to point in the world using the input source, according to the platform’s conventions for aiming with that kind of source. The aim pose is defined as follows:
-
For tracked hands: The ray that follows platform conventions for how the user aims at objects in the world with their entire hand, with +Y up, +X to the right, and -Z forward. The ray chosen will be runtime-dependent, often a ray emerging from the hand at a target pointed by moving the forearm.
-
For handheld motion controllers: The ray that follows platform conventions for how the user targets objects in the world with the motion controller, with +Y up, +X to the right, and -Z forward. This is usually 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 ray chosen will be runtime-dependent, although this will often emerge from the frontmost tip of a motion controller.
-
-
grip_surface - (Provided by
XR_VERSION_1_1
) A pose that allows applications to reliably anchor visual content relative to the user’s physical hand, whether the user’s hand is tracked directly or its position and orientation is inferred by a physical controller. The grip_surface pose is defined as follows:-
The grip_surface position: The user’s physical palm centroid, at the surface of the palm. For the avoidance of doubt, the palm does not include fingers.
-
The grip_surface orientation’s +X axis: When a user is holding the controller and straightens their index fingers pointing forward, the ray that is normal (perpendicular) to the user’s palm (away from the palm in the left hand, into the palm in the right hand).
-
The grip_surface orientation’s -Z axis: When a user is holding the controller and straightens their index finger, the ray that is parallel to their finger’s pointing direction.
-
The grip_surface orientation’s +Y axis: orthogonal to +Z and +X using the right-hand rule.
-
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
-
upper
-
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 squeeze or other components.
-
x, y - scalar components of 2D values. These vary in value from -1 to 1. These represent the 2D position of the input source with 0 being the rest state on each axis. -1 means all the way left for x axis or all the way down for y axis. +1 means all the way right for x axis or all the way up for y 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 grip and aim, or may be defined on other identifiers such as trackpad to let applications reason about the surface of that part.
-
proximity - The user is in physical proximity of input source. This may be present for any kind of input source representing a physical component, such as a button, if the device includes the necessary sensor. The state of a "proximity" component must be
XR_TRUE
if the same input source is returningXR_TRUE
for either a "touch" or any other component that implies physical contact. The runtime may returnXR_TRUE
for "proximity" when "touch" returnsXR_FALSE
which would indicate that the user is hovering just above, but not touching the input source in question. "proximity" components are always boolean. (Provided byXR_VERSION_1_1
)
Output 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
-
haptic_trigger - A haptic element located in the trigger (Provided by
XR_VERSION_1_1
) -
haptic_thumb - A haptic element located in the resting place of the thumb, like under the touchpad (Provided by
XR_VERSION_1_1
)
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 component paths:
-
…/input/select/click
-
…/input/menu/click
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.2. Bytedance PICO Neo 3 controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/bytedance/pico_neo3_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Bytedance PICO Neo3 Controller.
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
-
…/input/menu/click
-
…/input/system/click (may not be available for application use)
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/thumbstick/y
-
…/input/thumbstick/x
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/squeeze/click
-
…/input/squeeze/value
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.3. Bytedance PICO 4 controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/bytedance/pico4_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Bytedance PICO 4 Controller.
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
-
…/input/system/click (may not be available for application use)
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/thumbstick/y
-
…/input/thumbstick/x
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/squeeze/click
-
…/input/squeeze/value
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.4. Bytedance PICO G3 controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/bytedance/pico_g3_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Bytedance PICO G3 Controller.
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/menu/click
-
…/input/grip/pose
-
…/input/aim/pose
-
…/input/thumbstick
-
…/input/thumbstick/click
Note
When the runtime supports
|
Note
When designing suggested bindings for this interaction profile, you may suggest bindings for both /user/hand/left and /user/hand/right. However, only one of them will be active at a given time, so do not design interactions that require simultaneous use of both hands. |
6.4.5. 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 on the Google Daydream Controller.
Supported component paths:
-
…/input/select/click
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/grip/pose
-
…/input/aim/pose
Note
When the runtime supports
|
6.4.6. HP Mixed Reality Motion Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/hp/mixed_reality_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the HP Mixed Reality Motion Controller.
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/y/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/b/click
-
-
…/input/menu/click
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.7. 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 component paths:
-
…/input/system/click (may not be available for application use)
-
…/input/squeeze/click
-
…/input/menu/click
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.8. HTC Vive Cosmos Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/htc/vive_cosmos_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Vive Cosmos Controller.
Supported component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/y/click
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/b/click
-
…/input/system/click (may not be available for application use)
-
-
…/input/shoulder/click
-
…/input/squeeze/click
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.9. HTC Vive Focus 3 Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/htc/vive_focus3_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Vive Focus 3 Controller.
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/y/click
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/b/click
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/click
-
…/input/squeeze/touch
-
…/input/squeeze/value
-
…/input/trigger/click
-
…/input/trigger/touch
-
…/input/trigger/value
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.10. 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 component paths:
-
…/input/system/click (may not be available for application use)
-
…/input/volume_up/click
-
…/input/volume_down/click
-
…/input/mute_mic/click
6.4.11. Magic Leap 2 Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/ml/ml2_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Magic Leap 2 controller.
Supported component paths:
-
…/input/menu/click
-
…/input/home/click (may not be available for application use)
-
…/input/trigger/click
-
…/input/trigger/value
-
…/input/trackpad/y
-
…/input/trackpad/x
-
…/input/trackpad/click
-
…/input/trackpad/force
-
…/input/trackpad/touch
-
…/input/aim/pose
-
…/input/grip/pose
-
…/input/shoulder/click
-
…/output/haptic
Note
When the runtime supports
|
6.4.12. 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 component paths:
-
…/input/menu/click
-
…/input/squeeze/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/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.13. 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 component paths:
-
…/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.14. 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 on the Oculus Go controller.
Supported component paths:
-
…/input/system/click (may not be available for application use)
-
…/input/trigger/click
-
…/input/back/click
-
…/input/trackpad/x
-
…/input/trackpad/y
-
…/input/trackpad/click
-
…/input/trackpad/touch
-
…/input/grip/pose
-
…/input/aim/pose
Note
When the runtime supports
|
6.4.15. 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 component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/trigger/proximity (Provided by
XR_VERSION_1_1
) -
…/input/thumb_resting_surfaces/proximity (Provided by
XR_VERSION_1_1
) -
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.16. Meta Touch Pro Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/meta/touch_pro_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Meta Touch Pro controller.
Supported component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/trigger/proximity
-
…/input/trigger_curl/value
-
…/input/trigger_slide/value
-
…/input/thumb_resting_surfaces/proximity
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/thumbrest/force
-
…/input/stylus/force
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
-
…/output/haptic_trigger
-
…/output/haptic_thumb
Note
When the runtime supports
|
6.4.17. Meta Touch Plus Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/meta/touch_plus_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Meta Touch Plus controller.
Supported component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/trigger/force
-
…/input/trigger/proximity
-
…/input/trigger_curl/value
-
…/input/trigger_slide/value
-
…/input/thumb_resting_surfaces/proximity
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.18. Meta Touch Controller (Rift CV1) Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/meta/touch_controller_rift_cv1
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Oculus Touch controller and is a legacy profile added to specifically represent the controller shipped with the Rift CV1.
Supported component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/trigger/proximity
-
…/input/thumb_resting_surfaces/proximity
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.19. Meta Touch Controller (Rift S / Quest 1) Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/meta/touch_controller_quest_1_rift_s
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Oculus Touch controller and is a legacy profile added to specifically represent the controller shipped with the Rift S and Quest 1.
Supported component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/trigger/proximity
-
…/input/thumb_resting_surfaces/proximity
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.20. Meta Touch Controller (Quest 2) Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/meta/touch_controller_quest_2
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Oculus Touch controller and is a legacy profile added to specifically represent the controller shipped with the Quest 2.
Supported component paths:
-
On /user/hand/left only:
-
…/input/x/click
-
…/input/x/touch
-
…/input/y/click
-
…/input/y/touch
-
…/input/menu/click
-
-
On /user/hand/right only:
-
…/input/a/click
-
…/input/a/touch
-
…/input/b/click
-
…/input/b/touch
-
…/input/system/click (may not be available for application use)
-
-
…/input/squeeze/value
-
…/input/trigger/value
-
…/input/trigger/touch
-
…/input/trigger/proximity
-
…/input/thumb_resting_surfaces/proximity
-
…/input/thumbstick/x
-
…/input/thumbstick/y
-
…/input/thumbstick/click
-
…/input/thumbstick/touch
-
…/input/thumbrest/touch
-
…/input/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.21. Samsung Odyssey Controller Profile
(Provided by XR_VERSION_1_1
)
Path: /interaction_profiles/samsung/odyssey_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Samsung Odyssey Controller. It is exactly the same, with the exception of the name of the interaction profile, as the Microsoft Mixed Reality Controller interaction profile. It enables the application to differentiate the newer form factor of motion controller released with the Samsung Odyssey headset. It enables the application to customize the appearance and experience of the controller differently from the original mixed reality motion controller.
Supported component paths:
-
…/input/menu/click
-
…/input/squeeze/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/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
6.4.22. Valve Index Controller Profile
Path: /interaction_profiles/valve/index_controller
Valid for user paths:
-
/user/hand/left
-
/user/hand/right
This interaction profile represents the input sources and haptics on the Valve Index controller.
Supported component paths:
-
…/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/squeeze/value
-
…/input/squeeze/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/grip/pose
-
…/input/aim/pose
-
…/output/haptic
Note
When the runtime supports
|
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
, LOCAL_FLOOR
, 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.
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 location of the left hand’s pose action space in 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 location 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
The XrReferenceSpaceType enumeration is defined as:
typedef enum XrReferenceSpaceType {
XR_REFERENCE_SPACE_TYPE_VIEW = 1,
XR_REFERENCE_SPACE_TYPE_LOCAL = 2,
XR_REFERENCE_SPACE_TYPE_STAGE = 3,
// Provided by XR_VERSION_1_1
XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR = 1000426000,
// Provided by XR_PICO_motion_tracking
XR_REFERENCE_SPACE_TYPE_ALGORITHM_GLOBAL_PICO = 1010002000,
XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrReferenceSpaceType;
Brief introductions to core reference space types follow. Each has full requirements in a subsequent section, linked from these descriptions.
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. 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.
7.1.1. View Reference Space
The XR_REFERENCE_SPACE_TYPE_VIEW
or VIEW
reference space tracks the
view origin used to generate view transforms for the primary viewer (or
centroid of view origins if stereo), with +Y up, +X to the right, and -Z
forward.
This space points in the forward direction for the viewer without
incorporating the user’s eye orientation, and is not gravity-aligned.
The VIEW
space is primarily useful when projecting from the user’s
perspective into another space to obtain a targeting ray, or when rendering
small head-locked content such as a reticle.
Content rendered in the VIEW
space will stay at a fixed point on
head-mounted displays and may be uncomfortable to view if too large.
To obtain the ideal view and projection transforms to use each frame for
rendering world content, applications should call xrLocateViews
instead of using this space.
7.1.2. Local Reference Space
The XR_REFERENCE_SPACE_TYPE_LOCAL
or LOCAL
reference space
establishes a world-locked origin, gravity-aligned to exclude pitch and
roll, with +Y up, +X to the right, and -Z forward.
This space locks in both its initial position and orientation, which the
runtime may define to be either the initial position at application launch
or some other calibrated zero position.
When a user needs to recenter the LOCAL
space, a runtime may offer some
system-level recentering interaction that is transparent to the application,
but which causes the current leveled head space to become the new LOCAL
space.
When such a recentering occurs, the runtime must queue the
XrEventDataReferenceSpaceChangePending event, with the recentered
LOCAL
space origin only taking effect for xrLocateSpace or
xrLocateViews calls whose XrTime
parameter is greater than or
equal to the XrEventDataReferenceSpaceChangePending::changeTime
in that event.
When views, controllers or other spaces experience tracking loss relative to
the LOCAL
space, 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_LOCATION_POSITION_VALID_BIT
and
XR_VIEW_STATE_POSITION_VALID_BIT
but it can clear
XR_SPACE_LOCATION_POSITION_TRACKED_BIT
and
XR_VIEW_STATE_POSITION_TRACKED_BIT
to indicate that the position is
inferred or last-known in this way.
When tracking is recovered, runtimes should snap the pose of other spaces
back into position relative to the original origin of LOCAL
space.
7.1.3. Stage Reference Space
The STAGE
reference space is a runtime-defined flat, rectangular space
that is empty and can be walked around on.
The origin is on the floor at the center of the rectangle, with +Y up, and
the X and Z axes aligned with the rectangle edges.
The runtime may not be able to locate spaces relative to the STAGE
reference space if the user has not yet defined one within the
runtime-specific UI.
Applications can use xrGetReferenceSpaceBoundsRect to determine the
extents of the STAGE
reference space’s XZ bounds rectangle, if defined.
The STAGE
space is useful when an application needs to render
standing-scale content (no bounds) or room-scale content (with bounds)
that is relative to the physical floor.
When the user redefines the origin or bounds of the current STAGE
space,
or the runtime otherwise switches to a new STAGE
space definition, the
runtime must queue the XrEventDataReferenceSpaceChangePending event,
with the new STAGE
space origin only taking effect for xrLocateSpace
or xrLocateViews calls whose XrTime
parameter is greater than
or equal to the
XrEventDataReferenceSpaceChangePending::changeTime
in that
event.
When views, controllers, or other spaces experience tracking loss relative
to the STAGE
space, 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_LOCATION_POSITION_VALID_BIT
and
XR_VIEW_STATE_POSITION_VALID_BIT
but it can clear
XR_SPACE_LOCATION_POSITION_TRACKED_BIT
and
XR_VIEW_STATE_POSITION_TRACKED_BIT
to indicate that the position is
inferred or last-known in this way.
When tracking is recovered, runtimes should snap the pose of other spaces
back into position relative to the original origin of the STAGE
space.
7.1.4. Local Floor Reference Space
Local floor reference space, indicated by
XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR
, is closely related to the LOCAL
reference space.
It always aligns with the LOCAL
space, and matches it in X and Z position.
However, unlike the LOCAL
space, the LOCAL_FLOOR
space has its Y axis
origin on the runtime’s best estimate of the floor level under the origin of
the LOCAL
space.
The location of the origin of the LOCAL_FLOOR
space must match the
LOCAL
space in the X and Z coordinates but not in the Y coordinate.
The orientation of the LOCAL_FLOOR
space must match the LOCAL
space.
The runtime must establish the Y axis origin at its best estimate of the
floor level under the origin of the LOCAL
space space, subject to
requirements under the following conditions to match the floor level of the
STAGE
space.
If all of the following conditions are true, the Y axis origin of the
LOCAL_FLOOR
space must match the Y axis origin of the STAGE
space:
-
the
STAGE
space is supported -
the location of the
LOCAL
space relative to theSTAGE
space has valid position (XR_SPACE_LOCATION_POSITION_VALID_BIT
is set) -
bounds are available from xrGetReferenceSpaceBoundsRect for the
STAGE
space -
the position of the
LOCAL
space relative to theSTAGE
space is within theSTAGE
space XZ bounds
That is, if there is a stage with bounds, and if the local space and thus the local floor is logically within the stage, the local floor and the stage share the same floor level.
When the origin of the LOCAL
space is changed in orientation or XZ
position, the origin of the LOCAL_FLOOR
space must also change
accordingly.
When a change in origin of the LOCAL_FLOOR
space occurs, the runtime must
queue the XrEventDataReferenceSpaceChangePending event, with the
changed LOCAL_FLOOR
space origin only taking effect for
xrLocateSpace or xrLocateViews calls whose XrTime
parameter is greater than or equal to the
XrEventDataReferenceSpaceChangePending::changeTime
in that
event.
The xrGetReferenceSpaceBoundsRect function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetReferenceSpaceBoundsRect(
XrSession session,
XrReferenceSpaceType referenceSpaceType,
XrExtent2Df* bounds);
XR systems may have limited real world spatial ranges in which users can freely move around while remaining tracked. Applications sometimes 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 support boundaries.
If a runtime is unable to provide bounds for a given space,
XR_SPACE_BOUNDS_UNAVAILABLE
must be returned and all fields of
bounds
must 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 application during calls to xrCreateReferenceSpace.
The runtime must return XR_ERROR_REFERENCE_SPACE_UNSUPPORTED
if the
XrReferenceSpaceType passed in referenceSpaceType
is not
supported by this session
.
When a runtime will begin operating with updated space bounds, the runtime must queue a corresponding XrEventDataReferenceSpaceChangePending event.
The XrEventDataReferenceSpaceChangePending structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataReferenceSpaceChangePending {
XrStructureType type;
const void* next;
XrSession session;
XrReferenceSpaceType referenceSpaceType;
XrTime changeTime;
XrBool32 poseValid;
XrPosef poseInPreviousSpace;
} XrEventDataReferenceSpaceChangePending;
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 applications 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
XrFrameState::predictedDisplayTime
of future frames to avoid
threshold issues with applications that calculate future frame times using
XrFrameState::predictedDisplayPeriod
.
The poseInPreviousSpace
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 application during calls to
xrCreateReferenceSpace.
If the runtime does not know the location of the space’s new origin relative
to its previous origin, poseValid
must be false, and the position and
orientation of poseInPreviousSpace
are undefined.
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 be unlocatable unless the action set that contains the corresponding pose action was set as active via the most recent xrSyncActions call. 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 xrSyncActions is called.
If xrLocateSpace is called with an unlocatable action space, the
implementation must return no position or orientation and both
XR_SPACE_LOCATION_POSITION_VALID_BIT
and
XR_SPACE_LOCATION_ORIENTATION_VALID_BIT
must be unset.
If XrSpaceVelocity is also supplied,
XR_SPACE_VELOCITY_LINEAR_VALID_BIT
and
XR_SPACE_VELOCITY_ANGULAR_VALID_BIT
must be unset.
If xrLocateViews is called with an unlocatable action space, the
implementation must return no position or orientation and both
XR_VIEW_STATE_POSITION_VALID_BIT
and
XR_VIEW_STATE_ORIENTATION_VALID_BIT
must be unset.
7.3. Space Lifecycle
There are a small set of core APIs that allow applications to reason about reference spaces, action spaces, and their relative locations.
7.3.1. xrEnumerateReferenceSpaces
The xrEnumerateReferenceSpaces function is defined as:
// Provided by XR_VERSION_1_0
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 identical buffer contents 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:
// Provided by XR_VERSION_1_0
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 XrReferenceSpaceCreateInfo structure is defined as:
typedef struct XrReferenceSpaceCreateInfo {
XrStructureType type;
const void* next;
XrReferenceSpaceType referenceSpaceType;
XrPosef poseInReferenceSpace;
} XrReferenceSpaceCreateInfo;
7.3.3. xrCreateActionSpace
The xrCreateActionSpace function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrCreateActionSpace(
XrSession session,
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 XrSession handle. See Action Spaces Lifetime for details.
The runtime must return XR_ERROR_ACTION_TYPE_MISMATCH
if the action
provided in XrActionSpaceCreateInfo::action
is not of type
XR_ACTION_TYPE_POSE_INPUT
.
The XrActionSpaceCreateInfo structure is defined as:
typedef struct XrActionSpaceCreateInfo {
XrStructureType type;
const void* next;
XrAction action;
XrPath subactionPath;
XrPosef poseInActionSpace;
} XrActionSpaceCreateInfo;
7.3.4. xrDestroySpace
The xrDestroySpace function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrDestroySpace(
XrSpace space);
XrSpace handles are destroyed using xrDestroySpace. The runtime may still use this space if there are active dependencies (e.g, compositions in progress).
7.4. Locating Spaces
Applications use the xrLocateSpace function to find the pose of an
XrSpace’s origin within a base XrSpace at a given historical or
predicted time.
If an application wants to know the velocity of the space’s origin, it can
chain an XrSpaceVelocity structure to the next
pointer of the
XrSpaceLocation structure when calling the xrLocateSpace
function.
Applications should inspect the output XrSpaceLocationFlagBits and
XrSpaceVelocityFlagBits to determine the validity and tracking status
of the components of the location.
7.4.1. xrLocateSpace
xrLocateSpace provides the physical location of a space in a base space at a specified time, if currently known by the runtime.
// Provided by XR_VERSION_1_0
XrResult xrLocateSpace(
XrSpace space,
XrSpace baseSpace,
XrTime time,
XrSpaceLocation* location);
For a time
in the past, the runtime should locate 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 locate 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 location with no position and XR_SPACE_LOCATION_POSITION_VALID_BIT
unset.
Some devices improve their understanding of the world as the device is used.
The location 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
XrPosef::position
and XrPosef::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_LOCATION_POSITION_VALID_BIT
but it can clear
XR_SPACE_LOCATION_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 to locate
space
in baseSpace
(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 location with no position and
XR_SPACE_LOCATION_POSITION_VALID_BIT
unset.
The runtime must return a location with both
XR_SPACE_LOCATION_POSITION_VALID_BIT
and
XR_SPACE_LOCATION_POSITION_TRACKED_BIT
set when locating 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 location in this case is the difference in the two spaces'
application-specified transforms relative to that common entity.
During tracking loss, the runtime should return a location with
XR_SPACE_LOCATION_POSITION_VALID_BIT
and
XR_SPACE_LOCATION_ORIENTATION_VALID_BIT
set and
XR_SPACE_LOCATION_POSITION_TRACKED_BIT
and
XR_SPACE_LOCATION_ORIENTATION_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 continue to make use of the runtime’s latest
knowledge of the world.
If an XrSpaceVelocity structure is chained to the
XrSpaceLocation::next
pointer, and the velocity is observed or
can be calculated by the runtime, the runtime must fill in the linear
velocity of the origin of space within the reference frame of
baseSpace
and set the XR_SPACE_VELOCITY_LINEAR_VALID_BIT
.
Similarly, if an XrSpaceVelocity structure is chained to the
XrSpaceLocation::next
pointer, and the angular velocity is
observed or can be calculated by the runtime, the runtime must fill in the
angular velocity of the origin of space within the reference frame of
baseSpace
and set the XR_SPACE_VELOCITY_ANGULAR_VALID_BIT
.
The following example code shows how an application can get both the
location and velocity of a space within a base space using the
xrLocateSpace function by chaining an XrSpaceVelocity to the
next
pointer of XrSpaceLocation and calling xrLocateSpace.
XrSpace space; // previously initialized
XrSpace baseSpace; // previously initialized
XrTime time; // previously initialized
XrSpaceVelocity velocity {XR_TYPE_SPACE_VELOCITY};
XrSpaceLocation location {XR_TYPE_SPACE_LOCATION, &velocity};
xrLocateSpace(space, baseSpace, time, &location);
The XrSpaceLocation structure is defined as:
typedef struct XrSpaceLocation {
XrStructureType type;
void* next;
XrSpaceLocationFlags locationFlags;
XrPosef pose;
} XrSpaceLocation;
The XrSpaceLocation::locationFlags
member is of the following
type, and contains a bitwise-OR of zero or more of the bits defined in
XrSpaceLocationFlagBits.
typedef XrFlags64 XrSpaceLocationFlags;
Valid bits for XrSpaceLocationFlags are defined by XrSpaceLocationFlagBits, which is specified as:
// Flag bits for XrSpaceLocationFlags
static const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_VALID_BIT = 0x00000001;
static const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_VALID_BIT = 0x00000002;
static const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT = 0x00000004;
static const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_TRACKED_BIT = 0x00000008;
The flag bits have the following meanings:
The XrSpaceVelocity structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrSpaceVelocity {
XrStructureType type;
void* next;
XrSpaceVelocityFlags velocityFlags;
XrVector3f linearVelocity;
XrVector3f angularVelocity;
} XrSpaceVelocity;
The XrSpaceVelocity::velocityFlags
member is of the following
type, and contains a bitwise-OR of zero or more of the bits defined in
XrSpaceVelocityFlagBits.
typedef XrFlags64 XrSpaceVelocityFlags;
Valid bits for XrSpaceVelocityFlags are defined by XrSpaceVelocityFlagBits, which is specified as:
// Flag bits for XrSpaceVelocityFlags
static const XrSpaceVelocityFlags XR_SPACE_VELOCITY_LINEAR_VALID_BIT = 0x00000001;
static const XrSpaceVelocityFlags XR_SPACE_VELOCITY_ANGULAR_VALID_BIT = 0x00000002;
The flag bits have the following meanings:
7.4.2. Locate spaces
Applications can use xrLocateSpaces function to locate an array of spaces.
The xrLocateSpaces function is defined as:
// Provided by XR_VERSION_1_1
XrResult xrLocateSpaces(
XrSession session,
const XrSpacesLocateInfo* locateInfo,
XrSpaceLocations* spaceLocations);
xrLocateSpaces provides the physical location of one or more spaces in a base space at a specified time, if currently known by the runtime.
The XrSpacesLocateInfo::time
, the
XrSpacesLocateInfo::baseSpace
, and each space in
XrSpacesLocateInfo::spaces
, in the locateInfo
parameter,
all follow the same specifics as the corresponding inputs to the
xrLocateSpace function.
The XrSpacesLocateInfo structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrSpacesLocateInfo {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
uint32_t spaceCount;
const XrSpace* spaces;
} XrSpacesLocateInfo;
The time
, the baseSpace
, and each space in spaces
all
follow the same specifics as the corresponding inputs to the
xrLocateSpace function.
The baseSpace
and all of the XrSpace handles in the spaces
array must be valid and share the same parent XrSession.
If the time
is invalid, the xrLocateSpaces must return
XR_ERROR_TIME_INVALID
.
The spaceCount
must be a positive number, i.e. the array spaces
must not be empty.
Otherwise, the runtime must return XR_ERROR_VALIDATION_FAILURE
.
The XrSpaceLocations structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrSpaceLocations {
XrStructureType type;
void* next;
uint32_t locationCount;
XrSpaceLocationData* locations;
} XrSpaceLocations;
The XrSpaceLocations structure contains an array of space locations in
the member locations
, to be used as output for xrLocateSpaces.
The application must allocate this array to be populated with the function
output.
The locationCount
value must be the same as
XrSpacesLocateInfo::spaceCount
, otherwise, the
xrLocateSpaces function must return
XR_ERROR_VALIDATION_FAILURE
.
The XrSpaceLocationData structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrSpaceLocationData {
XrSpaceLocationFlags locationFlags;
XrPosef pose;
} XrSpaceLocationData;
This is a single element of the array in
XrSpaceLocations::locations
, and is used to return the pose and
location flags for a single space with respect to the specified base space
from a call to xrLocateSpaces.
It does not accept chained structures to allow for easier use in dynamically
allocated container datatypes.
Chained structures are possible with the XrSpaceLocations that
describes an array of these elements.
7.4.3. Locate space velocities
Applications can request the velocities of spaces by chaining the XrSpaceVelocities structure to the next pointer of XrSpaceLocations when calling xrLocateSpaces.
The XrSpaceVelocities structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrSpaceVelocities {
XrStructureType type;
void* next;
uint32_t velocityCount;
XrSpaceVelocityData* velocities;
} XrSpaceVelocities;
The velocities
member contains an array of space velocities in the
member velocities
, to be used as output for xrLocateSpaces.
The application must allocate this array to be populated with the function
output.
The velocityCount
value must be the same as
XrSpacesLocateInfo::spaceCount
, otherwise, the
xrLocateSpaces function must return
XR_ERROR_VALIDATION_FAILURE
.
The XrSpaceVelocityData structure is defined as:
// Provided by XR_VERSION_1_1
typedef struct XrSpaceVelocityData {
XrSpaceVelocityFlags velocityFlags;
XrVector3f linearVelocity;
XrVector3f angularVelocity;
} XrSpaceVelocityData;
This is a single element of the array in
XrSpaceVelocities::velocities
, and is used to return the linear
and angular velocity and velocity flags for a single space with respect to
the specified base space from a call to xrLocateSpaces.
It does not accept chained structures to allow for easier use in dynamically
allocated container datatypes.
7.4.4. Example code for xrLocateSpaces
The following example code shows how an application retrieves both the location and velocity of one or more spaces in a base space at a given time using the xrLocateSpaces function.
XrInstance instance; // previously initialized
XrSession session; // previously initialized
XrSpace baseSpace; // previously initialized
std::vector<XrSpace> spacesToLocate; // previously initialized
// Prepare output buffers to receive data and get reused in frame loop.
std::vector<XrSpaceLocationData> locationBuffer(spacesToLocate.size());
std::vector<XrSpaceVelocityData> velocityBuffer(spacesToLocate.size());
// Get function pointer for xrLocateSpaces.
PFN_xrLocateSpaces xrLocateSpaces;
CHK_XR(xrGetInstanceProcAddr(instance, "xrLocateSpaces",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrLocateSpaces)));
// application frame loop
while (1) {
// Typically the time is the predicted display time returned from xrWaitFrame.
XrTime displayTime; // previously initialized.
XrSpacesLocateInfo locateInfo{XR_TYPE_SPACES_LOCATE_INFO};
locateInfo.baseSpace = baseSpace;
locateInfo.time = displayTime;
locateInfo.spaceCount = (uint32_t)spacesToLocate.size();
locateInfo.spaces = spacesToLocate.data();
XrSpaceLocations locations{XR_TYPE_SPACE_LOCATIONS};
locations.locationCount = (uint32_t)locationBuffer.size();
locations.locations = locationBuffer.data();
XrSpaceVelocities velocities{XR_TYPE_SPACE_VELOCITIES};
velocities.velocityCount = (uint32_t)velocityBuffer.size();
velocities.velocities = velocityBuffer.data();
locations.next = &velocities;
CHK_XR(xrLocateSpaces(session, &locateInfo, &locations));
for (uint32_t i = 0; i < spacesToLocate.size(); i++) {
const auto positionAndOrientationTracked =
XR_SPACE_LOCATION_POSITION_TRACKED_BIT | XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT;
const auto orientationOnlyTracked = XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT;
if ((locationBuffer[i].locationFlags & positionAndOrientationTracked) == positionAndOrientationTracked) {
// if the location is 6dof tracked
do_something(locationBuffer[i].pose.position);
do_something(locationBuffer[i].pose.orientation);
const auto velocityValidBits =
XR_SPACE_VELOCITY_LINEAR_VALID_BIT | XR_SPACE_VELOCITY_ANGULAR_VALID_BIT;
if ((velocityBuffer[i].velocityFlags & velocityValidBits) == velocityValidBits) {
do_something(velocityBuffer[i].linearVelocity);
do_something(velocityBuffer[i].angularVelocity);
}
}
else if ((locationBuffer[i].locationFlags & orientationOnlyTracked) == orientationOnlyTracked) {
// if the location is 3dof tracked
do_something(locationBuffer[i].pose.orientation);
if ((velocityBuffer[i].velocityFlags & XR_SPACE_VELOCITY_ANGULAR_VALID_BIT) == XR_SPACE_VELOCITY_ANGULAR_VALID_BIT) {
do_something(velocityBuffer[i].angularVelocity);
}
}
}
}
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,
// Provided by XR_VERSION_1_1
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET = 1000037000,
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 function is defined as:
// Provided by XR_VERSION_1_0
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.
Runtimes must always return identical buffer contents from this enumeration
for the given systemId
and for the lifetime of the instance.
8.2.2. xrGetViewConfigurationProperties
The xrGetViewConfigurationProperties function is defined as:
// Provided by XR_VERSION_1_0
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* next;
XrViewConfigurationType viewConfigurationType;
XrBool32 fovMutable;
} XrViewConfigurationProperties;
8.2.4. xrEnumerateViewConfigurationViews
The xrEnumerateViewConfigurationViews function is defined as:
// Provided by XR_VERSION_1_0
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
.
Runtimes must always return identical buffer contents from this enumeration
for the given systemId
and viewConfigurationType
for the
lifetime of the instance.
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* 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
XrSwapchainSubImage::imageRect
values, and
XrSwapchainCreateInfo for more information about creating swapchains
appropriately sized to support those
XrSwapchainSubImage::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
XrSpace sceneSpace; // 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;
XrViewConfigurationType viewConfig = XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM;
for(uint32_t i = 0; i < configurationCount; ++i)
{
if (configurationTypes[i] == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO)
{
configFound = true;
viewConfig = configurationTypes[i];
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,
viewConfig,
0,
&viewCount,
nullptr));
std::vector<XrViewConfigurationView> configViews(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW});
CHK_XR(xrEnumerateViewConfigurationViews(instance, system,
viewConfig,
viewCount,
&viewCount,
configViews.data()));
// Set the primary view configuration for the session.
XrSessionBeginInfo beginInfo = {XR_TYPE_SESSION_BEGIN_INFO};
beginInfo.primaryViewConfigurationType = viewConfig;
CHK_XR(xrBeginSession(session, &beginInfo));
// Allocate a buffer according to viewCount.
std::vector<XrView> views(viewCount, {XR_TYPE_VIEW});
// Run a per-frame loop.
while (!quit)
{
// Wait for a new frame.
XrFrameWaitInfo frameWaitInfo{XR_TYPE_FRAME_WAIT_INFO};
XrFrameState frameState{XR_TYPE_FRAME_STATE};
CHK_XR(xrWaitFrame(session, &frameWaitInfo, &frameState));
// Begin frame immediately before GPU work
XrFrameBeginInfo frameBeginInfo { XR_TYPE_FRAME_BEGIN_INFO };
CHK_XR(xrBeginFrame(session, &frameBeginInfo));
std::vector<XrCompositionLayerBaseHeader*> layers;
XrCompositionLayerProjectionView projViews[2] = { /*...*/ };
XrCompositionLayerProjection layerProj{ XR_TYPE_COMPOSITION_LAYER_PROJECTION};
if (frameState.shouldRender) {
XrViewLocateInfo viewLocateInfo{XR_TYPE_VIEW_LOCATE_INFO};
viewLocateInfo.viewConfigurationType = viewConfig;
viewLocateInfo.displayTime = frameState.predictedDisplayTime;
viewLocateInfo.space = sceneSpace;
XrViewState viewState{XR_TYPE_VIEW_STATE};
XrView views[2] = { {XR_TYPE_VIEW}, {XR_TYPE_VIEW}};
uint32_t viewCountOutput;
CHK_XR(xrLocateViews(session, &viewLocateInfo, &viewState, configViews.size(), &viewCountOutput, views));
// ...
// Use viewState and frameState for scene render, and fill in projViews[2]
// ...
// Assemble composition layers structure
layerProj.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
layerProj.space = sceneSpace;
layerProj.viewCount = 2;
layerProj.views = projViews;
layers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader*>(&layerProj));
}
// End frame and submit layers, even if layers is empty due to shouldRender = false
XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO};
frameEndInfo.displayTime = frameState.predictedDisplayTime;
frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
frameEndInfo.layerCount = (uint32_t)layers.size();
frameEndInfo.layers = layers.data();
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.
9.1. Session Lifecycle
A typical XR session coordinates the application and the runtime through session control functions and session state events.
|
A session is considered running after a successful call to
xrBeginSession and remains running until any call is made to
xrEndSession.
Certain functions are only valid to call when a session is running, such as
xrWaitFrame, or else the XR_ERROR_SESSION_NOT_RUNNING
error
must be returned by the runtime.
A session is considered not running before a successful call to
xrBeginSession and becomes not running again after any call is made to
xrEndSession.
Certain functions are only valid to call when a session is not running, such
as xrBeginSession, or else the XR_ERROR_SESSION_RUNNING
error
must be returned by the runtime.
If an error is returned from xrBeginSession, the session remains in its current running or not running state. Calling xrEndSession always transitions a session to the not running state, regardless of any errors returned.
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.
An application must call xrBeginSession when the session is in the
XR_SESSION_STATE_READY
state, or
XR_ERROR_SESSION_NOT_READY
will be returned; it must call
xrEndSession when the session is in the XR_SESSION_STATE_STOPPING
state, otherwise
XR_ERROR_SESSION_NOT_STOPPING
will be returned.
This is to allow the runtimes to seamlessly transition from one
application’s session to another.
The application can call xrDestroySession at any time during the
session life cycle, however, it must stop using the XrSession handle
immediately in all threads and stop using any related resources.
Therefore, it’s typically undesirable to destroy a
running session and instead it’s recommended to wait for
XR_SESSION_STATE_EXITING
to destroy a
session.
9.2. Session Creation
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 an
XrGraphicsBinding*
struct of one (and only one) of the enabled
graphics API extensions to the next chain of XrSessionCreateInfo.
The application must call the xrGet*GraphicsRequirements
method
(where *
is a placeholder) provided by the chosen graphics API extension
before attempting to create the session (for example,
).
Unless specified differently in the graphics API extension, the application
is responsible for creating a valid graphics device binding based on the
requirements returned by xrGet*GraphicsRequirements
methods (for
details refer to the extension specification of the graphics API).
The xrCreateSession function is defined as:
// Provided by XR_VERSION_1_0
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, and a
corresponding XrEventDataSessionStateChanged event to the
XR_SESSION_STATE_IDLE
state must be generated as the first such event
for the new session.
The runtime must return XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING
(XR_ERROR_VALIDATION_FAILURE
may be returned due to legacy behavior)
on calls to xrCreateSession if a function named like
xrGet*GraphicsRequirements
has not been called for the same
instance
and XrSessionCreateInfo::systemId
.
(See graphics binding extensions for details.)
The XrSessionCreateInfo structure is defined as:
typedef struct XrSessionCreateInfo {
XrStructureType type;
const void* next;
XrSessionCreateFlags createFlags;
XrSystemId systemId;
} XrSessionCreateInfo;
The XrSessionCreateInfo::createFlags
member is of the following
type, and contains a bitwise-OR of zero or more of the bits defined in
XrSessionCreateFlagBits.
typedef XrFlags64 XrSessionCreateFlags;
Valid bits for XrSessionCreateFlags are defined by XrSessionCreateFlagBits.
// Flag bits for XrSessionCreateFlags
There are currently no session creation flags. This is reserved for future use.
The xrDestroySession function is defined as.
// Provided by XR_VERSION_1_0
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.
The application is responsible for ensuring that it has no calls using
session
in progress when the session is destroyed.
xrDestroySession can be called when the session is in any session state.
9.3. Session Control
The xrBeginSession function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrBeginSession(
XrSession session,
const XrSessionBeginInfo* beginInfo);
When the application receives XrEventDataSessionStateChanged event
with the XR_SESSION_STATE_READY
state, the application should then
call xrBeginSession to start rendering frames for display to the user.
After this function successfully returns, the session is considered to be running. The application should then start its frame loop consisting of some sequence of xrWaitFrame/xrBeginFrame/xrEndFrame calls.
If the session is already running when the application
calls xrBeginSession, the runtime must return error
XR_ERROR_SESSION_RUNNING
.
If the session is not running when the application
calls xrBeginSession, but the session is not yet in the
XR_SESSION_STATE_READY
state, the runtime must return error
XR_ERROR_SESSION_NOT_READY
.
Note that a runtime may decide not to show the user any given frame from a
session at any time, for example if the user has switched to a different
application’s running session.
The application should check whether xrWaitFrame returns
XrFrameState::shouldRender
set to true before rendering a given
frame to determine whether that frame will be visible to the user.
Runtime session frame state must start in a reset state when a session transitions to running so that no state is carried over from when the same session was previously running. Frame state in this context includes xrWaitFrame, xrBeginFrame, and xrEndFrame call order enforcement.
If XrSessionBeginInfo::primaryViewConfigurationType
in
beginInfo
is not supported by the XrSystemId
used to create
the session
, the runtime must return
XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED
.
The XrSessionBeginInfo structure is defined as:
typedef struct XrSessionBeginInfo {
XrStructureType type;
const void* next;
XrViewConfigurationType primaryViewConfigurationType;
} XrSessionBeginInfo;
The xrEndSession function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrEndSession(
XrSession session);
When the application receives XrEventDataSessionStateChanged event
with the XR_SESSION_STATE_STOPPING
state, the application should stop
its frame loop and then call xrEndSession to end the
running session.
This function signals to the runtime that the application will no longer
call xrWaitFrame, xrBeginFrame or xrEndFrame from any
thread allowing the runtime to safely transition the session to
XR_SESSION_STATE_IDLE
.
The application must also avoid reading input state or sending haptic
output after calling xrEndSession.
If the session is not running when the application
calls xrEndSession, the runtime must return error
XR_ERROR_SESSION_NOT_RUNNING
.
If the session is still running when the application
calls xrEndSession, but the session is not yet in the
XR_SESSION_STATE_STOPPING
state, the runtime must return error
XR_ERROR_SESSION_NOT_STOPPING
.
If the application wishes to exit a running session, the application can
call xrRequestExitSession so that the session transitions from
XR_SESSION_STATE_IDLE
to XR_SESSION_STATE_EXITING
.
When an application wishes to exit a running session,
it can call xrRequestExitSession, requesting that the runtime
transition through the various intermediate session states including
XR_SESSION_STATE_STOPPING
to XR_SESSION_STATE_EXITING
.
On platforms where an application’s lifecycle is managed by the system, session state changes may be implicitly triggered by application lifecycle state changes. On such platforms, using platform-specific methods to alter application lifecycle state may be the preferred method of provoking session state changes. The behavior of xrRequestExitSession is not altered, however explicit session exit may not interact with the platform-specific application lifecycle.
The xrRequestExitSession function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrRequestExitSession(
XrSession session);
If session
is not running when
xrRequestExitSession is called, XR_ERROR_SESSION_NOT_RUNNING
must be returned.
9.4. Session 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.4.1. XrEventDataSessionStateChanged
The XrEventDataSessionStateChanged structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataSessionStateChanged {
XrStructureType type;
const void* 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_SYNCHRONIZED = 3,
XR_SESSION_STATE_VISIBLE = 4,
XR_SESSION_STATE_FOCUSED = 5,
XR_SESSION_STATE_STOPPING = 6,
XR_SESSION_STATE_LOSS_PENDING = 7,
XR_SESSION_STATE_EXITING = 8,
XR_SESSION_STATE_MAX_ENUM = 0x7FFFFFFF
} XrSessionState;
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, begin its session
and synchronize its frame loop with the runtime.
The application does this by successfully calling xrBeginSession and
then running its frame loop by calling xrWaitFrame, xrBeginFrame
and xrEndFrame in a loop.
If the runtime wishes to return the session to the
XR_SESSION_STATE_IDLE
state, it must wait until the application calls
xrBeginSession.
After returning from the xrBeginSession call, the runtime may then
immediately transition forward through the
XR_SESSION_STATE_SYNCHRONIZED
state to the
XR_SESSION_STATE_STOPPING
state, to request that the application end
this session.
If the system supports a user engagement sensor and runtime is in
XR_SESSION_STATE_IDLE
state, the runtime may wait until the user
starts engaging with the device before transitioning to the
XR_SESSION_STATE_READY
state.
Receiving the XR_SESSION_STATE_SYNCHRONIZED
state indicates that the
application has synchronized its frame loop with
the runtime, but its frames are not visible to the user.
The application should continue running its frame loop by calling
xrWaitFrame, xrBeginFrame and xrEndFrame, although it
should avoid heavy GPU work so that other visible applications can take CPU
and GPU precedence.
The application can save resources here by skipping rendering and not
submitting any composition layers until xrWaitFrame returns an
XrFrameState with shouldRender
set to true.
A runtime may use this frame synchronization to facilitate seamless
switching from a previous XR application to this application on a frame
boundary.
Receiving the XR_SESSION_STATE_VISIBLE
state indicates that the
application has synchronized its frame loop with
the runtime, and the session’s frames will be visible to the user, but the
session is not eligible to receive XR input.
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.
The application should continue running its frame loop, rendering and
submitting its composition layers, although it may wish to pause its
experience, as users cannot interact with the application at this time.
It is important for applications to continue rendering when visible, even
when they do not have focus, so the user continues to see something
reasonable underneath modal pop-ups.
Runtimes should make input actions inactive while the application is
unfocused, and applications should react to an inactive input action by
skipping rendering of that action’s input avatar (depictions of hands or
other tracked objects controlled by the user).
Receiving the XR_SESSION_STATE_FOCUSED
state indicates that the
application has synchronized its frame loop with
the runtime, the session’s frames will be visible to the user, and the
session is eligible to receive XR input.
The runtime should only give one session XR input focus at any given time.
The application should be running its frame loop, rendering and submitting
composition layers, including input avatars (depictions of hands or other
tracked objects controlled by the user) for any input actions that are
active.
The runtime should avoid rendering its own input avatars when an
application is focused, unless input from a given source is being captured
by the runtime at the moment.
Receiving the XR_SESSION_STATE_STOPPING
state indicates that the
runtime has determined that the application should halt its rendering loop.
Applications should exit their rendering loop and call xrEndSession
when in this state.
A possible reason for this would be to minimize contention between multiple
applications.
If the system supports a user engagement sensor and the session is running,
the runtime may transition to the XR_SESSION_STATE_STOPPING
state
when the user stops engaging with the device.
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 if they
do not have a non-XR user experience.
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 application 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 are 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_SRGB8_ALPHA8
, 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
OpenXR applications should avoid submitting linear encoded 8 bit color data
(e.g. Gritz, L. and d’Eon, E. 2007. The Importance of Being Linear. In: H. Nguyen, ed., GPU Gems 3. Addison-Wesley Professional. https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-24-importance-being-linear |
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 function is defined as:
// Provided by XR_VERSION_1_0
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
.
Texture formats should be in order from highest to lowest runtime
preference.
The application should use the highest preference format that it supports
for optimal performance and quality.
Runtimes must always return identical buffer contents from this enumeration for the lifetime of the session.
The xrCreateSwapchain function is defined as:
// Provided by XR_VERSION_1_0
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 runtime must return XR_ERROR_FEATURE_UNSUPPORTED
if any bit of
the create or usage flags specified in the XrSwapchainCreateInfo is
unsupported.
The XrSwapchainCreateInfo structure is defined as:
typedef struct XrSwapchainCreateInfo {
XrStructureType type;
const void* next;
XrSwapchainCreateFlags createFlags;
XrSwapchainUsageFlags usageFlags;
int64_t format;
uint32_t sampleCount;
uint32_t width;
uint32_t height;
uint32_t faceCount;
uint32_t arraySize;
uint32_t mipCount;
} XrSwapchainCreateInfo;
The XrSwapchainCreateInfo::createFlags
member is of the
following type, and contains a bitwise-OR of zero or more of the bits
defined in XrSwapchainCreateFlagBits.
typedef XrFlags64 XrSwapchainCreateFlags;
Valid bits for XrSwapchainCreateFlags are defined by XrSwapchainCreateFlagBits, which is specified as:
// Flag bits for XrSwapchainCreateFlags
static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT = 0x00000001;
static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT = 0x00000002;
The flag bits have the following meanings:
A runtime may implement any of these, but is not required to.
A runtime must return XR_ERROR_FEATURE_UNSUPPORTED
from
xrCreateSwapchain if an XrSwapchainCreateFlags bit is requested
but not implemented.
XrSwapchainUsageFlags specify the intended usage of the swapchain
images.
The XrSwapchainCreateInfo::usageFlags
member is of this type,
and contains a bitwise-OR of one or more of the bits defined in
XrSwapchainUsageFlagBits.
typedef XrFlags64 XrSwapchainUsageFlags;
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 must match the intended usage.
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;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND = 0x00000080;
static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR = 0x00000080; // alias of XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND
The flag bits have the following meanings:
The number of images in each swapchain is implementation-defined except in the case of a static swapchain. To obtain the number of images actually allocated, call xrEnumerateSwapchainImages.
Swapchains will be created with graphics API-specific flags appropriate to the type of underlying image and its usage.
Runtimes must honor underlying graphics API limits when creating resources.
The xrDestroySwapchain function is defined as:
// Provided by XR_VERSION_1_0
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:
// Provided by XR_VERSION_1_0
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.
Runtimes must always return identical buffer contents from this enumeration for the lifetime of the swapchain.
Note: images
is a pointer to an array of structures of graphics
API-specific type, not an array of structure pointers.
The pointer submitted as images
will be treated as an array of the
expected graphics API-specific type based on the graphics API used at
session creation time.
If the type
member of any array element accessed in this way does not
match the expected value, the runtime must return
XR_ERROR_VALIDATION_FAILURE
.
Note
Under a typical memory model, a runtime must treat the supplied pointer as
an opaque blob beginning with XrSwapchainImageBaseHeader, until after
it has verified the XrSwapchainImageBaseHeader:: |
The XrSwapchainImageBaseHeader structure is defined as:
typedef struct XrSwapchainImageBaseHeader {
XrStructureType type;
void* next;
} XrSwapchainImageBaseHeader;
The XrSwapchainImageBaseHeader is a base structure that is extended by
graphics API-specific XrSwapchainImage*
child structures.
Before an application builds 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 to 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 (non-static) swapchain at a time, for example if the application implements a multiple frame deep rendering pipeline.
The xrAcquireSwapchainImage function is defined as:
// Provided by XR_VERSION_1_0
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 the next
available 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 runtime must return XR_ERROR_CALL_ORDER_INVALID
if a
swapchain
created with the XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT
set in XrSwapchainCreateInfo::createFlags
and this function has
been successfully called previously for this swapchain.
This function only provides the index of the swapchain image, for example for use in recording command buffers. It does not wait for the image to be usable by the application. The application must call xrWaitSwapchainImage for each "acquire" call before submitting graphics commands that write to the image.
The XrSwapchainImageAcquireInfo structure is defined as:
typedef struct XrSwapchainImageAcquireInfo {
XrStructureType type;
const void* next;
} XrSwapchainImageAcquireInfo;
Because this structure only exists to support extension-specific structures,
xrAcquireSwapchainImage will accept a NULL
argument for
xrAcquireSwapchainImage::acquireInfo
for applications that are
not using any relevant extensions.
The xrWaitSwapchainImage function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrWaitSwapchainImage(
XrSwapchain swapchain,
const XrSwapchainImageWaitInfo* waitInfo);
Before an application begins 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 without timeout, the app must release 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
must be 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 eventually relinquish ownership of a swapchain image to the application and must not block indefinitely.
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* next;
XrDuration timeout;
} XrSwapchainImageWaitInfo;
Once an application is done submitting commands that reference the swapchain image, the application must release the swapchain image. xrReleaseSwapchainImage will implicitly release the oldest swapchain image which has been acquired. The swapchain image must have been successfully waited on without timeout 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 may be used in one frame.
The xrReleaseSwapchainImage function is defined as:
// Provided by XR_VERSION_1_0
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 defined as:
typedef struct XrSwapchainImageReleaseInfo {
XrStructureType type;
const void* next;
} XrSwapchainImageReleaseInfo;
Because this structure only exists to support extension-specific structures,
xrReleaseSwapchainImage will accept a NULL
argument for
xrReleaseSwapchainImage::releaseInfo
for applications that are
not using any relevant extensions.
10.2. View and Projection State
An application uses xrLocateViews to retrieve the viewer pose and projection parameters needed to render each view for use in a composition projection layer.
The xrLocateViews function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrLocateViews(
XrSession session,
const XrViewLocateInfo* viewLocateInfo,
XrViewState* viewState,
uint32_t viewCapacityInput,
uint32_t* viewCountOutput,
XrView* views);
The xrLocateViews function returns the view and projection info for a particular display time. This time is typically the target display time 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 specified view configuration type, along with an XrViewState containing additional state data shared across all views. 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.
If an application gives a viewLocateInfo
with a
XrViewLocateInfo::viewConfigurationType
that was not passed in
the session’s call to xrBeginSession via the
XrSessionBeginInfo::primaryViewConfigurationType
, or enabled
though an extension, then the runtime must return
XR_ERROR_VALIDATION_FAILURE
.
The XrViewLocateInfo structure is defined as:
typedef struct XrViewLocateInfo {
XrStructureType type;
const void* next;
XrViewConfigurationType viewConfigurationType;
XrTime displayTime;
XrSpace space;
} XrViewLocateInfo;
The XrViewLocateInfo structure contains the display time and space used to locate the view XrView structures.
The runtime must return error
XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED
if the given
viewConfigurationType
is not one of the supported type reported by
xrEnumerateViewConfigurations.
The XrViewState structure is defined as:
typedef struct XrViewState {
XrStructureType type;
void* 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.
The XrViewState::viewStateFlags
member is of this type, and
contains a bitwise-OR of zero or more of the bits defined in
XrViewStateFlagBits.
typedef XrFlags64 XrViewStateFlags;
Valid bits for XrViewStateFlags are defined by XrViewStateFlagBits, which is specified as:
// 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;
The flag bits have the following meanings:
10.3. Frame Synchronization
An application synchronizes its rendering loop to the runtime by calling xrWaitFrame.
The xrWaitFrame function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrWaitFrame(
XrSession session,
const XrFrameWaitInfo* frameWaitInfo,
XrFrameState* frameState);
xrWaitFrame throttles the application frame loop in order to synchronize application frame submissions with the display. xrWaitFrame returns a predicted display time for the next time that the runtime predicts a composited frame will be displayed. The runtime may affect this computation by changing the return values and throttling of xrWaitFrame in response to feedback from frame submission and completion times in xrEndFrame. A subsequent xrWaitFrame call must block until the previous frame has been begun with xrBeginFrame and must unblock independently of the corresponding call to xrEndFrame. Refer to xrBeginSession for details on how a transition to session running resets the frame function call order.
When less than one frame interval has passed since the previous return from xrWaitFrame, the runtime should block until the beginning of the next frame interval. If more than one frame interval has passed since the last return from xrWaitFrame, the runtime may return immediately or block until the beginning of the next frame interval.
In the case that an application has pipelined frame submissions, the application should compute the appropriate target display time using both the predicted display time and predicted display interval. The application should use the computed target display time when requesting space and view locations for rendering.
The XrFrameState::predictedDisplayTime
returned by
xrWaitFrame must be monotonically increasing.
The runtime may dynamically adjust the start time of the frame 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 the
session
is not running.
Note
The engine simulation should advance based on the display time. Every stage in the engine pipeline should use the exact same display time for one particular application-generated frame. An accurate and consistent display time across all stages and threads in the engine pipeline is important to avoid object motion judder. If the application has multiple pipeline stages, the application should pass its computed display time through its pipeline, as xrWaitFrame must be called only once per frame. |
The XrFrameWaitInfo structure is defined as:
typedef struct XrFrameWaitInfo {
XrStructureType type;
const void* next;
} XrFrameWaitInfo;
Because this structure only exists to support extension-specific structures,
xrWaitFrame must accept a NULL
argument for
xrWaitFrame::frameWaitInfo
for applications that are not using
any relevant extensions.
The XrFrameState structure is defined as:
typedef struct XrFrameState {
XrStructureType type;
void* next;
XrTime predictedDisplayTime;
XrDuration predictedDisplayPeriod;
XrBool32 shouldRender;
} XrFrameState;
XrFrameState describes the time at which the next frame 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.
For any frame where shouldRender
is XR_FALSE
, the application
should avoid heavy GPU work for that frame, for example by not rendering
its layers.
This typically happens when the application is transitioning into or out of
a running session, or when some system UI is fully covering the application
at the moment.
As long as the session is running, the application
should keep running the frame loop to maintain the frame synchronization to
the runtime, even if this requires calling xrEndFrame with all layers
omitted.
10.4. 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 to xrBeginFrame
must 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.
A successful call to xrBeginFrame again with no intervening
xrEndFrame call must 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.
An application may call xrEndFrame without having called
xrReleaseSwapchainImage since the previous call to xrEndFrame
for any swapchain passed to xrEndFrame.
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:
// Provided by XR_VERSION_1_0
XrResult xrBeginFrame(
XrSession session,
const XrFrameBeginInfo* frameBeginInfo);
xrBeginFrame is called prior to the start of frame rendering.
The application should still call xrBeginFrame but omit rendering
work for the frame if XrFrameState::shouldRender
is
XR_FALSE
.
Runtimes must not perform frame synchronization or throttling through the xrBeginFrame function and should instead do so through xrWaitFrame.
The runtime must return the error code XR_ERROR_CALL_ORDER_INVALID
if
there was no corresponding successful call to xrWaitFrame.
The runtime must return the success code XR_FRAME_DISCARDED
if a
prior xrBeginFrame has been called without an intervening call to
xrEndFrame.
Refer to xrBeginSession for details on how a transition to
session running resets the frame function call order.
The runtime must return XR_ERROR_SESSION_NOT_RUNNING
if the
session
is not running.
The XrFrameBeginInfo structure is defined as:
typedef struct XrFrameBeginInfo {
XrStructureType type;
const void* next;
} XrFrameBeginInfo;
Because this structure only exists to support extension-specific structures,
xrBeginFrame will accept a NULL
argument for
xrBeginFrame::frameBeginInfo
for applications that are not using
any relevant extensions.
The xrEndFrame function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrEndFrame(
XrSession session,
const XrFrameEndInfo* frameEndInfo);
xrEndFrame may return immediately to the application.
XrFrameEndInfo::displayTime
should be computed using values
returned by xrWaitFrame.
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.
Note
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. |
Every call to xrEndFrame must be preceded by a successful call to
xrBeginFrame.
Failure to do so must result in XR_ERROR_CALL_ORDER_INVALID
being
returned by xrEndFrame.
Refer to xrBeginSession for details on how a transition to
session running resets the frame function call order.
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.
If no layers are provided then the display must be cleared.
XR_ERROR_LAYER_INVALID
must be returned if an unknown, unsupported
layer type, or NULL
pointer is passed as one of the
XrFrameEndInfo::layers.
XR_ERROR_LAYER_INVALID
must be returned if a layer references a
swapchain that has no released swapchain image.
XR_ERROR_LAYER_LIMIT_EXCEEDED
must 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
must be returned if
XrFrameEndInfo::layers contains a composition layer which references
pixels outside of the associated swapchain image or if negatively sized.
XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED
must be returned if
XrFrameEndInfo::environmentBlendMode is not supported.
XR_ERROR_SESSION_NOT_RUNNING
must be returned if the session
is not running.
Note
Applications should discard frames for which xrEndFrame returns a recoverable error over attempting to resubmit the frame with different frame parameters to provide a more consistent experience across different runtime implementations. |
The XrFrameEndInfo structure is defined as:
typedef struct XrFrameEndInfo {
XrStructureType type;
const void* 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.
10.5. 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 must 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.6. 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
must be returned by xrEndFrame.
Composition layers must be drawn in the same order as they are specified in via XrFrameEndInfo, with the 0th layer drawn first. Layers must be 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.6.1. Composition Layer Flags
XrCompositionLayerFlags specifies options for individual composition layers, and contains a bitwise-OR of zero or more of the bits defined in XrCompositionLayerFlagBits.
typedef XrFlags64 XrCompositionLayerFlags;
Valid bits for XrCompositionLayerFlags are defined by XrCompositionLayerFlagBits, which is specified as:
// Flag bits for XrCompositionLayerFlags
// XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT is deprecated and should not be used
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001;
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002;
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT = 0x00000004;
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_MRC_COMPOSITION_BIT_PICO = 0x40000000;
static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_INVERTED_ALPHA_BIT_EXT = 0x00000008;
The flag bits have the following meanings:
10.6.2. 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.
Layer swapchain textures may contain an alpha channel, depending on the
image format.
If a submitted swapchain’s texture format does not include an alpha channel
or if the XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT
is
unset, then the layer alpha is initialized to one.
If the swapchain texture format color encoding is other than RGBA, it is converted to RGBA.
If the texture color channels are encoded without premultiplying by alpha,
the XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT
should be set.
The effect of this bit alters the layer color as follows:
LayerColor.RGB *= LayerColor.A
LayerColor is then clamped to a range of [0.0, 1.0].
The layer blending operation is defined as:
CompositeColor = LayerColor + CompositeColor * (1 - LayerColor.A)
Before the first layer is composited, all components of CompositeColor are initialized to zero.
10.6.3. 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 used 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* next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
} XrCompositionLayerBaseHeader;
All composition layer structures begin with the elements described in the XrCompositionLayerBaseHeader. The XrCompositionLayerBaseHeader structure 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;
Runtimes must return XR_ERROR_VALIDATION_FAILURE
if the
XrSwapchainSubImage::imageArrayIndex
is equal to or greater than
the XrSwapchainCreateInfo::arraySize
that the
XrSwapchainSubImage::swapchain
was created with.
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:
// Provided by XR_VERSION_1_0
typedef struct XrCompositionLayerProjection {
XrStructureType type;
const void* 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
an XrSpace which is also world-locked, such as the |
The XrCompositionLayerProjectionView structure is defined as:
typedef struct XrCompositionLayerProjectionView {
XrStructureType type;
const void* 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
must be composited in view array order.
Quad Layer Composition
The XrCompositionLayerQuad structure defined as:
// Provided by XR_VERSION_1_0
typedef struct XrCompositionLayerQuad {
XrStructureType type;
const void* next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
XrEyeVisibility eyeVisibility;
XrSwapchainSubImage subImage;
XrPosef pose;
XrExtent2Df 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.6.4. 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 environment 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.
The environment may be perceived in two ways. It could be the user’s view of the physical world that exists beyond the displays, or it could be a synthetic environment including virtual components generated externally from the application. Alternatively, it could be a combination of both these elements.
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 application in that mode may render a glow as a grounding effect
around the black shadow to ensure the shadow can be seen.
Similarly, an application designed for
XR_ENVIRONMENT_BLEND_MODE_OPAQUE
or
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 XR_ENVIRONMENT_BLEND_MODE_OPAQUE
or
XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
modes.
For devices that support video/optical passthrough or synthetic
environments, they may support the XR_ENVIRONMENT_BLEND_MODE_ADDITIVE
or XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
modes.
Selecting one of these modes would display the environment in the
background, contingent upon the capability and status of the headsets.
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 application
chooses each frame.
For example, if an application 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
application’s layers.
The xrEnumerateEnvironmentBlendModes function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrEnumerateEnvironmentBlendModes(
XrInstance instance,
XrSystemId systemId,
XrViewConfigurationType viewConfigurationType,
uint32_t environmentBlendModeCapacityInput,
uint32_t* environmentBlendModeCountOutput,
XrEnvironmentBlendMode* environmentBlendModes);
Enumerates the set of environment blend modes that this runtime supports for a given view configuration of the system. Environment blend modes should be in order from highest to lowest runtime preference.
Runtimes must always return identical buffer contents from this enumeration
for the given systemId
and viewConfigurationType
for the
lifetime of the instance.
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 application 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{XR_TYPE_ACTION_SET_CREATE_INFO};
strcpy(actionSetInfo.actionSetName, "gameplay");
strcpy(actionSetInfo.localizedActionSetName, "Gameplay");
actionSetInfo.priority = 0;
XrActionSet inGameActionSet;
CHK_XR(xrCreateActionSet(instance, &actionSetInfo, &inGameActionSet));
// create a "teleport" input action
XrActionCreateInfo actioninfo{XR_TYPE_ACTION_CREATE_INFO};
strcpy(actioninfo.actionName, "teleport");
actioninfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT;
strcpy(actioninfo.localizedActionName, "Teleport");
XrAction teleportAction;
CHK_XR(xrCreateAction(inGameActionSet, &actioninfo, &teleportAction));
// create a "player_hit" output action
XrActionCreateInfo hapticsactioninfo{XR_TYPE_ACTION_CREATE_INFO};
strcpy(hapticsactioninfo.actionName, "player_hit");
hapticsactioninfo.actionType = XR_ACTION_TYPE_VIBRATION_OUTPUT;
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{XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING};
suggestedBindings.interactionProfile = interactionProfilePath;
suggestedBindings.suggestedBindings = bindings;
suggestedBindings.countSuggestedBindings = 2;
CHK_XR(xrSuggestInteractionProfileBindings(instance, &suggestedBindings));
XrSessionActionSetsAttachInfo attachInfo{XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO};
attachInfo.countActionSets = 1;
attachInfo.actionSets = &inGameActionSet;
CHK_XR(xrAttachSessionActionSets(session, &attachInfo));
// application main loop
while (1)
{
// sync action data
XrActiveActionSet activeActionSet{inGameActionSet, XR_NULL_PATH};
XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO};
syncInfo.countActiveActionSets = 1;
syncInfo.activeActionSets = &activeActionSet;
CHK_XR(xrSyncActions(session, &syncInfo));
// query input action state
XrActionStateBoolean teleportState{XR_TYPE_ACTION_STATE_BOOLEAN};
XrActionStateGetInfo getInfo{XR_TYPE_ACTION_STATE_GET_INFO};
getInfo.action = teleportAction;
CHK_XR(xrGetActionStateBoolean(session, &getInfo, &teleportState));
if (teleportState.changedSinceLastSync && teleportState.currentState)
{
// fire haptics using output action
XrHapticVibration vibration{XR_TYPE_HAPTIC_VIBRATION};
vibration.amplitude = 0.5;
vibration.duration = 300;
vibration.frequency = 3000;
XrHapticActionInfo hapticActionInfo{XR_TYPE_HAPTIC_ACTION_INFO};
hapticActionInfo.action = hapticsAction;
CHK_XR(xrApplyHapticFeedback(session, &hapticActionInfo, (const XrHapticBaseHeader*)&vibration));
}
}
11.2. Action Sets
XR_DEFINE_HANDLE(XrActionSet)
Action sets are application-defined collections of actions. They are attached to a given XrSession with a xrAttachSessionActionSets call. They are enabled or disabled by the application via xrSyncActions 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:
// Provided by XR_VERSION_1_0
XrResult xrCreateActionSet(
XrInstance instance,
const XrActionSetCreateInfo* createInfo,
XrActionSet* actionSet);
The xrCreateActionSet function creates an action set and returns a handle to the created action set.
The XrActionSetCreateInfo structure is defined as:
typedef struct XrActionSetCreateInfo {
XrStructureType type;
const void* next;
char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE];
char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE];
uint32_t priority;
} 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 input sources from action sets with a lower priority
number if those specific input sources 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 XR_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
or
XR_ERROR_LOCALIZED_NAME_INVALID
respectively.
If actionSetName
or localizedActionSetName
are duplicates of the
corresponding field for any existing action set in the specified instance,
the runtime must return XR_ERROR_NAME_DUPLICATED
or
XR_ERROR_LOCALIZED_NAME_DUPLICATED
respectively.
If the conflicting action set is destroyed, the conflicting field is no
longer considered 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:
// Provided by XR_VERSION_1_0
XrResult xrDestroyActionSet(
XrActionSet actionSet);
Action set handles can be destroyed by calling xrDestroyActionSet. When an action set handle is destroyed, all handles of actions in that action set are also destroyed.
The implementation must not free underlying resources for the action set while there are other valid handles that refer to those resources. The implementation may release resources for an action set when all of the action spaces for actions in that action set have been destroyed. See Action Spaces Lifetime for details.
Resources for all action sets in an instance must be freed when the instance containing those actions sets is destroyed.
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:
// Provided by XR_VERSION_1_0
XrResult xrCreateAction(
XrActionSet actionSet,
const XrActionCreateInfo* createInfo,
XrAction* action);
xrCreateAction creates an action and returns its handle.
If actionSet
has been included in a call to
xrAttachSessionActionSets, the implementation must return
XR_ERROR_ACTIONSETS_ALREADY_ATTACHED
.
The XrActionCreateInfo structure is defined as:
typedef struct XrActionCreateInfo {
XrStructureType type;
const void* next;
char actionName[XR_MAX_ACTION_NAME_SIZE];
XrActionType actionType;
uint32_t countSubactionPaths;
const XrPath* subactionPaths;
char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE];
} 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_UNSUPPORTED
:
-
Each path provided is one of:
-
/user/head
-
/user/hand/left
-
/user/hand/right
-
/user/gamepad
-
-
No path appears in the list more than once
Extensions may append additional top level user paths to the above list.
Note
Earlier revisions of the spec mentioned /user but it could not be implemented as specified and was removed as errata. |
The runtime must return XR_ERROR_PATH_UNSUPPORTED
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
or
XR_ERROR_LOCALIZED_NAME_INVALID
respectively.
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
or
XR_ERROR_LOCALIZED_NAME_DUPLICATED
respectively.
If the conflicting action is destroyed, the conflicting field is no longer
considered 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_ACTION_TYPE_BOOLEAN_INPUT = 1,
XR_ACTION_TYPE_FLOAT_INPUT = 2,
XR_ACTION_TYPE_VECTOR2F_INPUT = 3,
XR_ACTION_TYPE_POSE_INPUT = 4,
XR_ACTION_TYPE_VIBRATION_OUTPUT = 100,
XR_ACTION_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrActionType;
The xrDestroyAction function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrDestroyAction(
XrAction action);
Action handles can be destroyed by calling xrDestroyAction. Handles for actions that are part of an action set are automatically destroyed when the action set’s handle is destroyed.
The implementation must not destroy the underlying resources for an action when xrDestroyAction is called. Those resources are still used to make action spaces locatable and when processing action priority in xrSyncActions. Destroying the action handle removes the application’s access to these resources, but has no other change on actions.
Resources for all actions in an instance must be freed when the instance containing those actions sets is destroyed.
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 suggest bindings for their actions to runtimes so that raw
input data is mapped appropriately to the application’s actions.
Suggested bindings also serve as a signal indicating the hardware that has
been tested by the application developer.
Applications can suggest bindings by calling
xrSuggestInteractionProfileBindings for each
interaction profile that the
application is developed and tested with.
If bindings are provided for an appropriate interaction profile, the runtime
may select one and input will begin to flow.
Interaction profile selection changes must only happen when
xrSyncActions is called.
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. If an input value cannot be converted to the type of the action, the value must be ignored and not contribute to the state of the action.
For actions created with XR_ACTION_TYPE_BOOLEAN_INPUT
when the runtime
is obeying suggested bindings: Boolean input sources must be 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 XR_TRUE
.
The runtime should use hysteresis when applying this threshold.
The threshold and hysteresis range may vary from device to device or
component to component and are 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/click instead
of …/example/path if it is available.
If a parent path does not have a …/click subpath, the runtime
must use …/value and apply the same thresholding that would be
applied to any scalar input.
In any other situation the runtime may provide an alternate binding for the
action or it will be unbound.
For actions created with XR_ACTION_TYPE_FLOAT_INPUT
when the runtime
is obeying suggested bindings: If the input value specified by the path is
scalar, the input value must be bound directly to the float.
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 a parent path does not have a …/value subpath, the runtime
must use …/click.
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 may provide an alternate binding for
the action or it will be unbound.
For actions created with XR_ACTION_TYPE_VECTOR2F_INPUT
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 may provide an alternate binding for
the action or it will be unbound.
For actions created with XR_ACTION_TYPE_POSE_INPUT
when the runtime is
obeying suggested bindings: Pose input sources must be 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 may provide an alternate binding for the
action or it will be unbound.
The xrSuggestInteractionProfileBindings function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrSuggestInteractionProfileBindings(
XrInstance instance,
const XrInteractionProfileSuggestedBinding* suggestedBindings);
The xrSuggestInteractionProfileBindings function provides action bindings for a single interaction profile. The application can call xrSuggestInteractionProfileBindings once per interaction profile that it supports.
The application can provide any number of bindings for each action.
If the application successfully calls xrSuggestInteractionProfileBindings more than once for an interaction profile, the runtime must discard the previous suggested bindings and replace them with the new suggested bindings for that profile.
If the interaction profile path does not follow the structure defined in
Interaction Profiles or suggested
bindings contain paths that do not follow the format defined in
Input subpaths (further described in
XrActionSuggestedBinding), the runtime must return
XR_ERROR_PATH_UNSUPPORTED
.
If the interaction profile or input source for any of the suggested bindings
does not exist in the allowlist defined in
Interaction Profile Paths, the
runtime must return XR_ERROR_PATH_UNSUPPORTED
.
A runtime must accept every valid binding in the allowlist though it is
free to ignore any of them.
If the action set for any action referenced in the suggestedBindings
parameter has been included in a call to xrAttachSessionActionSets,
the implementation must return XR_ERROR_ACTIONSETS_ALREADY_ATTACHED
.
The XrInteractionProfileSuggestedBinding structure is defined as:
typedef struct XrInteractionProfileSuggestedBinding {
XrStructureType type;
const void* 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 xrAttachSessionActionSets function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrAttachSessionActionSets(
XrSession session,
const XrSessionActionSetsAttachInfo* attachInfo);
xrAttachSessionActionSets attaches the XrActionSet handles in
XrSessionActionSetsAttachInfo::actionSets
to the session
.
Action sets must be attached in order to be synchronized with
xrSyncActions.
When an action set is attached to a session, that action set becomes immutable. See xrCreateAction and xrSuggestInteractionProfileBindings for details.
After action sets are attached to a session, if any unattached actions are
passed to functions for the same session, then for those functions the
runtime must return XR_ERROR_ACTIONSET_NOT_ATTACHED
.
The runtime must return XR_ERROR_ACTIONSETS_ALREADY_ATTACHED
if
xrAttachSessionActionSets is called more than once for a given
session
.
The XrSessionActionSetsAttachInfo structure is defined as:
typedef struct XrSessionActionSetsAttachInfo {
XrStructureType type;
const void* next;
uint32_t countActionSets;
const XrActionSet* actionSets;
} XrSessionActionSetsAttachInfo;
11.5. Current Interaction Profile
The xrGetCurrentInteractionProfile function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetCurrentInteractionProfile(
XrSession session,
XrPath topLevelUserPath,
XrInteractionProfileState* interactionProfile);
xrGetCurrentInteractionProfile retrieves the current interaction profile for a top level user path.
The runtime must return only interaction profiles for which the application has provided suggested bindings with xrSuggestInteractionProfileBindings or XR_NULL_PATH. 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. The runtime may return the last-known interaction profile in the event that no controllers are active.
If xrAttachSessionActionSets has not yet been called for the
session
, the runtime must return
XR_ERROR_ACTIONSET_NOT_ATTACHED
.
If topLevelUserPath
is not one of the top level user paths described
in Top level /user paths, the runtime must return
XR_ERROR_PATH_UNSUPPORTED
.
The XrInteractionProfileState structure is defined as:
typedef struct XrInteractionProfileState {
XrStructureType type;
void* next;
XrPath interactionProfile;
} XrInteractionProfileState;
The runtime must only include interaction profiles that the application has provided bindings for via xrSuggestInteractionProfileBindings or XR_NULL_PATH. 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_NULL_PATH.
The XrEventDataInteractionProfileChanged structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrEventDataInteractionProfileChanged {
XrStructureType type;
const void* next;
XrSession session;
} XrEventDataInteractionProfileChanged;
The XrEventDataInteractionProfileChanged event is queued to notify the application that the current interaction profile 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 xrSuggestInteractionProfileBindings. This event must only be queued for running sessions.
Upon receiving this event, an application can call xrGetCurrentInteractionProfile for each top level user path in use, if its behavior depends on the current interaction profile.
11.6. 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.
xrGetActionState*
calls for an action in an action set never bound to
the session with xrAttachSessionActionSets must return
XR_ERROR_ACTIONSET_NOT_ATTACHED
.
The result of calls to xrGetActionState*
for an XrAction and
subaction path must not change between calls to xrSyncActions.
When the combination of the parent XrActionSet and subaction path for
an action is passed to xrSyncActions, 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 xrSyncActions,
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 xrSyncActions.
When xrGetActionState*
or haptic output functions are called while the
session is not focused, the runtime must set
the isActive
value to XR_FALSE
and suppress all haptic output.
Furthermore, the runtime should stop all in-progress haptic events when a
session loses focus.
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 currentState
value is computed based on the current sync,
combining the underlying input sources bound to the provided
subactionPaths
within this action.
The changedSinceLastSync
value must be XR_TRUE
if the computed
currentState
value differs from the currentState
value that
would have been computed as of the previous sync for the same
subactionPaths
.
If there is no previous sync, or the action was not active for the previous
sync, the changedSinceLastSync
value must be set to XR_FALSE
.
The isActive
value must be XR_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 XR_FALSE
.
For any action which is inactive, the runtime must return zero (or
XR_FALSE
) for state, XR_FALSE
for changedSinceLastSync
,
and 0
for lastChangeTime
.
11.6.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 -
Float actions - The current state must be the state of the input with the largest absolute value
-
Vector2 actions - The current state must be the state of the input with the longest length
-
Pose actions - The current state must be the state of a single pose source. The source of the pose must only be changed during a call to xrSyncAction. The runtime should only change the source in response to user actions, such as picking up a new controller, or external events, such as a controller running out of battery.
-
Haptic actions - The runtime must send output events to all bound haptic devices
11.6.2. Structs to describe action and subaction paths
The XrActionStateGetInfo structure is used to provide action and
subaction paths when calling xrGetActionState*
function.
It is defined as:
typedef struct XrActionStateGetInfo {
XrStructureType type;
const void* next;
XrAction action;
XrPath subactionPath;
} XrActionStateGetInfo;
See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
The XrHapticActionInfo structure is used to provide action and
subaction paths when calling xr*HapticFeedback
function.
It is defined as:
typedef struct XrHapticActionInfo {
XrStructureType type;
const void* next;
XrAction action;
XrPath subactionPath;
} XrHapticActionInfo;
See XrActionCreateInfo for a description of subaction paths, and the restrictions on their use.
11.6.3. Boolean Actions
xrGetActionStateBoolean retrieves the current state of a boolean action. It is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetActionStateBoolean(
XrSession session,
const XrActionStateGetInfo* getInfo,
XrActionStateBoolean* state);
The XrActionStateBoolean structure is defined as:
typedef struct XrActionStateBoolean {
XrStructureType type;
void* next;
XrBool32 currentState;
XrBool32 changedSinceLastSync;
XrTime lastChangeTime;
XrBool32 isActive;
} XrActionStateBoolean;
When multiple input sources are bound to this action, the currentState
follows the previously defined rule to resolve ambiguity.
11.6.4. Scalar and Vector Actions
xrGetActionStateFloat retrieves the current state of a floating-point action. It is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetActionStateFloat(
XrSession session,
const XrActionStateGetInfo* getInfo,
XrActionStateFloat* state);
The XrActionStateFloat structure is defined as:
typedef struct XrActionStateFloat {
XrStructureType type;
void* next;
float currentState;
XrBool32 changedSinceLastSync;
XrTime lastChangeTime;
XrBool32 isActive;
} XrActionStateFloat;
When multiple input sources are bound to this action, the currentState
follows the previously defined rule to resolve ambiguity.
xrGetActionStateVector2f retrieves the current state of a two-dimensional vector action. It is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetActionStateVector2f(
XrSession session,
const XrActionStateGetInfo* getInfo,
XrActionStateVector2f* state);
The XrActionStateVector2f structure is defined as:
typedef struct XrActionStateVector2f {
XrStructureType type;
void* next;
XrVector2f currentState;
XrBool32 changedSinceLastSync;
XrTime lastChangeTime;
XrBool32 isActive;
} XrActionStateVector2f;
When multiple input sources are bound to this action, the currentState
follows the previously defined rule to resolve ambiguity.
11.6.5. Pose Actions
The xrGetActionStatePose function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetActionStatePose(
XrSession session,
const XrActionStateGetInfo* getInfo,
XrActionStatePose* state);
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, the application can create an action space using xrCreateActionSpace. Then, after each sync, the application can locate the pose of this action space within a base space using xrLocateSpace.
The XrActionStatePose structure is defined as:
typedef struct XrActionStatePose {
XrStructureType type;
void* next;
XrBool32 isActive;
} XrActionStatePose;
A pose action must not be bound to multiple input sources, according to the previously defined rule.
11.7. 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 xrSyncActions.
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 focused.
Output action requests for an action in an action set never attached to the
session with xrAttachSessionActionSets must return
XR_ERROR_ACTIONSET_NOT_ATTACHED
.
The only haptics type supported by unextended OpenXR is XrHapticVibration.
The xrApplyHapticFeedback function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrApplyHapticFeedback(
XrSession session,
const XrHapticActionInfo* hapticActionInfo,
const XrHapticBaseHeader* hapticFeedback);
Triggers a haptic event through the specified action of type
XR_ACTION_TYPE_VIBRATION_OUTPUT
.
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 session
is not focused, the runtime must return
XR_SESSION_NOT_FOCUSED
, and not trigger a haptic event.
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.
The XrHapticBaseHeader structure is defined as:
typedef struct XrHapticBaseHeader {
XrStructureType type;
const void* next;
} XrHapticBaseHeader;
The XrHapticVibration structure is defined as:
// Provided by XR_VERSION_1_0
typedef struct XrHapticVibration {
XrStructureType type;
const void* 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.
// Provided by XR_VERSION_1_0
#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.
// Provided by XR_VERSION_1_0
#define XR_FREQUENCY_UNSPECIFIED 0
The xrStopHapticFeedback function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrStopHapticFeedback(
XrSession session,
const XrHapticActionInfo* hapticActionInfo);
If a haptic event from this XrAction is in progress, when this function is called the runtime must stop that event.
If session
is not focused, the runtime must return
XR_SESSION_NOT_FOCUSED
.
11.8. Input Action State Synchronization
The xrSyncActions function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrSyncActions(
XrSession session,
const XrActionsSyncInfo* syncInfo);
xrSyncActions updates the current state of input actions.
Repeated input action state queries between subsequent synchronization calls
must return the same values.
The XrActionSet structures referenced in the
XrActionsSyncInfo::activeActionSets
must have been previously
attached to the session via xrAttachSessionActionSets.
If any action sets not attached to this session are passed to
xrSyncActions it must return XR_ERROR_ACTIONSET_NOT_ATTACHED
.
Subsets of the bound action sets can be synchronized in order to control
which actions are seen as active.
If session
is not focused, the runtime must return
XR_SESSION_NOT_FOCUSED
, and all action states in the session must be
inactive.
The XrActionsSyncInfo structure is defined as:
typedef struct XrActionsSyncInfo {
XrStructureType type;
const void* next;
uint32_t countActiveActionSets;
const XrActiveActionSet* activeActionSets;
} XrActionsSyncInfo;
The XrActiveActionSet structure is defined as:
typedef struct XrActiveActionSet {
XrActionSet actionSet;
XrPath subactionPath;
} XrActiveActionSet;
This structure defines a single active action set and subaction path combination. Applications can provide a list of these structures to the xrSyncActions function.
11.9. Bound Sources
An application can use the xrEnumerateBoundSourcesForAction and
xrGetInputSourceLocalizedName calls to prompt the user which physical
inputs to use in order to perform an action.
The bound sources
are opaque XrPath
values representing the
physical controls that an 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.
Once the bound sources for an action are obtained, the application can gather additional information about it. xrGetInputSourceLocalizedName returns a localized human-readable string describing the bound physical control, e.g. 'A Button'.
The xrEnumerateBoundSourcesForAction function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrEnumerateBoundSourcesForAction(
XrSession session,
const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
uint32_t sourceCapacityInput,
uint32_t* sourceCountOutput,
XrPath* sources);
If an action is unbound, xrEnumerateBoundSourcesForAction must assign
0
to the value pointed-to by sourceCountOutput
and not modify the
array.
xrEnumerateBoundSourcesForAction must return
XR_ERROR_ACTIONSET_NOT_ATTACHED
if passed an action in an action set
never attached to the session with xrAttachSessionActionSets.
As bindings for actions do not change between calls to xrSyncActions,
xrEnumerateBoundSourcesForAction must enumerate the same set of bound
sources, or absence of bound sources, for a given query (defined by the
enumerateInfo
parameter) between any two calls to xrSyncActions.
Note
The |
The XrBoundSourcesForActionEnumerateInfo structure is defined as:
typedef struct XrBoundSourcesForActionEnumerateInfo {
XrStructureType type;
const void* next;
XrAction action;
} XrBoundSourcesForActionEnumerateInfo;
The xrGetInputSourceLocalizedName function is defined as:
// Provided by XR_VERSION_1_0
XrResult xrGetInputSourceLocalizedName(
XrSession session,
const XrInputSourceLocalizedNameGetInfo* getInfo,
uint32_t bufferCapacityInput,
uint32_t* bufferCountOutput,
char* buffer);
xrGetInputSourceLocalizedName returns a string for the bound source in the current system locale.
If xrAttachSessionActionSets has not yet been called for the session,
the runtime must return XR_ERROR_ACTIONSET_NOT_ATTACHED
.
The XrInputSourceLocalizedNameGetInfo structure is defined as:
typedef struct XrInputSourceLocalizedNameGetInfo {
XrStructureType type;
const void* next;
XrPath sourcePath;
XrInputSourceLocalizedNameFlags whichComponents;
} XrInputSourceLocalizedNameGetInfo;
The result of passing an XrPath
sourcePath
not retrieved
from xrEnumerateBoundSourcesForAction is not specified.
The XrInputSourceLocalizedNameGetInfo::whichComponents
parameter
is of the following type, and contains a bitwise-OR of one or more of the
bits defined in XrInputSourceLocalizedNameFlagBits.
typedef XrFlags64 XrInputSourceLocalizedNameFlags;
// Flag bits for XrInputSourceLocalizedNameFlags
static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT = 0x00000001;
static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT = 0x00000002;
static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT = 0x00000004;
The flag bits have the following meanings:
12. List of Extensions
12.1. XR_PICO_adaptive_resolution
- Name String
-
XR_PICO_adaptive_resolution
- Extension Type
-
Instance extension
- Registered Extension Number
-
10011
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Johnson Zhang, Bytedance
Overview
The XrAdaptiveResolutionSettingPICO the setting of adaptive resolution function.
// Provided by XR_PICO_adaptive_resolution
typedef enum XrAdaptiveResolutionSettingPICO {
XR_ADAPTIVE_RESOLUTION_SETTING_HIGH_QUALITY_PICO = 0,
XR_ADAPTIVE_RESOLUTION_SETTING_BALANCED_PICO = 1,
XR_ADAPTIVE_RESOLUTION_SETTING_POWER_SAVING_PICO = 2,
XR_ADAPTIVE_RESOLUTION_SETTING_MAX_ENUM_PICO = 0x7FFFFFFF
} XrAdaptiveResolutionSettingPICO;
The xrUpdateAdaptiveResolutionPICO function is defined as:
// Provided by XR_PICO_adaptive_resolution
XrResult xrUpdateAdaptiveResolutionPICO(
XrSession session,
XrAdaptiveResolutionSettingPICO setting,
XrExtent2Di currentResolution,
XrExtent2Di* lastResolution);
12.2. XR_PICO_body_tracking2
- Name String
-
XR_PICO_body_tracking2
- Extension Type
-
Instance extension
- Registered Extension Number
-
10010
- Revision
-
1
- Extension and Version Dependencies
- Last Modified Date
-
2024-11-29
- IP Status
-
No known IP claims.
- Contributors
-
Shanliang Xu, Bytedance
Shuai Liu, Bytedance
Chenxi Bao, Bytedance
12.2.1. Overview
Applications should also enable the
extension to
be able to get more data associated with body tracking.XR_BD_body_tracking
This extension also enables developers to start the calibration application, and more status values and information about body tracking can be obtained.
12.2.2. Start body tracking calibration application
The xrStartBodyTrackingCalibrationAppPICO function is defined as:
// Provided by XR_PICO_body_tracking2
XrResult xrStartBodyTrackingCalibrationAppPICO(
XrSession session);
12.2.3. Get body tracking state
The xrGetBodyTrackingStatePICO function is defined as:
// Provided by XR_PICO_body_tracking2
XrResult xrGetBodyTrackingStatePICO(
XrSession session,
XrBodyTrackingStatePICO* state);
XrBodyTrackingStatePICO can describe the state of body tracking.
The XrBodyTrackingStatePICO structure is defined as:
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyTrackingStatePICO {
XrStructureType type;
const void* next;
XrBodyTrackingStatusPICO status;
XrBodyTrackingMessagePICO message;
} XrBodyTrackingStatePICO;
The XrBodyTrackingStatusPICO enum describes status values about body tracking.
// Provided by XR_PICO_body_tracking2
typedef enum XrBodyTrackingStatusPICO {
XR_BODY_TRACKING_STATUS_INVALID_PICO = 0,
XR_BODY_TRACKING_STATUS_VALID_PICO = 1,
XR_BODY_TRACKING_STATUS_LIMITED_PICO = 2,
XR_BODY_TRACKING_STATUS_MAX_ENUM_PICO = 0x7FFFFFFF
} XrBodyTrackingStatusPICO;
The XrBodyTrackingMessagePICO enum describes status message about body tracking.
// Provided by XR_PICO_body_tracking2
typedef enum XrBodyTrackingMessagePICO {
XR_BODY_TRACKING_MESSAGE_NO_ERROR_PICO = 0,
XR_BODY_TRACKING_MESSAGE_TRACKER_NOT_CALIBRATED_PICO = 1,
XR_BODY_TRACKING_MESSAGE_TRACKER_NUM_NOT_ENOUGH_PICO = 2,
XR_BODY_TRACKING_MESSAGE_TRACKER_STATE_NOT_SATISFIED_PICO = 3,
XR_BODY_TRACKING_MESSAGE_TRACKER_PERSISTENT_INVISIBILITY_PICO = 4,
XR_BODY_TRACKING_MESSAGE_TRACKER_DATA_ERROR_PICO = 5,
XR_BODY_TRACKING_MESSAGE_USER_CHANGE_PICO = 6,
XR_BODY_TRACKING_MESSAGE_TRACKING_POSE_ERROR_PICO = 7,
XR_BODY_TRACKING_MESSAGE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrBodyTrackingMessagePICO;
12.2.4. Set the model bone length parameters
XrBodyBoneLengthPICO can be provided in the next
chain of
XrBodyTrackerCreateInfoBD
when calling xrCreateBodyTrackerBD
to
pass on the lengths of the bones in the model.
The XrBodyBoneLengthPICO structure is defined as:
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyBoneLengthPICO {
XrStructureType type;
void* next;
float headBoneLength;
float neckBoneLength;
float torsoBoneLength;
float hipBoneLength;
float upperBoneLength;
float lowerBoneLength;
float footBoneLength;
float shoulderBoneLength;
float upperArmBoneLength;
float lowerArmBoneLength;
float handBoneLength;
} XrBodyBoneLengthPICO;
12.2.5. Get more data about body tracking
XrBodyTrackingPostureFlagsDataPICO can be provided in the next
chain of XrBodyJointLocationsBD
when calling
xrLocateBodyJointsBD
to get specific gesture state on body joints.
The XrBodyTrackingPostureFlagsDataPICO structure is defined as:
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyTrackingPostureFlagsDataPICO {
XrStructureType type;
void* next;
uint32_t jointCount;
XrBodyTrackingPosturePICO* postureFlag;
} XrBodyTrackingPostureFlagsDataPICO;
// Provided by XR_PICO_body_tracking2
typedef enum XrBodyTrackingPosturePICO {
XR_BODY_TRACKING_POSTURE_STOMP_PICO = 1,
XR_BODY_TRACKING_POSTURE_STATIC_PICO = 2,
XR_BODY_TRACKING_POSTURE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrBodyTrackingPosturePICO;
Enum | Description |
---|---|
|
stomp. |
|
static. |
XrBodyJointVelocitiesPICO can be provided in the next
chain of
XrBodyJointLocationsBD
when calling xrLocateBodyJointsBD
to an
array of body joints velocities.
The XrBodyJointVelocitiesPICO structure is defined as:
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyJointVelocitiesPICO {
XrStructureType type;
void* next;
uint32_t jointCount;
XrBodyJointVelocityPICO* jointVelocities;
} XrBodyJointVelocitiesPICO;
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyJointVelocityPICO {
XrSpaceVelocityFlags velocityFlags;
XrVector3f linearVelocity;
XrVector3f angularVelocity;
} XrBodyJointVelocityPICO;
XrBodyJointAccelerationsPICO can be provided in the next
chain
of XrBodyJointLocationsBD
when calling xrLocateBodyJointsBD
to
an array of body joints accelerations.
The XrBodyJointAccelerationsPICO structure is defined as:
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyJointAccelerationsPICO {
XrStructureType type;
void* next;
uint32_t jointCount;
XrBodyJointAccelerationPICO* jointAccelerations;
} XrBodyJointAccelerationsPICO;
// Provided by XR_PICO_body_tracking2
typedef struct XrBodyJointAccelerationPICO {
XrSpaceAccelerationFlagsPICO accelerationFlags;
XrVector3f linearAcceleration;
XrVector3f angularAcceleration;
} XrBodyJointAccelerationPICO;
typedef XrFlags64 XrSpaceAccelerationFlagsPICO;
// Flag bits for XrSpaceAccelerationFlagsPICO
static const XrSpaceAccelerationFlagsPICO XR_SPACE_ACCELERATION_LINEAR_VALID_BIT_PICO = 0x00000001;
static const XrSpaceAccelerationFlagsPICO XR_SPACE_ACCELERATION_ANGULAR_VALID_BIT_PICO = 0x00000002;
12.2.9. New Enum Constants
-
XR_PICO_BODY_TRACKING2_EXTENSION_NAME
-
XR_PICO_body_tracking2_SPEC_VERSION
-
Extending XrStructureType:
-
XR_TYPE_BODY_BONE_LENGTH_PICO
-
XR_TYPE_BODY_JOINT_ACCELERATIONS_PICO
-
XR_TYPE_BODY_JOINT_VELOCITIES_PICO
-
XR_TYPE_BODY_TRACKING_POSTURE_FLAGS_DATA_PICO
-
XR_TYPE_BODY_TRACKING_STATE_PICO
-
12.3. XR_PICO_composition_layer_fisheye
- Name String
-
XR_PICO_composition_layer_fisheye
- Extension Type
-
Instance extension
- Registered Extension Number
-
10004
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Xiaosong Wang, Bytedance
Overview
This extension allows an application to use the fisheye overlay layer to render fisheye video or other content. It adds an additional layer type where the XR runtime must map an fisheye coded image stemming from a swapchain onto the inside of a sphere.
New Structures
The XrCompositionLayerFisheyePICO structure is defined as:
// Provided by XR_PICO_composition_layer_fisheye
typedef struct XrCompositionLayerFisheyePICO {
XrStructureType type;
void* next;
XrCompositionLayerFlags layerFlags;
XrSpace space;
XrEyeVisibility eyeVisibility;
XrSwapchainSubImage subImage;
XrPosef pose;
float radius;
XrVector2f scale;
XrVector2f bias;
} XrCompositionLayerFisheyePICO;
Version History
-
Revision 1, 2024-09-24 (Xiaosong Wang)
-
Initial extension description
-
12.4. XR_PICO_expand_device
- Name String
-
XR_PICO_expand_device
- Extension Type
-
Instance extension
- Registered Extension Number
-
10009
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Johnson Zhang, Bytedance
Overview
This extension enables the application to use the motor vibration function of the extended device set, obtain battery information, and set/get the custom data protocol data defined by the developer.
Applications should also enable the XR_PICO_motion_tracking
extension to be able to define multiple thresholds.
The unique id used to retrieve the data for the expand device.
// Provided by XR_PICO_expand_device
XR_DEFINE_ATOM(XrExpandDeviceIdPICO)
12.4.1. Enumerate Expand Device
The XrExpandDeviceConnectionStatePICO describes that expand device connection state.
// Provided by XR_PICO_expand_device
typedef enum XrExpandDeviceConnectionStatePICO {
XR_EXPAND_DEVICE_CONNECTION_STATE_DISCONNECTED_PICO = 0,
XR_EXPAND_DEVICE_CONNECTION_STATE_CONNECTED_PICO = 1,
XR_EXPAND_DEVICE_CONNECTION_STATE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrExpandDeviceConnectionStatePICO;
The XrEventDataExpandDeviceConnectionStateChangedPICO structure is defined as:
// Provided by XR_PICO_expand_device
typedef struct XrEventDataExpandDeviceConnectionStateChangedPICO {
XrStructureType type;
void* next;
XrExpandDeviceIdPICO deviceId;
XrExpandDeviceConnectionStatePICO connectionState;
} XrEventDataExpandDeviceConnectionStateChangedPICO;
The xrEnumerateExpandDevicePICO function is defined as:
// Provided by XR_PICO_expand_device
XrResult xrEnumerateExpandDevicePICO(
XrSession session,
uint32_t deviceCapacityInput,
uint32_t* deviceCountOutput,
XrExpandDeviceIdPICO* devices);
12.4.2. Expand device battery state
The XrExpandDeviceChargingStatePICO describes the charging state of the expand device.
// Provided by XR_PICO_expand_device
typedef enum XrExpandDeviceChargingStatePICO {
XR_EXPAND_DEVICE_CHARGING_STATE_UNCHARGED_PICO = 0,
XR_EXPAND_DEVICE_CHARGING_STATE_TRICKLE_CHARGING_PICO = 1,
XR_EXPAND_DEVICE_CHARGING_STATE_CHARGING_PICO = 2,
XR_EXPAND_DEVICE_CHARGING_STATE_CHARGE_COMPLETED_PICO = 3,
XR_EXPAND_DEVICE_CHARGING_STATE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrExpandDeviceChargingStatePICO;
The XrExpandDeviceBatteryStatePICO structure is defined as:
// Provided by XR_PICO_expand_device
typedef struct XrExpandDeviceBatteryStatePICO {
XrStructureType type;
void* next;
float batteryLevel;
XrExpandDeviceChargingStatePICO chargingState;
} XrExpandDeviceBatteryStatePICO;
The xrGetExpandDeviceBatteryStatePICO function is defined as:
// Provided by XR_PICO_expand_device
XrResult xrGetExpandDeviceBatteryStatePICO(
XrSession session,
XrExpandDeviceIdPICO expandDevice,
XrExpandDeviceBatteryStatePICO* batteryState);
Applications can use this function get the battery state of expand device.
The XrEventDataExpandDeviceBatteryStateChangedPICO structure is defined as:
// Provided by XR_PICO_expand_device
typedef struct XrEventDataExpandDeviceBatteryStateChangedPICO {
XrStructureType type;
void* next;
XrExpandDeviceIdPICO deviceId;
XrExpandDeviceBatteryStatePICO batteryState;
} XrEventDataExpandDeviceBatteryStateChangedPICO;
12.4.3. Expand device custom data
The XrExpandDeviceCustomDataStatePICO describes whether custom data needs to be obtained.
typedef enum XrExpandDeviceCustomDataStatePICO {
XR_EXPAND_DEVICE_CUSTOM_DATA_STATE_EMPTY_PICO = 0,
XR_EXPAND_DEVICE_CUSTOM_DATA_STATE_READY_PICO = 1,
XR_EXPAND_DEVICE_CUSTOM_DATA_STATE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrExpandDeviceCustomDataStatePICO;
The xrSetExpandDeviceCustomDataCapabilityPICO function is defined as:
// Provided by XR_PICO_expand_device
XrResult xrSetExpandDeviceCustomDataCapabilityPICO(
XrSession session,
XrBool32 enable);
The XrEventDataExpandDeviceCustomDataStateChangedPICO structure is defined as:
// Provided by XR_PICO_expand_device
typedef struct XrEventDataExpandDeviceCustomDataStateChangedPICO {
XrStructureType type;
void* next;
XrExpandDeviceCustomDataStatePICO dataState;
} XrEventDataExpandDeviceCustomDataStateChangedPICO;
Applications can known whether need obtain the custom data by xrGetExpandDeviceCustomDataPICO when receive the event XrEventDataExpandDeviceCustomDataStateChangedPICO.
The XrExpandDeviceCustomDataPICO structure is defined as:
// Provided by XR_PICO_expand_device
typedef struct XrExpandDeviceCustomDataPICO {
XrStructureType type;
void* next;
XrExpandDeviceIdPICO deviceId;
uint8_t data[XR_MAX_EXPAND_DEVICE_CUSTOM_DATA_SIZE_PICO];
} XrExpandDeviceCustomDataPICO;
The xrSetExpandDeviceCustomDataPICO function is defined as:
// Provided by XR_PICO_expand_device
XrResult xrSetExpandDeviceCustomDataPICO(
XrSession session,
uint32_t dataCount,
const XrExpandDeviceCustomDataPICO* customData);
Applications can use this function set custom data of expand device.
The xrGetExpandDeviceCustomDataPICO function is defined as:
// Provided by XR_PICO_expand_device
XrResult xrGetExpandDeviceCustomDataPICO(
XrSession session,
uint32_t customDataCapacityInput,
uint32_t* customDataCountOutput,
XrExpandDeviceCustomDataPICO* customDatas);
Applications can use this function get custom data of expand device.
12.4.4. Expand device vibrate
The XrExpandDeviceMotorVibratePICO structure is described as follows:
// Provided by XR_PICO_expand_device
typedef struct XrExpandDeviceMotorVibratePICO {
XrStructureType type;
void* next;
XrDuration duration;
uint32_t frequency;
float amplitude;
} XrExpandDeviceMotorVibratePICO;
The XrExpandDeviceMotorVibratePICO structure describes the param to set expand device motor vibrate.
The xrSetExpandDeviceMotorVibratePICO function is defined as:
// Provided by XR_PICO_expand_device
XrResult xrSetExpandDeviceMotorVibratePICO(
XrSession session,
XrExpandDeviceIdPICO expandDevice,
XrExpandDeviceMotorVibratePICO* vibrate);
12.4.9. New Enum Constants
-
XR_MAX_EXPAND_DEVICE_CUSTOM_DATA_SIZE_PICO
-
XR_PICO_EXPAND_DEVICE_EXTENSION_NAME
-
XR_PICO_expand_device_SPEC_VERSION
-
Extending XrResult:
-
XR_ERROR_EXPAND_TRACKER_ID_INVALID_PICO
-
-
Extending XrStructureType:
-
XR_TYPE_EVENT_DATA_EXPAND_DEVICE_BATTERY_STATE_CHANGED_PICO
-
XR_TYPE_EVENT_DATA_EXPAND_DEVICE_CONNECTION_STATE_CHANGED_PICO
-
XR_TYPE_EVENT_DATA_EXPAND_DEVICE_CUSTOM_DATA_STATE_CHANGED_PICO
-
XR_TYPE_EXPAND_DEVICE_BATTERY_STATE_PICO
-
XR_TYPE_EXPAND_DEVICE_CUSTOM_DATA_PICO
-
XR_TYPE_EXPAND_DEVICE_MOTOR_VIBRATE_PICO
-
Version History
-
Revision 1, 2024-10-28 (Johnson Zhang)
-
Initial extension description
-
12.5. XR_PICO_external_camera
- Name String
-
XR_PICO_external_camera
- Extension Type
-
Instance extension
- Registered Extension Number
-
10001
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Shuai Liu, Bytedance
12.5.1. Overview
MRC Extension. This extension allows app to get the external camera’s pose and parameters.
12.5.2. Getting Camera Information
The xrGetExternalCameraInfoPICO function is defined as:
// Provided by XR_PICO_external_camera
XrResult xrGetExternalCameraInfoPICO(
XrSession session,
XrExternalCameraParameterPICO* info);
Applications can use this function to get camera info.
The XrExternalCameraParameterPICO structure is defined as:
// Provided by XR_PICO_external_camera
typedef struct XrExternalCameraParameterPICO {
XrStructureType type;
void* next;
int32_t width;
int32_t height;
float fov;
} XrExternalCameraParameterPICO;
An XrExternalCameraParameterPICO structure is used get camera info to xrGetExternalCameraInfoPICO.
New Structures
The XrEventDataMrcStatusChangedPICO structure is defined as:
// Provided by XR_PICO_external_camera
typedef struct XrEventDataMrcStatusChangedPICO {
XrStructureType type;
void* next;
int32_t mrcStatus;
} XrEventDataMrcStatusChangedPICO;
Receiving the XrEventDataMrcStatusChangedPICO event structure
indicates that the MRC status has changed, the event is mainly triggered by
the MRC state change on the mobile phone.
Application should remove the MRC layer if the mrcStatus
is 0, and
should create the MRC layer if the mrcStatus
is 1.
The MRC layer must be created with
XR_COMPOSITION_LAYER_MRC_COMPOSITION_BIT_PICO
set.
The XrMrcSpaceCreateInfoPICO structure is defined as:
// Provided by XR_PICO_external_camera
typedef struct XrMrcSpaceCreateInfoPICO {
XrStructureType type;
const void* next;
} XrMrcSpaceCreateInfoPICO;
When the application wants to locate the camera pose through xrLocateSpace, application should first create a referenceSpace, and must provide the XrMrcSpaceCreateInfoPICO in the next chain of XrReferenceSpaceCreateInfo. The runtime must locate the camera’s pose if the XrSpace is created providing XrMrcSpaceCreateInfoPICO.
New Functions
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_EVENT_DATA_MRC_STATUS_CHANGED_PICO
-
XR_TYPE_MRC_SPACE_CREATE_INFO_PICO
-
XR_TYPE_EXTERNAL_CAMERA_PARAMETER_PICO
XrCompositionLayerFlags enumeration is extended with:
-
XR_COMPOSITION_LAYER_MRC_COMPOSITION_BIT_PICO
Sample code
/*****************************************/
/* GetExternalCamera Information */
/*****************************************/
XrInstance instance; // previously initialized
XrSession session; // previously initialized
PFN_xrGetExternalCameraInfoPICO xrGetExternalCameraInfoPICO;
CHK_XR(xrGetInstanceProcAddr(instance, "xrGetExternalCameraInfoPICO",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrGetExternalCameraInfoPICO)));
XrExternalCameraParameterPICO xrExternalCameraInfoPico{XR_TYPE_EXTERNAL_CAMERA_PARAMETER_PICO};
CHK_XR(xrGetExternalCameraInfoPICO(session, &xrExternalCameraInfoPico));
/*********************************************/
/* Create Mrc Reference Space and Locate */
/*********************************************/
XrSpace mrcSpace; // previously initialized
XrMrcSpaceCreateInfoPICO mrcSpaceCreateInfoBd{XR_TYPE_MRC_SPACE_CREATE_INFO_PICO, nullptr};
XrReferenceSpaceCreateInfo createInfo {XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
createInfo.next = &mrcSpaceCreateInfoBd;
createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
createInfo.poseInReferenceSpace = {{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f}};
CHK_XR(xrCreateReferenceSpace(session, &createInfo, &mrcSpace));
//locate space every frame.
XrSpace locateSpace{XR_NULL_HANDLE};
XrTime time; // previously initialized
XrSpaceLocation hmdLocation{XR_TYPE_SPACE_LOCATION};
CHK_XR(xrLocateSpace(mrcSpace, locateSpace, time, &hmdLocation));
Version History
-
Revision 1, 2024-08-05 (Shuai Liu)
-
Initial extension description
-
12.6. XR_PICO_eye_tracker
- Name String
-
XR_PICO_eye_tracker
- Extension Type
-
Instance extension
- Registered Extension Number
-
10007
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Shuai Liu, Bytedance
12.6.1. Overview
This extension mainly supplies the ability to get some detailed eye tracking information. This extension does not supply any data related to eye gaze information, if applications want to get gaze information, applications should use the [XR_EXT_eye_gaze_interaction] extension.
12.6.2. Create eye tracker
The XrEyeTrackerPICO handle represents the resources for an eye tracker.
// Provided by XR_PICO_eye_tracker
XR_DEFINE_HANDLE(XrEyeTrackerPICO)
When apps need to get more information about the eyes, the applications
should check if the device supports eye tracking capability.
App can do that by passing in an
XrSystemEyeGazeInteractionPropertiesEXT
structure in next chain
structure when calling xrGetSystemProperties to acquire information
about the connected eye tracker.
The runtime must populate the XrSystemEyeGazeInteractionPropertiesEXT
structure with the relevant information to the XrSystemProperties
returned by the xrGetSystemProperties call.
Only the supportsEyeGazeInteraction
is set to XR_TRUE
can the
tracker be successfully created.
The XrEyeTrackerCreateInfoPICO structure is defined as:
// Provided by XR_PICO_eye_tracker
typedef struct XrEyeTrackerCreateInfoPICO {
XrStructureType type;
const void* next;
} XrEyeTrackerCreateInfoPICO;
Applications can create eye tracker by calling xrCreateEyeTrackerPICO.
The xrCreateEyeTrackerPICO function is defined as:
// Provided by XR_PICO_eye_tracker
XrResult xrCreateEyeTrackerPICO(
XrSession session,
const XrEyeTrackerCreateInfoPICO* createInfo,
XrEyeTrackerPICO* tracker);
The xrCreateEyeTrackerPICO function creates an eye tracker. All the following eye information must be acquired with the XrEyeTrackerPICO.
When application does not need eye tracker anymore, it should destroy the eye tracker by calling xrDestroyEyeTrackerPICO, in order to let the runtime release the resources.
The xrDestroyEyeTrackerPICO function is defined as:
// Provided by XR_PICO_eye_tracker
XrResult xrDestroyEyeTrackerPICO(
XrEyeTrackerPICO eyeTracker);
The xrDestroyEyeTrackerPICO function destroys an eye tracker.
12.6.3. Get eye detailed information
// Provided by XR_PICO_eye_tracker
typedef XrFlags64 XrEyeTrackerFlagsPICO;
// Flag bits for XrEyeTrackerFlagsPICO
static const XrEyeTrackerFlagsPICO XR_EYE_TRACKER_LEFT_BIT_PICO = 0x00000001;
static const XrEyeTrackerFlagsPICO XR_EYE_TRACKER_RIGHT_BIT_PICO = 0x00000002;
// Provided by XR_PICO_eye_tracker
typedef XrFlags64 XrEyeTrackerTrackingStateFlagsPICO;
// Flag bits for XrEyeTrackerTrackingStateFlagsPICO
static const XrEyeTrackerTrackingStateFlagsPICO XR_EYE_TRACKER_TRACKING_STATE_LEFT_EYE_BIT_PICO = 0x00000001;
static const XrEyeTrackerTrackingStateFlagsPICO XR_EYE_TRACKER_TRACKING_STATE_RIGHT_EYE_BIT_PICO = 0x00000002;
The XrEyeDataPICO structure is defined as:
// Provided by XR_PICO_eye_tracker
typedef struct XrEyeDataPICO {
XrStructureType type;
void* next;
float openness;
float pupilDilation;
XrVector2f middleCanthusUv;
} XrEyeDataPICO;
The XrEyeDataPICO structure is used to get one of the eyes data from the eye tracker by calling xrGetEyeDataPICO.
The XrEyeTrackerDataInfoPICO structure is defined as:
// Provided by XR_PICO_eye_tracker
typedef struct XrEyeTrackerDataInfoPICO {
XrStructureType type;
const void* next;
XrEyeTrackerFlagsPICO eyeTrackingFlags;
} XrEyeTrackerDataInfoPICO;
The XrEyeTrackerDataPICO structure is defined as:
// Provided by XR_PICO_eye_tracker
typedef struct XrEyeTrackerDataPICO {
XrStructureType type;
void* next;
XrEyeTrackerTrackingStateFlagsPICO trackingState;
XrEyeDataPICO leftEyeData;
XrEyeDataPICO rightEyeData;
} XrEyeTrackerDataPICO;
An XrEyeTrackerDataPICO structure is used get eye information from the eye tracker by calling xrGetEyeDataPICO.
The application can get the eye detailed information by calling xrGetEyeDataPICO.
The xrGetEyeDataPICO function is defined as:
// Provided by XR_PICO_eye_tracker
XrResult xrGetEyeDataPICO(
XrEyeTrackerPICO tracker,
const XrEyeTrackerDataInfoPICO* info,
XrEyeTrackerDataPICO* eyeTrackerData);
The xrGetEyeDataPICO function gets the eye detailed information.
Applications can get specific eye data by setting the
XrEyeTrackerFlagBitsPICO in info
.
The runtime must return only the data that the application want to get.
There are three kinds of eye data that an application can get:
-
Eye openness data
-
the data of eye openness is a float number, the value is between 0 and 1. If the eye is fully open, the value is 1.0. If the eye is closed, the value is 0.0.
-
-
Pupil diameter data
-
the data of pupil diameter is a float number, the value indicates the pupil diameter in millimeters.
-
-
Middle canthus data
-
the data of middle canthus is an XrVector2f structure. The value indicates the middle canthus position in the eye tracker camera. The data are the UV values under normalized coordinates, these values only can be used for verifying whether the positions are consistent.
-
Runtime must set the XrEyeTrackerTrackingStateFlagBitsPICO in
eyeTrackerData
if the specific data is reliable.
12.6.8. New Enum Constants
-
XR_PICO_EYE_TRACKER_EXTENSION_NAME
-
XR_PICO_eye_tracker_SPEC_VERSION
-
Extending XrObjectType:
-
XR_OBJECT_TYPE_EYE_TRACKER_PICO
-
-
Extending XrStructureType:
-
XR_TYPE_EYE_DATA_PICO
-
XR_TYPE_EYE_TRACKER_CREATE_INFO_PICO
-
XR_TYPE_EYE_TRACKER_DATA_INFO_PICO
-
XR_TYPE_EYE_TRACKER_DATA_PICO
-
Version History
-
Revision 1, 2024-11-30 (Shuai Liu)
-
Initial extension description
-
12.7. XR_PICO_layer_color_matrix
- Name String
-
XR_PICO_layer_color_matrix
- Extension Type
-
Instance extension
- Registered Extension Number
-
10027
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Tom Zhai, Bytedance
12.7.1. Overview
The XrLayerColorMatrixPICO extension is designed to support changes in saturation in addition to setting brightness and contrast. Before applying CCM matrix, the compositor applies ColorScaleBias and then applies ColorMatrix.
New Structures
The XrColorMatrix3x3fPICO structure is defined as:
// Provided by XR_PICO_layer_color_matrix
typedef struct XrColorMatrix3x3fPICO {
float m[9];
} XrColorMatrix3x3fPICO;
The XrLayerColorMatrixPICO structure is defined as:
// Provided by XR_PICO_layer_color_matrix
typedef struct XrLayerColorMatrixPICO {
XrStructureType type;
const void* next;
XrColorMatrix3x3fPICO matrix;
} XrLayerColorMatrixPICO;
When the application wants to change a layer’s color, application must provide the XrLayerColorMatrixPICO in the next chain of XrCompositionLayerBaseHeader.
New Functions
New Enum Constants
XrStructureType enumeration is extended with:
-
XR_TYPE_LAYER_COLOR_MATRIX_PICO
Sample code
XrSession session; // previously initialized
XrLayerColorMatrixPICO colorMatrix{XR_TYPE_LAYER_COLOR_MATRIX_PICO};
colorMatrix.matrix.m[0] = 0.5f;
colorMatrix.matrix.m[1] = 0.0f;
colorMatrix.matrix.m[2] = 0.0f;
colorMatrix.matrix.m[3] = 0.0f;
colorMatrix.matrix.m[4] = 0.5f;
colorMatrix.matrix.m[5] = 0.0f;
colorMatrix.matrix.m[6] = 0.0f;
colorMatrix.matrix.m[7] = 0.0f;
colorMatrix.matrix.m[8] = 0.5f;
colorMatrix.next = NULL;
XrFrameWaitInfo frameWaitInfo{XR_TYPE_FRAME_WAIT_INFO};
XrFrameBeginInfo frameBeginInfo{XR_TYPE_FRAME_BEGIN_INFO};
XrFrameState frameState{XR_TYPE_FRAME_STATE};
CHK_XR(xrWaitFrame(session, &frameWaitInfo, &frameState));
CHK_XR(xrBeginFrame(session, &frameBeginInfo));
XrCompositionLayerQuad quadLayer {XR_TYPE_COMPOSITION_LAYER_QUAD};
std::vector<XrCompositionLayerBaseHeader*> layers;
layers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader*>(&quadLayer));
XrFrameEndInfo frameEndInfo{XR_TYPE_FRAME_END_INFO};
frameEndInfo.displayTime = frameState.predictedDisplayTime;
frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND;
frameEndInfo.layerCount = (uint32_t)layers.size();;
frameEndInfo.layers = layers.data();
CHK_XR(xrEndFrame(session, &frameEndInfo));
In the above example, we added the colorMatrix structure to the next pointer of quadLayer. This will make the color matrix effective. In this example, the color scaling factor is (0.5, 0.5, 0.5), which means reducing the brightness of the red, green, and blue channels in the layer by 50%. The color deviation remains at the default value (0,0,0,0). SBC2ColorMatrix is an example of applying saturation brightness and combined contrast simultaneously to colorscale bias and colormatrix.
Version History
-
Revision 1, 2024-12-28 (Tom Zhai)
-
Initial extension description
-
12.8. XR_PICO_layer_settings
- Name String
-
XR_PICO_layer_settings
- Extension Type
-
Instance extension
- Registered Extension Number
-
10005
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Xiaosong Wang, Bytedance
Jiuchang Guan, Bytedance
Overview
This extension allows applications to request the use of processing options such as various sharpening or super-sampling or super resolution on a composition layer. In order to enable the functionality of this extension, you must pass the name of the extension into xrCreateInstance via the XrInstanceCreateInfo::enabledExtensionNames parameter as indicated in the Extensions section.
New Object Types
New Flag Types
New Enum Constants
New Enums
The XrLayerSettingsFlagBitsPICO describes which mode of layer setting.
// Flag bits for XrLayerSettingsFlagsPICO
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_FIXED_FOVEATED_NORMAL_SUPER_SAMPLING_BIT_PICO = 0x00000001;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_FIXED_FOVEATED_QUALITY_SUPER_SAMPLING_BIT_PICO = 0x00000002;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_FIXED_FOVEATED_NORMAL_SHARPENING_BIT_PICO = 0x00000004;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_FIXED_FOVEATED_QUALITY_SHARPENING_BIT_PICO = 0x00000008;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_SELF_ADAPTIVE_NORMAL_SHARPENING_BIT_PICO = 0x00000010;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_SELF_ADAPTIVE_QUALITY_SHARPENING_BIT_PICO = 0x00000020;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_SUPER_RESOLUTION_BIT_PICO = 0x00000040;
static const XrLayerSettingsFlagsPICO XR_LAYER_SETTINGS_NEUR_SUPER_RESOLUTION_BIT_PICO = 0x00000080;
New Structures
The XrLayerSettingsPICO structure is described as follows:
// Provided by XR_PICO_layer_settings
typedef struct XrLayerSettingsPICO {
XrStructureType type;
const void* next;
XrLayerSettingsFlagsPICO layerFlags;
} XrLayerSettingsPICO;
The XrLayerSettingsPICO structure contains pico additional flags to indicate which processing steps to perform on a composition layer..
Version History
-
Revision 1, 2024-09-4 (Xiaosong Wang)
-
Initial extension description
-
12.9. XR_PICO_motion_tracking
- Name String
-
XR_PICO_motion_tracking
- Extension Type
-
Instance extension
- Registered Extension Number
-
10003
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Johnson Zhang, Bytedance
Overview
// Provided by XR_PICO_motion_tracking
XR_DEFINE_ATOM(XrMotionTrackerIdPICO)
The unique motion tracker key used to retrieve the data about motion tracker.
12.9.1. request motion tracker
The xrRequestMotionTrackerDevicePICO function is defined as:
// Provided by XR_PICO_motion_tracking
XrResult xrRequestMotionTrackerDevicePICO(
XrSession session,
uint32_t deviceCount);
Applications must request how many trackers they want to use before using the trackers, if the count of connected trackers equals to the request count, application will receive an XrEventDataRequestMotionTrackerCompletePICO, otherwise, the runtime will launch the calibration app to let the users to connect the same count of trackers as requested. when the users finished connecting trackers, and exit the calibartion app, the application will receive the XrEventDataRequestMotionTrackerCompletePICO.
The XrEventDataRequestMotionTrackerCompletePICO structure is defined as:
// Provided by XR_PICO_motion_tracking
typedef struct XrEventDataRequestMotionTrackerCompletePICO {
XrStructureType type;
const void* next;
uint32_t trackerCount;
XrMotionTrackerIdPICO trackerIds[XR_MOTION_TRACKER_MAX_SIZE_PICO];
XrResult result;
} XrEventDataRequestMotionTrackerCompletePICO;
Once the application received the XrEventDataRequestMotionTrackerCompletePICO, the application should check if the count of the connected trackers is fit for the requirement, if the count of the connected trackrs is still insufficient or excessive, the application must call the xrRequestMotionTrackerDevicePICO again, until the count of the connected trackers just meets the demand.
12.9.2. motion tracker connection state
The XrMotionTrackerConnectionStatePICO the connection state of motion tracker when call xrPollEvent.
// Provided by XR_PICO_motion_tracking
typedef enum XrMotionTrackerConnectionStatePICO {
XR_MOTION_TRACKER_CONNECTION_STATE_DISCONNECTED_PICO = 0,
XR_MOTION_TRACKER_CONNECTION_STATE_CONNECTED_PICO = 1,
XR_MOTION_TRACKER_CONNECTION_STATE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrMotionTrackerConnectionStatePICO;
The XrEventDataMotionTrackerConnectionStateChangedPICO structure is defined as:
// Provided by XR_PICO_motion_tracking
typedef struct XrEventDataMotionTrackerConnectionStateChangedPICO {
XrStructureType type;
const void* next;
XrMotionTrackerIdPICO trackerId;
XrMotionTrackerConnectionStatePICO state;
} XrEventDataMotionTrackerConnectionStateChangedPICO;
The XrEventDataMotionTrackerConnectionStateChangedPICO structure is used by an application to instruct the power key event changed.
12.9.3. motion tracker battery state
The XrMotionTrackerChargingStatePICO the charging state of motion tracker when call xrPollEvent.
// Provided by XR_PICO_motion_tracking
typedef enum XrMotionTrackerChargingStatePICO {
XR_MOTION_TRACKER_CHARGING_STATE_UNCHARGED_PICO = 0,
XR_MOTION_TRACKER_CHARGING_STATE_TRICKLE_CHARGING_PICO = 1,
XR_MOTION_TRACKER_CHARGING_STATE_CHARGING_PICO = 2,
XR_MOTION_TRACKER_CHARGING_STATE_CHARGE_COMPLETED_PICO = 3,
XR_MOTION_TRACKER_CHARGING_STATE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrMotionTrackerChargingStatePICO;
The XrMotionTrackerBatteryStatePICO structure describes the information to get motion tracker.
typedef struct XrMotionTrackerBatteryStatePICO {
XrStructureType type;
void* next;
float batteryLevel;
XrMotionTrackerChargingStatePICO chargingState;
} XrMotionTrackerBatteryStatePICO;
The xrGetMotionTrackerBatteryStatePICO function is defined as:
// Provided by XR_PICO_motion_tracking
XrResult xrGetMotionTrackerBatteryStatePICO(
XrSession session,
XrMotionTrackerIdPICO trackerId,
XrMotionTrackerBatteryStatePICO* batteryState);
12.9.4. motion tracker key event
The XrEventDataMotionTrackerPowerKeyEventPICO structure is defined as:
// Provided by XR_PICO_motion_tracking
typedef struct XrEventDataMotionTrackerPowerKeyEventPICO {
XrStructureType type;
const void* next;
XrMotionTrackerIdPICO trackerId;
XrBool32 isLongClick;
} XrEventDataMotionTrackerPowerKeyEventPICO;
The XrEventDataMotionTrackerPowerKeyEventPICO structure is used by an application to instruct the power key event changed.
12.9.5. locate motion tracker
The XrMotionTrackerLocationInfoPICO structure describes the information to get motion tracker.
typedef struct XrMotionTrackerLocationInfoPICO {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrTime time;
} XrMotionTrackerLocationInfoPICO;
The application should request a time equal to the predicted display time for the rendered frame. The system will employ appropriate modeling to provide motion tracker at this time.
The XrMotionTrackerSpaceVelocityPICO structure is described as follows:
// Provided by XR_PICO_motion_tracking
typedef struct XrMotionTrackerSpaceVelocityPICO {
XrStructureType type;
void* next;
XrSpaceVelocityFlags velocityFlags;
XrVector3f linearVelocity;
XrVector3f angularVelocity;
XrVector3f linearAcceleration;
XrVector3f angularAcceleration;
} XrMotionTrackerSpaceVelocityPICO;
The XrMotionTrackerSpaceLocationPICO structure is described as follows:
// Provided by XR_PICO_motion_tracking
typedef struct XrMotionTrackerSpaceLocationPICO {
XrStructureType type;
void* next;
XrSpaceLocationFlags locationFlags;
XrPosef pose;
} XrMotionTrackerSpaceLocationPICO;
The xrLocateMotionTrackerPICO function is defined as:
// Provided by XR_PICO_motion_tracking
XrResult xrLocateMotionTrackerPICO(
XrSession session,
XrMotionTrackerIdPICO trackerId,
const XrMotionTrackerLocationInfoPICO* locationInfo,
XrMotionTrackerSpaceLocationPICO* location);
The xrLocateMotionTrackerPICO function obtains pose for a motion tracker at a specific time and within a specific coordinate system.
If an XrMotionTrackerSpaceVelocityPICO structure is chained to the
XrMotionTrackerSpaceLocationPICO::next
pointer, and the velocity
is observed or can be calculated by the runtime, the runtime must fill in
the linear velocity of the origin of space within the reference frame of
XrMotionTrackerLocationInfoPICO::baseSpace
and set the
XR_SPACE_VELOCITY_LINEAR_VALID_BIT
.
Similarly, if an XrMotionTrackerSpaceVelocityPICO structure is chained
to the XrMotionTrackerSpaceLocationPICO::next
pointer, and the
angular velocity is observed or can be calculated by the runtime, the
runtime must fill in the angular velocity of the origin of space within the
reference frame of XrMotionTrackerLocationInfoPICO::baseSpace
and set the XR_SPACE_VELOCITY_ANGULAR_VALID_BIT
.
12.9.6. Example code
XrInstance instance; // previously initialized
XrSession session; // previously initialized
XrSpace baseSpace; // previously initialized
/*****************************************/
/* async request motion tracker device */
/*****************************************/
int32_t targetCount = 1;
PFN_xrRequestMotionTrackerDevicePICO xrRequestMotionTrackerDevicePICO;
CHK_XR(xrGetInstanceProcAddr(instance, "xrRequestMotionTrackerDevicePICO",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrRequestMotionTrackerDevicePICO)));
PFN_xrLocateMotionTrackerPICO xrLocateMotionTrackerPICO;
CHK_XR(xrGetInstanceProcAddr(instance, "xrLocateMotionTrackerPICO",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrLocateMotionTrackerPICO)));
CHK_XR(xrRequestMotionTrackerDevicePICO(session, targetCount));
std::vector<XrMotionTrackerIdPICO> trackerIds;
XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
XrResult result = xrPollEvent(instance, &event);
if (result == XR_SUCCESS) {
switch (event.type) {
case XR_TYPE_EVENT_DATA_REQUEST_MOTION_TRACKER_COMPLETE_PICO: {
auto motion_tracker_event = reinterpret_cast<XrEventDataRequestMotionTrackerCompletePICO*>(&event);
trackerIds.clear();
for(int i= 0;i<motion_tracker_event->trackerCount;i++){
trackerIds.push_back(motion_tracker_event->trackerIds[i]);
}
break;
}
case XR_TYPE_EVENT_DATA_MOTION_TRACKER_CONNECTION_STATE_CHANGED_PICO: {
auto connection_state_event = reinterpret_cast<XrEventDataMotionTrackerConnectionStateChangedPICO*>(&event);
if(connection_state_event->state == XR_MOTION_TRACKER_CONNECTION_STATE_DISCONNECTED_PICO){
// remove it from vector
}else if(connection_state_event->state == XR_MOTION_TRACKER_CONNECTION_STATE_CONNECTED_PICO){
trackerIds.push_back(connection_state_event->trackerId);
}
break;
}
}
}
/*****************************************/
/* locate motion tracker */
/*****************************************/
XrMotionTrackerLocationInfoPICO locationInfoPico {XR_TYPE_MOTION_TRACKER_LOCATION_INFO_PICO,NULL,baseSpace};
XrMotionTrackerSpaceVelocityPICO velocityPico {XR_TYPE_MOTION_TRACKER_SPACE_VELOCITY_PICO,NULL};
XrMotionTrackerSpaceLocationPICO locationPico {XR_TYPE_MOTION_TRACKER_SPACE_LOCATION_PICO, &velocityPico};
for (XrMotionTrackerIdPICO trackerId : trackerIds) {
XrResult ret = xrLocateMotionTrackerPICO(session,trackerId, &locationInfoPico, &locationPico);
if(ret == XR_ERROR_MOTION_TRACKING_MODE_MISMATCH_PICO){
xrRequestMotionTrackerDevicePICO(session,targetCount);
break;
}
constexpr XrSpaceLocationFlags LocatableFlags = XR_SPACE_LOCATION_ORIENTATION_VALID_BIT | XR_SPACE_LOCATION_POSITION_VALID_BIT;
const bool isLocatable = (locationPico.locationFlags & LocatableFlags) == LocatableFlags;
if(isLocatable){
//do something
}
}
12.9.11. New Enum Constants
-
XR_MOTION_TRACKER_MAX_SIZE_PICO
-
XR_PICO_MOTION_TRACKING_EXTENSION_NAME
-
XR_PICO_motion_tracking_SPEC_VERSION
-
Extending XrReferenceSpaceType:
-
XR_REFERENCE_SPACE_TYPE_ALGORITHM_GLOBAL_PICO
-
-
Extending XrResult:
-
XR_ERROR_MOTION_TRACKER_COUNT_EXCEEDED_PICO
-
XR_ERROR_MOTION_TRACKER_ID_INVALID_PICO
-
XR_ERROR_MOTION_TRACKER_TYPE_MISMATCH_PICO
-
XR_ERROR_MOTION_TRACKING_MODE_MISMATCH_PICO
-
-
Extending XrStructureType:
-
XR_TYPE_EVENT_DATA_MOTION_TRACKER_CONNECTION_STATE_CHANGED_PICO
-
XR_TYPE_EVENT_DATA_MOTION_TRACKER_POWER_KEY_EVENT_PICO
-
XR_TYPE_EVENT_DATA_REQUEST_MOTION_TRACKER_COMPLETE_PICO
-
XR_TYPE_MOTION_TRACKER_BATTERY_STATE_PICO
-
XR_TYPE_MOTION_TRACKER_LOCATION_INFO_PICO
-
XR_TYPE_MOTION_TRACKER_SPACE_LOCATION_PICO
-
XR_TYPE_MOTION_TRACKER_SPACE_VELOCITY_PICO
-
Version History
-
Revision 1, 2024-09-24 (Johnson Zhang)
-
Initial extension description
-
12.10. XR_PICO_secure_mixed_reality
- Name String
-
XR_PICO_secure_mixed_reality
- Extension Type
-
Instance extension
- Registered Extension Number
-
10008
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Shuai Liu, Bytedance
Jimmy Alamparambil, Bytedance
Yunhao Liu, Bytedance
12.10.1. Overview
Background
Currently, the latest XR devices equipped with stereo-view RGB camera, ToF depth sensor and video see-through (VST) functionalities offer mixed-reality (MR) capabilities at hardware level. However, developers may find it hard to develop customized MR applications right now, because the RGB cameras or depth data can not be easily accessed as on mobile phones due to privacy concerns. MR functionalities are limited to system-level MR features, such as static anchors or hand gesture recognition. In order to overcome this hinder, we hereby present the PICO Secure Mixed Reality extension (SecureMR), which securely protects users' privacy and yet unleashes the potential of AI-empowered mixed reality usage.
Architecture
The core of SecureMR is an isolated secure service, to which developers are allowed to deploy any MR algorithms that require RGB and depth data, and render 3D MR assets directly to the screen. The interfaces between the client apps and the SecureMR service always act unidirectionally: only for the app developers to send in data, 3D assets, algorithms and commands, but not allowing any data back to the app which might contain camera images or other sensitive data. The architecture is illustrated as follows, where applications can use the APIs in this extension to input data and commands to the secure service, the outputs of which will be directly presented as steroscopic views to users, and cannot be fed back to caller applications.
Under such architecture, the developers' app will still not obtain access to camera or sensor data, but the isolated SecureMR service acts as a delegate, executing the developers' algorithms and render commands on behalf of the developers' app and presenting the MR outcomes to the users.
Concepts
In order to ensure the unidirectional interactions between the runtime and applications, and enable applications to deploy arbitrary algorithms of various complexities, the following concepts are adopted within this extension.
- Tensor
-
SecureMR uses the term "tensor" to describe any chunk of data. This term is widely used in machine learning circles, but in this extension it has more restricitve definition. Because SecureMR is designed to be an isolated MR service to delegate applications' algorithms, the contents of a tensor will be stored only in the SecureMR service. Applications can maintain a handle as the reference to the tensor.
Applications can create and write data to them via the handles. Additionally, applications can use tensors in an algorithm delegated to SecureMR. But applications are restricted from retrieving tensor data using the tensor handles they created or wrote to.
Normally, a tensor is defined by the following four attributes:
-
Dimensions: an array of unsigned integers, defining the size of the tensor per dimension.
-
Channel: a single unsigned integer, defining the number of channels, consistent with the definition of channel in OpenCV.
Note that consistent with OpenCV convention, channel will not be a dimension in the tensor’s shape. For instance, a 1-channel tensor of shape(1024, 1024, 3)
is different from a 3-channel tensor of shape(1024, 1024)
, even though both have 1024x1024x3 elements in total.Figure 7. Tensors of the same total number of values, but different in the last dimensions and the channel, leading to different arrangement. -
Datatype: specifying the data type of each element in the tensor, such as
UINT8
,INT8
,INT32
,FLOAT32
,FLOAT64
, and etc., consistent with OpenCV’s datatypes. -
Usage: a flag to declare how a tensor’s content will be interpreted when digested in an algorithm. The usage flag shall be one of the following, each with different restrictions on its dimensions, channel or data type:
-
Matrix usage: the tensor will be treated as a collection of matrices; naturally, such a tensor must have at least 2 dimensions. This is the default usage.
-
Scalar usage: the tensor will be treated as a collection of single values; naturally, the channel must be 1.
-
Timestamp usage: the tensor will be used to store camera timestamp; the channel must be 4, the datatype must be INT32, and there must be 1 dimension only, along which the length must be 1.
-
Color usage: the tensor will be treated as a collection of RGB or RGBA colors; for RGB colors, the channel must be 3, whereas for RGBA colors, the channel must be 4; the data type must be integral.
-
Point usage: the tensor will be treated as a collection of 2D or 3D points; hence, its channel must be 2 or 3.
-
Slice usage: the tensor will be used to describe a python-style slice on other tensors; it is required the channel must be 2 or 3, and the data type must be integer. A 2-channel slice will be treated as
(START, END)
, whereas a 3-channel slice will be treated as(START, END, SKIP)
.
For example, a 2-channel slice tensor whose content is(0, -1)
is equivalent to such codes in python:arr[0:-1] # all values from the first to the last
A 3-channel slice tensor whose content is
(5, 10, 2)
is equivalent to this in python:arr[5:10:2] # values at index 5, 7, 9
-
Usage affects how the data in a tensor can be interpreted and involved in algorithms. For example, a 1-channel FLOAT32 tensor of shape
(10, 3, 4)
:-
If its usage is declared as MAT, it will be treated as 10 3x4 matrices in calculation.
-
If its usage is declared as SCALAR, it will be treated as 120 (=10x3x4) independent scalars, so it will not be applied to matrix operations but only elementwise computation.
-
- Operators
-
Operators are nodes to implement a developer-defined algorithm. They intake some tensors (called operands), perform operations, and output the results to some other tensors (called results). Thus, app developers can easily use operators and tensors to build an algorithm and hand it over to the SecureMR service for execution.
Similar to tensors, operators are constructed and executed on the SecureMR service; what the app developers can manipulate are handles to the operators.
Developers can write their algorithms, whether they are machine learning ones or not, in PyTorch, TensorFlow, or ONNX, convert them using our conversion tools into binary algorithm package, and load the package to the SecureMR operators. These operators will be executed on NPUs and accelerated.
For development simplicity, we also provide some predefined CPU operators, for preprocessing/postprocessing, such as matrix algebra, value assignment, sorting, and non maximum suppression (NMS), etc. Mixed-reality operators are also available to display algorithm outcomes on screen. These MR operators can be utilized to render glTF tensors, display text, track objects of interest, modify the materials or textures of glTFs, or even animate them.
- Pipelines
-
If operators are considered algorithm nodes, then tensors represent the edges between these nodes, facilitating data flow among them. From this perspective, operators and tensors form a computation graph. In SecureMR, we refer to such computation graphs as "pipelines."
Once a pipeline is created, developers can add operators and tensors within it. The pipeline is not executed until developers submit it. Each submission will schedule the SecureMR service to run the entire pipeline once and return a "run handle" as a reference to the scheduled execution.
When submitting a pipeline, developers can specify two scheduling hints: wait-for and condition.
-
Developers can use a previous run handle as the wait-for hint, to indicate to the SecureMR service that this execution shall be scheduled after the completion of the one referred to by the hint.
-
Developers can use a tensor handle as the condition hint, to indicate that this execution will be conducted on condition that the tensor is true (non-zero). Otherwise, the execution will be discarded.
- Pipeline local tensors v.s. global tensors across pipelines
-
A pipeline encapsulates tensors and operators as its local members, making it challenging to share data between pipelines. Global tensors provide a solution to this issue.
Typically, a tensor is defined within a pipeline for data flow between operators created in the same scope, namely a "local tensor." Conversely, a global tensor is defined independently of any pipeline, allowing its data to be shared across them.
All the previous discussions regarding data types, shapes, channels, usage flags, and their limitations apply equally to both local and global tensors. The only difference lies in their scope: local to a single pipeline, or shared among all pipelines.
- Placeholders for global-to-pipeline-local mapping
-
For thread safety, global tensors cannot be bound to operators directly. They have to go through a mechanism called placeholder mapping.
A placeholder is a dummy local tensor defined in the pipeline as if it were a local tensor. Hence, it can be bound to operators as operands or results. However, placeholders, as the name suggests, behave like "pointers," with no underlying content or data storage but holding a reference to some global tensor.
When a pipeline is submitted for execution, developers can map local placeholders to compatible global tensors. The mapping will only be valid for a single submission, allowing developers to reuse the same pipeline with different data inputs for different executions.
Figure 8. Illustration of data sharing between pipeline one and pipeline two using placeholder mapping. Placeholders i and ii in Pipeline One are mapped to global tensors (a) and (b), writing the pipeline’s outputs to them; while Pipeline Two has placeholders mapped to the same global tensors, reading the latest values. - Scheduling pipeline execution
-
Scheduling of pipeline execution follows these principles:
-
Multiple executions of the same pipeline will not happen concurrently.
-
If an execution involves reading from a global tensor, it will wait until there are no other executions writing to the same global tensor.
-
If an execution involves writing to a global tensor, it will wait until there are no other executions writing to or reading from the same global tensor.
-
An execution will always happen after the one specified by its wait-for hint is completed, if not null.
-
An execution will be discarded if the condition hint is not null and refers to an all-zero tensor.
-
-
12.10.2. Create a secure mixed reality framework
We need a top-level context handle to keep track of resources and algorithms deployed in SecureMR, including the memory and structures. We will implicitly create an inference engine, a renderer, and a camera provider for each client process that has created the framework handle.
We will hang this off the XrSession.
// Provided by XR_PICO_secure_mixed_reality
XR_DEFINE_HANDLE(XrSecureMrFrameworkPICO)
The XrSecureMrFrameworkPICO represents the framework handle.
An application must create an XrSecureMrFrameworkPICO handle before calling other functions defined in this extension.
The xrCreateSecureMrFrameworkPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrCreateSecureMrFrameworkPICO(
XrSession session,
const XrSecureMrFrameworkCreateInfoPICO* createInfo,
XrSecureMrFrameworkPICO* framework);
An application must create an XrSecureMrFrameworkPICO handle using xrCreateSecureMrFrameworkPICO function.
An application cannot call xrCreateSecureMrFrameworkPICO function if there is another XrSecureMrFrameworkPICO handle in the same process not destroyed.
The function also opens the stereoview RGB camera to provide image access
within the lifecycle of XrSecureMrFrameworkPICO.
An application must declare the desired resolution of each camera image
when creating the XrSecureMrFrameworkPICO handle, via
createInfo
.
The XrSecureMrFrameworkCreateInfoPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrFrameworkCreateInfoPICO {
XrStructureType type;
const void* next;
int32_t width;
int32_t height;
} XrSecureMrFrameworkCreateInfoPICO;
The XrSecureMrFrameworkCreateInfoPICO structure describes the information to create an XrSecureMrFrameworkPICO handle.
The xrDestroySecureMrFrameworkPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrDestroySecureMrFrameworkPICO(
XrSecureMrFrameworkPICO framework);
An application can destroy an XrSecureMrFrameworkPICO handle using xrDestroySecureMrFrameworkPICO function.
An application should destroy the XrSecureMrFrameworkPICO if the application no longer needs it in order that the runtime releases resources, stops the renderer, shuts down the inference engine and closes the RGB camera.
It is advised that an applications destroys the XrSecureMrFrameworkPICO whenever the application is paused, as the running inference engine and the camera provider in backend may increase power consumption significantly, depending on the algorithm complexity deployed on them.
12.10.3. Create a secure mixed reality pipeline
As is aforementioned, pipelines are computation graphs composed by operators, and local tensors or placeholders which connect operators and transfer data in between. Pipelines are also the units for algorithm scheduling and executing, as pipelines can be scheduled individually to run in parallel, sequentially, or conditionally.
A pipeline can be submitted multiple times; each submission schedules the pipeline to be run once, and creates a run handle for execution order control. Scheduled pipeline runs can be conducted concurrently, if they are not from the same pipeline, and not competing for the same global tensors shared with other ongoing pipeline runs.
Developers can split algorithms into multiple cooperative pipelines if they would like to increase overall performance by parallelism.
The representation of a pipeline is defined as:
// Provided by XR_PICO_secure_mixed_reality
XR_DEFINE_HANDLE(XrSecureMrPipelinePICO)
An application must create an XrSecureMrPipelinePICO handle with an valid XrSecureMrFrameworkPICO, on which the lifecycle of the pipeline is dependent.
The xrCreateSecureMrPipelinePICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrCreateSecureMrPipelinePICO(
XrSecureMrFrameworkPICO framework,
const XrSecureMrPipelineCreateInfoPICO* createInfo,
XrSecureMrPipelinePICO* pipeline);
An application can create an XrSecureMrPipelinePICO handle using the xrCreateSecureMrPipelinePICO function.
The XrSecureMrPipelineCreateInfoPICO structure used to create a pipeline is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrPipelineCreateInfoPICO {
XrStructureType type;
const void* next;
} XrSecureMrPipelineCreateInfoPICO;
The xrDestroySecureMrPipelinePICO function to destroy an XrSecureMrPipelinePICO handle is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrDestroySecureMrPipelinePICO(
XrSecureMrPipelinePICO pipeline);
An application should destroy the XrSecureMrPipelinePICO if the application no longer needs it in order to let the runtime release resources.
12.10.4. Operators
When pipelines are viewed as executable computation graphs, operators are the nodes within. Operators define the most basic manipulations of data from their input tensors, namely the operands, and write outcomes to the result tensors. All the operand and result tensors of an operator must be created within the same pipeline as where the operator is created.
For the simplicity of control, operators will be executed in the same order as they are created in their pipeline.
Operators are customizable. You can write algorithms or train machine learning models in ONNX, PyTorch or TensorFlow, and convert them into binary algorithm packages. We can load these binary algorithm packages into operators, and they can be accelerated by nerual processing units (NPUs) if applicable. The customized operators expect operand and result tensor of either FLOAT32 or UINT8 type, up to the developers' choices.
We also provide a bunch of predefined CPU operators, for fundamental preprocessing/postprocessing needs, to simplify your development efforts, such as arithmetic computation, normalization, non-maximum suppression and so on. They are executed on CPU. The predefined operators each have different requirements on operand and result tensors' datatype, usage declaration and dimensions. Applications should ensure the operand and result tensors linked to these predefined operators match the requirements in the following sections.
Additionally, we provide mixed-reality operators, to render glTF objects, show texts, switch glTF textures, adjust glTF materials and control animations based on data from algorithms. Although data in tensors cannot be read by applications, using these MR operators, an application can present data-driven MR effects to users. The render results from these MR operators will be projected on a special layer between the see-through background layer and any of the app's layers.
Operators are all represented as XrSecureMrOperatorPICO
which is an
[XR_OPAQUE64].
// Provided by XR_PICO_secure_mixed_reality
XR_DEFINE_OPAQUE_64(XrSecureMrOperatorPICO)
The creation of operators
The xrCreateSecureMrOperatorPICO function creates operators, defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrCreateSecureMrOperatorPICO(
XrSecureMrPipelinePICO pipeline,
const XrSecureMrOperatorCreateInfoPICO* createInfo,
XrSecureMrOperatorPICO* secureMrOperator);
The XrSecureMrOperatorCreateInfoPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorCreateInfoPICO {
XrStructureType type;
const void* next;
XrSecureMrOperatorBaseHeaderPICO* operatorInfo;
XrSecureMrOperatorTypePICO operatorType;
} XrSecureMrOperatorCreateInfoPICO;
Enum XrSecureMrOperatorTypePICO is used to distinguish different types of operators to be created.
For the operator types listed below, extra configurations will needed for
creation, in which cases the application must pass in a pointer to an
corresponding structure listed below, casted to an
XrSecureMrOperatorBaseHeaderPICO pointer as operatorInfo
.
operatorType |
Required structure as operatorInfo |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For other cases, where no configuration is required, the application must
pass in a null pointer or a pointer to a
XrSecureMrOperatorBaseHeaderPICO as operatorInfo
.
The XrSecureMrOperatorBaseHeaderPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorBaseHeaderPICO {
XrStructureType type;
const void* next;
} XrSecureMrOperatorBaseHeaderPICO;
Structures to an operator of type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO
(referred to as
"an inference operator") is one type of customizable operator.
Developers can deploy pretrained machine learning models (or any
NPU-acceleratable algorithms) inside pipelines.
In order to do so, developers should convert the algorithm implementation to certain format supported in XrSecureMrModelTypePICO. At run-time, developers should read the context binary into application's memory, and use the structures listed below to construct the operator from the memory.
typedef enum XrSecureMrModelTypePICO {
XR_SECURE_MR_MODEL_TYPE_QNN_CONTEXT_BINARY_PICO = 1,
XR_SECURE_MR_MODEL_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrModelTypePICO;
XrSecureMrModelTypePICO represents the algorithm implementation formats.
Enum | Description |
---|---|
|
Developer-customized algorithm implemented as QNN context binary format, to be deploy as a customized operator of type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO |
XrSecureMrModelEncodingPICO represents the encoding type (data interpreted as floating-point values or unsigned integers) of a operand or result of an inference operator.
typedef enum XrSecureMrModelEncodingPICO {
XR_SECURE_MR_MODEL_ENCODING_FLOAT_32_PICO = 1,
XR_SECURE_MR_MODEL_ENCODING_UFIXED_POINT8_PICO = 2,
XR_SECURE_MR_MODEL_ENCODING_SFIXED_POINT8_PICO = 3,
XR_SECURE_MR_MODEL_ENCODING_UFIXED_POINT16_PICO = 4,
XR_SECURE_MR_MODEL_ENCODING_INT32_PICO = 5,
XR_SECURE_MR_MODEL_ENCODING_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrModelEncodingPICO;
Such a customizable inference operator expects its operand or result to be
of either XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
if the
corresponding encoding type is
XR_SECURE_MR_MODEL_ENCODING_FLOAT_32_PICO
, or
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
otherwise.
The encoding type must match the expected encoding type of corresponding input or output node in the algorithm implementation to be loaded.
Enum | Description |
---|---|
|
used to declare that the operand or result of a operator deploying developer-customized algorithm (operator type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO) is encoded as float32 |
|
used to declare that the operand or result of a operator deploying developer-customized algorithm (operator type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO) is encoded as unsigned 8-bit integer |
|
used to declare that the operand or result of a operator deploying developer-customized algorithm (operator type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO) is encoded as signed 8-bit integer |
|
used to declare that the operand or result of a operator deploying developer-customized algorithm (operator type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO) is encoded as unsigned 16-bit integer |
|
used to declare that the operand or result of a operator deploying developer-customized algorithm (operator type XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO) is encoded as signed 32-bit integer |
The XrSecureMrOperatorIOMapPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorIOMapPICO {
XrStructureType type;
const void* next;
XrSecureMrModelEncodingPICO encodingType;
char nodeName[XR_MAX_OPERATOR_NODE_NAME_PICO];
char operatorIOName[XR_MAX_OPERATOR_NODE_NAME_PICO];
} XrSecureMrOperatorIOMapPICO;
An XrSecureMrOperatorIOMapPICO structure corresponds to either an
operand or a result of an inference operator.
Note there are two names associated with each structure, nodeName
and
operatorIOName
.
The former refers to the name inside your algorithm implementation while the
latter is the name you give to the operator's operand or result.
Thereafter, you can link tensors to the operator's operands or results
using the names you set in operatorIOName
via
xrSetSecureMrOperatorOperandByNamePICO or
xrSetSecureMrOperatorResultByNamePICO.
The motivation of such design is based on the consideration that developers may want to use off-the-shelf algorithms, such as some available pretrained machine learning models. The input or output nodes for these algorithms may not come with comprehensible names. Hence, the structure provides a renaming of algorithms' internal input/output names to operators' operand/result names. Additionally, an algorithm may have multiple internal nodes accepting inputs or producing intermedia outcomes. You can also use XrSecureMrOperatorIOMapPICO structure to select those internal nodes as additional operands or shortcut results.
For example, an object classification algorithm may produce the category index as the final outcome node, where the score for each category is its preceding node. You may use XrSecureMrOperatorIOMapPICO to set the all-category scores from this internal nodes as a supplementary result.
The XrSecureMrOperatorModelPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorModelPICO {
XrStructureType type;
const void* next;
uint32_t modelInputCount;
XrSecureMrOperatorIOMapPICO* modelInputs;
uint32_t modelOutputCount;
XrSecureMrOperatorIOMapPICO* modelOutputs;
uint32_t bufferSize;
void* buffer;
XrSecureMrModelTypePICO modelType;
const char* modelName;
} XrSecureMrOperatorModelPICO;
The XrSecureMrOperatorUpdateGltfPICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO
.
Creating a customized inference operator is a time-consuming operation, so applications should not create the model operator in time sensitive thread.
Structures to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
An operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
can be
used to update different attributes of a glTF object for data-driven
animation, such as to translate or rotate the glTF object, drive skeleton
animations, alter material parameters, change textures dynamically, or
control animation replay.
The attributes to be updated are defined through
XrSecureMrGltfOperatorAttributePICO.
typedef enum XrSecureMrGltfOperatorAttributePICO {
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_TEXTURE_PICO = 1,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_ANIMATION_PICO = 2,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_WORLD_POSE_PICO = 3,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_LOCAL_TRANSFORM_PICO = 4,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_METALLIC_FACTOR_PICO = 5,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_ROUGHNESS_FACTOR_PICO = 6,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_OCCLUSION_MAP_TEXTURE_PICO = 7,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_BASE_COLOR_FACTOR_PICO = 8,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_FACTOR_PICO = 9,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_STRENGTH_PICO = 10,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_TEXTURE_PICO = 11,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_BASE_COLOR_TEXTURE_PICO = 12,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_NORMAL_MAP_TEXTURE_PICO = 13,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_METALLIC_ROUGHNESS_TEXTURE_PICO = 14,
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrGltfOperatorAttributePICO;
XrSecureMrGltfOperatorAttributePICO specifies which attribute of the glTF object the operator will be updating.
Enum | Description |
---|---|
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the content of a glTF’s texture |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to toggle and adjust the timer of a glTF’s pre-recorded animation |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the world pose of a glTF model, relative to OpenXR LOCAL or VIEW space, determined by the settings of Operator SWITCH_GLTF_RENDER_STATUS |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the local transform of glTF’s nodes |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the metallic factor of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the roughness factor of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to change the texture sampler index used as occlusion map of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the base color factor of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the emissive color factor of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the emissive strength factor of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the texture sampler index used as emissive color map of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the texture sampler index used as base color map of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the texture sampler index used as normal map of a glTF’s material |
|
Configure an operator of type XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO to update the texture sampler index used as metallic-roughness map of a glTF’s material |
The XrSecureMrOperatorUpdateGltfPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorUpdateGltfPICO {
XrStructureType type;
const void* next;
XrSecureMrGltfOperatorAttributePICO attribute;
} XrSecureMrOperatorUpdateGltfPICO;
The XrSecureMrOperatorUpdateGltfPICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
.
Structures to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_ARITHMETIC_COMPOSE_PICO
The XrSecureMrOperatorArithmeticComposePICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorArithmeticComposePICO {
XrStructureType type;
const void* next;
char configText[XR_MAX_ARITHMETIC_COMPOSE_OPERATOR_CONFIG_LENGTH_PICO];
} XrSecureMrOperatorArithmeticComposePICO;
Note that the operator conducts matrix multiplications and divisions, rather than elementwise operations.
The XrSecureMrOperatorArithmeticComposePICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_ARITHMETIC_COMPOSE_PICO
.
Structures to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO
XrSecureMrComparisonPICO provides the types of elementwise comparison
that we support in the predefined operator of type
XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO
.
typedef enum XrSecureMrComparisonPICO {
XR_SECURE_MR_COMPARISON_UNKNOWN_PICO = 0,
XR_SECURE_MR_COMPARISON_LARGER_THAN_PICO = 1,
XR_SECURE_MR_COMPARISON_SMALLER_THAN_PICO = 2,
XR_SECURE_MR_COMPARISON_SMALLER_OR_EQUAL_PICO = 3,
XR_SECURE_MR_COMPARISON_LARGER_OR_EQUAL_PICO = 4,
XR_SECURE_MR_COMPARISON_EQUAL_TO_PICO = 5,
XR_SECURE_MR_COMPARISON_NOT_EQUAL_PICO = 6,
XR_SECURE_MR_COMPARISON_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrComparisonPICO;
Enum | Description |
---|---|
|
An unknown type. |
|
Configure the pre-defined operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO, to perform larger-than comparison on input tensors |
|
Configure the pre-defined operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO, to perform smaller-than comparison on input tensors |
|
Configure the pre-defined operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO, to perform smaller-than-or-equal-to comparison on input tensors |
|
Configure the pre-defined operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO, to perform larger-than-or-equal-to comparison on input tensors |
|
Configure the pre-defined operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO, to perform equal-to comparison on input tensors |
|
Configure the pre-defined operator of type XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO, to perform not-equal-to comparison on input tensors |
The XrSecureMrOperatorComparisonPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorComparisonPICO {
XrStructureType type;
const void* next;
XrSecureMrComparisonPICO comparison;
} XrSecureMrOperatorComparisonPICO;
The XrSecureMrOperatorComparisonPICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO
.
Structure to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_NORMALIZE_PICO
typedef enum XrSecureMrNormalizeTypePICO {
XR_SECURE_MR_NORMALIZE_TYPE_L1_PICO = 1,
XR_SECURE_MR_NORMALIZE_TYPE_L2_PICO = 2,
XR_SECURE_MR_NORMALIZE_TYPE_INF_PICO = 3,
XR_SECURE_MR_NORMALIZE_TYPE_MINMAX_PICO = 4,
XR_SECURE_MR_NORMALIZE_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrNormalizeTypePICO;
Enum | Description |
---|---|
|
L1 normalization |
|
L2 normalization |
|
INF normalization |
|
MIN-MAX normalization |
The four types of normalization observes the same underlying mathematic
formulas as OpenCV NORM_L1
, NORM_L2
, NORM_INF
and NORM_MINMAX
respectively, and are defined as follows.
- L1 Normalization
- L2 Normalization
- INF Normalization
- MIN-MAX Normalization
The XrSecureMrOperatorNormalizePICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorNormalizePICO {
XrStructureType type;
const void* next;
XrSecureMrNormalizeTypePICO normalizeType;
} XrSecureMrOperatorNormalizePICO;
The XrSecureMrOperatorNormalizePICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_NORMALIZE_PICO
.
Structure to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_NMS_PICO
The XrSecureMrOperatorNonMaximumSuppressionPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorNonMaximumSuppressionPICO {
XrStructureType type;
const void* next;
float threshold;
} XrSecureMrOperatorNonMaximumSuppressionPICO;
The XrSecureMrOperatorNonMaximumSuppressionPICO structure describes
the information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_NMS_PICO
.
Structure to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_UV_TO_3D_IN_CAM_SPACE_PICO
The XrSecureMrOperatorUVTo3DPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorUVTo3DPICO {
XrStructureType type;
const void* next;
} XrSecureMrOperatorUVTo3DPICO;
The XrSecureMrOperatorUVTo3DPICO structure describes the information
to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_UV_TO_3D_IN_CAM_SPACE_PICO
.
Structure to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO
XrSecureMrMatrixSortTypePICO defines the option to sort a matrix using
the operator of XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO
:
typedef enum XrSecureMrMatrixSortTypePICO {
XR_SECURE_MR_MATRIX_SORT_TYPE_COLUMN_PICO = 1,
XR_SECURE_MR_MATRIX_SORT_TYPE_ROW_PICO = 2,
XR_SECURE_MR_MATRIX_SORT_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrMatrixSortTypePICO;
Enum | Description |
---|---|
|
used for configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO, to sort input matrix column-wisely |
|
used for configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO, to sort input matrix row-wisely |
The XrSecureMrOperatorSortMatrixPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorSortMatrixPICO {
XrStructureType type;
const void* next;
XrSecureMrMatrixSortTypePICO sortType;
} XrSecureMrOperatorSortMatrixPICO;
The XrSecureMrOperatorSortMatrixPICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO
.
Structures to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
typedef enum XrSecureMrFontTypefacePICO {
XR_SECURE_MR_FONT_TYPEFACE_DEFAULT_PICO = 1,
XR_SECURE_MR_FONT_TYPEFACE_SANS_SERIF_PICO = 2,
XR_SECURE_MR_FONT_TYPEFACE_SERIF_PICO = 3,
XR_SECURE_MR_FONT_TYPEFACE_MONOSPACE_PICO = 4,
XR_SECURE_MR_FONT_TYPEFACE_BOLD_PICO = 5,
XR_SECURE_MR_FONT_TYPEFACE_ITALIC_PICO = 6,
XR_SECURE_MR_FONT_TYPEFACE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrFontTypefacePICO;
Enum | Description |
---|---|
|
used in configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO, default typeface |
|
used in configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO, sans-serif typeface |
|
used in configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO, serif typeface |
|
used in configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO, monospace typeface |
|
used in configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO, bold typeface |
|
used in configuration of an operator of type XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO, italic typeface |
The XrSecureMrOperatorRenderTextPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorRenderTextPICO {
XrStructureType type;
const void* next;
XrSecureMrFontTypefacePICO typeface;
const char* languageAndLocale;
int32_t width;
int32_t height;
} XrSecureMrOperatorRenderTextPICO;
The XrSecureMrOperatorRenderTextPICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
.
Structure to create an operator of type XR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO
The XrSecureMrOperatorColorConvertPICO structure is defined as:
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrOperatorColorConvertPICO {
XrStructureType type;
const void* next;
int32_t convert;
} XrSecureMrOperatorColorConvertPICO;
The XrSecureMrOperatorColorConvertPICO structure describes the
information to create an XrSecureMrOperatorPICO
of type
XR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO
Operator specifications
Operators each have specified requirements on their operand and result tensors' datatype, dimensions and channels.
XrSecureMrOperatorTypePICO lists all operator types, including customizable operators like the inference operator, the predefined ones for preprocessing/postprocessing, and those for mixed-reality effects.
typedef enum XrSecureMrOperatorTypePICO {
XR_SECURE_MR_OPERATOR_TYPE_UNKNOWN_PICO = 0,
XR_SECURE_MR_OPERATOR_TYPE_ARITHMETIC_COMPOSE_PICO = 1,
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MIN_PICO = 4,
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MAX_PICO = 5,
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MULTIPLY_PICO = 6,
XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO = 7,
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_OR_PICO = 8,
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_AND_PICO = 9,
XR_SECURE_MR_OPERATOR_TYPE_ALL_PICO = 10,
XR_SECURE_MR_OPERATOR_TYPE_ANY_PICO = 11,
XR_SECURE_MR_OPERATOR_TYPE_NMS_PICO = 12,
XR_SECURE_MR_OPERATOR_TYPE_SOLVE_P_N_P_PICO = 13,
XR_SECURE_MR_OPERATOR_TYPE_GET_AFFINE_PICO = 14,
XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_PICO = 15,
XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_POINT_PICO = 16,
XR_SECURE_MR_OPERATOR_TYPE_UV_TO_3D_IN_CAM_SPACE_PICO = 17,
XR_SECURE_MR_OPERATOR_TYPE_ASSIGNMENT_PICO = 18,
XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO = 19,
XR_SECURE_MR_OPERATOR_TYPE_NORMALIZE_PICO = 21,
XR_SECURE_MR_OPERATOR_TYPE_CAMERA_SPACE_TO_WORLD_PICO = 22,
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO = 23,
XR_SECURE_MR_OPERATOR_TYPE_ARGMAX_PICO = 24,
XR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO = 25,
XR_SECURE_MR_OPERATOR_TYPE_SORT_VEC_PICO = 26,
XR_SECURE_MR_OPERATOR_TYPE_INVERSION_PICO = 27,
XR_SECURE_MR_OPERATOR_TYPE_GET_TRANSFORM_MAT_PICO = 28,
XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO = 29,
XR_SECURE_MR_OPERATOR_TYPE_SWITCH_GLTF_RENDER_STATUS_PICO = 30,
XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO = 31,
XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO = 32,
XR_SECURE_MR_OPERATOR_TYPE_LOAD_TEXTURE_PICO = 33,
XR_SECURE_MR_OPERATOR_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrOperatorTypePICO;
The operator's specifications corresponding to each operator type are listed below:
XR_SECURE_MR_OPERATOR_TYPE_ARITHMETIC_COMPOSE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ARITHMETIC_COMPOSE_PICO
is a predefined CPU operator. It can be used for arbitrary arithmetic computation. During its creation, applications must provide a arithmetic expression using XrSecureMrOperatorArithmeticComposePICO, in which{IDX}
denotes the IDX-th operands whereIDX
must be a single digit from0
to9
, and+
,-
,*
,/
and parentheses are allowed. Nested parentheses are allowed as well.Applications must provide the operands whose indices are referred to in the expression with local tensors. The operand name to be used in xrSetSecureMrOperatorOperandByNamePICO is
{IDX}
whereIDX
is a single digit matching the operand's index used in the expression. The tensors set as the operator's operands must be created with usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
.The operator has exactly one result. Applications must set a local tensor as the result. The tensor set as the result must be created with usage flag
XR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
. Applications can useresult
as the result name in xrSetSecureMrOperatorResultByNamePICO, or index0
as the result index in xrSetSecureMrOperatorResultByIndexPICO.The channel and dimensions of each operand must permit the expression to be carried out following matrix arithmetic rules. For example, if the arithmetic expression is
{0} * {1}
, operand 0, operand 1 and the result must all have two dimensions only, and operand 0's last dimension must match the first of operand 1, while operand 0's first dimension must match that of the result’s and operand 1's last dimension must also match the last of the result’s. XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MIN_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MIN_PICO
is a predefined CPU operator. It can be used to compute the min values of two tensors element-by-element.Such an operator has two operands and one result. The two operands and the result must have exactly the same datatypes, channels, numbers of dimensions and sizes on each dimension.
Applications can use the name "operand0" and "operand1" to refer to the two operands respectively in xrSetSecureMrOperatorOperandByNamePICO, or index 0 and 1 in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set tensors for both operands.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage flags.
Each value in the result tensor will be the min of the corresponding values of both operand tensors.
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MAX_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MAX_PICO
is a predefined CPU operator. It can be used to compute the max values of two tensors element-by-element.Such an operator has two operands and one result. The two operands and the result must have exactly the same datatypes, channels, numbers of dimensions and sizes on each dimension.
Applications can use the name "operand0" and "operand1" to refer to the two operands respectively in xrSetSecureMrOperatorOperandByNamePICO, or index 0 and 1 in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set tensors for both operands.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage flags.
Each value in the result tensor will be the max of the corresponding values of both operand tensors.
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MULTIPLY_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_MULTIPLY_PICO
is a predefined CPU operator. It can be used to multiply values of two tensors element-by-element.Such an operator has two operands and one result. The two operands and the result must have exactly the same datatypes, channels, numbers of dimensions and sizes on each dimension.
Applications can use the name "operand0" and "operand1" to refer to the two operands respectively in xrSetSecureMrOperatorOperandByNamePICO, or index 0 and 1 in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set tensors for both operands.
Applications can use name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage.
Each value in the result tensor will be the multiplication of the corresponding values of both operand tensors.
XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_CUSTOMIZED_COMPARE_PICO
is a predefined CPU operator. It can be used to compare values of two tensors element-by-element.Such an operator has two operands and one result. The two operands must have exactly the same datatypes, channels, numbers of dimensions and sizes on each dimension.
The result must have exact the channels, numbers of dimensions, and sizes on each dimension as the operands. The datatype of the result must be an integral type, i.e. any of
Applications can use the name "operand0" and "operand1" to refer to the two operands respectively in xrSetSecureMrOperatorOperandByNamePICO, or index 0 and 1 in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set tensors for both operands.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage.
Each value in the result tensor will be the comparison results of the corresponding values of both operand tensors: zero if the comparison returns false on the pair of operand values, non-zero otherwise. The comparison is determined by the application via XrSecureMrOperatorComparisonPICO. Values from operand 0 will be placed at the left-hand side of the comparison and those from operand 1 at the right-hand side.
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_OR_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_OR_PICO
is a predefined CPU operator. It can be used to take logical OR operation of two integral tensors element-by-element.Such an operator has two operands and one result. The two operands and the result must have exactly the same channels, numbers of dimensions and sizes on each dimension. The datatypes of the two operands and the result can be different, but must be one of the integral types, i.e. any of
Applications can use the name "operand0" and "operand1" to refer to the two operands respectively in xrSetSecureMrOperatorOperandByNamePICO, or index 0 and 1 in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set tensors for both operands.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage.
Each value in the result tensor will be the logical OR results of the corresponding values of both operand tensors: zero if the result if logical false, non-zero if otherwise.
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_AND_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ELEMENTWISE_AND_PICO
is a predefined CPU operator. It can be used to take logical AND operation of two integral tensors element-by-element.Such an operator has two operands and one result. The two operands and the result must have exactly the same channels, numbers of dimensions and sizes on each dimension. The datatypes of the two operands and the result can be different, but must be one of the integral types, i.e. any of:
Applications can use the name "operand0" and "operand1" to refer to the two operands respectively in xrSetSecureMrOperatorOperandByNamePICO, or index 0 and 1 in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set tensors for both operands.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage.
Each value in the result tensor will be the logical AND results of the corresponding values of both operand tensors: zero if the result if logical false, non-zero if otherwise.
XR_SECURE_MR_OPERATOR_TYPE_ALL_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ALL_PICO
is a predefined CPU operator. It can be used to take logical AND operation among all values of one tensor.Such an operator has one operand and one result. There is no requirement on the operand. The result must be of exact one channel, and exact one dimensions, where the size on the only dimension must be 1, i.e. the result tensor must contain one value only. The datatype of the result must be an integral type, i.e. any of
Applications can use the name "operand" or index 0 to refer to the operand respectively in xrSetSecureMrOperatorOperandByNamePICO or in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set a tensor for the operand.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage.
The only value of the result will be zero if any of the values in the operand are zeros, and will be non-zero otherwise.
XR_SECURE_MR_OPERATOR_TYPE_ANY_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ANY_PICO
is a predefined CPU operator. It can be used to take logical OR operation among all values of one tensor.Such an operator has one operands and one result. There is no requirements on the operand. The result must be of 1 channel, and 1 dimension, where the size on the only dimension must be 1, i.e. the result tensor must contain one value only. The datatype of the result must be an integral type, i.e. any of
Applications can use the name "operand" or index 0 to refer to the operand respectively in xrSetSecureMrOperatorOperandByNamePICO or in xrSetSecureMrOperatorOperandByIndexPICO. Applications must set a tensor for the operand.
Applications can use the name "result" or index 0 to refer to the result in xrSetSecureMrOperatorResultByNamePICO, or in xrSetSecureMrOperatorResultByIndexPICO. Applications must set a tensor for the result.
No additional requirements on the operand and result tensors' usage.
The only value of the result will be zero if all of the values in the operand are zeros, and will be non-zero otherwise.
XR_SECURE_MR_OPERATOR_TYPE_NMS_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_NMS_PICO
is a predefined CPU operator. It can be used to conduct non-maximum suppression on bounding boxes. The operator can be found useful in filtering out overlapping bounding boxes and sort them accordingly to their confidence scores, such as in cases of object detection or face detection.The operator must have two tensors as its operands.
Applications can use the name "scores" or index 0 to refer to the first operand, which describes the confidence scores of the bounding boxes. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The channel must be 1. If created with usage flagXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
astensorType
, the operand tensor must be of one dimension, and the size on that dimension should beN
, whereN
is the number of bounding boxes. If created with usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
, the operand tensor must be of two dimensions, either(1, N)
or(N, 1)
, whereN
is the number of bounding boxes.Applications can use the name "boxes" or index 1 to refer to the second operand, which describes the 2D coordinates in XXYY format of the bounding boxes. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The usage flag used astensorType
during creation must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. If the channel is 1, the operand tensor must be of two dimensions:(N, 4)
, specifying the 4 coordinates for each of theN
bounding boxes. If the channel is 4, the operand tensor must be of two dimensions: either(1, N)
or(N, 1)
, whereN
is the number of bounding boxes.The operator can have three tensors as its results.
Applications can use the name "scores" or index 0 to refer to the first result, which will store the confidence scores of the bounding boxes passing the non-maximum suppression, sorted from max to min. The channel must be 1, and the datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. If created with usage flagXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
astensorType
, the result tensor must be of one dimension, and the size on that dimension should beM
, whereM
is the expected number of bounding boxes. If created with usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
, the result tensor must be of two dimensions, either(1, M)
or(M, 1)
, whereM
is the expected number of bounding boxes.Applications can use the name "boxes" or index 1 to refer to the second result, which describes the 2D coordinates in XXYY format of the bounding boxes passed the non-maximum suppression, corresponding to the order in result
scores
. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The usage flag used astensorType
during creation must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. If the channel is 1, the result tensor must be of two dimensions:(M, 4)
, specifying the 4 coordinates for each of theM
bounding boxes. If the channel is 4, the result tensor must be of two dimensions: either(1, M)
or(M, 1)
, whereM
is the expected number of bounding boxes.Applications can use the name "indices" or index 1 to refer to the third operand, which describes the original index of the bounding boxes in operand
boxes
. The channel must be 1. The datatype must beThe usage flag used as
tensorType
during creation must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. If created with usage flagXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
astensorType
, the result tensor must be of one dimension, and the size on that dimension should beM
, whereM
is the expected number of bounding boxes. If created with usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
, the result tensor must be of two dimensions, either(1, M)
or(M, 1)
, whereM
is the expected number of bounding boxes.At least one result must be set. If more than one result are set with tensors, the
M
in the result tensors' dimensions must be the same.The choice of
M
depends on the application logic. Logically,M
must be smaller thanN
. Ideally,M
may match the exact required number of the detection targets to be presented through the mixed-reality operators. For example, a face detection application may would like to detect at most 5 human faces and make corresponding MR effects at the same time. The machine learning algorithm it uses may output N=896 bounding boxes as candidates so the NMS operator is used to filter out the ones overlapping with others or with lower confidence scores. A proper choice ofM
can be 5, matching the maximum number of MR effects to be rendered. XR_SECURE_MR_OPERATOR_TYPE_SOLVE_P_N_P_PICO
-
An operator of
XR_SECURE_MR_OPERATOR_TYPE_SOLVE_P_N_P_PICO
is a predefined CPU operator and performs the OpenCV solve P-N-P algorithm. The algorithm inverses a camera projection. It solves the most likely poses of a 3D object, usually a mesh, given the mesh vertices' coordinates in the model space, a camera intrinsic matrix, and the mesh's projection by the camera. The result pose is expressed under the view space. Hence, such an operator can be found useful for cases like determining 3D poses based on 2D feature points.Applications must provide three operands to the operator.
Applications can use the name "object points" or index 0 to refer to the first operand, which describe the 3D vertex coordinates in the model space. The channel must be 3. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The operand must have one dimension:(P,)
, or two dimensions:(P, 1)
or(1, P)
, whereP
is the total number of vertices.Applications can use the name "image points" or index 1 to refer to the second operand, which describe the projection result of the vertices as 2D coordinates on the camera's projection plane. The channel must be 2. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The operand must have one dimension:(P,)
or two dimensions:(P, 1)
or(1, P)
, whereP
is the total number of vertices.Applications can use the name "camera matrix" or index 2 to refer to the third operand, which describe the camera intrinsic matrix used for projection. The usage flag used as
tensorType
must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and channel must be 1. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The result must be a 2-dimensional tensor, with dimensions =(3, 3)
.If the intrinsic matrix returned from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
is used, the matrix will project points to a range from 0.0 to 1.0, with (0.5, 0.5) being the center. Hence, the operand "object points" should be scaled accordingly.The operator can have two results.
Applications can use the name "rotation" or index 0 to refer to the first result, which describe the rotation of the result pose in the view space. The rotation is expressed as an angle-axis vector. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The channel must be 1 and the usage flag fortensorType
must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. The result must have two dimensions: either(3, 1)
or(1, 3)
.Applications can use the name "translation" or index 1 to refer to the first result, which describe the translation of the result pose in the view space. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The channel must be 1 and the usage flag fortensorType
must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. The result must have two dimensions: either(3, 1)
or(1, 3)
. XR_SECURE_MR_OPERATOR_TYPE_GET_AFFINE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_GET_AFFINE_PICO
is a predefined CPU operator. It gives an affine transform matrix from one 2D space to another. It can be found useful in cases like clipping, scaling, rotating, translating, resizing, or tilting a 2D image.To compute a valid affine transform, 3 pairs of points in the source 2D space and the destination 2D space must be given.
Applications must provide two operands and one result.
Applications can use the name "src" or index 0 to refer to the first operand, which describe 3 points in the source 2D space. The channel must be 2. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The operand must have one dimension only, and the size along it must be 3, or two dimensions:(3, 1)
or(1, 3)
.Applications can use the name "dst" or index 1 to refer to the second operand, which describe the same 3 points as operand "src", but in the destination 2D space. The channel must be 2. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The operand must have one dimension only, and the size along it must be 3, or two dimensions:(3, 1)
or(1, 3)
.For example, if the affine transform is used to resize an image of 512x512 to 128x128, the 3 "src" points can be:
(0.0,0.0), (0,511.0), (511.0,0.0)
, and the 3 "dst" points can be:(0.0,0.0), (0,127.0), (127.0,0.0)
.Applications can use the name "result" or index 0 to refer to the only result, which stores the result affine transform matrix. The usage flag used as
tensorType
must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and channel must be 1. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The result must be a 2-dimensional tensor, with dimensions =(2, 3)
.Note: the operator only computes and stores the affine transform matrix. To clip, scale, rotate, translate, resize, tilt or perform other affine transformation, you need operators of
XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_PICO
orXR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_POINT_PICO
with this operator's result as operands to make the affine transform takes effect. XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_PICO
is a predefined CPU operator, and it performs affine transform onto a 2D image.The operator has two operands and a result.
Applications can use the name "affine" or index 0 to refer to the first operand, which is the 2x3 affine transform matrix (either from the result of an operator of type
XR_SECURE_MR_OPERATOR_TYPE_GET_AFFINE_PICO
, or is manually formulated). The usage flag used astensorType
must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and channel must be 1. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The result must be a 2-dimensional tensor, with dimensions =(2, 3)
.Applications can use the name "src image" or index 1 to refer to the second operand, which is the source image to be affined.
Applications can use the name "dst image" or index 0 to refer to the only result, which stores the outcoming image of applying operand "affine" onto operand "src image".
Both the "src image" and the "dst image" must have
XR_SECURE_MR_TENSOR_TYPE_MAT_PICO
as their usage flags. The channel must be 1. Operand "src image" and result "dst image" must both be of 2 dimensions, and the sizes on each dimension must match.There is no additional requirements on the datatype of operand "src image" and result "dst image", except the two must have the same datatype.
XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_POINT_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_APPLY_AFFINE_POINT_PICO
is a predefined CPU operator, and it performs affine transform onto a batch of 2D points rather than the whole image.The operator has two operands and a result.
Applications can use the name "affine" or index 0 to refer to the first operand, which is the 2x3 affine transform matrix (either from the result of an operator of type
XR_SECURE_MR_OPERATOR_TYPE_GET_AFFINE_PICO
, or is manually formulated). The usage flag used astensorType
must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and channel must be 1. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The result must be a 2-dimensional tensor, with dimensions =(2, 3)
.Applications can use the name "src points" or index 1 to refer to the second operand, which is the coordinates of the points in the source space.
Applications can use the name "dst points" or index 0 to refer to the only result, which stores the coordinates of the points in the destination space after operand "affine" being applied onto operand "src points".
Both the "src points" and the "dst point" must have 2 channels, and must both be of 1 dimension:
(P,)
, or two dimensions:(P, 1)
or(1, P)
, whereP
is the number of points.There is no additional requirements on the datatype of operand "src image" and result "dst image", except the two must have the same datatype.
XR_SECURE_MR_OPERATOR_TYPE_UV_TO_3D_IN_CAM_SPACE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_UV_TO_3D_IN_CAM_SPACE_PICO
is a predefined CPU operator, and it utilizes the stereoview RGB image, and the depth sensor (if available) to recover the 3D coordinates in the camera space from 2D points on the left-eye RGB images. The operator can be useful for mixed reality applications using conventional computer vision algorithms, which may run only on mono-view RGB inputs, and produce detection or estimation only as 2D points on the image, but a 3D pose with depth estimation is needed for MR rendering.The operator's functionality is similar to an operator of type
XR_SECURE_MR_OPERATOR_TYPE_SOLVE_P_N_P_PICO
, both of which computes 3D poses from 2D points. However, the Solve P-N-P one requires prior knowledge about the local 3D coordinates corresponding to all 2D points; and this UV-to-3D operator relies on the stereoview images (and probably depth sensor) to achieve such effect. Nevertheless, there is a limitation of the UV-to-3D operator, that is the 2D points must be relative to the left-eye image.The operator has five operands and one result, to which applications must set all tensors.
Applications can use the name "uv" or index 0 to refer to the first operand, which is the pixel coordinates of 2D points to be queried. The 2D points must be on the left-eye RGB image obtained from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
. Their coordinates must be integers in pixels, origin at the top-left corner of the image, and within the range(0 ~ WIDTH, 0 ~ HEIGHT)
, where the WIDTH and the HEIGHT are the resolution of a single-eye camera's output. The operand must be of 2 channels, and must be of an integral datatype, i.e. any ofThe operand must have usage flag
XR_SECURE_MR_TENSOR_TYPE_POINT_PICO
astensorType
when the tensor is created, and must have one dimension only. For simplicity, we will usePn
to denote the size along this dimension, i.e. the number of points.Applications can use the name "timestamp" or index 1 to refer to the second operand, which is the camera timestamp returned as result "timestamp" from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
. The operand must be of 4 channels, and must be of datatypeXR_SECURE_MR_TENSOR_DATA_TYPE_INT32_PICO
. The operand also must have usage flagXR_SECURE_MR_TENSOR_TYPE_TIMESTAMP_PICO
astensorType
and must have one dimension along which the size is exactly 1.Applications can use the name "camera intrinsic" or index 2 to refer to the third operand, which is the camera intrinsic matrix returned as result "camera matrix" from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
. The operand must be of 1 channel, and must be of datatypeXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The operand also must have usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
and must have two dimensions:(3, 3)
. In short, the operand must be a 3x3 floating-point matrix.Applications can use the name "left image" or index 3 to refer to the fourth operand, which is the left-eye RGB image, returned as result "left image" from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
. The operand must be of 3 channels, must be of datatypeXR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
, must have usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and must have two dimensions:(height, width)
, equal to the RGB camera's resolution declared in xrCreateSecureMrFrameworkPICO.Applications can use the name "right image" or index 4 to refer to the fifth operand, which is the right-eye RGB image, returned as result "right image" from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
. The operand must be of 3 channels, must be of datatypeXR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
, must have usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and must have two dimensions:(height, width)
, equal to the RGB camera's resolution declared in xrCreateSecureMrFrameworkPICO.Applications can use the name "point_xyz" or index 0 to refer to the only result, which is the 3D coordinates recovered from the given 2D coordinates for each point in operand "uv". The 3D coordinates are described in the left-eye RGB camera's view space. The result must be of 3 channels, and of datatype
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
.Also, the result's dimensions and channels must be one of the following combinations:
Both operand "uv" for the points' 2D coordinates and result "point_xyz" for the points' 3D coordinates are all relative to the left-eye camera's view space.
XR_SECURE_MR_OPERATOR_TYPE_ASSIGNMENT_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ASSIGNMENT_PICO
is a predefined CPU operator, to select values from one tensor (the operand) and assign the values to the other (the result). Applications can use this operator for taking slices from tensors, copying values, converting datatypes, reshaping dimensions and so on.The operator has 5 operands and 1 result.
Applications can use the name "src" or index 0 to refer to the first operand, which is the source of the copy assignment. There is no requirement on its dimensions, datatypes, channels, and usage type. For the convenience of the following explanation, we will use
Ns
to denote the number of its dimensions, andCs
to denote its number of channels.Applications must set a tensor as operand "src".
Applications can use the name "src slices" or index 1 to refer to the second operand, which is the slicing indices on each of the
Ns
dimensions of operand "src". The operand's number of channels must be 2 or 3, and its usage flag must be:XR_SECURE_MR_TENSOR_TYPE_SLICE_PICO
. The operand must have one dimension only, and the size along the dimension must beNs
. If it has 2 channels, the two channels indicate the start index (included) and the end index (excluded) of the slice on the corresponding dimension of operand "src". If it has 3 channels, they specify the start index (included), the end index (excluded) and the skip on each dimension of operand "src".For example, an application can use a tensor with 2 dimensions:
(4, 4)
as operand "src", and would select the first 2x3 matrix from it. The application can use a 2-channel tensor as operand "src slices", which has one dimension:(2,)
. The content of operand "src slices" will be(0, 2),(0, 3)
, meaning the slice on the first dimension of operand "src" is from index 0 to index 1, and the slice on the second dimension is from index 0 to index 2, therefore resulting in a 2x3 matrix.Also, an application can use a tensor with 3 dimensions:
(5, 1024, 1024)
, storing 5 successive 1024x1024 RGB images, as operand "src". If the application would like to select the images at index 0, 2, and 4, it can use a 3-channel tensor with one dimension:(3,)
as operand "src slices". Note the magic number3
as the size of the only dimension of operand "src slice" match the number of dimensions of operand "src". The content of operand "src slices" can be(0,-1,2),(0,-1,1),(0,-1,1)
. The first triple(0,-1,2)
means on the first dimension of operand "src", the slice is taken every second index from index 0 to the dimension end (denoted by code:-1), i.e. index 0, 2, 4 are taken. For this dimension, triple(0,-1,2)
is equivalent to triple(0:5,2)
. The second and the third triples(0,-1,1)
mean on the second and the third dimensions of operand "src", the entire dimension, from index 0 to index 1023 one-by-one.Applications can set no tensor to this operand, if no slice is needed on dimensions of operand "src"
Applications can use the name "src channel slice" or index 2 to refer to the third operand, which is the slicing indices on the channels of operand "src". The operand's number of channels must be 2 or 3, and its usage flag must be:
XR_SECURE_MR_TENSOR_TYPE_SLICE_PICO
. The operand must have one dimension only, and the size along the dimension must be1
. The operand performs exactly same slicing functionality as operand "src slices", but it slices the channels of operand "src" rather than its dimensions.For example, an application can use a 3-channel tensor of 2 dimensions:
(1024, 1024)
as operand "src", describing a RGB image, and would like to pick only the G channel. The application can omit operand "src slices" but use a 2-channel tensor of one dimension:(1,)
as operand "src channel slice". The content of the tensor as operand "src channel slice" shall be(1,2)
, which means the channel index 1 is picked from operand "src".Applications can set no tensor to this operand, if no slice is needed on channels of operand "src"
Applications can use the name "dst slices" or index 3 to refer to the fourth operand, and can use the name "dst channel slice" or index 4 to refer to the fifth operand. Operand "dst slices" has exactly the same requirements and functionalities as operand "src slices", but the slices are applied onto each dimension of the result rather than that of operand "src". Similarly, operand "dst channel slice" has exactly the same requirements and functionalities as operand "src channel slice", but the slice is applied onto the result's channels rather than that of operand "src".
For exampmle, an application can have a single-dimension tensor of 2 dimensions:
(1024, 1024)
, representing a greyscale image, and a single-dimension tensor of 3 dimensions:(3, 2048, 1024)
, to store a batch of three 1024x1024 greyscale images. The application would like to copy the 2-dimensional greyscale image to be the first 1024 rows of the first slot in the 3-dimensional image batch. Thus, the application can set the 2-dimension tensor as operand "src", the 3-diemsnion tensor as the result, a 2-channel tensor of 1 dimension:(3,)
as operand "dst slices", and another 2-channel tensor of 1 dimension:(1,)
as operand "dst channel slice". The content of operand "dst slices" is this example can be(0,1),(0,1024),(0,-1)
.Applications can use the name "dst" or index 0 to refer to the only result, which is the destination of the copy assignment. There is no requirements on channel, dimensions, datatype and usage flag of result "dst". If the datatype of result "dst" does not match that of operand "src", automatically datatype conversion will be carried out.
There are batch-operation acceleration if the operator only involve datatype conversion but no slice on either operand "src" or result "dst", i.e. no tensor set for operand "src slices", "src channel slice", "dst slices" and "dst channel slice".
The execution of the operator will be aborted if the total number of values sliced from operand "src" does not match the number of values sliced from result "dst".
XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_RUN_MODEL_INFERENCE_PICO
(an inference operator) is a customizable operator where applications can deploy compiled binary algorithm package of their own, via XrSecureMrOperatorModelPICO.The datatypes and names of the operator's operands and results are also application-customizable through XrSecureMrOperatorIOMapPICO.
The index of operands are the index of the corresponding XrSecureMrOperatorIOMapPICO declaring the operand in the
modelInputs
array of XrSecureMrOperatorModelPICO.The index of results are the index of the corresponding XrSecureMrOperatorIOMapPICO declaring the result in the
modelOutputs
array of XrSecureMrOperatorIOMapPICO.There is no requirements on the usage flag of operands or results, as long as it is not
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
. A glTF tensor cannot be used in an inference operator.There is no additional requirements on the dimensions and channels of operands and results, but the total count of values (the multiplication of sizes along all dimensions, times the number of channels), must match desired amount of values in the algorithm's input/output nodes mapped to the operands or results.
For example, a face detection algorithm may expect a 3-channel 192x192 RGB image input. The application deploying it can provide a 1-channel tensor of 3 dimensions:
(3, 192, 192)
, or a 3-channel tensor of 2 dimensions:(192, 192)
, or even a 3-channel tensor of 1 dimension:(36864,)
, as long as the total count of values match the desired 3x192x192 inputs. XR_SECURE_MR_OPERATOR_TYPE_NORMALIZE_PICO
-
an operator of type
XR_SECURE_MR_OPERATOR_TYPE_NORMALIZE_PICO
is a predefined CPU operator, which can be used to normalize a tensor.The operator has two operands and one result.
Applications can use the name "operand0" or index 0 to refer to the first operand, which is the tensor to be normalized. There is no requirements on the tensor's datatype, channel, dimensions and usage flag, as long as its usage flag is not
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
.Applications must set a tensor to operand "operand0".
Applications can use the name "alpha_beta" or index 1 to refer to the second operand, which specifies the alpha parameter and the beta parameter for normalization. The operand must be of 1 channel, and of datatype
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. It also must have usage flagXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
as itstensorType
during tensor creation. Its number of dimensions must be 1, and the size along the only dimension must be 2, i.e. the tensor shall contain two floating-point values only, where the first is the alpha parameter and the second is the beta parameter.Applications can set no tensor to operand "alpha_beta" to use the default parameters, where alpha is 1.00 and beta is 0.00.
Applications can use the name "result" or index 0 to refer to the only result, which is the normalization result. Its datatype, usage flag, dimensions, and number of channels must be the same as operand "operand0".
Applications must set tensors to the result.
XR_SECURE_MR_OPERATOR_TYPE_CAMERA_SPACE_TO_WORLD_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_CAMERA_SPACE_TO_WORLD_PICO
is a mixed-reality operator, providing transform matrices from both-eye's camera space at their exposure timepoints to the world-lockedXR_REFERENCE_SPACE_TYPE_LOCAL
space. The operator may be found useful under the scenarios like placing a world-locked tag or a glTF object according to the detection result, offsetting the headset's own movement. Note that operators of typeXR_SECURE_MR_OPERATOR_TYPE_SOLVE_P_N_P_PICO
and typeXR_SECURE_MR_OPERATOR_TYPE_UV_TO_3D_IN_CAM_SPACE_PICO
produce 3D coordinates or poses with respect to the camera's view space at the exposure time.The operator requires only one operand, which can be referred to using name "timestamp", or index 0. It is the camera timestamp returned as result "timestamp" from an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
. The operand must be of 4 channels, and must be of datatypeXR_SECURE_MR_TENSOR_DATA_TYPE_INT32_PICO
. The operand also must have usage flagXR_SECURE_MR_TENSOR_TYPE_TIMESTAMP_PICO
astensorType
and must have one dimension along which the size is exactly 1.The operator has two optional results.
Applications can use the name "right" or index 0 to refer to the first result; or use the name "left" or index 1 to refer to the second. The results are the transform matrices from the left-eye and the right-eye RGB cameras' view spaces at the exposure timestamp. Hence, they must both be 1-channel floating-point 4x4 matrices, i.e. their datatypes must be either
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
, their usage must be declared asXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, and they must be of two dimensions:(4, 4)
, and their number of channels must be 1.Calling the operator may involve access to the depth data and requires the processing of point clouds, both of which can be time consuming. Applications should avoid calling the operators in a frequency higher than 20Hz.
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
-
An operator of
XR_SECURE_MR_OPERATOR_TYPE_RECTIFIED_VST_ACCESS_PICO
is a mixed-reality operator.Recall that in xrCreateSecureMrFrameworkPICO, a stereoview camera provider is created associated with the framework handle. The operator accesses the camera provider to fetch the latest RGB images for both eyes.
The operator makes GPU calls to reproject and rectify the raw images from camera. Hence, applications should be aware that calling the operator frequently may increase the power consumption and the GPU delay.
The operator has no operands, with four results.
Applications can use the name "right image" or index 0 to refer to the first result, which is the RGB image from the right-eye camera. Also, applications can use the name "left image" or index 1 to refer to the second result, which is the RGB image from the left-eye camera.
Both result "right image" and "left image" must have 3 channels, and of datatype
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
. Their usage must be declared asXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. They must be of two dimensions:(height, width)
, where the height and the width must match theheight
andwidth
in XrSecureMrFrameworkCreateInfoPICO when the framework handle is created. XR_SECURE_MR_OPERATOR_TYPE_ARGMAX_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_ARGMAX_PICO
is a predefined CPU operator, to find index of the maximum along each channel.The operator has one operand and one result, to both of which applications must set tensors.
Applications can use the name "operand" or index 0 to refer to the only operand. There is no requirements on the operand, as long as its usage flag is not
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
. For convenience of explanation, we useN
to denote its number of dimensions, andC
to denote its number of channels.Applications can use the name "result" or index 0 to refer to the only result. It shall be a tensor of
C
elements to store theC
indices along all channels of the operand. Each element shall haveN
channels, as it is an index for aN
dimensional tensor.Hence, if it has only one dimension, the size along the dimension must be
C
. If it has two dimensions, the dimensions must be(C, 1)
or(1, C)
. Also, the result must haveN
channels, corresponding to the number of dimensions of the operand. XR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO
is a predefined CPU operator, and performs the same functionality as the OpenCVcvtColor
API.The operator has an operand, indexed 0 and named "src", and a result, indexed 0 and named "dst", for the source and the destination of color conversion respectively.
Both the operand and the result must have two dimensions:
(height, width)
and their heights and widths must match. The channels of the operand and that of the result must be compatible of the color conversion flag declared for the operator viaXR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO
.For example, if the color conversion is from RGB to GRB, then both the operand and the result shall be of 3 channels.
Additionally, the usage flag of both the operand and the result must be
XR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. XR_SECURE_MR_OPERATOR_TYPE_SORT_VEC_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_SORT_VEC_PICO
is a predefined CPU operator, as a compensation for the limitation of operators of typeXR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO
.The operator can be used to sort 1-dimensional tensor, and have one operand together with two results.
Applications can use the name "operand" or index 0 to refer to the operand, which is the 1-dimension tensor to be sorted. Its number of channels must be 1 as well.
Applications must set a tensor to the operand.
Applications can use the name "sorted" or index 0 to refer to the first result, which is the sorted result of the operand from the maximum to the minimum. It must be a 1-dimensional 1-channel tensor, with the same datatype and size along the only dimension as the operand.
Applications can use the name "indices" or index 1 to refer to the second result, which is the original indices in the operand of sort result. It must be a 1-dimensional 1-channel tensor, with the same size along the only dimension as the operand. Its datatype must be of integral types, i.e. any of:
XR_SECURE_MR_OPERATOR_TYPE_INVERSION_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_CONVERT_COLOR_PICO
is a predefined CPU operator, for matrix inversion.The operator has an operand, indexed 0 and named "operand", and a result, indexed 0 and named "result", as the original matrix and its inversion respectively.
Both the operand and the result must have two dimensions of identical sizes:
(N, N)
and the number N must match. The channels of the operand and that of the result must also be the same and compatible for matrix inversion operation.Additionally, the usage flag of both the operand and the result must be
XR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. XR_SECURE_MR_OPERATOR_TYPE_GET_TRANSFORM_MAT_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_GET_TRANSFORM_MAT_PICO
is a predefined CPU operator, to compute a 4x4 transform matrix from a rotation vector, a translation vector and an optional scale vector. Hence, the operator performs the Rodriguez operation.The operator has three operands for rotation, translation and scaling vector respectively. The operator has one result.
Applications can use the name "rotation" or index 0 to refer to the first operand, which is the rotation vector, expressed in axis-angle.
Applications can use the name "translation" or index 1 to refer to the second operand, which is the translation vector.
Applications can use the name "scale" or index 2 to refer to the third operand, which is the scaling vector.
All three operands must have two dimensions:
(3,1)
or(1,3)
, i.e. a column vector or a row vector; and they must have usage flagXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
during tensor creation. Also, their numbers of channels must be 1, and their datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
.Applications must set tensors for operand "rotation" and operand "translation". Operand "scale" is optional.
Applications can use the name "result" or index 0 to refer to the only result, which is the 4x4 transform matrix. The result must have two dimensions:
(4,4)
, and must be of 1 channel. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
, and the usage must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_SORT_MAT_PICO
is a predefined CPU operator, to perform the same functionality as OpenCVsortMat
API.The operator can be used to sort a 1-channel 2-dimensional tensor, i.e. a matrix, and have one operand together with two results.
Applications can use the name "operand" or index 0 to refer to the operand, which must be the 2-dimensional tensor to be sorted. Its number of channels must be 1. The result must have usage flag
XR_SECURE_MR_TENSOR_TYPE_MAT_PICO
astensorType
during tensor creation.Applications must set a tensor to the operand.
Applications can use the name "sorted" or index 0 to refer to the first result, which is the sorted result of the operand from the maximum to the minimum. It must be a 2-dimensional 1-channel tensor, with the same datatype, usage and size along each dimension as the operand. The sorting is performed either row-by-row or column-by-column, depending on the settings in XrSecureMrOperatorSortMatrixPICO.
Applications can use the name "indices" or index 1 to refer to the second result, which is sort result's original indices in the row or the column of the operand. It must be a 2-dimensional 1-channel tensor, with the same usage and size along each dimension as the operand. Its datatype must be of integral types, i.e. any of
XR_SECURE_MR_OPERATOR_TYPE_SWITCH_GLTF_RENDER_STATUS_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_SWITCH_GLTF_RENDER_STATUS_PICO
is a mixed-reality operator, to turn on/off the rendering of a glTF object.The operator has four operands, and no result.
Applications can use the name "gltf" or index 0 to refer to the first operand, which is the target glTF object. The operand must be declared with usage flag
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
. Applications must set a glTF tensor to the operand.Applications can use the name "world pose" or index 1 to refer to the second operand, which is the initial world pose for the target glTF object to be rendered. By default, the world pose is relative to the world-locked OpenXR
XR_REFERENCE_SPACE_TYPE_LOCAL
reference space. You can use operand "view locked" to change to theXR_REFERENCE_SPACE_TYPE_VIEW
reference space. The operand must be of 1 channel, and of 2 dimensions:(4,4)
. It must be declared withXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
usage flag. Its datatype must be eitherXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. Hence, the operand must be a 4x4 floating-point 1-channel matrix.Applications can omit the operand, in which case, the glTF object will not be shown, equivalent to set operand "visible" to be false.
Applications can use the name "visible" or index 2 to refer to the third operand, which determines whether the turn on or off the rendering of the glTF object. There is no requirements on the operand. If the operand is evaluated to be true (non-zero), the rendering is turned on; otherwise, the rendering is turned off.
Applications can omit the operand, in which case, operand "visibility" will be regarded as true by default.
Applications can use the name "view locked" or index 3 to refer to the fourth operand, which determines whether using
XR_REFERENCE_SPACE_TYPE_VIEW
orXR_REFERENCE_SPACE_TYPE_LOCAL
as the reference space to which operand "world pose" is relative to. There is no requirements on the operand. If the operand is evaluated to be true (non-zero), theXR_REFERENCE_SPACE_TYPE_VIEW
is chosen, otherwiseXR_REFERENCE_SPACE_TYPE_LOCAL
.Applications can omit the operand, in which case, operand "world pose" is by default relative to
XR_REFERENCE_SPACE_TYPE_LOCAL
reference space.Note that if operand "view locked" is true, the transform matrices returned from operators of type
XR_SECURE_MR_OPERATOR_TYPE_CAMERA_SPACE_TO_WORLD_PICO
should not be applied, as the specification explicitly states the matrices fromXR_SECURE_MR_OPERATOR_TYPE_CAMERA_SPACE_TO_WORLD_PICO
are transforms toward theXR_REFERENCE_SPACE_TYPE_LOCAL
reference space.If a glTF object already visible is turned on again, no error will occur, and the glTF object's poses will be updated according to operand "world pose".
XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
is a mixed-reality operator, to update poses, animations, materials or other attributes of a glTF object. The operator is designed for data-driven animation. The target attribute to be updated is determined via XrSecureMrOperatorUpdateGltfPICO.The operator has no result. It can have 2 or 3 operands depending on the attribute to be updated.
For all use cases, the first operand is consistent, which can be referred to using name "gltf" or index 0, specifying the glTF object to be updated. The operand must be declared with usage flag
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
.Applications must set a glTF tensor to the operand.
The
attribute
of XrSecureMrOperatorUpdateGltfPICO used as thecreateInfo
during the creation of the operator affects the names and the requirements of the second and the third (if applicable) operand. The names for the second and the third (if applicable) operands are listed below:Attributes Name for the second operand (index 1) Name for the third operand (index 2) XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_TEXTURE_PICO
"texture ID"
"rgb image"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_ANIMATION_PICO
"animation ID"
"animation timer"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_LOCAL_TRANSFORM_PICO
"world pose"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_WORLD_POSE_PICO
"node ID"
"transform"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_METALLIC_FACTOR_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_ROUGHNESS_FACTOR_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_OCCLUSION_MAP_TEXTURE_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_BASE_COLOR_FACTOR_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_FACTOR_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_STRENGTH_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_TEXTURE_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_BASE_COLOR_TEXTURE_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_NORMAL_MAP_TEXTURE_PICO
"material ID"
"value"
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_METALLIC_ROUGHNESS_TEXTURE_PICO
"material ID"
"value"
-
For operands named "texture ID", "animation ID", "node ID" or "material ID", they must be a 1-channel tensor of one dimension, length along which must be
N
, whereN
specifies the number of textures, animations, nodes or materials to be updated. The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
, and the usage flag must beXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
. The operands containN
IDs, where each ID is an index of one target texture, animation, node or material in the glTF json file’s corresponding section.-
For example, if an application would like to update the local transform of one certain node in the target glTF, developers can locate the node in the raw glTF json file among the "nodes" array. The node ID will be the index of the target node in that array (starting from 0).
-
One exception is for "texture ID", applications can dynamically add new textures using operator of type
XR_SECURE_MR_OPERATOR_TYPE_LOAD_TEXTURE_PICO
, and can use the new texture IDs from the result as operand "texture ID". -
For "animation ID",
N
must be 1.
-
-
Operands named "rgb image" must be of 3 or 4 channels, for RGB textures or RGBA textures respectively. The datatype of the operand must be
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
. Its usage flag must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. The operand must have 3 dimensions:(N, HEIGHT, WIDTH)
, or have 2 dimensions:(HEIGHT, WIDTH)
ifN
= 1.N
must match the length of operand "texture ID".HEIGHT
andWIDTH
must match the target textures' original sizes, and the number of channels (i.e. whether RGB or RGBA) must also match that of the target texture. -
Operands named "animation timer" must have 1 channel, and 1 dimension only. The length along the dimension must be 1, i.e. the operand must have 1 value only. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
, and the usage flag must beXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
. The animation trace specified by operand "animation ID" will be replayed at the timepoint equal to operand "animation timer" mod the length of the target animation. -
For the operand named "world pose", it must be of 1 channel, and 2 dimensions:
(4, 4)
. It also must be declared withXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
usage flag. Its datatype must be eitherXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. Hence, the operand must be a 4x4 floating-point 1-channel matrix. -
For the operand named "transform", it must be of 1 channel, and of 3 dimensions:
(N, 4, 4)
, whereN
is number of nodes and must match the length of operand "node ID". It also must be declared withXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
usage flag. Its datatype must be eitherXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. Hence, the operand must be a 4x4 floating-point 1-channel matrix. IfN
== 1, operand "transform" can also be 2 dimensions:(4, 4)
, to avoid unnecessary copy assignment. -
The operand named "value" must have one dimension only. The length along the only dimension must match that of the operand "material ID". The requirements on the operand's usage flag and the number of channels can be affected by the
attribute
of XrSecureMrOperatorUpdateGltfPICO, listed in the table below.Attributes Datatype for operand "value" Usage flag for operand "value" Channels for operand "value" Meaning of the content XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_METALLIC_FACTOR_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
factor value
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_ROUGHNESS_FACTOR_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
factor value
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_OCCLUSION_MAP_TEXTURE_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
texture ID
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_BASE_COLOR_FACTOR_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
XR_SECURE_MR_TENSOR_TYPE_COLOR_PICO
4
RGBA color
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_FACTOR_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
XR_SECURE_MR_TENSOR_TYPE_COLOR_PICO
4
RGBA color
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_STRENGTH_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
factor value
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_EMISSIVE_TEXTURE_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
texture ID
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_BASE_COLOR_TEXTURE_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
texture ID
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_NORMAL_MAP_TEXTURE_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
texture ID
XR_SECURE_MR_GLTF_OPERATOR_ATTRIBUTE_MATERIAL_METALLIC_ROUGHNESS_TEXTURE_PICO
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
1
texture ID
In the above table, "texture ID" refers to the either the texture's index specified in the original glTF json file, or the results from operators of type
XR_SECURE_MR_OPERATOR_TYPE_LOAD_TEXTURE_PICO
-
XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
is a mixed-reality operator, to render text on a glTF object's one texture.Six operands are needed for this operator.
Applications can use the name "text" or index 0 to refer to the first operand. It is the content of the text to be rendered. The way it is rendered depends on the tensor's usage flag and datatype. If the usage flag is
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
, and the datatype is one character types, i.e. one ofXR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
, orXR_SECURE_MR_TENSOR_DATA_TYPE_INT8_PICO
, the operand content will be interpreted as a UTF-8 encoded string. If the usage flag isXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
, but the datatype is not any character types, the content will be rendered as an array of numeric values. If the usage flag isXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, the content will be rendered as matrices, where only the first 4 rows and columns, and the last row and the last column will be rendered if the matrix is too large. If the usage flag are others except forXR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
, the content will be rendered as an array of tuples. If the usage flag isXR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
, the content cannot be rendered, and the execution will be aborted.Applications can use the name "start" or index 1 to refer to the second operand, which is the starting XY coordinate on the target texture of the bottom-left tip of the first character's baseline. It should be of datatype
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The X and Y values should be scaled to 0~1, relative to the absolute width and height of the texture. The operand must have 1 channel and 1 dimension, and the dimension must of length 1, i.e. the operand can only have 1 value.Applications can use the name "color" or index 2 to refer to the third operand, which is text color and the background color in RGBA. The operand's usage flag must
XR_SECURE_MR_TENSOR_TYPE_COLOR_PICO
, with 4 channels for RGBA colors. The operand must have one dimension, and the length along the dimension must be 2, i.e. the operand must have two RGBA values, the first of which specifies the text color, whereas the second for the background color.Applications can use the name "gltf" or index 3 to refer to the fourth operand, which is the target glTF object. The operand must be a tensor with usage flag
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
.Applications can use the name "texture ID" or index 4 to refer to the fifth operand, specifying the target texture on which the text will be rendered. The operand must be a 1-channel 1-dimensional tensor, with the length along the only dimension to be 1, i.e. the tensor can only have 1 value. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
. The usage flag must beXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
.Additionally, the target texture size in pixels must match the canvas size set via XrSecureMrOperatorRenderTextPICO when the operator is created.
Applications can use the name "font size" or index 5 to refer to the sixth operand, specifying the text font size The operand must be a 1-channel 1-dimensional tensor, with the length along the only dimension to be 1, i.e. the tensor can only have 1 value. The datatype must be
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO
orXR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO
. The usage flag must beXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
.Applications must set tensors to all six operands.
XR_SECURE_MR_OPERATOR_TYPE_LOAD_TEXTURE_PICO
-
An operator of type
XR_SECURE_MR_OPERATOR_TYPE_LOAD_TEXTURE_PICO
is a mixed-reality operator for loading a batch of textures to glTF dynamically from a tensor.The operator can be found useful under scenarios such as: using an AIGC algorithm to generate a picture, and attaching the picture to a glTF object for presentation; or preparing a blank texture for text rendering using an operator of type
XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
.The operator has two operands and a result.
Applications can use the name "gltf" or index 0 to refer to the first operand, which is the target glTF object. The operand must be a tensor with usage flag
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO
.Applications can use the name "rgb image" or index 1 to refer to the second operand, which is the tensor from which the textures will be created. The operand must be of 3 or 4 channels, for RGB textures or RGBA textures respectively. The datatype of the operand must be
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO
. Its usage flag must beXR_SECURE_MR_TENSOR_TYPE_MAT_PICO
. The tensor must have 3 dimensions:(N, HEIGHT, WIDTH)
whereN
is the number of textures to be created in this batch, or have 2 dimensions:(HEIGHT, WIDTH)
ifN
= 1.HEIGHT
andWIDTH
will be the textures' sizes.Applications must set tensors for both operands.
The operator has one result.
Applications can use the name "texture ID" or index 0 to refer to the only result, which stores the IDs corresponding to each newly created texture in the batch. The IDs can thereafter be used in other mixed-reality operators of type
XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
, orXR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
to refer to certain textures.The result must be of 1-channel and have one dimension. The length along this dimension must match the
N
of operand "rgb image". The datatype must beXR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO
, and the usage flag must beXR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
.Note: the operator only creates a texture, but the texture is by default not bound to any glTF material so will not be visible. Applications can use operators of type
XR_SECURE_MR_OPERATOR_TYPE_UPDATE_GLTF_PICO
to bind the returned texture ID to material attributes.
12.10.5. Tensor
All the data in the pipelines are in the form of Tensors, including the multi-dimensional arrays such as scalars or matrices, and the glTF objects to be rendered.
It is said in the section for operators that tensors inside a pipeline pass data between operators, from one's results to another's operands. These tensors are the pipelines' local tensors. Pipelines can be executed in parallel at different threads. Thus, apart from the local tensors, we will also need a mechanism to safely share data among the pipelines across threads: the global tensors.
A global tensor is defined independently of any pipeline. Conversely, a local tensor is only valid within the pipeline where it is created.
For thread safety concerns, we make the following rule: an operator in a pipeline can only use the local tensors created in the same pipeline as its operands or results. Thus, we need a broker between a pipeline's local scope and the global scope: the placeholders.
Placeholders are a special type of local tensors. They behave in exactly the same manner, created inside a pipeline and able to be used as operators' operands or results. However, a placeholder holds no data and has no underlying storage. Instead, it is a reference to some compatible global tensor. Writing to a placeholder will in fact write to the global tensor it is referring to. Similarly, reading from a placeholder will access the data stored in the connected global tensor.
When a pipeline is submitted and schedule for one pipeline run, a mapping from its local placeholder to the global tensors is expected to be determined. The mapping will only be valid for this pipeline run. Thus, developers can dynamically alter the mapping, so that the same pipeline can be re-submit multiple times, but run on different inputs and outputs.
Global Tensor
// Provided by XR_PICO_secure_mixed_reality
XR_DEFINE_HANDLE(XrSecureMrTensorPICO)
The xrCreateSecureMrTensorPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrCreateSecureMrTensorPICO(
XrSecureMrFrameworkPICO framework,
const XrSecureMrTensorCreateInfoBaseHeaderPICO* createInfo,
XrSecureMrTensorPICO* globalTensor);
placeHolder
of createInfo
must be false, for global tensors'
creation.
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrTensorCreateInfoBaseHeaderPICO {
XrStructureType type;
const void* next;
XrBool32 placeHolder;
} XrSecureMrTensorCreateInfoBaseHeaderPICO;
The XrSecureMrTensorCreateInfoBaseHeaderPICO structure is the base tensor create info.
Two structures: sline:XrSecureMrTensorCreateInfoShapePICO and XrSecureMrTensorCreateInfoGltfPICO extend the XrSecureMrTensorCreateInfoBaseHeaderPICO, for creating standard multi-dimensional tensors (a.k.a. the "shape" tensors), and glTF tensors specially for mixed-reality effects.
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrTensorCreateInfoShapePICO {
XrStructureType type;
const void* next;
XrBool32 placeHolder;
uint32_t dimensionsCount;
void* dimensions;
XrSecureMrTensorFormatPICO* format;
} XrSecureMrTensorCreateInfoShapePICO;
The number of elements contained by a multi-dimensional tensor equals the
multiplications of sizes along every dimension, i.e. the multiplication of
values in array dimensions
in the
XrSecureMrTensorCreateInfoShapePICO.
Each element consists of channel
values of type datatype
.
For example, an 128x128 tensor storing a R8G8B8A8
image has 16384
elements, and each element can be a 4 uint8
values, where 4 is the number
of channels, and uint8
being the datatype.
Applications should pass in XrSecureMrTensorCreateInfoShapePICO pointer when calling xrCreateSecureMrTensorPICO if want to create an shape tensor.
Supported datatypes are:
typedef enum XrSecureMrTensorDataTypePICO {
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT8_PICO = 1,
XR_SECURE_MR_TENSOR_DATA_TYPE_INT8_PICO = 2,
XR_SECURE_MR_TENSOR_DATA_TYPE_UINT16_PICO = 3,
XR_SECURE_MR_TENSOR_DATA_TYPE_INT16_PICO = 4,
XR_SECURE_MR_TENSOR_DATA_TYPE_INT32_PICO = 5,
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT32_PICO = 6,
XR_SECURE_MR_TENSOR_DATA_TYPE_FLOAT64_PICO = 7,
XR_SECURE_MR_TENSOR_DATA_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrTensorDataTypePICO;
Enum | Description |
---|---|
|
indicating the data type is uint8 |
|
indicating the data type is int8 |
|
indicating the data type is uint16 |
|
indicating the data type is int16 |
|
indicating the data type is int32 |
|
indicating the data type is float32 |
|
indicating the data type is float64 |
Listed below are the usage flags for tensors, which is an attribute for
tensor creation via format
in
XrSecureMrTensorCreateInfoShapePICO.
typedef enum XrSecureMrTensorTypePICO {
XR_SECURE_MR_TENSOR_TYPE_POINT_PICO = 1,
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO = 2,
XR_SECURE_MR_TENSOR_TYPE_SLICE_PICO = 3,
XR_SECURE_MR_TENSOR_TYPE_COLOR_PICO = 4,
XR_SECURE_MR_TENSOR_TYPE_TIMESTAMP_PICO = 5,
XR_SECURE_MR_TENSOR_TYPE_MAT_PICO = 6,
XR_SECURE_MR_TENSOR_TYPE_GLTF_PICO = 7,
XR_SECURE_MR_TENSOR_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrSecureMrTensorTypePICO;
Usage flags indicate to the predefined and mixed-reality operators how the content of a tensor will be interpreted.
Enum | Description |
---|---|
|
indicating the tensor will be used as point; this restricts the channel of tensor to be either 2 or 3 |
|
indicating the tensor will be used as scalar; this restricts the channel of tensor to be 1 only |
|
indicating the tensor will be used as slice; this restricts the channel of tensor to be either 2 (START, END) or 3 (START, END, SKIP) |
|
indicating the tensor will be used as color; this restricts the channel of tensor to be either 3 (RGB) or 4 (RGBA); the datatype must be one of integral types |
|
indicating the tensor will be used as timestamp; this restricts the channel of tensor to be 4, and the datatype to be INT32 only |
|
indicating the tensor will be used as matrix |
|
indicating the tensor will be used as glTF object |
The XrSecureMrTensorFormatPICO structure defined below describes the
format of the tensor, consisting of three attributes: data type, channel and
a tensorType
flag to describe the tensor's usage.
typedef struct XrSecureMrTensorFormatPICO {
XrSecureMrTensorDataTypePICO dataType;
int8_t channel;
XrSecureMrTensorTypePICO tensorType;
} XrSecureMrTensorFormatPICO;
Consistent with OpenCV's convention, the channel attribute is not a part of
the tensor dimensions.
A 3-dimensional single-channel tensor with shape (1024, 512, 3)
is
different from a 2-dimensional 3-channel tensor with shape (1024, 512)
.
The former can be regarded as 1024 matrices of shape 512x3, while the latter
is a single 1024x512 matrix, but each element has three components, such as
X, Y and Z, or R, G, and B.
The tensor's usage flag, determined by the tensorType
attribute,
affects the way the tensor is to be used by the operators, especially in the
predefined CPU ones.
Take a 3-dimensional single-channel tensor with shape (10, 4, 3)
as an
example.
If the usage is XR_SECURE_MR_TENSOR_TYPE_MAT_PICO
, the tensor will be
treated as 10 matrices of shape 4x3.
However, the usage is XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
, it will be
regarded as a collection of 120 (=10x4x3) separated values.
This can lead to differences in the outcome of the same operators.
For instance, a render-text operator of type
XR_SECURE_MR_OPERATOR_TYPE_RENDER_TEXT_PICO
, if the operand to be
rendered is marked to be used as scalars (tensorType
=
XR_SECURE_MR_TENSOR_TYPE_SCALAR_PICO
), will render the tensor content
as a multi-line UTF-8 encoded string.
Otherwise, the same operator will render the raw values from the tensor in
digits.
A glTF object to be rendered for mixed-reality effects is also represented as a tensor. XrSecureMrTensorCreateInfoGltfPICO specifies information to create such a "renderable" tensor from a loaded glTF file.
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrTensorCreateInfoGltfPICO {
XrStructureType type;
const void* next;
XrBool32 placeHolder;
uint32_t bufferSize;
void* buffer;
} XrSecureMrTensorCreateInfoGltfPICO;
Applications can use XrSecureMrTensorCreateInfoGltfPICO to load a glTF
file already read to memory as a glTF tensor.
The glTF file cannot be of a binary glb
format.
Textures must be embedded in it and cannot use external URI links.
Creating a glTF tensor is a time-consuming operation, so applications should not create the glTF tensor in time sensitive threads. Local glTF tensors in pipelines must be placeholders. Applications should not create non-placeholder glTF local tensors in pipelines.
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrTensorBufferPICO {
XrStructureType type;
const void* next;
uint32_t bufferSize;
void* buffer;
} XrSecureMrTensorBufferPICO;
The XrSecureMrTensorBufferPICO structure describes the buffer of the tensor's content.
The xrResetSecureMrTensorPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrResetSecureMrTensorPICO(
XrSecureMrTensorPICO tensor,
XrSecureMrTensorBufferPICO* tensorBuffer);
Applications can set or reset the content of a non-glTF global tensor by using xrResetSecureMrTensorPICO.
Applications must not reset the content of a glTF global tensor.
The tensor's new content described by tensorBuffer
must have
bufferSize
equal to the size of target tensor's datatype, or the multiple
of the target tensor's element size (the tensor's channel times the size
of its datatype), but not exceeding the total size of the tensor
(multiplication of the tensor's all dimensions, times its channels, times
its datatype size).
The xrDestroySecureMrTensorPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrDestroySecureMrTensorPICO(
XrSecureMrTensorPICO globalTensor);
The XrSecureMrTensorPICO can be destroyed. Applications should destroy the tensor when it is no longer needed.
Pipeline tensor
// Provided by XR_PICO_secure_mixed_reality
XR_DEFINE_OPAQUE_64(XrSecureMrPipelineTensorPICO)
The xrCreateSecureMrPipelineTensorPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrCreateSecureMrPipelineTensorPICO(
XrSecureMrPipelinePICO pipeline,
const XrSecureMrTensorCreateInfoBaseHeaderPICO* createInfo,
XrSecureMrPipelineTensorPICO* pipelineTensor);
Pipeline tensor are only valid within the XrSecureMrPipelinePICO
specified by pipeline
during its creation.
Applications can create different types of tensor by passing in different
createInfo like the XrSecureMrTensorPICO.
Applications must not create a non-placeholder glTF pipeline tensor, as
glTF tensor must either be a global tensor, or a pipeline placeholder.
The xrResetSecureMrPipelineTensorPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrResetSecureMrPipelineTensorPICO(
XrSecureMrPipelinePICO pipeline,
XrSecureMrPipelineTensorPICO tensor,
XrSecureMrTensorBufferPICO* tensorBuffer);
Applications can reset an XrSecureMrPipelineTensorPICO
by calling
xrResetSecureMrPipelineTensorPICO, similar to resetting a global
tensor's content.
The tensor's new content described by tensorBuffer
must have
bufferSize
equal to the size of target tensor's datatype, or the multiple
of the target tensor's element size (the tensor's channel times the size
of its datatype), but not exceeding the total size of the tensor
(multiplication of the tensor's all dimensions, times its channels, times
its datatype size).
12.10.6. Use pipeline tensors as operands and results of operators
You can pass any XrSecureMrPipelineTensorPICO
into an operator as
an operand by calling xrSetSecureMrOperatorOperandByNamePICO or
xrSetSecureMrOperatorOperandByIndexPICO.
Applications can use either function to set tensors to operands.
Applications must never use global XrSecureMrTensorPICO as an
operator’s operands or results.
Global tensors must be mapped to pipeline placeholder tensors via
XrSecureMrPipelineIOPairPICO before being accessed by an operator.
The xrSetSecureMrOperatorOperandByNamePICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrSetSecureMrOperatorOperandByNamePICO(
XrSecureMrPipelinePICO pipeline,
XrSecureMrOperatorPICO tensorOperator,
XrSecureMrPipelineTensorPICO pipelineTensor,
const char* inputName);
Applications can use xrSetSecureMrOperatorOperandByNamePICO to set the operand by name.
inputName
must be a valid operand name of the target operator.
If the operator is a customized one created from a binary algorithm package,
the inputName
must match one operatorIOName
of
XrSecureMrOperatorIOMapPICO provided among modelInputs
of
XrSecureMrOperatorModelPICO when the operator is created.
If the operator is a predefined one, such as a preprocessing, postprocessing
or mixed-reality operator provided by this extension, the inputName
must match one of the predefined operand names of the operator.
pipelineTensor
must match with the desired operand's requirements in
terms of its dimensions, channel, datatype and usage.
The xrSetSecureMrOperatorOperandByIndexPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrSetSecureMrOperatorOperandByIndexPICO(
XrSecureMrPipelinePICO pipeline,
XrSecureMrOperatorPICO tensorOperator,
XrSecureMrPipelineTensorPICO pipelineTensor,
int32_t index);
Applications can use xrSetSecureMrOperatorOperandByIndexPICO to set the operand by indices.
index
must be a valid operand index of the target operator.
If the operator is a customized one created from a binary algorithm package,
the index
must be smaller than modelInputCount
of
XrSecureMrOperatorModelPICO when the operator is created.
If the operator is a predefined one, such as a preprocessing, postprocessing
or mixed-reality operator provided by this extension, the index
must
be smaller than number of the operands of this operator.
pipelineTensor
must match with the desired operand's requirements in
terms of its dimensions, channel, datatype and usage.
The xrSetSecureMrOperatorResultByNamePICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrSetSecureMrOperatorResultByNamePICO(
XrSecureMrPipelinePICO pipeline,
XrSecureMrOperatorPICO tensorOperator,
XrSecureMrPipelineTensorPICO pipelineTensor,
const char* name);
Applications can use xrSetSecureMrOperatorResultByNamePICO to set the result by name.
name
must be a valid result name of the target operator.
If the operator is a customized one created from a binary algorithm package,
the name
must match one operatorIOName
of
XrSecureMrOperatorIOMapPICO provided among modelOutputs
of
XrSecureMrOperatorModelPICO when the operator is created.
If the operator is a predefined one, such as a preprocessing, postprocessing
or mixed-reality operator provided by this extension, the name
must
match one predefined result name of the operator.
pipelineTensor
must match with the desired result's requirements in
terms of its dimensions, channel, datatype and usage.
The xrSetSecureMrOperatorResultByIndexPICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrSetSecureMrOperatorResultByIndexPICO(
XrSecureMrPipelinePICO pipeline,
XrSecureMrOperatorPICO tensorOperator,
XrSecureMrPipelineTensorPICO pipelineTensor,
int32_t index);
Applications can use xrSetSecureMrOperatorResultByIndexPICO to set the result by indices.
index
must be a valid operand index of the target operator.
If the operator is a customized one created from a binary algorithm package,
the index
must be smaller than modelOutputCount
of
XrSecureMrOperatorModelPICO when the operator is created.
If the operator is a predefined one, such as a preprocessing, postprocessing
or mixed-reality operator provided by this extension, the index
must
be smaller than number of the results of this operator.
pipelineTensor
must match with the desired operand's requirements in
terms of its dimensions, channel, datatype and usage.
Execute pipeline
// Provided by XR_PICO_secure_mixed_reality
#define XR_PIPELINE_RUN_IDLE_PICO 0
XR_PIPELINE_RUN_IDLE_PICO defines a basetype, which is an opaque 64 bit value, which may be implemented as an opaque, distinct pointer type on platforms with 64-bit pointers.
After we set up a pipeline, we can schedule it to be executed.
Applications can submit the pipeline for one execution by calling
xrExecuteSecureMrPipelinePICO.
The submitted execution can be further referred to via
XrSecureMrPipelineRunPICO
.
Applications can use XrSecureMrPipelineRunPICO
to specify the
dependency of different pipeline executions.
// Provided by XR_PICO_secure_mixed_reality
XR_DEFINE_OPAQUE_64(XrSecureMrPipelineRunPICO)
The xrExecuteSecureMrPipelinePICO function is defined as:
// Provided by XR_PICO_secure_mixed_reality
XrResult xrExecuteSecureMrPipelinePICO(
XrSecureMrPipelinePICO pipeline,
const XrSecureMrPipelineExecuteParameterPICO* parameter,
XrSecureMrPipelineRunPICO* pipelineRun);
Applications can submit the pipeline for one execution by calling xrExecuteSecureMrPipelinePICO.
Applications can submit the same pipeline multiple times.
Applications can submit the same pipeline even if there is another execution scheduled from the same pipeline. The executions from the same pipeline will be executed in sequence, in the order they are submitted.
Executions from the same pipeline will not be conducted concurrently.
Applications can pass in different parameters for different purposes.
Applications can map global tensors to pipeline's local placeholders so
that the operators inside the pipeline can access the shared data from other
pipelines, via pipelineIOPair
of parameter
.
Applications can map different global tensors to pipeline's local
placeholders to reuse the same pipeline on different input or output data,
as the mapping specified by pipelineIOPair
of parameter
are only
valid for one pipeline execution.
The submitted pipeline execution will be conducted after all executions of
the same pipeline submitted before it has been completed, and its
prerequisite pipeline execution specified by pipelineRunToBeWaited
of
parameter
has been completed, and there is no other pipeline execution
concurrently writing to the global tensors this pipeline execution is
accessing through pipelineIOPair
of parameter
, and there is no other
pipeline execution concurrently accessing the global tensors the pipeline
execution will write through pipelineIOPair
of parameter
.
If the application want to execute the pipeline as soon as possible, they
can pass in XR_PIPELINE_RUN_IDLE_PICO as pipelineRunToBeWaited
of
parameter
.
Applications can also execute a pipeline conditionally depending on the
value of a global tensor by setting conditionTensor
of parameter
.
The pipeline execution will be aborted if the global tensor specified by
conditionTensor
of parameter
is all zero.
Applications can set conditionTensor
of parameter
to be null if the
pipeline execution shall not be aborted on any occasion.
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrPipelineExecuteParameterPICO {
XrStructureType type;
const void* next;
XrSecureMrPipelineRunPICO pipelineRunToBeWaited;
XrSecureMrTensorPICO conditionTensor;
uint32_t pairCount;
XrSecureMrPipelineIOPairPICO* pipelineIOPair;
} XrSecureMrPipelineExecuteParameterPICO;
// Provided by XR_PICO_secure_mixed_reality
typedef struct XrSecureMrPipelineIOPairPICO {
XrStructureType type;
const void* next;
XrSecureMrPipelineTensorPICO localPlaceHolderTensor;
XrSecureMrTensorPICO globalTensor;
} XrSecureMrPipelineIOPairPICO;
Applications must set the localPlaceHolderTensor
to be a pipeline’s
local tensor whose placeHolder
of
XrSecureMrTensorCreateInfoBaseHeaderPICO during its creation is true.
Applications must set the localPlaceHolderTensor
to be a placeholder
tensor local to the pipeline
of xrExecuteSecureMrPipelinePICO.
Applications must set the globalTensor
to be a global tensor of the
same dimensions, channel, datatype and usage as the local tensor.
12.10.12. New Enum Constants
-
XR_MAX_ARITHMETIC_COMPOSE_OPERATOR_CONFIG_LENGTH_PICO
-
XR_MAX_OPERATOR_NODE_NAME_PICO
-
XR_PICO_SECURE_MIXED_REALITY_EXTENSION_NAME
-
XR_PICO_secure_mixed_reality_SPEC_VERSION
-
Extending XrObjectType:
-
XR_OBJECT_TYPE_SECURE_MR_FRAMEWORK_PICO
-
XR_OBJECT_TYPE_SECURE_MR_PIPELINE_PICO
-
XR_OBJECT_TYPE_SECURE_MR_TENSOR_PICO
-
-
Extending XrResult:
-
XR_ERROR_SECURE_MR_INVALID_PARAM_PICO
-
XR_ERROR_SECURE_MR_OTHER_INTERNAL_ERROR_PICO
-
XR_ERROR_SECURE_MR_PIPELINE_LOCKED_PICO
-
XR_ERROR_SECURE_MR_UNREGISTERED_HANDLE_PICO
-
XR_ERROR_SECURE_MR_USAGE_BEFORE_INIT_PICO
-
-
Extending XrStructureType:
-
XR_TYPE_SECURE_MR_FRAMEWORK_CREATE_INFO_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_ARITHMETIC_COMPOSE_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_BASE_HEADER_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_COLOR_CONVERT_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_COMPARISON_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_CREATE_INFO_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_IO_MAP_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_MODEL_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_NON_MAXIMUM_SUPPRESSION_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_NORMALIZE_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_RENDER_TEXT_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_SORT_MATRIX_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_UPDATE_GLTF_PICO
-
XR_TYPE_SECURE_MR_OPERATOR_UV_TO_3D_PICO
-
XR_TYPE_SECURE_MR_PIPELINE_CREATE_INFO_PICO
-
XR_TYPE_SECURE_MR_PIPELINE_EXECUTE_PARAMETER_PICO
-
XR_TYPE_SECURE_MR_PIPELINE_IO_PAIR_PICO
-
XR_TYPE_SECURE_MR_TENSOR_BUFFER_PICO
-
XR_TYPE_SECURE_MR_TENSOR_CREATE_INFO_BASE_HEADER_PICO
-
XR_TYPE_SECURE_MR_TENSOR_CREATE_INFO_GLTF_PICO
-
XR_TYPE_SECURE_MR_TENSOR_CREATE_INFO_SHAPE_PICO
-
Version History
-
Revision 1, 2024-10-11 (Shuai Liu)
-
Initial extension description
-
12.11. XR_PICO_virtual_boundary
- Name String
-
XR_PICO_virtual_boundary
- Extension Type
-
Instance extension
- Registered Extension Number
-
10002
- Revision
-
1
- Extension and Version Dependencies
- Contributors
-
Johnson Zhang, Bytedance
Overview
This extension allows an application to set virtual boundary disable/visible/seeThroughVisible, get virtual boundary status and triggerData.
New Object Types
New Flag Types
New Enum Constants
New Enums
The XrVirtualBoundaryModePICO describes which mode of virtual boundary when call xrGetVirtualBoundaryModePICO.
// Provided by XR_PICO_virtual_boundary
typedef enum XrVirtualBoundaryModePICO {
XR_VIRTUAL_BOUNDARY_MODE_STATIONARY_PICO = 0,
XR_VIRTUAL_BOUNDARY_MODE_CUSTOM_PICO = 1,
XR_VIRTUAL_BOUNDARY_MODE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrVirtualBoundaryModePICO;
The XrVirtualBoundaryEdgeTypePICO describes which edge type of virtual boundary.
// Provided by XR_PICO_virtual_boundary
typedef enum XrVirtualBoundaryEdgeTypePICO {
XR_VIRTUAL_BOUNDARY_EDGE_TYPE_OUTER_CONTOUR_PICO = 0,
XR_VIRTUAL_BOUNDARY_EDGE_TYPE_INSCRIBED_RECTANGLE_PICO = 1,
XR_VIRTUAL_BOUNDARY_EDGE_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrVirtualBoundaryEdgeTypePICO;
The XrVirtualBoundaryTriggerNodeTypePICO describes whether the node is trigger virtual boundary when call xrGetVirtualBoundaryTriggerPICO.
// Provided by XR_PICO_virtual_boundary
typedef enum XrVirtualBoundaryTriggerNodeTypePICO {
XR_VIRTUAL_BOUNDARY_TRIGGER_NODE_TYPE_LEFT_HAND_PICO = 0,
XR_VIRTUAL_BOUNDARY_TRIGGER_NODE_TYPE_RIGHT_HAND_PICO = 1,
XR_VIRTUAL_BOUNDARY_TRIGGER_NODE_TYPE_HEAD_PICO = 2,
XR_VIRTUAL_BOUNDARY_TRIGGER_NODE_TYPE_MAX_ENUM_PICO = 0x7FFFFFFF
} XrVirtualBoundaryTriggerNodeTypePICO;
New Structures
The XrVirtualBoundaryInfoPICO structure is described as follows:
// Provided by XR_PICO_virtual_boundary
typedef struct XrVirtualBoundaryInfoPICO {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrVirtualBoundaryEdgeTypePICO edgeType;
} XrVirtualBoundaryInfoPICO;
The XrVirtualBoundaryInfoPICO structure describes the information to get boundary geometry / trigger node /trigger point.
The XrVirtualBoundaryTriggerNodePICO structure is defined as:
// Provided by XR_PICO_virtual_boundary
typedef struct XrVirtualBoundaryTriggerNodePICO {
XrStructureType type;
void* next;
XrVirtualBoundaryInfoPICO* boundaryInfo;
XrVirtualBoundaryTriggerNodeTypePICO node;
} XrVirtualBoundaryTriggerNodePICO;
The XrVirtualBoundaryTriggerPointPICO structure is defined as:
// Provided by XR_PICO_virtual_boundary
typedef struct XrVirtualBoundaryTriggerPointPICO {
XrStructureType type;
void* next;
XrVirtualBoundaryInfoPICO* boundaryInfo;
XrVector3f point;
} XrVirtualBoundaryTriggerPointPICO;
The XrVirtualBoundaryTriggerBaseHeaderPICO structure is defined as:
// Provided by XR_PICO_virtual_boundary
typedef struct XrVirtualBoundaryTriggerBaseHeaderPICO {
XrStructureType type;
void* next;
XrVirtualBoundaryInfoPICO* boundaryInfo;
} XrVirtualBoundaryTriggerBaseHeaderPICO;
The XrVirtualBoundaryTriggerBaseHeaderPICO is a base structure that
can be overridden by a XrVirtualBoundaryTrigger*
child structure.
The XrVirtualBoundaryStatusPICO structure is defined as:
typedef struct XrVirtualBoundaryStatusPICO {
XrStructureType type;
void* next;
XrBool32 isReady;
XrBool32 isEnabled;
XrBool32 isVisible;
} XrVirtualBoundaryStatusPICO;
The XrVirtualBoundaryTriggerPICO structure is defined as:
typedef struct XrVirtualBoundaryTriggerPICO {
XrStructureType type;
void* next;
XrBool32 isTriggering;
XrBool32 isValid;
float closestDistance;
XrVector3f closestPoint;
XrVector3f closestPointNormal;
} XrVirtualBoundaryTriggerPICO;
New Functions
The xrGetVirtualBoundaryModePICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrGetVirtualBoundaryModePICO(
XrSession session,
XrVirtualBoundaryModePICO* mode);
Applications can use this function to get mode of virtual boundary.
The xrGetVirtualBoundaryStatusPICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrGetVirtualBoundaryStatusPICO(
XrSession session,
XrVirtualBoundaryStatusPICO* status);
Applications can use this function get virtual boundary status.
The xrSetVirtualBoundaryEnablePICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrSetVirtualBoundaryEnablePICO(
XrSession session,
XrBool32 enable);
Applications can use this function set virtual boundary disable or enable.
The xrSetVirtualBoundaryVisiblePICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrSetVirtualBoundaryVisiblePICO(
XrSession session,
XrBool32 visible);
Applications can use this function set virtual boundary visible or disvisible.
The xrGetVirtualBoundaryGeometryPICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrGetVirtualBoundaryGeometryPICO(
XrSession session,
const XrVirtualBoundaryInfoPICO* boundaryInfo,
uint32_t geometryCapacityInput,
uint32_t* geometryCountOutput,
XrVector3f* geometries);
Applications can use this function get virtual boundary geometry.
The xrGetVirtualBoundaryTriggerPICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrGetVirtualBoundaryTriggerPICO(
XrSession session,
const XrVirtualBoundaryTriggerBaseHeaderPICO* triggerInfo,
XrVirtualBoundaryTriggerPICO* boundaryTrigger);
Applications can use this function get the node or point whether triggered virtual boundary.
The xrSetVirtualBoundarySeeThroughVisiblePICO function is defined as:
// Provided by XR_PICO_virtual_boundary
XrResult xrSetVirtualBoundarySeeThroughVisiblePICO(
XrSession session,
XrBool32 visible);
Applications can use this function set seethrough visible or not.
12.11.1. Example code
/*****************************************/
/* xrGetVirtualBoundaryGeometryPICO */
/*****************************************/
XrInstance instance; // previously initialized
XrSession session; // previously initialized
XrSpace refSpace; // previously initialized
PFN_xrGetVirtualBoundaryGeometryPICO xrGetVirtualBoundaryGeometryPICO;
CHK_XR(xrGetInstanceProcAddr(instance, "xrGetVirtualBoundaryGeometryPICO",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrGetVirtualBoundaryGeometryPICO)));
PFN_xrGetVirtualBoundaryTriggerPICO xrGetVirtualBoundaryTriggerPICO;
CHK_XR(xrGetInstanceProcAddr(instance, "xrGetVirtualBoundaryTriggerPICO",
reinterpret_cast<PFN_xrVoidFunction*>(
&xrGetVirtualBoundaryTriggerPICO)));
XrVirtualBoundaryInfoPICO boundaryInfoPico{XR_TYPE_VIRTUAL_BOUNDARY_INFO_PICO,NULL,refSpace,XR_VIRTUAL_BOUNDARY_EDGE_TYPE_OUTER_CONTOUR_PICO};
uint32_t geometryCapacityOutput = 0;
CHK_XR(xrGetVirtualBoundaryGeometryPICO(session, &boundaryInfoPico, 0, &geometryCapacityOutput, NULL));
XrVector3f* geometries = new XrVector3f[geometryCapacityOutput];
CHK_XR(xrGetVirtualBoundaryGeometryPICO(session, &boundaryInfoPico, geometryCapacityOutput, &geometryCapacityOutput, geometries));
//do something with geometries
delete[] geometries;
/*****************************************/
/* xrGetVirtualBoundaryTriggerPICO Node */
/*****************************************/
XrVirtualBoundaryTriggerPICO boundaryTriggerPico{XR_TYPE_VIRTUAL_BOUNDARY_TRIGGER_PICO};
XrVirtualBoundaryTriggerNodePICO triggerNodePico{XR_TYPE_VIRTUAL_BOUNDARY_TRIGGER_NODE_PICO,NULL,&boundaryInfoPico,XR_VIRTUAL_BOUNDARY_TRIGGER_NODE_TYPE_LEFT_HAND_PICO};
xrGetVirtualBoundaryTriggerPICO(session,(XrVirtualBoundaryTriggerBaseHeaderPICO*)&triggerNodePico,&boundaryTriggerPico);
/*****************************************/
/* xrGetVirtualBoundaryTriggerPICO POINT */
/*****************************************/
XrVector3f point;// previously initialized
XrVirtualBoundaryTriggerPointPICO triggerPointPico{XR_TYPE_VIRTUAL_BOUNDARY_TRIGGER_POINT_PICO,NULL,&boundaryInfoPico};
triggerPointPico.point = point;
xrGetVirtualBoundaryTriggerPICO(session,(XrVirtualBoundaryTriggerBaseHeaderPICO*)&triggerPointPico,&boundaryTriggerPico);
Version History
-
Revision 1, 2024-09-4 (Johnson Zhang)
-
Initial extension description
-
13. Core Revisions (Informative)
New minor versions of the OpenXR API are defined periodically by the Khronos OpenXR Working Group. These consist of some amount of additional functionality added to the core API, potentially including both new functionality and functionality promoted from extensions.
13.1. Version 1.1
13.1.1. OpenXR 1.1 Promotions
OpenXR version 1.1 promoted a number of key extensions into the core API:
-
XR_KHR_locate_spaces
-
XR_KHR_maintenance1
-
XR_EXT_hp_mixed_reality_controller
-
XR_EXT_local_floor
-
XR_EXT_palm_pose
-
XR_EXT_samsung_odyssey_controller
-
XR_EXT_uuid
-
XR_BD_controller_interaction
-
XR_FB_touch_controller_pro
-
XR_HTC_vive_cosmos_controller_interaction
-
XR_HTC_vive_focus3_controller_interaction
-
XR_META_touch_controller_plus
-
XR_ML_ml2_controller_interaction
-
XR_VARJO_quad_views
All differences in behavior between these extensions and the corresponding OpenXR 1.1 functionality are summarized below.
Differences Relative to XR_EXT_local_floor
XR_EXT_local_floor
The definition of this space was made more precise, and it was clarified
that the mandatory support of this space does not dictate any particular
quality of floor level estimation.
Applications that can provide a head-relative interaction experience in the
absence of a defined stage continue to use LOCAL
space, while those that
need higher quality assertions about floor level continue to use STAGE
space or scene understanding extensions to detect floor level.
The (mandatory) presence of this space when enumerating reference spaces is
a convenience for portability rather than an assertion that e.g. floor
detection scene understanding has taken place or that the floor is
inherently walkable.
Differences Relative to XR_EXT_palm_pose
XR_EXT_palm_pose
The input identifier palm_ext
defined in the extension has been renamed to
grip_surface
to more clearly describe its intended use and distinguish it
from hand tracking.
Differences Relative to XR_VARJO_quad_views
XR_VARJO_quad_views
The view configuration type enumerant
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO
was renamed to
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET
, to
clarify that it is not vendor-specific nor the only way four views are
possible.
In OpenXR 1.1, a runtime may support
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET
, but
this is optional like the other view configuration types.
Use xrEnumerateViewConfigurations to determine if it is provided,
rather than using the presence or absence of the extension.
Differences Relative to XR_FB_touch_controller_pro
XR_FB_touch_controller_pro
The interaction profile path was changed from /interaction_profiles/facebook/touch_controller_pro to /interaction_profiles/meta/touch_pro_controller. Note the updated company name and different word order in the device name level.
The following input/output subpaths were renamed when changing to this new interaction profile path:
-
…/input/stylus_fb/force → …/input/stylus/force
-
…/input/trigger/proximity_fb → …/input/trigger/proximity
-
…/output/haptic_trigger_fb → …/output/haptic_trigger
-
…/output/haptic_thumb_fb → …/output/haptic_thumb
-
…/input/thumb_fb/proximity_fb → …/input/thumb_resting_surfaces/proximity
-
…/input/trigger/curl_fb → …/input/trigger_curl/value
-
…/input/trigger/slide_fb → …/input/trigger_slide/value
The last two changes listed moved from being components on the trigger identifier to being independent identifiers in order to clarify how they relate to actions bound to other trigger components with regards to action priority.
Differences Relative to XR_META_touch_controller_plus
XR_META_touch_controller_plus
The interaction profile path was changed from /interaction_profiles/meta/touch_controller_plus to /interaction_profiles/meta/touch_plus_controller. Note the different word order in the device name level.
The following input subpaths were renamed when changing to this new interaction profile path: * …/input/trigger/proximity_meta → …/input/trigger/proximity * …/input/thumb_meta/proximity_meta → …/input/thumb_resting_surfaces/proximity * …/input/trigger/curl_meta → …/input/trigger_curl/value * …/input/trigger/slide_meta → …/input/trigger_slide/value
13.1.2. Additional OpenXR 1.1 Changes
In addition to the promoted extensions described above, OpenXR 1.1 changed the following:
-
Substantial clarifications in the input and fundamentals chapters, intended to be non-substantive.
-
Added the following legacy interaction profiles to represent specific controllers shipped under the Oculus/Meta Touch name and previously grouped into a single Oculus Touch interaction profile:
-
/interaction_profiles/meta/touch_controller_rift_cv1 - Meta Touch Controller (Rift CV1) Profile
-
/interaction_profiles/meta/touch_controller_quest_1_rift_s - Meta Touch Controller (Rift S / Quest 1) Profile
-
/interaction_profiles/meta/touch_controller_quest_2 - Meta Touch Controller (Quest 2) Profile
-
13.1.6. New Enum Constants
-
XR_UUID_SIZE
-
Extending XrReferenceSpaceType:
-
XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR
-
-
Extending XrResult:
-
XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED
-
XR_ERROR_PERMISSION_INSUFFICIENT
-
-
Extending XrStructureType:
-
XR_TYPE_SPACES_LOCATE_INFO
-
XR_TYPE_SPACE_LOCATIONS
-
XR_TYPE_SPACE_VELOCITIES
-
-
Extending XrViewConfigurationType:
-
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET
-
13.2. Loader Runtime and API Layer Negotiation Version 1.0
The OpenXR version 1.0.33 patch release included ratification of the runtime
and API layer negotiation API, associated with the identifier
XR_LOADER_VERSION_1_0
, substantially unchanged from the unratified
form previously described in the loader design document.
This interface is intended for use only between the loader, runtimes, and
API layers, and is not typically directly used by an application.
13.3. Version 1.0
OpenXR version 1.0 defined the initial core API.
13.3.4. New Structures
-
Extending XrSpaceLocation:
13.3.7. New Enum Constants
-
XR_FALSE
-
XR_MAX_API_LAYER_DESCRIPTION_SIZE
-
XR_MAX_API_LAYER_NAME_SIZE
-
XR_MAX_APPLICATION_NAME_SIZE
-
XR_MAX_ENGINE_NAME_SIZE
-
XR_MAX_EXTENSION_NAME_SIZE
-
XR_MAX_PATH_LENGTH
-
XR_MAX_RESULT_STRING_SIZE
-
XR_MAX_RUNTIME_NAME_SIZE
-
XR_MAX_STRUCTURE_NAME_SIZE
-
XR_MAX_SYSTEM_NAME_SIZE
-
XR_TRUE
Index
Flags and Flag Bits
-
XrCompositionLayerFlags — See also XrCompositionLayerFlagBits
-
XrEyeTrackerFlagsPICO — See also XrEyeTrackerFlagBitsPICO
-
XrEyeTrackerTrackingStateFlagsPICO — See also XrEyeTrackerTrackingStateFlagBitsPICO
-
XrInputSourceLocalizedNameFlags — See also XrInputSourceLocalizedNameFlagBits
-
XrInstanceCreateFlags — See also XrInstanceCreateFlagBits
-
XrLayerSettingsFlagsPICO — See also XrLayerSettingsFlagBitsPICO
-
XrSessionCreateFlags — See also XrSessionCreateFlagBits
-
XrSpaceAccelerationFlagsPICO — See also XrSpaceAccelerationFlagBitsPICO
-
XrSpaceLocationFlags — See also XrSpaceLocationFlagBits
-
XrSpaceVelocityFlags — See also XrSpaceVelocityFlagBits
-
XrSwapchainCreateFlags — See also XrSwapchainCreateFlagBits
-
XrSwapchainUsageFlags — See also XrSwapchainUsageFlagBits
-
XrViewStateFlags — See also XrViewStateFlagBits
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_FLOAT = 24,
XR_TYPE_ACTION_STATE_VECTOR2F = 25,
XR_TYPE_ACTION_STATE_POSE = 27,
XR_TYPE_ACTION_SET_CREATE_INFO = 28,
XR_TYPE_ACTION_CREATE_INFO = 29,
XR_TYPE_INSTANCE_PROPERTIES = 32,
XR_TYPE_FRAME_WAIT_INFO = 33,
XR_TYPE_COMPOSITION_LAYER_PROJECTION = 35,
XR_TYPE_COMPOSITION_LAYER_QUAD = 36,
XR_TYPE_REFERENCE_SPACE_CREATE_INFO = 37,
XR_TYPE_ACTION_SPACE_CREATE_INFO = 38,
XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING = 40,
XR_TYPE_VIEW_CONFIGURATION_VIEW = 41,
XR_TYPE_SPACE_LOCATION = 42,
XR_TYPE_SPACE_VELOCITY = 43,
XR_TYPE_FRAME_STATE = 44,
XR_TYPE_VIEW_CONFIGURATION_PROPERTIES = 45,
XR_TYPE_FRAME_BEGIN_INFO = 46,
XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW = 48,
XR_TYPE_EVENT_DATA_EVENTS_LOST = 49,
XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING = 51,
XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED = 52,
XR_TYPE_INTERACTION_PROFILE_STATE = 53,
XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO = 55,
XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO = 56,
XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO = 57,
XR_TYPE_ACTION_STATE_GET_INFO = 58,
XR_TYPE_HAPTIC_ACTION_INFO = 59,
XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO = 60,
XR_TYPE_ACTIONS_SYNC_INFO = 61,
XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO = 62,
XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO = 63,
// Provided by XR_VERSION_1_1
XR_TYPE_SPACES_LOCATE_INFO = 1000471000,
// Provided by XR_VERSION_1_1
XR_TYPE_SPACE_LOCATIONS = 1000471001,
// Provided by XR_VERSION_1_1
XR_TYPE_SPACE_VELOCITIES = 1000471002,
// Provided by XR_PICO_external_camera
XR_TYPE_EVENT_DATA_MRC_STATUS_CHANGED_PICO = 1010000000,
// Provided by XR_PICO_external_camera
XR_TYPE_MRC_SPACE_CREATE_INFO_PICO = 1010000001,
// Provided by XR_PICO_external_camera
XR_TYPE_EXTERNAL_CAMERA_PARAMETER_PICO = 1010000002,
// Provided by XR_PICO_virtual_boundary
XR_TYPE_VIRTUAL_BOUNDARY_INFO_PICO = 1010001001,
// Provided by XR_PICO_virtual_boundary
XR_TYPE_VIRTUAL_BOUNDARY_STATUS_PICO = 1010001002,
// Provided by XR_PICO_virtual_boundary
XR_TYPE_VIRTUAL_BOUNDARY_TRIGGER_NODE_PICO = 1010001003,
// Provided by XR_PICO_virtual_boundary
XR_TYPE_VIRTUAL_BOUNDARY_TRIGGER_POINT_PICO = 1010001004,
// Provided by XR_PICO_virtual_boundary
XR_TYPE_VIRTUAL_BOUNDARY_TRIGGER_PICO = 1010001005,
// Provided by XR_PICO_motion_tracking
XR_TYPE_MOTION_TRACKER_BATTERY_STATE_PICO = 1010002000,
// Provided by XR_PICO_motion_tracking
XR_TYPE_MOTION_TRACKER_LOCATION_INFO_PICO = 1010002001,
// Provided by XR_PICO_motion_tracking
XR_TYPE_MOTION_TRACKER_SPACE_LOCATION_PICO = 1010002002,
// Provided by XR_PICO_motion_tracking
XR_TYPE_MOTION_TRACKER_SPACE_VELOCITY_PICO = 1010002003,
// Provided by XR_PICO_motion_tracking
XR_TYPE_EVENT_DATA_REQUEST_MOTION_TRACKER_COMPLETE_PICO = 1010002004,
// Provided by XR_PICO_motion_tracking
XR_TYPE_EVENT_DATA_MOTION_TRACKER_CONNECTION_STATE_CHANGED_PICO = 1010002005,
// Provided by XR_PICO_motion_tracking
XR_TYPE_EVENT_DATA_MOTION_TRACKER_POWER_KEY_EVENT_PICO = 1010002006,
// Provided by XR_PICO_composition_layer_fisheye
XR_TYPE_COMPOSITION_LAYER_FISHEYE_PICO = 1010003000,
// Provided by XR_PICO_layer_settings
XR_TYPE_LAYER_SETTINGS_PICO = 1010004000,
// Provided by XR_PICO_eye_tracker
XR_TYPE_EYE_TRACKER_CREATE_INFO_PICO = 1010006000,
// Provided by XR_PICO_eye_tracker
XR_TYPE_EYE_TRACKER_DATA_INFO_PICO = 1010006001,
// Provided by XR_PICO_eye_tracker
XR_TYPE_EYE_TRACKER_DATA_PICO = 1010006002,
// Provided by XR_PICO_eye_tracker
XR_TYPE_EYE_DATA_PICO = 1010006003,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_FRAMEWORK_CREATE_INFO_PICO = 1010007000,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_PIPELINE_CREATE_INFO_PICO = 1010007001,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_BASE_HEADER_PICO = 1010007002,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_CREATE_INFO_PICO = 1010007003,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_MODEL_PICO = 1010007004,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_UPDATE_GLTF_PICO = 1010007005,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_RENDER_TEXT_PICO = 1010007006,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_ARITHMETIC_COMPOSE_PICO = 1010007007,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_COMPARISON_PICO = 1010007008,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_NORMALIZE_PICO = 1010007009,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_NON_MAXIMUM_SUPPRESSION_PICO = 1010007010,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_TENSOR_BUFFER_PICO = 1010007011,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_TENSOR_CREATE_INFO_BASE_HEADER_PICO = 1010007012,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_TENSOR_CREATE_INFO_SHAPE_PICO = 1010007013,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_TENSOR_CREATE_INFO_GLTF_PICO = 1010007014,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_UV_TO_3D_PICO = 1010007015,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_PIPELINE_EXECUTE_PARAMETER_PICO = 1010007016,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_PIPELINE_IO_PAIR_PICO = 1010007017,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_IO_MAP_PICO = 1010007018,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_SORT_MATRIX_PICO = 1010007019,
// Provided by XR_PICO_secure_mixed_reality
XR_TYPE_SECURE_MR_OPERATOR_COLOR_CONVERT_PICO = 1010007020,
// Provided by XR_PICO_expand_device
XR_TYPE_EXPAND_DEVICE_MOTOR_VIBRATE_PICO = 1010008000,
// Provided by XR_PICO_expand_device
XR_TYPE_EXPAND_DEVICE_CUSTOM_DATA_PICO = 1010008001,
// Provided by XR_PICO_expand_device
XR_TYPE_EXPAND_DEVICE_BATTERY_STATE_PICO = 1010008002,
// Provided by XR_PICO_expand_device
XR_TYPE_EVENT_DATA_EXPAND_DEVICE_CONNECTION_STATE_CHANGED_PICO = 1010008004,
// Provided by XR_PICO_expand_device
XR_TYPE_EVENT_DATA_EXPAND_DEVICE_BATTERY_STATE_CHANGED_PICO = 1010008005,
// Provided by XR_PICO_expand_device
XR_TYPE_EVENT_DATA_EXPAND_DEVICE_CUSTOM_DATA_STATE_CHANGED_PICO = 1010008006,
// Provided by XR_PICO_body_tracking2
XR_TYPE_BODY_BONE_LENGTH_PICO = 1010009001,
// Provided by XR_PICO_body_tracking2
XR_TYPE_BODY_TRACKING_POSTURE_FLAGS_DATA_PICO = 1010009002,
// Provided by XR_PICO_body_tracking2
XR_TYPE_BODY_JOINT_VELOCITIES_PICO = 1010009003,
// Provided by XR_PICO_body_tracking2
XR_TYPE_BODY_JOINT_ACCELERATIONS_PICO = 1010009004,
// Provided by XR_PICO_body_tracking2
XR_TYPE_BODY_TRACKING_STATE_PICO = 1010009005,
// Provided by XR_PICO_layer_color_matrix
XR_TYPE_LAYER_COLOR_MATRIX_PICO = 1010026000,
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 10^9 (base 10). Each extension is assigned a block of 1000 enums, starting at the enum base and arranged by the extension’s number.
// Provided by XR_VERSION_1_0
#define XR_EXTENSION_ENUM_BASE 1000000000
// Provided by XR_VERSION_1_0
#define XR_EXTENSION_ENUM_STRIDE 1000
For example, if extension number 5 wants to use an enum value of 3, the final enum is computed by:
enum = XR_EXTENSION_ENUM_BASE + (extension_number - 1) * XR_EXTENSION_ENUM_STRIDE + enum_value
1000004003 = 1000000000 + 4 * 1000 + 3
The maximum allowed enum value in an extension is 2,147,482,999, which belongs to extension number 1147483.
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 defined in the core specification were originally listed/defined
here, but have been moved to be adjacent to their associated FlagBits
type.
See the Index for a list.
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
Three version numbers are defined in openxr.h
.
Each is packed into a 32-bit integer as described in
API Version Number Function-like
Macros.
// Provided by XR_VERSION_1_0
// OpenXR current version number.
#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 45)
XR_CURRENT_API_VERSION is the current version of the OpenXR API.
In many cases, XR_API_VERSION_1_0 or XR_API_VERSION_1_1 are preferred for source forward-compatibility.
// Provided by XR_VERSION_1_0
// OpenXR 1.0 version number
#define XR_API_VERSION_1_0 XR_MAKE_VERSION(1, 0, XR_VERSION_PATCH(XR_CURRENT_API_VERSION))
XR_API_VERSION_1_0 is the version of the OpenXR 1.0 API. The "major" and "minor" components are always 1.0, while the "patch" component matches XR_CURRENT_API_VERSION.
// Provided by XR_VERSION_1_1
// OpenXR 1.1 version number
#define XR_API_VERSION_1_1 XR_MAKE_VERSION(1, 1, XR_VERSION_PATCH(XR_CURRENT_API_VERSION))
XR_API_VERSION_1_1 is the version of the OpenXR 1.1 API. The "major" and "minor" components are always 1.1, while the "patch" component matches XR_CURRENT_API_VERSION.
API Version Number Function-like Macros
API Version Numbers are three components, packed into a single 64-bit integer. The following macros manipulate version components and packed version numbers.
#define XR_MAKE_VERSION(major, minor, patch) \
((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))
XR_MAKE_VERSION constructs a packed 64-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.
// Provided by XR_VERSION_1_0
#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL)
XR_VERSION_MAJOR extracts the API major version number from a packed version number.
// Provided by XR_VERSION_1_0
#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL)
XR_VERSION_MINOR extracts the API minor version number from a packed version number.
// Provided by XR_VERSION_1_0
#define XR_VERSION_PATCH(version) (uint32_t)((uint64_t)(version) & 0xffffffffULL)
XR_VERSION_PATCH extracts the API patch version number from a packed version number.
Handle and Atom Macros
// Provided by XR_VERSION_1_0
#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.
// Provided by XR_VERSION_1_0
#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.
// Provided by XR_VERSION_1_0
#if !defined(XR_DEFINE_OPAQUE_64)
#if (XR_PTR_SIZE == 8)
#define XR_DEFINE_OPAQUE_64(object) typedef struct object##_T* object;
#else
#define XR_DEFINE_OPAQUE_64(object) typedef uint64_t object;
#endif
#endif
XR_DEFINE_OPAQUE_64 defines an opaque 64 bit value, which may be implemented as an opaque, distinct pointer type on platforms with 64 bit pointers.
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.
Android Notes
Android specific notes for using the OpenXR specification.
Android Runtime category tag for immersive mode selection
Android applications should add the <category
android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
tag
inside the intent-filter to indicate that the activity starts in an
immersive OpenXR mode and will not touch the native Android 2D surface.
The HMD suffix indicates the preferred form-factor used by the application and can be used by launchers to filter applications listed.
For example:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
</intent-filter>
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:
|
Provisional |
A feature is released provisionally in order to get wider feedback on the functionality before it is finalized. Provisional features may change in ways that break backwards compatibility, and thus are not recommended for use in production applications. |
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.
Working Group Contributors to OpenXR
-
Adam Gousetis, Google (version 1.0)
-
Alain Zanchetta, Microsoft (version 1.1)
-
Alex Turner, Microsoft (versions 1.0, 1.1)
-
Alex Sink, HTC (version 1.1)
-
Alfredo Muniz, XEED (version 1.1) (Working Group Chair)
-
Andreas Loeve Selvik, Meta Platforms (versions 1.0, 1.1)
-
Andres Rodriguez, Valve Software (version 1.0)
-
Armelle Laine, Qualcomm Technologies (version 1.0)
-
Attila Maczak, CTRL-labs (version 1.0)
-
David Fields, Microsoft (version 1.1)
-
Baolin Fu, Bytedance (version 1.1)
-
Blake Taylor, Magic Leap (version 1.0)
-
Brad Grantham, Google (version 1.0)
-
Brandon Jones, Google (version 1.0)
-
Brent E. Insko, Intel (version 1.0) (former Working Group Chair)
-
Brent Wilson, Microsoft (version 1.0)
-
Bryce Hutchings, Microsoft (versions 1.0, 1.1)
-
Cass Everitt, Meta Platforms (versions 1.0, 1.1)
-
Charles Egenbacher, Epic Games (version 1.0)
-
Charlton Rodda, Collabora (version 1.1)
-
Chris Kuo, HTC (version 1.1)
-
Chris Osborn, CTRL-labs (version 1.0)
-
Christine Perey, Perey Research & Consulting (version 1.0)
-
Christoph Haag, Collabora (version 1.0, 1.1)
-
Christopher Fiala, Epic Games (version 1.1)
-
Craig Donner, Google (version 1.0)
-
Dan Ginsburg, Valve Software (version 1.0)
-
Dave Houlton, LunarG (version 1.0)
-
Dave Shreiner, Unity Technologies (version 1.0)
-
Darryl Gough, Microsoft (version 1.1)
-
Denny Rönngren, Varjo (versions 1.0, 1.1)
-
Dmitriy Vasilev, Samsung Electronics (version 1.0)
-
Doug Twileager, ZSpace (version 1.0)
-
Ed Hutchins, Meta Platforms (version 1.0)
-
Eryk Pecyna, Meta Platforms (version 1.1)
-
Frederic Plourde, Collabora (version 1.1)
-
Gloria Kennickell, Meta Platforms (version 1.0)
-
Gregory Greeby, AMD (version 1.0)
-
Guodong Chen, Huawei (version 1.0)
-
Jack Pritz, Unity Technologies (versions 1.0, 1.1)
-
Jakob Bornecrantz, Collabora (versions 1.0, 1.1)
-
Jared Cheshier, PlutoVR (versions 1.0, 1.1)
-
Jared Finder, Google (version 1.1)
-
Javier Martinez, Intel (version 1.0)
-
Jeff Bellinghausen, Valve Software (version 1.0)
-
Jiehua Guo, Huawei (version 1.0)
-
Joe Ludwig, Valve Software (versions 1.0, 1.1)
-
John Kearney, Meta Platforms (version 1.1)
-
Johannes van Waveren, Meta Platforms (version 1.0)
-
Jon Leech, Khronos (version 1.0)
-
Jonas Pegerfalk, Tobii (version 1.1)
-
Jonathan Wright, Meta Platforms (versions 1.0, 1.1)
-
Juan Wee, Samsung Electronics (version 1.0)
-
Jules Blok, Epic Games (version 1.0)
-
Jun Yan, ByteDance (version 1.1)
-
Karl Schultz, LunarG (version 1.0)
-
Karthik Kadappan, Magic Leap (version 1.1)
-
Karthik Nagarajan, Qualcomm Technologies (version 1.1)
-
Kaye Mason, Google (version 1.0)
-
Krzysztof Kosiński, Google (version 1.0)
-
Kyle Chen, HTC (version 1.1)
-
Lachlan Ford, Google (versions 1.0, 1.1)
-
Lubosz Sarnecki, Collabora (version 1.0)
-
Mark Young, LunarG (version 1.0)
-
Martin Renschler, Qualcomm Technologies (version 1.0)
-
Matias Koskela, Tampere University of Technology (version 1.0)
-
Matt Wash, Arm (version 1.0)
-
Mattias Brand, Tobii (version 1.0)
-
Mattias O. Karlsson, Tobii (version 1.0)
-
Matthieu Bucchianeri, Microsoft (version 1.1)
-
Michael Gatson, Dell (version 1.0)
-
Minmin Gong, Microsoft (version 1.0)
-
Mitch Singer, AMD (version 1.0)
-
Nathan Nuber, Valve (version 1.1)
-
Nell Waliczek, Microsoft (version 1.0)
-
Nick Whiting, Epic Games (version 1.0) (former Working Group Chair)
-
Nigel Williams, Sony (version 1.0)
-
Nihav Jain, Google, Inc (version 1.1)
-
Paul Pedriana, Meta Platforms (version 1.0)
-
Paulo Gomes, Samsung Electronics (version 1.0)
-
Peter Kuhn, Unity Technologies (versions 1.0, 1.1)
-
Peter Peterson, HP Inc (version 1.0)
-
Philippe Harscoet, Samsung Electronics (versions 1.0, 1.1)
-
Pierre-Loup Griffais, Valve Software (version 1.0)
-
Rafael Wiltz, Magic Leap (version 1.1)
-
Rajeev Gupta, Sony (version 1.0)
-
Remi Arnaud, Starbreeze (version 1.0)
-
Remy Zimmerman, Logitech (version 1.0)
-
Ria Hsu, HTC (version 1.1)
-
River Gillis, Google (version 1.0)
-
Robert Blenkinsopp, Ultraleap (version 1.1)
-
Robert Memmott, Meta Platforms (version 1.0)
-
Robert Menzel, NVIDIA (version 1.0)
-
Robert Simpson, Qualcomm Technologies (version 1.0)
-
Robin Bourianes, Starbreeze (version 1.0)
-
Ron Bessems, Magic Leap (version 1.1) (Working Group Vice-Chair)
-
Rune Berg, independent (version 1.1)
-
Rylie Pavlik, Collabora (versions 1.0, 1.1) (Spec Editor)
-
Ryan Vance, Epic Games (version 1.0)
-
Sam Martin, Arm (version 1.0)
-
Satish Salian, NVIDIA (version 1.0)
-
Scott Flynn, Unity Technologies (version 1.0)
-
Shanliang Xu, Bytedance (version 1.1)
-
Sean Payne, CTRL-labs (version 1.0)
-
Sophia Baldonado, PlutoVR (version 1.0)
-
Steve Smith, Epic Games (version 1.0)
-
Sungye Kim, Intel (version 1.0)
-
Tom Flynn, Samsung Electronics (version 1.0)
-
Trevor F. Smith, Mozilla (version 1.0)
-
Victor Brodin, Epic Games (version 1.1)
-
Vivek Viswanathan, Dell (version 1.0)
-
Wenlin Mao, Meta Platforms (version 1.1)
-
Xiang Wei, Meta Platforms (version 1.1)
-
Yin Li, Microsoft (versions 1.0, 1.1)
-
Yuval Boger, Sensics (version 1.0)
-
Zhanrui Jia, Bytedance (version 1.1)
-
Zheng Qin, Microsoft (version 1.0)