XR_EXT_spatial_container
Name String
XR_EXT_spatial_container
Extension Type
Instance extension
Registered Extension Number
811
Revision
1
Ratification Status
Not ratified
Extension and Version Dependencies
Last Modified Date
2026-08-06
IP Status
No known IP claims.
Contributors
Jared Finder, Google
Andreas Loeve Selvik, Meta Platforms
Lachlan Ford, Google
Cass Everitt, Meta Platforms
Adam Gousetis, Meta Platforms
Ankur Agrawal, Unity Technologies
Bjorn Swenson, LÖVR
Denny Rönngren, Varjo Technologies
Fredia Huya-Kouadio, Godot Engine
Guodong Rong, Meta Platforms
Jakob Bornecrantz, NVIDIA
Jian Zhang, ByteDance
John Kearney, Meta Platforms
Jonathan Wright, Meta Platforms
Junfeng She, ByteDance
Kenny Vercaemer, Google
Kurtis Eveleigh, Qualcomm
Mauricio Narvaez, Meta Platforms
Nathan Nuber, Valve Corporation
Nihav Jain, Google
Nikita Lutsenko, Meta Platforms
Praveen Babu J D, ByteDance
Rylie Pavlik, Collabora
Salar Khan, Google
Shuai Liu, ByteDance
Walter Luh, Meta Platforms
Yin Li, Microsoft
Zhipeng Liu, ByteDance
Overview
This extension defines a new class of displayable entities, called "spatial containers" that are analogous to the concept of "windows" in desktop 2D windowing systems.
In OpenXR 1.x, apps have exclusive control of all that the user sees and how that is blended on top of a user’s real or virtual environment. Runtimes only make slight modifications to what is displayed to ensure user safety. This app model is good for immersing a user in a single experience, but it does not extend to multiple simultaneous experiences. In particular, in AR and mixed reality environments, users often want to experience multiple different apps at the same time.
Spatial containers are like windows extended to 3D. The user is able to see multiple spatial containers simultaneously and provides input to a subset of them. The visible spatial containers are able to belong to different apps and runtimes manage their size and placement on behalf of the user.
This extension supports these new types of spatially bounded experiences in addition to existing immersive OpenXR experiences. Bounded OpenXR experiences are allowed to have slightly 3D content (flat panels with minor depth offsets) or volumes that host fully 3D content. Immersive OpenXR experiences are the existing full-screen immersive apps that have been supported since OpenXR 1.0. Apps are able to switch between the two types of content if the app chooses to.
This extension does not define any method for an app to render its content. How to draw content is defined in other extensions: XR_EXT_spatial_container_self_rendering .
Using spatial containers
An XrSpatialContainerEXT is a handle that represents a spatial container.
XR_DEFINE_HANDLE(XrSpatialContainerEXT)
An application starts rendering through a spatial container with the following steps:
- Create a spatial container with xrCreateSpatialContainerEXT .
- Modify any state on the container for initial presentation, such as its bounds mode.
- Request the runtime show the container with xrRequestSpatialContainerVisibleEXT .
- Wait for the runtime to be ready to show the container. When the runtime is ready, it queues an XrEventDataSpatialContainerVisibleChangedEXT event with
visibleset toXR_TRUE. - Begin rendering for the spatial container.
And tearing down a spatial container is as follows:
- Request the runtime hide the container with xrRequestSpatialContainerVisibleEXT .
- Wait for the runtime to finish hiding the container. When the runtime has fully hidden the container, it queues an XrEventDataSpatialContainerVisibleChangedEXT event with
visibleset toXR_FALSE. - End rendering for the spatial container.
- Destroy the container with xrDestroySpatialContainerEXT .
Note
By design, this extension delegates visibility and focus management to individual spatial containers. Because the session as a whole no longer represents a single visible or focused object, the session does not transition through the standard OpenXR state machine (READY, SYNCHRONIZED, VISIBLE, FOCUSED). Instead, the session remains in XR_SESSION_STATE_IDLE for its active lifetime, and the rules in Changes to session state specify how core OpenXR operations map to this mode.
Create a spatial container
The xrCreateSpatialContainerEXT function creates a new spatial container.
XrResult xrCreateSpatialContainerEXT(
XrSession session,
const XrSpatialContainerCreateInfoEXT* createInfo,
XrSpatialContainerEXT* spatialContainer);
Parameter Descriptions
sessionis the XrSession that creates the spatial container.createInfois a pointer to an XrSpatialContainerCreateInfoEXT containing parameters to create the spatial container.spatialContaineris a pointer to a handle in which the created XrSpatialContainerEXT is returned.
A newly created XrSpatialContainerEXT must be not visible, not interactable, and in bounds mode XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT . An app that wants a spatial container to start in immersive mode can request a bounds mode of XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT before requesting to show a spatial container.
Runtimes must return XR_ERROR_VALIDATION_FAILURE if any dimension of XrSpatialContainerCreateInfoEXT :: suggestedBounds is negative, infinite, or not a number. Runtimes must return XR_ERROR_LIMIT_REACHED if an app attempts to create more spatial containers than specified in XrSystemSpatialContainerPropertiesEXT :: maxSpatialContainerCount . If spatial containers were not enabled for this session , runtimes must return XR_ERROR_SPATIAL_CONTAINERS_NOT_ENABLED_EXT .
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrCreateSpatialContainerEXT -
sessionmust be a valid XrSession handle -
createInfomust be a pointer to a valid XrSpatialContainerCreateInfoEXT structure -
spatialContainermust be a pointer to an XrSpatialContainerEXT handle
Return Codes
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_CONTAINERS_NOT_ENABLED_EXTXR_ERROR_VALIDATION_FAILURE
The XrSpatialContainerCreateInfoEXT is passed to xrCreateSpatialContainerEXT to create a spatial container.
typedef struct XrSpatialContainerCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpatialContainerGraphicsPresentationEXT graphicsPresentation;
XrExtent3Df suggestedBounds;
} XrSpatialContainerCreateInfoEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.graphicsPresentationis an XrSpatialContainerGraphicsPresentationEXT that describes how this spatial container presents graphics.suggestedBoundsis an XrExtent3Df that describes the requested dimensions of the spatial container in meters.
An app that has no preference for its size can set suggestedBounds to {0, 0, 0}. A runtime may ignore the requested suggestedBounds .
A runtime that allows spatial containers to be bounded by shapes other than oriented boxes must use suggestedBounds as a bounding box around the other shapes. Oriented boxes are intended to be the most common bounding shape.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerCreateInfoEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_CREATE_INFO_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain -
graphicsPresentationmust be a valid XrSpatialContainerGraphicsPresentationEXT value
When a spatial container is no longer usable, runtimes must queue an XrEventDataSpatialContainerClosedEXT event.
typedef struct XrEventDataSpatialContainerClosedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrEventDataSpatialContainerClosedEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris the XrSpatialContainerEXT that this event is for.
Receiving the XrEventDataSpatialContainerClosedEXT event indicates that the runtime is no longer able to display a spatial container, for example due to the user clicking a "close" button or the session entering the XR_SESSION_STATE_LOSS_PENDING state.
After receiving the XrEventDataSpatialContainerClosedEXT event, an app should stop using that spatial container, tear down any associated state such as a render loop, and destroy the container. Runtimes must return XR_ERROR_SPATIAL_CONTAINER_CLOSED_EXT from all functions operating on that container other than xrDestroySpatialContainerEXT .
If a spatial container is visible when the runtime queues a close event, runtimes must first change the container to not visible and queue an XrEventDataSpatialContainerVisibleChangedEXT event.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrEventDataSpatialContainerClosedEXT -
typemust beXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_CLOSED_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
The xrDestroySpatialContainerEXT function destroys an existing spatial container.
XrResult xrDestroySpatialContainerEXT(
XrSpatialContainerEXT spatialContainer);
Parameter Descriptions
spatialContaineris an XrSpatialContainerEXT previously created by xrCreateSpatialContainerEXT .
After a spatial container is destroyed runtimes must not show the container’s contents any more and must not queue any additional events about the container.
An app should not destroy a spatial container that is visible as doing so may result in graphical artifacts, instead an app should request to hide the spatial container with xrRequestSpatialContainerVisibleEXT , wait for an XrEventDataSpatialContainerVisibleChangedEXT event, and then destroy the container.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrDestroySpatialContainerEXT -
spatialContainermust be a valid XrSpatialContainerEXT handle
Thread Safety
- Access to
spatialContainer, and any child handles, must be externally synchronized
Return Codes
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_RUNTIME_FAILURE
The spatial container space
The xrCreateSpatialContainerSpaceEXT function creates an XrSpace handle for the spatial container space of a specific spatial container.
XrResult xrCreateSpatialContainerSpaceEXT(
XrSession session,
const XrSpatialContainerSpaceCreateInfoEXT* createInfo,
XrSpace* space);
Parameter Descriptions
sessionis the XrSession that creates the space.createInfois a pointer to an XrSpatialContainerSpaceCreateInfoEXT containing parameters to create the space.spaceis a pointer to a handle in which the created XrSpace is returned.
The "spatial container space" for any given spatial container is a coordinate system with its origin at the center of that spatial container’s bounds. This space is typically used as the base space for functions like xrLocateSpace .
+X points to the right face of the container, +Y points to the top face of the container, and +Z points to the front face of the container. For example, if a container is gravity aligned, in front of the viewer, and the viewer is at the identity pose relative to the LOCAL space , runtimes must orient the container space with the identity orientation relative to the LOCAL space . Runtimes may set the pose of a container space relative to LOCAL space to any arbitrary pose when that container becomes visible.
ext spatial container space convention
Figure 18. Axes convention of spatial container space
The spatial container space is a non-world locked origin. Apps that want a world locked origin while in immersive mode can use a world locked space such as XR_REFERENCE_SPACE_TYPE_LOCAL .
Runtimes may change a spatial container space’s pose at any time, commonly to support a user moving a spatial container to a different position or rotation. Runtimes may also change the pose when transitioning between XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT and XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT bounds modes.
A spatial container space must continue to be a valid handle even if the spatial container it is for is destroyed with xrDestroySpatialContainerEXT . While a spatial container is not visible or destroyed, the spatial container space must be unlocatable relative to other spaces. XrSpaceLocation :: locationFlags and XrViewState ::viewStateFlags will be 0.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrCreateSpatialContainerSpaceEXT -
sessionmust be a valid XrSession handle -
createInfomust be a pointer to a valid XrSpatialContainerSpaceCreateInfoEXT structure -
spacemust be a pointer to an XrSpace handle
Return Codes
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_LIMIT_REACHEDXR_ERROR_OUT_OF_MEMORYXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXTXR_ERROR_VALIDATION_FAILURE
The XrSpatialContainerSpaceCreateInfoEXT is used with xrCreateSpatialContainerSpaceEXT to create an XrSpace handle.
typedef struct XrSpatialContainerSpaceCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrSpatialContainerSpaceCreateInfoEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris an XrSpatialContainerEXT to create a space for.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerSpaceCreateInfoEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_SPACE_CREATE_INFO_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain -
spatialContainermust be a valid XrSpatialContainerEXT handle
Presenting a spatial container
Submitting a spatial container’s contents are submitted to OpenXR for display is handled by other extensions: XR_EXT_spatial_container_self_rendering .
To allow other extensions to specify the graphics presentation method for a spatial container this extension defines the XrSpatialContainerGraphicsPresentationEXT enum.
typedef enum XrSpatialContainerGraphicsPresentationEXT {
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT = 1000813000,
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_CONFORMANCE_AUTOMATION_EXT = 1000814000,
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SYSTEM_RENDERING_EXTX1 = 1000815000,
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialContainerGraphicsPresentationEXT;
Enum Description
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
Spatial container uses OpenXR composition layers (Added by the XR_EXT_spatial_container_self_rendering extension)
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_CONFORMANCE_AUTOMATION_EXT
Spatial container is created for conformance testing and does not have a rendering path (Added by the XR_EXT_spatial_container_conformance_automation extension)
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SYSTEM_RENDERING_EXTX1
Spatial container uses OpenXR system rendering (Added by the XR_EXTX1_system_renderer extension)
Spatial container state
Spatial container state is managed by runtimes based on both app requests and the needs of the user. Because of this, each aspect of spatial container state documents the following things:
- When runtimes are allowed to change the spatial container state. For most spatial container state, runtimes may change the state at any time.
- How an app requests changes to the state. Runtimes may defer any request until it believes the request is suitable. Runtimes do not queue events when a request is deferred, so apps should not wait on such an event for unrelated logic.
- What event runtimes queue when the spatial container state changes. Runtimes queue events for all changes, including app requested changes and runtime initiated changes. Runtimes must not queue state change events that do not indicate a change, such as if an app makes two requests to hide a container in quick succession.
- What event runtimes queue when denying an app change request. Runtimes may deny a request for any reason, typically due to system policy related to maintaining a high quality user experience.
The xrGetSpatialContainerStateEXT function queries the current state of the spatial container.
XrResult xrGetSpatialContainerStateEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerStateGetInfoEXT* getInfo,
XrSpatialContainerStateEXT* state);
Parameter Descriptions
spatialContaineris the XrSpatialContainerEXT to query.getInfois the XrSpatialContainerStateGetInfoEXT with the information used to get the state of the spatial container.stateis a pointer to the XrSpatialContainerStateEXT in which the spatial container state is returned.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrGetSpatialContainerStateEXT -
spatialContainermust be a valid XrSpatialContainerEXT handle - If
getInfois notNULL,getInfomust be a pointer to a valid XrSpatialContainerStateGetInfoEXT structure -
statemust be a pointer to an XrSpatialContainerStateEXT structure
Return Codes
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXTXR_ERROR_VALIDATION_FAILURE
The XrSpatialContainerStateGetInfoEXT is used with xrGetSpatialContainerStateEXT to query an XrSpatialContainerStateEXT .
typedef struct XrSpatialContainerStateGetInfoEXT {
XrStructureType type;
const void* next;
} XrSpatialContainerStateGetInfoEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerStateGetInfoEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_STATE_GET_INFO_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
typedef struct XrSpatialContainerStateEXT {
XrStructureType type;
void* next;
XrBool32 visible;
XrBool32 interactable;
XrSpatialContainerBoundsModeEXT boundsMode;
} XrSpatialContainerStateEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.visiblerepresents whether a spatial container is visible.interactablerepresents if a spatial container is currently able to receive any type of input. It is similar to "focus" for desktop 2D windowing systems with the difference that multiple spatial containers may be interactable at once.boundsModeis the current XrSpatialContainerBoundsModeEXT of the spatial container.
Changes to a spatial container’s state is communicated via events.
Field Changed event
visible
XrEventDataSpatialContainerVisibleChangedEXT
interactable
XrEventDataSpatialContainerInteractableChangedEXT
boundsMode
XrEventDataSpatialContainerBoundsChangedEXT
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerStateEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_STATE_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Visibility
Apps request to show or hide a spatial container with xrRequestSpatialContainerVisibleEXT .
XrResult xrRequestSpatialContainerVisibleEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerVisibleRequestInfoEXT* info);
Parameter Descriptions
spatialContaineris the XrSpatialContainerEXT to request a change for.infois a pointer to an XrSpatialContainerVisibleRequestInfoEXT containing the requested visible state.
Showing or hiding a spatial container is an asynchronous operation.
Apps should request to hide a spatial container before destroying it, enabling runtimes to display a smooth transition. Runtimes should honor requests to hide a spatial container.
A runtime may deny requests to show a spatial container, in which case the runtime must queue an XrEventDataSpatialContainerVisibleRequestDeniedEXT event. For example, some runtimes will deny a request to show a spatial container that the user hid by interacting with a system provided "minimize" button.
Runtimes must not show a spatial container prior to the app requesting to show that spatial container at least once. After the app’s first request to show a spatial container, runtimes may change the visibility that spatial container independent of an app’s requests. This enables the app to control the initial state and contents of a spatial container and enables runtimes to provide system UI like a taskbar that allow a user to choose which spatial containers are visible.
Runtimes must deny requests to show a spatial container in a bounds mode not supported based on XrSystemSpatialContainerPropertiesEXT :: supportsBounded and XrSystemSpatialContainerPropertiesEXT :: supportsImmersive . This is possible when the default bounds mode, XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT , is unsupported for a given system.
Note
On some implementations showing or hiding a spatial container requires communicating with system services and may be deferred until after the user interacts with a system dialog. The asnchyronous design for requesting visibility state changes is intended to allow runtimes the time to complete both of these operations.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrRequestSpatialContainerVisibleEXT -
spatialContainermust be a valid XrSpatialContainerEXT handle -
infomust be a pointer to a valid XrSpatialContainerVisibleRequestInfoEXT structure
Return Codes
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXTXR_ERROR_VALIDATION_FAILURE
The XrSpatialContainerVisibleRequestInfoEXT is used with xrRequestSpatialContainerVisibleEXT to change a spatial container’s visibility.
typedef struct XrSpatialContainerVisibleRequestInfoEXT {
XrStructureType type;
const void* next;
XrBool32 visible;
} XrSpatialContainerVisibleRequestInfoEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.visiblerepresents whether a spatial container is requested to be shown or hidden.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerVisibleRequestInfoEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_VISIBLE_REQUEST_INFO_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Every time a runtime changes the visibility of a spatial container, the runtime must queue an XrEventDataSpatialContainerVisibleChangedEXT event with the new state.
typedef struct XrEventDataSpatialContainerVisibleChangedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
XrBool32 visible;
} XrEventDataSpatialContainerVisibleChangedEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris the XrSpatialContainerEXT that this event is for.visibleis the new visible state for the spatial container.
This event replaces XR_SESSION_STATE_VISIBLE , allowing the value to be different per-container. The event must be queued for all changes, including app requested changes and runtime initiated changes.
A runtime may delay rendering a container for a few frames after queuing this event with visible set to XR_TRUE to avoid displaying an empty container and provide the app time to submit its initial content. During this time, XrSpatialContainerStateEXT ::visible will be XR_TRUE . Runtimes should not delay rendering a container for over 0.5 seconds.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrEventDataSpatialContainerVisibleChangedEXT -
typemust beXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_VISIBLE_CHANGED_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Every time a runtime denies a request to show a container, the runtime must queue an XrEventDataSpatialContainerVisibleRequestDeniedEXT event.
typedef struct XrEventDataSpatialContainerVisibleRequestDeniedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrEventDataSpatialContainerVisibleRequestDeniedEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris the XrSpatialContainerEXT that this event is for.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrEventDataSpatialContainerVisibleRequestDeniedEXT -
typemust beXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_VISIBLE_REQUEST_DENIED_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Interactable
An app cannot request a spatial container be interactable. What spatial containers are interactable is fully controlled by runtimes. A spatial container that is interactable must also be visible.
Every time a runtime changes the interactable state of a spatial container, the runtime must queue an XrEventDataSpatialContainerInteractableChangedEXT event with the new state.
typedef struct XrEventDataSpatialContainerInteractableChangedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
XrBool32 interactable;
} XrEventDataSpatialContainerInteractableChangedEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris the XrSpatialContainerEXT that this event is for.interactableis the new interactable state for the spatial container.
This event replaces XR_SESSION_STATE_FOCUSED , allowing the value to be different per-container. The event is queued for all changes, including runtime initiated changes.
Runtimes may enable or disable interaction with a spatial container at any time. If a runtime only supports at most one spatial container being interactable at a time, when the runtime changes the interactable spatial container, the runtime must queue the event for the spatial container that stops being interactable ( interactable set to false) before the event for the container that starts being interactable ( interactable set to true).
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrEventDataSpatialContainerInteractableChangedEXT -
typemust beXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_INTERACTABLE_CHANGED_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Bounds
A spatial container has a bounds mode and a bounding box. A spatial container’s bounds mode describes how the bounds behave. Its bounding box is what the spatial container draws inside of.
The XrSpatialContainerBoundsModeEXT enumeration identifies different modes a spatial container’s bounds are able to be in.
typedef enum XrSpatialContainerBoundsModeEXT {
XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT = 1,
XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT = 2,
XR_SPATIAL_CONTAINER_BOUNDS_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialContainerBoundsModeEXT;
Enum Description
XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT
Spatial container is bounded. The bounds are a finite box. The spatial container will only appear in this region.
XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT
Spatial container is immersive and has infinite bounds. The spatial container is displayed over the entire screen.
Spatial containers that are in bounds mode XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT have additional requirements:
- Runtimes must treat these spatial containers the same as a full-screen and immersive app created without spatial container usage, except for the behavior changes called out in Changes to session state .
- Runtimes may provide additional extensions that enable immersive spatial containers to behave differently from full-screen and immersive apps created without this extension.
- Runtimes must report infinite bounds for these spatial containers.
- Runtimes may hide other spatial containers while an immersive spatial container is visible. Because this might be different per runtime, apps should not rely on spatial containers being automatically shown or hidden based on immersive spatial container visibility. Like all other visible state transitions, runtimes must queue an XrEventDataSpatialContainerVisibleChangedEXT event when a spatial container is hidden due to an immersive container being visible.
Note
The above requirements imply that all runtimes can implement the OpenXR 1.x path without this extension by implicitly creating a spatial container, setting the container’s bounds mode to immersive, and requesting it be visible.
Apps request to change a spatial container’s bounds mode with xrRequestSpatialContainerBoundsModeEXT .
XrResult xrRequestSpatialContainerBoundsModeEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerBoundsModeRequestInfoEXT* info);
Parameter Descriptions
spatialContaineris the XrSpatialContainerEXT to request a change for.infois a pointer to an XrSpatialContainerBoundsModeRequestInfoEXT containing the requested bounds mode.
Changing a spatial container’s bounds mode is an asynchronous operation and runtimes may queue a changed or denied event many seconds after the app requests a change. This allows runtimes to pop up UI that is necessary to allow a user to safely enter an immersive mode.
Runtimes must honor a request to change the bounds mode for a not visible spatial container. If a runtime would deny a bounds mode request for a not visible container, it instead may reject or defer a request to show such a spatial container. This allows apps to start a container as an immersive container. A runtime may deny requests to change the bounds mode of a visible spatial container, in which case the runtime must queue an XrEventDataSpatialContainerBoundsModeRequestDeniedEXT event. For example, some runtimes will deny a request to change the bounds mode of a visible spatial container that the user is not actively interacting with.
Runtimes must return XR_ERROR_VALIDATION_FAILURE if an app requests a bounds mode not supported based on XrSystemSpatialContainerPropertiesEXT :: supportsBounded and XrSystemSpatialContainerPropertiesEXT :: supportsImmersive .
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrRequestSpatialContainerBoundsModeEXT -
spatialContainermust be a valid XrSpatialContainerEXT handle -
infomust be a pointer to a valid XrSpatialContainerBoundsModeRequestInfoEXT structure
Return Codes
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXTXR_ERROR_VALIDATION_FAILURE
The XrSpatialContainerBoundsModeRequestInfoEXT is used with xrRequestSpatialContainerBoundsModeEXT to change a spatial container’s bounds mode.
typedef struct XrSpatialContainerBoundsModeRequestInfoEXT {
XrStructureType type;
const void* next;
XrSpatialContainerBoundsModeEXT boundsMode;
} XrSpatialContainerBoundsModeRequestInfoEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.boundsModeis the desired XrSpatialContainerBoundsModeEXT for the spatial container.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerBoundsModeRequestInfoEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_BOUNDS_MODE_REQUEST_INFO_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain -
boundsModemust be a valid XrSpatialContainerBoundsModeEXT value
Every time a runtime changes the bounds or bounds mode of a spatial container, the runtime must queue an XrEventDataSpatialContainerBoundsChangedEXT event with the new bounds information.
typedef struct XrEventDataSpatialContainerBoundsChangedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
XrExtent3Df bounds;
XrBool32 infiniteBounds;
XrSpatialContainerBoundsModeEXT boundsMode;
} XrEventDataSpatialContainerBoundsChangedEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris the XrSpatialContainerEXT that this event is for.boundsis the new width, height, and depth of the spatial container’s bounds.infiniteBoundsis true if the container has infinite bounds.boundsModeis the new XrSpatialContainerBoundsModeEXT of the spatial container.
The event is queued for all changes, including app requested changes and runtime initiated changes.
While a user is interactively resizing a spatial container, runtimes must behave in one of the following ways:
- queue many events, likely at framerate, as the user is resizing the spatial container
- queue a single event at the end of the resize
If a runtime queues only a single event at the end of the resize, that runtime must continue to report the old bounds from xrGetSpatialContainerBoundsEXT until the runtime queues a resize event. Runtimes must coalesce multiple unpolled bounds changed events. In other words, if the bounds or bounds mode changes while there is an XrEventDataSpatialContainerBoundsChangedEXT event still queued, runtimes must report only a single event containing the last bounds change that occurred. Because apps can also poll a spatial container’s bounds directly with xrGetSpatialContainerBoundsEXT , the number of bounds changes from events can be different the number of changes from polling based on the timing of runtime generated bounds changes, app calls to xrPollEvent , and app calls to xrGetSpatialContainerBoundsEXT .
When a spatial container’s bounds changes, the spatial container’s local origin may change as well. For example, if a runtime allows a user to resize the spatial container’s bounds by dragging one of the container’s edges, the bounds and the local origin for that container will change when the user drags a single edge. In such situations, the runtime must change the bounds and the local origin simultaneously.
Runtimes must set infiniteBounds to XR_TRUE and set width, height, and depth to 0.0 to represent infinite bounds. Runtimes must set infiniteBounds to XR_FALSE and set width, height, and depth to finite positive numbers for finite bounds.
Runtimes must set bounds and infiniteBounds following the same rules as for XrSpatialContainerBoundsEXT .
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrEventDataSpatialContainerBoundsChangedEXT -
typemust beXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_BOUNDS_CHANGED_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Every time a runtime denies a request to change the bounds mode of a container, the runtime must queue an XrEventDataSpatialContainerBoundsModeRequestDeniedEXT event.
typedef struct XrEventDataSpatialContainerBoundsModeRequestDeniedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrEventDataSpatialContainerBoundsModeRequestDeniedEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.spatialContaineris the XrSpatialContainerEXT that this event is for.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrEventDataSpatialContainerBoundsModeRequestDeniedEXT -
typemust beXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_BOUNDS_MODE_REQUEST_DENIED_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
The XrSpatialContainerBoundsEXT structure describes the bounding box of a spatial container.
typedef struct XrSpatialContainerBoundsEXT {
XrStructureType type;
void* next;
XrExtent3Df bounds;
XrBool32 infiniteBounds;
} XrSpatialContainerBoundsEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.boundsis the width, height, and depth of the spatial container’s bounds. The bounds are in meters.infiniteBoundsis true if the container has infinite bounds.
Runtimes must set infiniteBounds to XR_TRUE and set width, height, and depth to 0.0 to represent infinite bounds. Runtimes must set infiniteBounds to XR_FALSE and set width, height, and depth to finite positive numbers for finite bounds.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerBoundsEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_BOUNDS_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
The xrGetSpatialContainerBoundsEXT function queries the current bounds of a spatial container.
XrResult xrGetSpatialContainerBoundsEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerBoundsGetInfoEXT* getInfo,
XrSpatialContainerBoundsEXT* bounds);
Parameter Descriptions
spatialContaineris the XrSpatialContainerEXT to query.getInfois the XrSpatialContainerBoundsGetInfoEXT with the information used to get the state of the spatial container.boundsis a pointer to the XrSpatialContainerBoundsEXT in which the bounds is returned.
While a spatial container is bounded it must not have infinite bounds, while a spatial container is immersive it must have infinite bounds.
Runtimes may change a spatial container’s bounds to any positive finite value at any time while the spatial container is bounded. Changes to a spatial container’s bounds is communicated via XrEventDataSpatialContainerBoundsChangedEXT .
With this extension, an app cannot request changes to bounds other than changing between bounded and immersive with xrRequestSpatialContainerBoundsModeEXT . Other extensions might provide such a way in the future.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrGetSpatialContainerBoundsEXT -
spatialContainermust be a valid XrSpatialContainerEXT handle - If
getInfois notNULL,getInfomust be a pointer to a valid XrSpatialContainerBoundsGetInfoEXT structure -
boundsmust be a pointer to an XrSpatialContainerBoundsEXT structure
Return Codes
XR_SUCCESSXR_SESSION_LOSS_PENDING
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SESSION_LOSTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXTXR_ERROR_VALIDATION_FAILURE
The XrSpatialContainerBoundsGetInfoEXT structure is an input structure that exists for future extension purposes.
typedef struct XrSpatialContainerBoundsGetInfoEXT {
XrStructureType type;
const void* next;
} XrSpatialContainerBoundsGetInfoEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSpatialContainerBoundsGetInfoEXT -
typemust beXR_TYPE_SPATIAL_CONTAINER_BOUNDS_GET_INFO_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
The XrSpatialContainerVolumeClippingEXT enumeration identifies different volume clipping behavior for a spatial container.
typedef enum XrSpatialContainerVolumeClippingEXT {
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_NONE_EXT = 0,
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT = 1,
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialContainerVolumeClippingEXT;
Enum Description
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_NONE_EXT
No content is clipped to the bounding volume of the spatial container. Content can draw outside of the spatial container’s bounds.
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT
Content is strictly clipped to the bounding volume of the spatial container.
There is no use of this enumeration in this extension. It is defined to allow other extensions to specify the volume clipping behavior desired. For example, an app may want to draw a background for a bounded spatial container. A monocular cubemap a convenient way to specify a background, however a monocular cubemap is conceptually positioned at infinity which is outside of the container.
System capabilities
An app can inspect system capabilities by chaining an XrSystemSpatialContainerPropertiesEXT structure to the XrSystemProperties when calling xrGetSystemProperties .
typedef struct XrSystemSpatialContainerPropertiesEXT {
XrStructureType type;
void* next;
uint32_t maxSpatialContainerCount;
XrBool32 supportsBounded;
XrBool32 supportsImmersive;
} XrSystemSpatialContainerPropertiesEXT;
Member Description
typeis the XrStructureType of this structure.nextisNULLor a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.maxSpatialContainerCountis the maximum number of spatial containers that are able to be created.supportsBoundedis true if spatial containers are able to be bounded.supportsImmersiveis true if spatial containers are allowed to be immersive.
Runtimes that support this extension should support an app creating many spatial containers, only limited by memory allocation. A runtime may have a different limit for the number of simultaneous displayed spatial containers. There is no way to query the number of simultaneous displayed containers in this extension because a runtime may limit individual apps based on the state across all running apps. The assumption is that highly constrained devices and less constrained devices will have different limits for the number of simultaneously displayed containers; highly constrained devices may support only one spatial container being displayed at a time and less constrained devices may support a large number of spatial containers being displayed simultaneously, subject to rendering compute limits.
Runtimes that support this extension must support at least one of bounded spatial containers or immersive spatial containers.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSystemSpatialContainerPropertiesEXT -
typemust beXR_TYPE_SYSTEM_SPATIAL_CONTAINER_PROPERTIES_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
The xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT function returns the graphics presentation methods supported on a system.
XrResult xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT(
XrInstance instance,
XrSystemId systemId,
uint32_t graphicsPresentationCapacityInput,
uint32_t* graphicsPresentationCountOutput,
XrSpatialContainerGraphicsPresentationEXT* graphicsPresentations);
Parameter Descriptions
instanceis the XrInstance from whichsystemIdwas retrieved.systemIdis theXrSystemIdbeing queried.graphicsPresentationCapacityInputis the capacity of thegraphicsPresentationsarray, or 0 to indicate a request to retrieve the required capacity.graphicsPresentationCountOutputis a pointer to the count of graphics presentations written, or a pointer to the required capacity in the case thatgraphicsPresentationCapacityInputis 0.graphicsPresentationsis a pointer to an array of XrSpatialContainerGraphicsPresentationEXT values, but can be null ifgraphicsPresentationCapacityInputis 0.- See the Buffer Size Parameters section for a detailed description of retrieving the required
graphicsPresentationssize.
Runtimes must always return identical buffer contents from this enumeration for the given systemId and for the lifetime of the instance.
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to calling xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT -
instancemust be a valid XrInstance handle -
graphicsPresentationCountOutputmust be a pointer to auint32_tvalue - If
graphicsPresentationCapacityInputis not0,graphicsPresentationsmust be a pointer to an array ofgraphicsPresentationCapacityInputXrSpatialContainerGraphicsPresentationEXT values
Return Codes
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
Changes to session state
Spatial container support is enabled for a session by chaining an XrSessionCreateInfoSpatialContainersEXT when calling xrCreateSession .
typedef struct XrSessionCreateInfoSpatialContainersEXT {
XrStructureType type;
const void* next;
} XrSessionCreateInfoSpatialContainersEXT;
When spatial container support is enabled, an XrSession behaves differently. This is because when using spatial containers the session no longer presents image content on the display(s), the spatial containers do so instead. Therefore, when this extension is enabled a session is effectively "headless". Unlike other headless extensions, apps can submit image data through the spatial containers.
Enabling spatial container support alters core OpenXR APIs in the following way.
runtime: losing system or device
runtime: losing system or device
xrDestroySession
xrDestroySession
IDLE
(running)
IDLE...
xrGetSystem
xrCreateSession
xrGetSystem...
xrCreateInstance
xrCreateIn...
xrDestroySession
xrDestroySession
LOSS_PENDING
(not running)
LOSS_PENDING...
xrDestroyInstance
xrDestroyInstance
app: optionally
relaunch XR
app: optionally...
Figure 19. New session state machine
- The session never enters the states
XR_SESSION_STATE_VISIBLE,XR_SESSION_STATE_FOCUSED, orXR_SESSION_STATE_EXITING. Runtimes must never queue events for these states. These states are replaced by per-spatial container events XrEventDataSpatialContainerVisibleChangedEXT , XrEventDataSpatialContainerInteractableChangedEXT , and XrEventDataSpatialContainerClosedEXT , respectively. - The session also never enters the states
XR_SESSION_STATE_READY,XR_SESSION_STATE_SYNCHRONIZED,XR_SESSION_STATE_STOPPING. Runtimes must never queue events for these states. There are no replacement for these states. - Runtimes must treat the session as running when it is in the state
XR_SESSION_STATE_IDLE. - Runtimes must treat the session as focused when it is in the state
XR_SESSION_STATE_IDLEand at least one spatial container exists which is interactable. - The xrBeginSession and xrEndSession functions are no longer needed. Runtimes must return
XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXTwhen these functions are called. Other extensions may provide replacements for these functions. - The xrRequestExitSession function is also no longer needed. Runtimes must return
XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXTwhen this function is called. Apps that want to exit a running session instead can call xrRequestSpatialContainerVisibleEXT to hide their containers, and destroy the session after all containers are no longer visible. Extensions that would queue additional events when the session starts running is called now must queue those events after session creation. Such extensions are called out below.
Extension Event
XR_EXT_user_presence
XrEventDataUserPresenceChangedEXT
XR_META_boundary_visibility
XrEventDataBoundaryVisibilityChangedMETA
- The xrLocateViews function is not valid to call for the session. Runtimes must return
XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXTfrom xrLocateViews . Other extensions may provide ways to locate the views for a particular spatial container. - The xrWaitFrame function must always set XrFrameState ::
shouldRenderto false. Other extensions may provide ways to know if a particular spatial container should update its composition layers. - The xrEndFrame function is not a valid way to submit composition layers. If an app sets XrFrameEndInfo ::
layerCountto a non-zero value, runtimes must returnXR_ERROR_VALIDATION_FAILURE. Other extensions may provide ways to submit composition layers for a particular spatial container. - Entering the state
XR_SESSION_STATE_LOSS_PENDINGalso closes all spatial containers. Runtimes must queue an XrEventDataSpatialContainerClosedEXT event for each active spatial container before queueing a session state change forXR_SESSION_STATE_LOSS_PENDING. - The xrCreateSession function no longer needs a graphics API binding structure. Other extensions may require a graphics binding, for example for a spatial container to render using a graphics API.
The above behavior is slightly different from the behavior in XR_MND_headless . Runtimes must not enable the headless session behavior from XR_MND_headless when spatial container support is enabled for that session.
Note
When spatial containers are enabled, a session transitions between only two states: XR_SESSION_STATE_IDLE (running) and XR_SESSION_STATE_LOSS_PENDING (not running). As a result, runtimes no longer return XR_ERROR_SESSION_RUNNING or XR_ERROR_SESSION_NOT_RUNNING . Instead, when a session is not running, runtimes return either XR_ERROR_SESSION_LOST or XR_SESSION_LOSS_PENDING following the rules in OpenXR core. Furthermore, xrBeginSession , the only function that returns XR_ERROR_SESSION_RUNNING , will now always return XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXT .
Valid Usage (Implicit)
- The
XR_EXT_spatial_containerextension must be enabled prior to using XrSessionCreateInfoSpatialContainersEXT -
typemust beXR_TYPE_SESSION_CREATE_INFO_SPATIAL_CONTAINERS_EXT -
nextmust beNULLor a valid pointer to the next structure in a structure chain
Android Manifest entries
AOSP based runtimes may have custom behavior based on the initial spatial container state that is started before running any app code. For example, a runtime may alter resources allocated for the activity, launch animations, or splash screen display. The following properties are provided for this purpose. They replace the <category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" /> tag, which spatial container based apps should not specify except for compatibility with earlier AOSP based runtimes.
<property android:name="org.khronos.openxr.PROPERTY_ACTIVITY_HINT_XR_SPATIAL_CONTAINER_USED_BOUNDS_MODES"
android:value="list of modes" />
This property hints to runtimes that the bounds modes used by an activity. By default it is an empty list, which implies no hint.
The following strings are valid for this attribute. Multiple values are separated by | , such as "bounded|immersive" .
Value
Description
"2d_panel"
The activity displays using Android’s 2D view framework.
"bounded"
The activity uses XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT .
"immersive"
The activity uses XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT .
<property android:name="org.khronos.openxr.PROPERTY_ACTIVITY_HINT_XR_SPATIAL_CONTAINER_INITIAL_BOUNDS_MODE"
android:value="XR_SPATIAL_CONTAINER_INITIAL_BOUNDS_MODE_BOUNDED|
XR_SPATIAL_CONTAINER_INITIAL_BOUNDS_MODE_IMMERSIVE|
XR_SPATIAL_CONTAINER_INITIAL_BOUNDS_MODE_UNDEFINED" />
This property hints to runtimes the activity’s initial XrSpatialContainerBoundsModeEXT when it is first created. By default it is the string XR_SPATIAL_CONTAINER_INITIAL_BOUNDS_MODE_UNDEFINED, which implies no hint.
Runtimes must not require apps to have these properties to otherwise behave according to this spec. Runtimes must not alter app visible behavior based on these properties. All such metadata must be specifiable at either the <activity> level or the <application> level. If specified at the <application> level, it applies to all activities in the application that do not specify their own values.
Example code
The following code shows how to use this extension for perception-only use cases without any rendering.
XrInstance instance; // Already initialized
// Create the session with spatial containers enabled
XrSession session;
XrSessionCreateInfoSpatialContainersEXT spatialContainerCreateInfo {
.type = XR_TYPE_SESSION_CREATE_INFO_SPATIAL_CONTAINERS_EXT,
};
XrSessionCreateInfo sessionCreateInfo {
.type = XR_TYPE_SESSION_CREATE_INFO,
.next = &spatialContainerCreateInfo, // Enable spatial containers
};
(void)sessionCreateInfo.systemId; // Other create fields set in usual way
CHK_XR(xrCreateSession(instance, &sessionCreateInfo, &session));
// Because spatial containers are enabled, the session is considered
// running. App is able to query perception data such as head poses and hand
// poses.
// Based on app logic or when a system lost event happens, destroy the
// session
CHK_XR(xrDestroySession(session));
New Object Types
New Commands
- xrCreateSpatialContainerEXT
- xrCreateSpatialContainerSpaceEXT
- xrDestroySpatialContainerEXT
- xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT
- xrGetSpatialContainerBoundsEXT
- xrGetSpatialContainerStateEXT
- xrRequestSpatialContainerBoundsModeEXT
- xrRequestSpatialContainerVisibleEXT
New Structures
- XrEventDataSpatialContainerBoundsChangedEXT
- XrEventDataSpatialContainerBoundsModeRequestDeniedEXT
- XrEventDataSpatialContainerClosedEXT
- XrEventDataSpatialContainerInteractableChangedEXT
- XrEventDataSpatialContainerVisibleChangedEXT
- XrEventDataSpatialContainerVisibleRequestDeniedEXT
- XrSpatialContainerBoundsEXT
- XrSpatialContainerBoundsGetInfoEXT
- XrSpatialContainerBoundsModeRequestInfoEXT
- XrSpatialContainerCreateInfoEXT
- XrSpatialContainerSpaceCreateInfoEXT
- XrSpatialContainerStateEXT
- XrSpatialContainerStateGetInfoEXT
- XrSpatialContainerVisibleRequestInfoEXT
Extending XrSessionCreateInfo :
Extending XrSystemProperties :
New Enums
- XrSpatialContainerBoundsModeEXT
- XrSpatialContainerGraphicsPresentationEXT
- XrSpatialContainerVolumeClippingEXT
New Enum Constants
XR_EXT_SPATIAL_CONTAINER_EXTENSION_NAMEXR_EXT_spatial_container_SPEC_VERSIONExtending XrObjectType :
XR_OBJECT_TYPE_SPATIAL_CONTAINER_EXT
Extending XrResult :
XR_ERROR_COMPATIBLE_SPATIAL_CONTAINER_MISSING_EXTXR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXTXR_ERROR_SPATIAL_CONTAINERS_NOT_ENABLED_EXTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXT
Extending XrStructureType :
XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_BOUNDS_CHANGED_EXTXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_BOUNDS_MODE_REQUEST_DENIED_EXTXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_CLOSED_EXTXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_INTERACTABLE_CHANGED_EXTXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_VISIBLE_CHANGED_EXTXR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_VISIBLE_REQUEST_DENIED_EXTXR_TYPE_SESSION_CREATE_INFO_SPATIAL_CONTAINERS_EXTXR_TYPE_SPATIAL_CONTAINER_BOUNDS_EXTXR_TYPE_SPATIAL_CONTAINER_BOUNDS_GET_INFO_EXTXR_TYPE_SPATIAL_CONTAINER_BOUNDS_MODE_REQUEST_INFO_EXTXR_TYPE_SPATIAL_CONTAINER_CREATE_INFO_EXTXR_TYPE_SPATIAL_CONTAINER_SPACE_CREATE_INFO_EXTXR_TYPE_SPATIAL_CONTAINER_STATE_EXTXR_TYPE_SPATIAL_CONTAINER_STATE_GET_INFO_EXTXR_TYPE_SPATIAL_CONTAINER_VISIBLE_REQUEST_INFO_EXTXR_TYPE_SYSTEM_SPATIAL_CONTAINER_PROPERTIES_EXT
Issues
How do we handle multiple outstanding visible requests? Should the app get one change / denied back or multiple? The answer might be different if the calls are over multiple frames. The answer might also be different if the multiple requests result in a noop, i.e. requesting a spatial container to be visible, then not visible for a container that starts out not visible.
- Resolved. Different choices for change events and denied events. Noop requests do not queue a change event, this just generates noise for the app developer and is easy for runtimes to filter out. If multiple visible requests get denied, runtimes must each generate a corresponding denied event.
How is a conformance automation extension expected to be defined so that all the optional spec text for policy behaviors is still testable by CTS?
- Resolved. Separate test extension. There will be a test extension runtimes implement for CTS only, allowing CTS to control all the system policy.
Do we need an event for when a spatial container’s position changes?
- Resolved. No. The spatial container space is non-world locked and other such spaces, like
XR_REFERENCE_SPACE_TYPE_VIEW, do not have events when they change.
- Resolved. No. The spatial container space is non-world locked and other such spaces, like
How does xrSyncActions work if there are multiple spatial containers?
- Resolved. No change needed. xrSyncActions would apply to all spatial containers in the session. If an app wants to direct the input actions to a particular spatial container it can look at interactable per-container state to choose which containers are valid targets. If an app wants to only sync the input action state for a single spatial container that would require an additional extension. However, we expect to instead focus on an extension that allows apps to be fully event based and avoid the need for an xrSyncActions call in a frame loop.
How does infrequently updated apps deal with input?
- Resolved. No change needed. While valuable to EXT_spatial_container, it is also valuable outside of spatial containers. This is able to be handled via an event channel extension and work in both cases. For spatial containers we will add additional ways to filter events for a single spatial container.
Do we need a wait to throttle / control timing of the input loop for apps with decoupled input and rendering loops?
- Resolved. No change needed. This is expected to be handled via event channel and present request extensions. Present request extension allows rendering to be event based and decoupled from a frame loop.
Can a spatial container get its pose relative to other spatial containers? Key thoughts here: Do we have a use case for this? And if so, how do the spatial container spaces connect to LOCAL?
- Resolved. Yes. This is already possible for spatial containers within the same session by going through
XR_REFERENCE_SPACE_TYPE_VIEWand supporting view-dependent content is desirable. For sharing spatial container poses across sessions (like to another process) the expected path is to leverageXR_EXT_spatial_anchorand its existing persistence and sharing patterns.
- Resolved. Yes. This is already possible for spatial containers within the same session by going through
Is a spatial container’s space locatable if it is not visible?
- Resolved. No. The spatial container’s space is not locatable when the spatial container is not visible. This implies that it does not have spatialized audio nor is the app able to "warm up" view dependent content when the spatial_container is not visible. These are both ok because when a spatial container is not visible, the app is expected to stop any CPU / GPU load that is used for that spatial container.
Where is the spatial container space expected to be placed in the spatial container? Suggestions have been the center or the minimal point (minX, minY, minZ).
- Resolved. In the center. There is no location that does not move in most of the ways a spatial container resize UX is expected (moving edges). Center is commonly used in other parts of OpenXR. We did not align with windows in 2D computing, which use the minimum coordinate, because 3D model viewers often do not follow this convention.
When is a runtime expected to create resources underlying the spatial container? This sometimes involves IPC with system services.
- Resolved. Synchronously as part of
xrCreateSpatialContainerEXT. While there might be IPC involved, the actual creation of a container is generally expected to be cheap. Some vendors have global mutexes around managing containers but these are not expected to commonly be a long wait. Issues with mutex contention are vendor-specific bugs that are expected to get addressed by each vendor.
- Resolved. Synchronously as part of
Do we need a signal that an XrSession will create spatial containers and therefore not support the legacy rendering path?
- Resolved. Yes. We change the session state machine in a fundamental way.
Version History
Revision 1, 2026-08-06 (Jared Finder, Google)
- Initial extension description