### XR_EXT_spatial_container_self_rendering

**Name String**

`XR_EXT_spatial_container_self_rendering`

**Extension Type**

Instance extension

**Registered Extension Number**

814

**Revision**

1

**Ratification Status**

Not ratified

**Extension and Version Dependencies**

`XR_EXT_spatial_container`

**Last Modified Date**

2026-08-06

**IP Status**

No known IP claims.

**Contributors**

Lachlan Ford, Google  

Andreas Loeve Selvik, Meta Platforms  

Adam Gousetis, Meta Platforms  

Bjorn Swenson, LÖVR  

Cass Everitt, Meta Platforms  

Christian Kruse, Meta Platforms  

Denny Rönngren, Varjo Technologies  

Fredia Huya-Kouadio, Godot Engine  

Jakob Bornecrantz, NVIDIA  

Jared Finder, Google  

Jonathan Wright, Meta Platforms  

Jian Zhang, ByteDance  

Kurtis Eveleigh, Qualcomm  

Mauricio Narvaez, Meta Platforms  

Nick Klingensmith, Qualcomm  

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

## Overview

This extension defines "self rendering" for spatial containers. A self rendered spatial container's pixels are all generated by an app and submitted to the runtime using standard OpenXR swapchains and composition layers. Because spatial containers do not always take up all of a screen's pixels, the runtime informs apps of each spatial container's recommended resolution and view configuration to enable apps to render more efficiently.

This extension combined with `XR_EXT_spatial_container` is intended to offer a superset of the capabilities of conventional OpenXR 1.x core composition layer rendering. OpenXR 1.x runtimes that support graphical rendering and this extension **must** set [XrSystemSpatialContainerPropertiesEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSystemSpatialContainerPropertiesEXT) :: `supportsImmersive` to true to indicate they support immersive spatial containers.

## Spatial Container Rendering Lifecycle

To use self rendering for a spatial container, an app sets the [XrSpatialContainerCreateInfoEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerCreateInfoEXT) :: `graphicsPresentation` to `XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT` when calling [xrCreateSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrCreateSpatialContainerEXT) . Then that app **can** manage whether a spatial container is actively rendering by calling the [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) and [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) functions. These functions replace [xrBeginSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginSession) and [xrEndSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndSession) . They are not per-frame operations, such as [xrBeginFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame) and [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) .

Every frame, an app goes through the following steps:

- Call [xrWaitFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrWaitFrame) and [xrBeginFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame) . These functions have no container-specific structures and function as they do in the core spec.
- Retrieve view poses, projection parameters, and rendering recommendations for all spatial containers actively rendering with [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT) . For each spatial container, the runtime reports whether its composition layers **should** be rendered and the recommended way to render the layers by filling out [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) .
- Render pixels into composition layers normally. These operations have no container-specific structures.
- Submit composition layers for all spatial containers actively rendering by calling [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) and chaining [XrSpatialContainerLayerFrameEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerFrameEndInfoEXT) .

