XrActionSet
handle, you call xrCreateActionSet
and pass an XrInstance
handle as a parameter. XrInstance
is the parent handle to XrActionSet
handles. Similarly, destroying an XrSession
also destroys its associated XrSpace
and XrSwapchain
handles. The following diagram shows the handle type hierarchy for the most significant core (KHR) handle types, along with a non-core handle type given as an example.Handle type | Description |
---|---|
XrInstance | Enables apps to use the OpenXR runtime. These handles are the only ones without a parent. |
XrSession | Enables interaction with a specific XR device, allows for user input, rendering, managing events, and more. Generally, it is a graphics interaction with a particular XrSystem using a particular graphics binding. |
XrAction | Refers to individual actions when retrieving input data or sending haptic events. Apps receive input action states without directly receiving input from the hardware. |
XrActionSet | Refers to groups of actions that are valid in a certain context (for example, all actions to interact with a menu UI). Action sets can be enabled or disabled. |
XrSwapchain | Manages display of rendered images as a series of frame buffers. Images can be organized in multiple swapchains (queues of images to be displayed to the user). |
XrSpace | Represents spaces that the app can reason about through xrLocateSpace . |
XrPath
and XrSystemID
. The XrPath
atom refers to a string that corresponds to a fixed numerical value and represents a semantic path. For example, the path /interaction_profiles/oculus/touch_controller
represents the Meta Quest Touch Controller interaction profile as a path. The XrSystemId
atom represents a value that identifies the user’s system among those that support OpenXR. Both atoms are children of an XrInstance
handle.next
pointer. Here is an example that illustrates the idea of struct-chaining.XrInstanceCreateInfo
struct helps runtimes iterate through a struct pointer chain when creating an instance. It stores, among else, extension names and other instance-related information. This struct type is defined as:typedef struct XrInstanceCreateInfo {
XrStructureType type;
const void* next;
...
const char* const* enabledExtensionNames;
} XrInstanceCreateInfo;
type
is an enum value XrStructureType that defines the type of this struct, for example XR_TYPE_INSTANCE_CREATE_INFO
which is used in storing info about creating an instance.next
is NULL or a pointer to the next struct in a struct-chain.enabledExtensionNames
is a pointer to a string array with the names of extensions to enable.type
and next
members is essential in struct-chaining.XrInstanceCreateInfo
is created and then the instance is created by calling xrCreateInstance
(passing the struct and an m_instance
instance handle):XrInstanceCreateInfo createInfo{XR_TYPE_INSTANCE_CREATE_INFO};
createInfo.next = m_platformPlugin->GetInstanceCreateExtension();
...
createInfo.enabledExtensionNames = extensions.data();
...
CHECK_XRCMD(xrCreateInstance(&createInfo, &m_instance));
m_platformPlugin
is basically a shared pointer to a nested struct of XrBaseInStructure
type that provides extensions to XrInstanceCreateInfo
(for calling xrCreateInstance
). An XrBaseInStructure
allows iterating through a read-only struct pointer chain and is defined as:typedef struct XrBaseInStructure {
XrStructureType type;
const struct XrBaseInStructure* next;
} XrBaseInStructure;
XrBaseOutStructure
allows iterating through a struct pointer chain that returns data back to the app.typedef struct XrBaseOutStructure {
XrStructureType type;
struct XrBaseOutStructure* next;
} XrBaseOutStructure;
xrCreateInstance
. The runtime ignores all unrecognized structs in a next chain (including those that relate to extensions that are not enabled).type
and next
members which will be unmodified.xrFunction
that can be called in parameter form:XrResult xrFunction(uint32_t capacityInput, uint32_t* countOutput, float* elements);
elements
is a pointer to a buffer which stores floats or just nullptr
when requesting the buffer sizecapacityInput
is the number of elements in the buffer or 0
when requesting the required buffer sizecountOutput
is a valid pointer to the actual number of elements found in the buffer (independent of the capacityInput
and elements
parameters)elements
. In parameter form, the first call to xrFunction
must pass:countOutput
pointernullptr
as elements
0
as capacityInput
capacityInput
is 0
, the function sets the value pointed to by countOutput
to the required size in number of elements and returns XR_SUCCESS
, so elements
is ignored.countOutput
points to. So, the second call to xrFunction
retrieves the data by passing:countOutput
points toelements
capacityInput
capacityInput
is:countOutput
to the required capacity, and returns XR_ERROR_SIZE_INSUFFICIENT
. The data in elements
is then undefined.countOutput
to the count of the elements that have been written to the elements
buffer.countOutput
can be the actual value, rather than a pointer. Here is how an alternative xrFunction
function would look like:XrResult xrFunction(XrBuffer* buffer);
XrBuffer
is defined as:struct XrBuffer {
uint32_t capacityInput;
uint32_t countOutput;
float* elements;
};
elements
is a struct that has type
and next
fields, you must set next
to nullptr
or a struct that defines type
and next
.XrEnvironmentBlendMode
enum. Calling xrEnumerateEnvironmentBlendModes
twice retrieves information about environment blend modes for a desired system:uint32_t count;
CHECK_XRCMD(xrEnumerateEnvironmentBlendModes(m_instance, m_systemId, type, 0, &count, nullptr));
...
std::vector<XrEnvironmentBlendMode> blendModes(count);
CHECK_XRCMD(xrEnumerateEnvironmentBlendModes(m_instance, m_systemId, type, count, &count, blendModes.data()));
count
stores the number of supported blend modes and vector blendModes
stores the supported environment blend modes.