Destroying an [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle implicitly removes it from the active render set. An app **may** destroy a spatial container even if it made a successful call to [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) not associated with a corresponding call to [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) . The runtime **must** behave as if [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) is implicitly called if needed early in the implementation of [xrDestroySpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrDestroySpatialContainerEXT) if it returns successfully.

When an app receives an [XrEventDataSpatialContainerClosedEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrEventDataSpatialContainerClosedEXT) event for a container in the active render set, that app **should** call [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) and destroy the [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle.

The [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) function adds the spatial container to the per-session active render set, allowing an app to submit composition layers for the spatial container to [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) .

    XrResult xrBeginSpatialContainerRenderingEXT(
        XrSession                                   session,
        const XrSpatialContainerBeginInfoEXT*       beginInfo);

### Parameter Descriptions

- `session` is the [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) .
- `beginInfo` is a pointer to an [XrSpatialContainerBeginInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerBeginInfoEXT) structure.

Apps typically call this in response to a visible-changed event with [XrEventDataSpatialContainerVisibleChangedEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrEventDataSpatialContainerVisibleChangedEXT) :: `visible` set to true.

If the spatial container was not created with `XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT` when calling [xrCreateSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrCreateSpatialContainerEXT) , the runtime **must** return `XR_ERROR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MISSING_EXT` .

If the spatial container is already in the active render set, the runtime **must** return `XR_ERROR_SPATIAL_CONTAINER_IS_RENDERING_EXT` .

If [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) is called at a time when the app could not call [xrWaitFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrWaitFrame) (i.e. inside the [xrBeginFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame) and [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) window), the runtime **must** return `XR_ERROR_CALL_ORDER_INVALID` .

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrBeginSpatialContainerRenderingEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to calling [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrBeginSpatialContainerRenderingEXT-session-parameter) `session` **must** be a valid [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrBeginSpatialContainerRenderingEXT-beginInfo-parameter) `beginInfo` **must** be a pointer to a valid [XrSpatialContainerBeginInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerBeginInfoEXT) structure

### Thread Safety

- Access to the `session` parameter by any other [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) , [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) , or [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) call **must** be externally synchronized

### Return Codes

[Success](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-successcodes)

- `XR_SUCCESS`
- `XR_SESSION_LOSS_PENDING`

[Failure](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-errorcodes)

- `XR_ERROR_CALL_ORDER_INVALID`
- `XR_ERROR_FUNCTION_UNSUPPORTED`
- `XR_ERROR_HANDLE_INVALID`
- `XR_ERROR_INSTANCE_LOST`
- `XR_ERROR_RUNTIME_FAILURE`
- `XR_ERROR_SESSION_LOST`
- `XR_ERROR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MISSING_EXT`
- `XR_ERROR_SPATIAL_CONTAINER_IS_RENDERING_EXT`
- `XR_ERROR_VALIDATION_FAILURE`
- `XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED`

The [XrSpatialContainerBeginInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerBeginInfoEXT) structure is used to specify the parameters for beginning rendering of a spatial container.

    typedef struct XrSpatialContainerBeginInfoEXT {
        XrStructureType            type;
        const void*                next;
        XrSpatialContainerEXT      spatialContainer;
        XrViewConfigurationType    primaryViewConfigurationType;
    } XrSpatialContainerBeginInfoEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `spatialContainer` is the [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) to begin rendering.
- `primaryViewConfigurationType` is the primary [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) to be used for the spatial container.

`primaryViewConfigurationType` is the view configuration that the app intends to use when rendering. The runtime **may** decay the view configuration to a type with fewer views for optimization purposes (e.g. a container is very far away and small such that stereo is imperceptible). The runtime returns details about the decayed view configuration from calls to [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT) .

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerBeginInfoEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerBeginInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerBeginInfoEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerBeginInfoEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerBeginInfoEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerBeginInfoEXT-spatialContainer-parameter) `spatialContainer` **must** be a valid [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerBeginInfoEXT-primaryViewConfigurationType-parameter) `primaryViewConfigurationType` **must** be a valid [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) value

The [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) function removes the spatial container from the active render set.

    XrResult xrEndSpatialContainerRenderingEXT(
        XrSession                                   session,
        const XrSpatialContainerEndInfoEXT*         endInfo);

### Parameter Descriptions

- `session` is the [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) .
- `endInfo` is a pointer to an [XrSpatialContainerEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerEndInfoEXT) structure.

Apps typically call this in response to a visible-changed event with [XrEventDataSpatialContainerVisibleChangedEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrEventDataSpatialContainerVisibleChangedEXT) :: `visible` set to false.

If the spatial container is not in the active render set, the runtime **must** return `XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT` .

If [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) is called at a time when the app could not call [xrWaitFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrWaitFrame) (i.e. during the period between [xrBeginFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrBeginFrame) and [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) calls), the runtime **must** return `XR_ERROR_CALL_ORDER_INVALID` .

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrEndSpatialContainerRenderingEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to calling [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrEndSpatialContainerRenderingEXT-session-parameter) `session` **must** be a valid [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrEndSpatialContainerRenderingEXT-endInfo-parameter) `endInfo` **must** be a pointer to a valid [XrSpatialContainerEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerEndInfoEXT) structure

### Thread Safety

- Access to the `session` parameter by any other [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) , [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) , or [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) call **must** be externally synchronized

### Return Codes

[Success](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-successcodes)

- `XR_SUCCESS`
- `XR_SESSION_LOSS_PENDING`

[Failure](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-errorcodes)

- `XR_ERROR_CALL_ORDER_INVALID`
- `XR_ERROR_FUNCTION_UNSUPPORTED`
- `XR_ERROR_HANDLE_INVALID`
- `XR_ERROR_INSTANCE_LOST`
- `XR_ERROR_RUNTIME_FAILURE`
- `XR_ERROR_SESSION_LOST`
- `XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT`
- `XR_ERROR_VALIDATION_FAILURE`

The [XrSpatialContainerEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerEndInfoEXT) structure is used to specify the parameters for ending rendering of a spatial container.

    typedef struct XrSpatialContainerEndInfoEXT {
        XrStructureType          type;
        const void*              next;
        XrSpatialContainerEXT    spatialContainer;
    } XrSpatialContainerEndInfoEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `spatialContainer` is the [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) to end rendering.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerEndInfoEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerEndInfoEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerEndInfoEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerEndInfoEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerEndInfoEXT-spatialContainer-parameter) `spatialContainer` **must** be a valid [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle

## Locating views via [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT)

The [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT) function locates views for a set of spatial containers.

    XrResult xrLocateSpatialContainerViewsEXT(
        XrSession                                   session,
        const XrSpatialContainerViewsLocateInfoEXT* locateInfo,
        uint32_t                                    viewStateCount,
        XrSpatialContainerViewStateEXT*             viewStates,
        uint32_t                                    viewCount,
        XrView*                                     views);

### Parameter Descriptions

- `session` is the [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) .
- `locateInfo` is a pointer to an [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT) structure.
- `viewStateCount` is the count of the `viewStates` array.
- `viewStates` is a pointer to an array of [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) structures to be populated by the runtime.
- `viewCount` is the count of the `views` array.
- `views` is a pointer to an array of [XrView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrView) structures.

This function replaces [xrLocateViews](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrLocateViews) , allowing an app to query views for multiple spatial containers simultaneously.

Views for all spatial containers are returned in the single `views` array. The views are ordered based on the index of the spatial container in the [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT) :: `viewLocateInfos` array, then the view index for that container.

For example, if an app provides three spatial containers in [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT) :: `viewLocateInfos` :

- Index 0: `XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO` (1 view)
- Index 1: `XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO` (2 views)
- Index 2: `XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET` (4 views)

Then the runtime **must** fill out the `views` array with 7 views:

- `views` \[0\] is the view for container 0.
- `views` \[1\] is the left eye view for container 1.
- `views` \[2\] is the right eye view for container 1.
- `views` \[3\] is the left eye view for container 2.
- `views` \[4\] is the right eye view for container 2.
- `views` \[5\] is the left eye inset view for container 2.
- `views` \[6\] is the right eye inset view for container 2.

If `viewCount` is not equal to the sum of the view counts for each spatial container's requested view configuration type, the runtime **must** return `XR_ERROR_VALIDATION_FAILURE` .

The runtime **may** decay the view configuration to a type with fewer views for optimization purposes (e.g. a container is very far away and small such that stereo is imperceptible). If the runtime decays the view configuration, the runtime **must** still return the original number of views for that container, populating the extra views with duplicates of the decayed views. For example, if `XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO` is decayed to `XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO` , both index 0 and index 1 will contain the single mono view. Consequently, the total number of views returned in the `views` array is independent of if the runtime decided to decay any view configurations or not.

The runtime **should** adapt each [XrView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrView) :: `fov` returned such that the frustum is as small as possible while still containing the entire bounds of the corresponding spatial container. Runtimes **may** return non-symmetrical FOVs, for example if a spatial container is at an oblique angle to the user's view, or is partially occluded by another object. Runtimes **may** freely position the target rendering surface for the spatial container. Due to the nature of multi-app rendering, where spatial containers are detached from the user, the runtime **may** return [XrView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrView) values not suitable for pixel rendering, for example if the spatial container is not visible on screen there are no valid values to set [XrView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrView) :: `fov` to. In such cases, runtimes **must** set [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) :: `shouldSubmitLayers` to false.

The runtime returns additional per-spatial container rendering state information in the `viewStates` array. If `viewStateCount` is not equal to [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT) :: `viewLocateInfoCount` , the runtime **must** return `XR_ERROR_VALIDATION_FAILURE` .

After the runtime queues an [XrEventDataSpatialContainerClosedEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrEventDataSpatialContainerClosedEXT) event for a spatial container, this function **must** return `XR_FALSE` in [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) :: `shouldSubmitLayers` and 0 in [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) :: `viewStateFlags` for the corresponding spatial container.

For spatial containers with actively changing locations in the real world, the runtime **should** take the container's motion into account when filling out `views` to minimize reprojection artifacts.

If [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT) is called for one or more spatial containers not currently in the active render set, the runtime **must** return `XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT` .

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to calling [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-session-parameter) `session` **must** be a valid [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-locateInfo-parameter) `locateInfo` **must** be a pointer to a valid [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT) structure
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-viewStates-parameter) `viewStates` **must** be a pointer to an array of `viewStateCount` [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) structures
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-views-parameter) `views` **must** be a pointer to an array of `viewCount` [XrView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrView) structures
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-viewStateCount-arraylength) The `viewStateCount` parameter **must** be greater than `0`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-xrLocateSpatialContainerViewsEXT-viewCount-arraylength) The `viewCount` parameter **must** be greater than `0`

### Return Codes

[Success](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-successcodes)

- `XR_SUCCESS`
- `XR_SESSION_LOSS_PENDING`

[Failure](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#fundamentals-errorcodes)

- `XR_ERROR_FUNCTION_UNSUPPORTED`
- `XR_ERROR_HANDLE_INVALID`
- `XR_ERROR_INSTANCE_LOST`
- `XR_ERROR_RUNTIME_FAILURE`
- `XR_ERROR_SESSION_LOST`
- `XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT`
- `XR_ERROR_TIME_INVALID`
- `XR_ERROR_VALIDATION_FAILURE`
- `XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED`

The [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT) structure contains the parameters for locating views across a collection of spatial containers.

    typedef struct XrSpatialContainerViewsLocateInfoEXT {
        XrStructureType                               type;
        const void*                                   next;
        XrTime                                        displayTime;
        uint32_t                                      viewLocateInfoCount;
        const XrSpatialContainerViewLocateInfoEXT*    viewLocateInfos;
    } XrSpatialContainerViewsLocateInfoEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `displayTime` is the `XrTime` at which to locate the views.
- `viewLocateInfoCount` is the number of entries in the `viewLocateInfos` array.
- `viewLocateInfos` is a pointer to an array of [XrSpatialContainerViewLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewLocateInfoEXT) structures.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewsLocateInfoEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewsLocateInfoEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_VIEWS_LOCATE_INFO_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewsLocateInfoEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewsLocateInfoEXT-viewLocateInfos-parameter) `viewLocateInfos` **must** be a pointer to an array of `viewLocateInfoCount` valid [XrSpatialContainerViewLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewLocateInfoEXT) structures
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewsLocateInfoEXT-viewLocateInfoCount-arraylength) The `viewLocateInfoCount` parameter **must** be greater than `0`

The [XrSpatialContainerViewLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewLocateInfoEXT) structure contains the parameters for an individual spatial container to locate views for.

    typedef struct XrSpatialContainerViewLocateInfoEXT {
        XrStructureType            type;
        const void*                next;
        XrViewConfigurationType    viewConfigurationType;
        XrSpace                    space;
        XrSpatialContainerEXT      spatialContainer;
    } XrSpatialContainerViewLocateInfoEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `viewConfigurationType` is an [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) to be used for the spatial container.
- `space` is the [XrSpace](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpace) in which the spatial container's views are located.
- `spatialContainer` is the [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle.

The app **can** provide any valid [XrSpace](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpace) in `space` , however it is recommended that it provide the spatial container space for the corresponding [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) specified within the [XrSpatialContainerViewLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewLocateInfoEXT) structure.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerViewLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewLocateInfoEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_VIEW_LOCATE_INFO_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-viewConfigurationType-parameter) `viewConfigurationType` **must** be a valid [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) value
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-space-parameter) `space` **must** be a valid [XrSpace](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpace) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-spatialContainer-parameter) `spatialContainer` **must** be a valid [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewLocateInfoEXT-commonparent) Both of `space` and `spatialContainer` **must** have been created, allocated, or retrieved from the same [XrSession](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSession)

The [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) structure is populated by calls to [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT) with per-spatial container rendering suitability information.

    typedef struct XrSpatialContainerViewStateEXT {
        XrStructureType            type;
        void*                      next;
        XrViewStateFlags           viewStateFlags;
        XrViewConfigurationType    viewConfigurationType;
        XrBool32                   shouldSubmitLayers;
        XrExtent2Di                recommendedImageExtent;
    } XrSpatialContainerViewStateEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `viewStateFlags` is a bitmask of [XrViewStateFlags](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewStateFlags) . These flags have the same purpose as the viewStateFlags in the core [XrViewState](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewState) structure.
- `viewConfigurationType` is an [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) which indicates the view configuration type the runtime is using for the spatial container, which runtimes **may** decay to a view configuration with a lower number of views than the one requested.
- `shouldSubmitLayers` is an `XrBool32` returned by the runtime. If `XR_FALSE` , the app **should** avoid submitting composition for this spatial container as it is currently not visible or is in a state where rendering is not required.
- `recommendedImageExtent` is an [XrExtent2Di](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrExtent2Di) structure representing the recommended resolution for the spatial container.

As with core OpenXR view location, the app **must** check the [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) :: `viewStateFlags` to ensure the position and orientation are valid and tracked before using the view data for rendering.

The app **should** check `shouldSubmitLayers` and `viewConfigurationType` to avoid rendering more than the runtime recommends. When `shouldSubmitLayers` is false, the app changes its rendering behavior as follows:

- The app **must** not read the corresponding [XrView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrView) :: `fov` .
- The app **must** not read `recommendedImageExtent` .
- The app **should** avoid rendering to swapchains and submitting composition layers for the corresponding spatial container.
- The app **should** set [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) :: `retainPreviousSubmission` to true. If the app chooses to submit layers anyway, it is up to the runtime to determine what it wants to do with the layers (e.g. the runtime **may** choose to drop them).

`recommendedImageExtent` is explicitly for layers that will be updated based on the container position or user's view. When updating layers with content that depends on the spatial container's position or user's view (such as normal 3D content), the app **should** render to this smaller viewport instead of the default recommended view size. When updating layers with content that does not depend on the spatial container's position or user's view (such as static quad layers), the app **may** safely ignore these values. For view dependent layers, `recommendedImageExtent` is a recommendation to the app from the runtime intended to minimize aliasing and improve rendering performance. The app is free to submit at full resolution if it wishes.

The [XrExtent2Di](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrExtent2Di) :: `width` and [XrExtent2Di](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrExtent2Di) :: `height` of `recommendedImageExtent` **must** always be a positive integer less than or equal to the [XrViewConfigurationView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationView) :: `recommendedImageRectWidth` and [XrViewConfigurationView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationView) :: `recommendedImageRectHeight` of the [XrViewConfigurationView](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationView) for the spatial container's primary view configuration. An app **should** not recreate a swapchain solely because `recommendedImageExtent` changed, as it is a dynamic hint to the app specifying the [XrSwapchainSubImage](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSwapchainSubImage) :: `imageRect` to use in the [XrSwapchainSubImage](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSwapchainSubImage) of any full resolution composition layers it submits, and **can** change every frame.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewStateEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewStateEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_VIEW_STATE_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewStateEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewStateEXT-viewStateFlags-parameter) `viewStateFlags` **must** be a valid combination of [XrViewStateFlagBits](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewStateFlagBits) values
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewStateEXT-viewStateFlags-requiredbitmask) `viewStateFlags` **must** not be `0`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerViewStateEXT-viewConfigurationType-parameter) `viewConfigurationType` **must** be a valid [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) value

### View reference space

The view reference space remains unchanged as it is in OpenXR core. As in core, it is not intended for rendering use.

## Submitting layers via [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame)

In order to render spatial containers, the app **must** supply a list of layers associated with their respective spatial containers to [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) . This is accomplished via the [XrSpatialContainerLayerFrameEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerFrameEndInfoEXT) structure.

    typedef struct XrSpatialContainerLayerFrameEndInfoEXT {
        XrStructureType                      type;
        const void*                          next;
        uint32_t                             containerLayerCount;
        const XrSpatialContainerLayerEXT*    containerLayers;
    } XrSpatialContainerLayerFrameEndInfoEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `containerLayerCount` is the count of elements in the `containerLayers` array.
- `containerLayers` is a pointer to an array of [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) structures.

The `containerLayers` array contains an [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) for each spatial container in the active render set (the containers managed per-session by [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT) and [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT) ). Each [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) contains a list of [XrCompositionLayerBaseHeader](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerBaseHeader) pointers associated with the given spatial container. Runtimes **may** composite containers in any order they choose, independent of the order of the `containerLayers` . For example, runtimes **may** composite containers based on their depth relative to the user, have a spatial container act as a background layer, or 'pin' a spatial container such that it is always on top regardless of its depth. Runtimes **may** composite layers using different strategies for spatial containers in bounded or immersive modes. For example, runtimes **may** precomposite each bounded spatial container's composition layers into a single stereo quad layer that is combined with all other containers in a second composition step.

[XrFrameEndInfo](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrFrameEndInfo) :: `displayTime` and [XrFrameEndInfo](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrFrameEndInfo) :: `environmentBlendMode` will be applied to all spatial containers supplied in [XrSpatialContainerLayerFrameEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerFrameEndInfoEXT) .

When this structure is passed to [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) by being chained onto [XrFrameEndInfo](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrFrameEndInfo) , the following additional error cases are added based on the active render set:

- If a spatial container is referenced by more than one element of `containerLayers` , runtimes **must** return `XR_ERROR_SPATIAL_CONTAINER_DUPLICATE_EXT` .
- If a spatial container in the active render set is not referenced by an element of `containerLayers` , runtimes **must** return `XR_ERROR_SPATIAL_CONTAINER_MISSING_EXT` .
- If a spatial container referenced by `containerLayers` is not a member of the active render set, runtimes **must** return `XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT` .

Furthermore, if there are any spatial containers in the active render set and this structure is not chained onto [XrFrameEndInfo](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrFrameEndInfo) , runtimes **must** return `XR_ERROR_SPATIAL_CONTAINER_MISSING_EXT` .

In any of the above error cases, the runtime **must** not render any content for any spatial container.

If no spatial containers are in the active render set, an app **can** call [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) as long as it is not submitting any composition layers.

Note that individual swapchains **may** be submitted for multiple containers via layers in a valid structure, e.g. A quad layer rendered via a single swapchain submitted to multiple spatial containers. This case is handled uniformly with other rendering: the runtime **must** render the quad in all such spatial containers.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerFrameEndInfoEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerLayerFrameEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerFrameEndInfoEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerFrameEndInfoEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_LAYER_FRAME_END_INFO_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerFrameEndInfoEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerFrameEndInfoEXT-containerLayers-parameter) `containerLayers` **must** be a pointer to an array of `containerLayerCount` valid [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) structures
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerFrameEndInfoEXT-containerLayerCount-arraylength) The `containerLayerCount` parameter **must** be greater than `0`

The [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) structure groups standard composition layers and associates them with a specific spatial container.

    typedef struct XrSpatialContainerLayerEXT {
        XrStructureType                               type;
        const void*                                   next;
        XrSpatialContainerEXT                         spatialContainer;
        XrBool32                                      retainPreviousSubmission;
        uint32_t                                      layerCount;
        const XrCompositionLayerBaseHeader* const*    layers;
    } XrSpatialContainerLayerEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `spatialContainer` is the [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) identifying the target container.
- `retainPreviousSubmission` is an `XrBool32` . If `XR_TRUE` , the runtime will retain the last submitted frame for this spatial container.
- `layerCount` is the number of composition layers in the `layers` array.
- `layers` is a pointer to an array of [XrCompositionLayerBaseHeader](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerBaseHeader) pointers.

When `retainPreviousSubmission` is `XR_TRUE` , the runtime **must** reuse the composition layers and swapchain image contents as latched during the most recent [xrEndFrame](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrEndFrame) call where `retainPreviousSubmission` was `XR_FALSE` . Any subsequent modifications to swapchains used by retained layers **must** not be reflected in the rendered output.

For layers submitted for an individual spatial container (intra-container rendering), the runtime **must** follow the already specified rules for layer composition ordering. That is to say the layers within containers **must** be drawn in the same order as they are specified, composed via painter's algorithm.

"Clearing" a spatial container refers to the removal of all content from a spatial container, resulting in nothing being rendered for that container in the current frame. Runtimes **must** treat this equivalent to the app submitting transparent black (all bits 0) for every pixel inside the container. "Retaining" a spatial container refers to the runtime continuing to display the most recently submitted set of layers for that container.

For each spatial container the app **can** specify whether to submit new layers, retain the previous submission, or clear the spatial container:

- To submit new layers, the app provides a non-zero `layerCount` and a valid `layers` pointer.
- To clear a spatial container, the `layerCount` for its entry **must** be 0 and `retainPreviousSubmission` **must** be `XR_FALSE` .
- To retain the last submitted layers and swapchain images (retaining), the `layerCount` for its entry **must** be 0 and `retainPreviousSubmission` **must** be `XR_TRUE` .

This explicit per-container control ensures that the app's intent is clearly communicated in every frame.

If `retainPreviousSubmission` is `XR_TRUE` and `layerCount` is not 0, the runtime **must** return `XR_ERROR_VALIDATION_FAILURE` .

If [XrSpatialContainerCompositionLayerViewConfigurationEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerCompositionLayerViewConfigurationEXT) is not chained to an [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) that is part of a spatial container, the runtime **must** return `XR_ERROR_VALIDATION_FAILURE` . This structure is only applicable to [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) layers. If it is chained to other layer types (e.g. quad or cylinder layers), the runtime **must** return `XR_ERROR_VALIDATION_FAILURE` .

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains) . See also: [XrSpatialContainerLayerVolumeClippingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerVolumeClippingEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerEXT-spatialContainer-parameter) `spatialContainer` **must** be a valid [XrSpatialContainerEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerEXT) handle
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerEXT-layers-parameter) If `layerCount` is not `0` , `layers` **must** be a pointer to an array of `layerCount` valid [XrCompositionLayerBaseHeader](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerBaseHeader) -based structures. See also: [XrCompositionLayerCubeKHR](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerCubeKHR) , [XrCompositionLayerCylinderKHR](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerCylinderKHR) , [XrCompositionLayerEquirect2KHR](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerEquirect2KHR) , [XrCompositionLayerEquirectKHR](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerEquirectKHR) , [XrCompositionLayerPassthroughANDROID](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerPassthroughANDROID) , [XrCompositionLayerPassthroughFB](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerPassthroughFB) , [XrCompositionLayerPassthroughHTC](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerPassthroughHTC) , [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) , [XrCompositionLayerQuad](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerQuad)

### Specifying View Configuration for Projection Layers

The [XrSpatialContainerCompositionLayerViewConfigurationEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerCompositionLayerViewConfigurationEXT) structure is used to specify the view configuration used to render a projection layer for a spatial container.

    typedef struct XrSpatialContainerCompositionLayerViewConfigurationEXT {
        XrStructureType            type;
        const void*                next;
        XrViewConfigurationType    viewConfigurationType;
    } XrSpatialContainerCompositionLayerViewConfigurationEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `viewConfigurationType` is the [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) that was used to render the [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) .

When submitting an [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) for a spatial container, the app **must** specify which view configuration was used to render the layer. This is necessary because the app **can** choose each frame whether to render with the spatial container's primary view configuration or the runtime's suggested decayed view configuration, if any.

When [XrSpatialContainerCompositionLayerViewConfigurationEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerCompositionLayerViewConfigurationEXT) is chained, the app **must** ensure that [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) :: `viewCount` is a valid view count for the [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) specified in the chained structure. The `viewConfigurationType` specified in the chained structure **must** be the [XrSpatialContainerBeginInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerBeginInfoEXT) :: `primaryViewConfigurationType` specified when the container was begun, or the decayed view configuration type returned by the runtime in [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT) , or additional values enabled through an extension.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerCompositionLayerViewConfigurationEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerCompositionLayerViewConfigurationEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerCompositionLayerViewConfigurationEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerCompositionLayerViewConfigurationEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_COMPOSITION_LAYER_VIEW_CONFIGURATION_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerCompositionLayerViewConfigurationEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerCompositionLayerViewConfigurationEXT-viewConfigurationType-parameter) `viewConfigurationType` **must** be a valid [XrViewConfigurationType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrViewConfigurationType) value

### Pixel clipping behavior

Apps **should** inform the runtime if they render pixels outside of a spatial container's bounds or not by chaining [XrSpatialContainerLayerVolumeClippingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerVolumeClippingEXT) when submitting composition layers.

    typedef struct XrSpatialContainerLayerVolumeClippingEXT {
        XrStructureType                        type;
        const void*                            next;
        XrSpatialContainerVolumeClippingEXT    volumeClipping;
    } XrSpatialContainerLayerVolumeClippingEXT;

### Member Description

- `type` is the [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) of this structure.
- `next` is `NULL` or a pointer to the next structure in a structure chain.
- `volumeClipping` is the [XrSpatialContainerVolumeClippingEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerVolumeClippingEXT) the app has applied.

This structure serves as a hint for if the app renders pixels outside the bounds of a spatial container. When a spatial container is in immersive mode, because the bounds are infinite this hint has no meaning.

For bounded spatial containers using self rendering, the runtime needs to reason about both the 3D volume bounds and the 2D pixel bounds. The 3D volume bounds is returned from [xrGetSpatialContainerBoundsEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#xrGetSpatialContainerBoundsEXT) . The 2D pixel bounds is the projection of the 3D volume bounds onto each display for the system.

Runtimes **must** discard pixels from swapchain images outside the 2D pixel bounds, however runtimes **must** not discard pixels that are inside the 2D pixel bounds but outside of the 3D volume bounds. Stereo effects where content appears to extend beyond or in front of the container's 3D volume bounds are possible. Apps **may** discard pixels outside of the 3D volume bounds of a bounded spatial container to reduce depth paradoxes and **should** set `volumeClipping` based on how they do so. Depth paradoxes often cause eye strain and user discomfort.

Runtimes **may** use `volumeClipping` to adjust how they display a particular spatial container. For example, when set to `XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT` a runtime could render rear faces of the 3D volume bounds that would cause depth paradoxes if the spatial container drew pixels behind the container's 3D volume bounds.

Future extensions **may** allow for clipping based the 3D volume bounds if depth information is submitted.

### Valid Usage (Implicit)

- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerVolumeClippingEXT-extension-notenabled) The `XR_EXT_spatial_container_self_rendering` extension **must** be enabled prior to using [XrSpatialContainerLayerVolumeClippingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerVolumeClippingEXT)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerVolumeClippingEXT-type-type) `type` **must** be `XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT`
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerVolumeClippingEXT-next-next) `next` **must** be `NULL` or a valid pointer to the [next structure in a structure chain](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#valid-usage-for-structure-pointer-chains)
- [](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#VUID-XrSpatialContainerLayerVolumeClippingEXT-volumeClipping-parameter) `volumeClipping` **must** be a valid [XrSpatialContainerVolumeClippingEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerVolumeClippingEXT) value

## New Commands

- [xrBeginSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrBeginSpatialContainerRenderingEXT)
- [xrEndSpatialContainerRenderingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrEndSpatialContainerRenderingEXT)
- [xrLocateSpatialContainerViewsEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#xrLocateSpatialContainerViewsEXT)

## New Structures

- [XrSpatialContainerBeginInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerBeginInfoEXT)
- [XrSpatialContainerEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerEndInfoEXT)
- [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT)
- [XrSpatialContainerViewLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewLocateInfoEXT)
- [XrSpatialContainerViewStateEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewStateEXT)
- [XrSpatialContainerViewsLocateInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerViewsLocateInfoEXT)
- Extending [XrCompositionLayerProjection](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrCompositionLayerProjection) :

  - [XrSpatialContainerCompositionLayerViewConfigurationEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerCompositionLayerViewConfigurationEXT)
- Extending [XrFrameEndInfo](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrFrameEndInfo) :

  - [XrSpatialContainerLayerFrameEndInfoEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerFrameEndInfoEXT)
- Extending [XrSpatialContainerLayerEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerEXT) :

  - [XrSpatialContainerLayerVolumeClippingEXT](https://developer.android.com/develop/xr/openxr/extensions/XR_EXT_spatial_container_self_rendering#XrSpatialContainerLayerVolumeClippingEXT)

## New Enum Constants

- `XR_EXT_SPATIAL_CONTAINER_SELF_RENDERING_EXTENSION_NAME`
- `XR_EXT_spatial_container_self_rendering_SPEC_VERSION`
- Extending [XrResult](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrResult) :

  - `XR_ERROR_SPATIAL_CONTAINER_DUPLICATE_EXT`
  - `XR_ERROR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_MISSING_EXT`
  - `XR_ERROR_SPATIAL_CONTAINER_IS_RENDERING_EXT`
  - `XR_ERROR_SPATIAL_CONTAINER_MISSING_EXT`
  - `XR_ERROR_SPATIAL_CONTAINER_NOT_RENDERING_EXT`
- Extending [XrSpatialContainerGraphicsPresentationEXT](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrSpatialContainerGraphicsPresentationEXT) :

  - `XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT`
- Extending [XrStructureType](https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XrStructureType) :

  - `XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_COMPOSITION_LAYER_VIEW_CONFIGURATION_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_LAYER_FRAME_END_INFO_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_VIEWS_LOCATE_INFO_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_VIEW_LOCATE_INFO_EXT`
  - `XR_TYPE_SPATIAL_CONTAINER_VIEW_STATE_EXT`

## Code Samples

    // Example: Complete lifecycle, view location, and frame submission for spatial containers
    PFN_xrBeginSpatialContainerRenderingEXT xrBeginSpatialContainerRenderingEXT; // previously initialized
    PFN_xrEndSpatialContainerRenderingEXT xrEndSpatialContainerRenderingEXT; // previously initialized
    PFN_xrLocateSpatialContainerViewsEXT xrLocateSpatialContainerViewsEXT; // previously initialized

    XrSession session; // previously initialized

    // We want to update this container
    XrSpatialContainerEXT containerA; // previously initialized with XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
    XrSpace containerASpace; // previously initialized

    // We want to retain this container
    XrSpatialContainerEXT containerB; // previously initialized with XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
    XrSpace containerBSpace; // previously initialized

    // 1. Add to active render set when the app is ready to start submitting layers
    XrSpatialContainerBeginInfoEXT beginInfoA {
      .type = XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT,
      .spatialContainer = containerA,
      .primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
    };
    CHK_XR(xrBeginSpatialContainerRenderingEXT(session, &beginInfoA));

    XrSpatialContainerBeginInfoEXT beginInfoB {
      .type = XR_TYPE_SPATIAL_CONTAINER_BEGIN_INFO_EXT,
      .spatialContainer = containerB,
      .primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
    };
    CHK_XR(xrBeginSpatialContainerRenderingEXT(session, &beginInfoB));

    // ... Frame Loop ...


    XrTime displayTime; // returned from xrWaitFrame

    const std::vector<XrSpatialContainerEXT> containers = {containerA, containerB};
    const std::vector<XrSpace> containerSpaces = {containerASpace, containerBSpace};
    uint32_t containerCount = static_cast<uint32_t>(containers.size());

    // 2. Setup individual locate info for each container
    std::vector<XrSpatialContainerViewLocateInfoEXT> containerLocateInfos(containerCount, {
      .type = XR_TYPE_SPATIAL_CONTAINER_VIEW_LOCATE_INFO_EXT,
    });

    for (uint32_t i = 0; i < containerCount; ++i) {
        containerLocateInfos[i].viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
        containerLocateInfos[i].space = containerSpaces[i]; // Recommended to use container's own space
        containerLocateInfos[i].spatialContainer = containers[i];
    }

    // Setup bulk locate info
    XrSpatialContainerViewsLocateInfoEXT locateInfo {
      .type = XR_TYPE_SPATIAL_CONTAINER_VIEWS_LOCATE_INFO_EXT,
      .displayTime = displayTime,
      .viewLocateInfoCount = containerCount,
      .viewLocateInfos = containerLocateInfos.data(),
    };

    // Prepare states to be populated by the runtime
    std::vector<XrSpatialContainerViewStateEXT> viewStates(containerCount, {
      .type = XR_TYPE_SPATIAL_CONTAINER_VIEW_STATE_EXT,
    });

    // Call the dedicated locate views function
    // We know the required view count is 2 per container for STEREO
    const uint32_t viewsPerConfig = 2;
    uint32_t totalViewCount = containerCount * viewsPerConfig;
    std::vector<XrView> views(totalViewCount, {.type = XR_TYPE_VIEW});

    CHK_XR(xrLocateSpatialContainerViewsEXT(session, &locateInfo, containerCount, viewStates.data(), totalViewCount, views.data()));

    // Process results
    for (uint32_t i = 0; i < containerCount; ++i) {
        XrBool32 shouldSubmitLayers = viewStates[i].shouldSubmitLayers;
        XrExtent2Di recommendedImageExtent = viewStates[i].recommendedImageExtent;
        XrViewConfigurationType viewConfigurationType = viewStates[i].viewConfigurationType;
        bool isDecayedToMono = (viewConfigurationType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO);
        if (shouldSubmitLayers) {
            // App is expected to also verify viewStates[i].viewStateFlags has valid orientation/position bits before rendering
            XrView& leftView = views[i * viewsPerConfig];
            XrView& rightView = views[i * viewsPerConfig + 1];
            // If isDecayedToMono is true, left and right will be identical.
        } else {
            // Skip layer submission but retain previous submission when calling
            // xrEndFrame.
        }
    }

    // 3. Setup projection layer for container A
    XrCompositionLayerProjection projectionLayer = {.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION};
    // ... standard projection layer setup (space, viewCount, views, etc.) ...

    // Specify which view configuration was used to render this specific layer
    XrSpatialContainerCompositionLayerViewConfigurationEXT containerViewConfig {
      .type = XR_TYPE_SPATIAL_CONTAINER_COMPOSITION_LAYER_VIEW_CONFIGURATION_EXT,
      // Even if the runtime decayed to MONO, we indicate what we actually rendered
      .viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
    };

    // Chain it to the projection layer
    projectionLayer.next = &containerViewConfig;
    const XrCompositionLayerBaseHeader* layersA[1] = {reinterpret_cast<const XrCompositionLayerBaseHeader*>(&projectionLayer)};

    // Note: In a real app, you are required to submit ALL active containers in the render set.

    XrSpatialContainerLayerVolumeClippingEXT containerClippingA = {
      .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT,
      // Set volumeClipping appropriately for the rendering done.
      .volumeClipping = XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT,
    };

    // Setup container A (Update with new pixels)
    XrSpatialContainerLayerEXT containerLayerA {
      .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT,
      .next = &containerClippingA,
      .spatialContainer = containerA,
      .retainPreviousSubmission = XR_FALSE,
      .layerCount = 1,
      .layers = layersA,
    };

    XrSpatialContainerLayerVolumeClippingEXT containerClippingB {
      .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_VOLUME_CLIPPING_EXT,
      // Set volumeClipping appropriately for the rendering done.
      .volumeClipping = XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT,
    };

    // Setup container B (Explicitly retain previous frame)
    XrSpatialContainerLayerEXT containerLayerB {
      .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_EXT,
      .next = &containerClippingB,
      .spatialContainer = containerB,
      .retainPreviousSubmission = XR_TRUE,
      .layerCount = 0, // Required to be 0 when retaining
      .layers = nullptr,
    };

    // Aggregate all container layers
    XrSpatialContainerLayerEXT containerLayers[] = { containerLayerA, containerLayerB };

    XrSpatialContainerLayerFrameEndInfoEXT spatialEndInfo {
      .type = XR_TYPE_SPATIAL_CONTAINER_LAYER_FRAME_END_INFO_EXT,
      .containerLayerCount = 2, // Must equal the number of active containers
      .containerLayers = containerLayers,
    };

    XrFrameEndInfo frameEndInfo {
      .type = XR_TYPE_FRAME_END_INFO,
      .next = &spatialEndInfo,
      .displayTime = displayTime,
      .environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND,
      .layerCount = 0, // MANDATORY: Must be 0 for self rendering extension
    };

    CHK_XR(xrEndFrame(session, &frameEndInfo));

    // ... End Frame Loop ...

    // 4. Remove from active render set when the container is destroyed or no longer needs rendering
    XrSpatialContainerEndInfoEXT endInfoA {
      .type = XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT,
      .spatialContainer = containerA,
    };
    CHK_XR(xrEndSpatialContainerRenderingEXT(session, &endInfoA));

    XrSpatialContainerEndInfoEXT endInfoB {
      .type = XR_TYPE_SPATIAL_CONTAINER_END_INFO_EXT,
      .spatialContainer = containerB,
    };
    CHK_XR(xrEndSpatialContainerRenderingEXT(session, &endInfoB));

## Version History

- Revision 1, 2026-08-06 (Lachlan Ford)

  - Initial extension description