XR_EXT_spatial_container
名称字符串
XR_EXT_spatial_container
扩展程序类型
实例扩展程序
已注册的扩展程序编号
811
修订版本
1
批准状态
未批准
扩展程序和版本依赖项
上次修改日期
2026-08-06
IP 状态
没有已知的 IP 权利主张。
创作贡献者
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
概览
此扩展定义了一类新的可显示实体,称为“空间容器”,类似于桌面 2D 窗口系统中的“窗口”概念。
在 OpenXR 1.x 中,应用可以独占控制用户看到的所有内容,以及这些内容如何叠加在用户的真实或虚拟环境之上。运行时只会对显示的内容进行细微修改,以确保用户安全。此应用模型非常适合让用户沉浸在单一体验中,但无法扩展到多个同时进行的体验。尤其是在 AR 和混合现实环境中,用户通常希望同时体验多个不同的应用。
空间容器就像是扩展到 3D 的窗口。用户能够同时看到多个空间容器,并向其中一部分容器提供输入。可见的空间容器可以属于不同的应用,运行时会代表用户管理其大小和位置。
除了现有的沉浸式 OpenXR 体验之外,此扩展程序还支持这些新型空间受限体验。有界 OpenXR 体验可以包含略带 3D 效果的内容(具有轻微深度偏移的平面面板)或承载全 3D 内容的体积。沉浸式 OpenXR 体验是指自 OpenXR 1.0 起就支持的现有全屏沉浸式应用。如果应用选择切换,则可以在这两种类型的内容之间切换。
此扩展程序未定义任何方法来让应用呈现其内容。如何绘制内容在其他扩展程序中定义:XR_EXT_spatial_container_self_rendering。
使用空间容器
XrSpatialContainerEXT 是表示空间容器的句柄。
XR_DEFINE_HANDLE(XrSpatialContainerEXT)
应用通过空间容器开始渲染,步骤如下:
- 使用 xrCreateSpatialContainerEXT 创建空间容器。
- 修改容器上的任何状态以进行初始呈现,例如其边界模式。
- 使用 xrRequestSpatialContainerVisibleEXT 请求运行时显示容器。
- 等待运行时准备好显示容器。当运行时准备就绪后,它会将 XrEventDataSpatialContainerVisibleChangedEXT 事件加入队列,并将
visible设置为XR_TRUE。 - 开始为空间容器进行渲染。
销毁空间容器的过程如下:
- 使用 xrRequestSpatialContainerVisibleEXT 请求运行时隐藏容器。
- 等待运行时完成隐藏容器。当运行时完全隐藏容器后,它会将 XrEventDataSpatialContainerVisibleChangedEXT 事件排入队列,并将
visible设置为XR_FALSE。 - 结束空间容器的渲染。
- 使用 xrDestroySpatialContainerEXT 销毁容器。
注意
根据设计,此扩展程序会将可见性和焦点管理委托给各个空间容器。由于会话作为一个整体不再代表单个可见或聚焦的对象,因此会话不会通过标准 OpenXR 状态机(READY、SYNCHRONIZED、VISIBLE、FOCUSED)进行转换。相反,会话会在其有效生命周期内保持 XR_SESSION_STATE_IDLE 状态,并且会话状态的变化中的规则会指定核心 OpenXR 操作如何映射到此模式。
创建空间容器
xrCreateSpatialContainerEXT 函数会创建一个新的空间容器。
XrResult xrCreateSpatialContainerEXT(
XrSession session,
const XrSpatialContainerCreateInfoEXT* createInfo,
XrSpatialContainerEXT* spatialContainer);
参数说明
session是创建该空间容器的 XrSession。createInfo是一个指向 XrSpatialContainerCreateInfoEXT 的指针,其中包含用于创建空间容器的参数。spatialContainer是一个指向句柄的指针,创建的 XrSpatialContainerEXT 将通过该句柄返回。
新创建的 XrSpatialContainerEXT 必须不可见、不可交互,并且处于边界模式 XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT。如果应用希望空间容器以沉浸模式启动,则可以在请求显示空间容器之前,请求 XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT 的边界模式。
如果 XrSpatialContainerCreateInfoEXT :: suggestedBounds 的任何维度为负数、无穷大或非数字,则运行时必须返回 XR_ERROR_VALIDATION_FAILURE。如果应用尝试创建的空间容器数量超过 XrSystemSpatialContainerPropertiesEXT :: maxSpatialContainerCount 中指定的数量,运行时必须返回 XR_ERROR_LIMIT_REACHED。如果未为此会话启用空间容器,则运行时必须返回 XR_ERROR_SPATIAL_CONTAINERS_NOT_ENABLED_EXT。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrCreateSpatialContainerEXT -
session必须是有效的 XrSession 句柄 -
createInfo必须是指向有效 XrSpatialContainerCreateInfoEXT 结构的指针 -
spatialContainer必须是指向 XrSpatialContainerEXT 句柄的指针
返回代码
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
XrSpatialContainerCreateInfoEXT 会传递给 xrCreateSpatialContainerEXT,以创建空间容器。
typedef struct XrSpatialContainerCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpatialContainerGraphicsPresentationEXT graphicsPresentation;
XrExtent3Df suggestedBounds;
} XrSpatialContainerCreateInfoEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。graphicsPresentation是一个 XrSpatialContainerGraphicsPresentationEXT,用于描述此空间容器如何呈现图形。suggestedBounds是一个 XrExtent3Df,用于描述所请求的空间容器尺寸(以米为单位)。
对尺寸没有偏好的应用可以将 suggestedBounds 设置为 {0, 0, 0}。运行时可能会忽略请求的 suggestedBounds。
如果运行时允许空间容器由定向框以外的形状限定,则必须使用 suggestedBounds 作为其他形状周围的边界框。定向框是最常见的边界形状。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerCreateInfoEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_CREATE_INFO_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针 -
graphicsPresentation必须是有效的 XrSpatialContainerGraphicsPresentationEXT 值
当空间容器不再可用时,运行时必须将 XrEventDataSpatialContainerClosedEXT 事件加入队列。
typedef struct XrEventDataSpatialContainerClosedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrEventDataSpatialContainerClosedEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是此事件所针对的 XrSpatialContainerEXT。
收到 XrEventDataSpatialContainerClosedEXT 事件表示运行时无法再显示空间容器,例如由于用户点击了“关闭”按钮或会话进入 XR_SESSION_STATE_LOSS_PENDING 状态。
收到 XrEventDataSpatialContainerClosedEXT 事件后,应用应停止使用该空间容器,销毁任何关联的状态(例如渲染循环),并销毁该容器。对于在该容器上运行的所有函数(xrDestroySpatialContainerEXT 除外),运行时必须返回 XR_ERROR_SPATIAL_CONTAINER_CLOSED_EXT。
如果运行时将关闭事件加入队列时空间容器可见,则运行时必须先将容器更改为不可见,并将 XrEventDataSpatialContainerVisibleChangedEXT 事件加入队列。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrEventDataSpatialContainerClosedEXT -
type必须为XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_CLOSED_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
xrDestroySpatialContainerEXT 函数用于销毁现有空间容器。
XrResult xrDestroySpatialContainerEXT(
XrSpatialContainerEXT spatialContainer);
参数说明
spatialContainer是一个先前由 xrCreateSpatialContainerEXT 创建的 XrSpatialContainerEXT。
空间容器销毁后,运行时不得再显示容器的内容,也不得将有关容器的任何其他事件加入队列。
应用不应销毁可见的空间容器,因为这样做可能会导致图形伪影,应用应使用 xrRequestSpatialContainerVisibleEXT 请求隐藏空间容器,等待 XrEventDataSpatialContainerVisibleChangedEXT 事件,然后销毁容器。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrDestroySpatialContainerEXT -
spatialContainer必须是有效的 XrSpatialContainerEXT 句柄
线程安全
- 对
spatialContainer及其任何子句柄的访问都必须在外部进行同步
返回代码
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_RUNTIME_FAILURE
空间容器空间
xrCreateSpatialContainerSpaceEXT 函数会为特定空间容器的空间容器空间创建一个 XrSpace 句柄。
XrResult xrCreateSpatialContainerSpaceEXT(
XrSession session,
const XrSpatialContainerSpaceCreateInfoEXT* createInfo,
XrSpace* space);
参数说明
session是创建该空间的 XrSession。createInfo是一个指向 XrSpatialContainerSpaceCreateInfoEXT 的指针,其中包含用于创建空间的参数。space是一个指向句柄的指针,创建的 XrSpace 将通过该句柄返回。
任何给定空间容器的“空间容器空间”都是一个坐标系,其原点位于该空间容器边界的中心。此空间通常用作 xrLocateSpace 等函数的基础空间。
+X 指向容器的右侧面,+Y 指向容器的顶面,+Z 指向容器的前面。例如,如果容器与重力对齐,位于查看者前方,并且查看者相对于 LOCAL 空间处于单位姿态,则运行时必须使容器空间相对于 LOCAL 空间具有单位方向。当容器变为可见时,运行时可以将容器空间相对于 LOCAL 空间的姿势设置为任意姿势。
ext 空间容器空间约定
图 18. 空间容器空间的轴惯例
空间容器空间是非世界锁定的原点。如果应用在沉浸模式下需要世界锁定原点,可以使用世界锁定空间,例如 XR_REFERENCE_SPACE_TYPE_LOCAL。
运行时可以随时更改空间容器空间的姿态,通常是为了支持用户将空间容器移动到不同的位置或旋转。在 XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT 和 XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT 边界模式之间转换时,运行时可能也会更改姿势。
即使空间容器空间所对应的空间容器已通过 xrDestroySpatialContainerEXT 销毁,空间容器空间必须继续作为有效句柄。当空间容器不可见或被销毁时,空间容器空间必须相对于其他空间无法定位。XrSpaceLocation :: locationFlags 和 XrViewState ::viewStateFlags 将为 0。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrCreateSpatialContainerSpaceEXT -
session必须是有效的 XrSession 句柄 -
createInfo必须是指向有效 XrSpatialContainerSpaceCreateInfoEXT 结构的指针 -
space必须是指向 XrSpace 句柄的指针
返回代码
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
XrSpatialContainerSpaceCreateInfoEXT 与 xrCreateSpatialContainerSpaceEXT 搭配使用,可创建 XrSpace 句柄。
typedef struct XrSpatialContainerSpaceCreateInfoEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrSpatialContainerSpaceCreateInfoEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是要为其创建空间的 XrSpatialContainerEXT。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerSpaceCreateInfoEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_SPACE_CREATE_INFO_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针 -
spatialContainer必须是有效的 XrSpatialContainerEXT 句柄
呈现空间容器
将空间容器的内容提交到 OpenXR 进行显示的操作由其他扩展程序处理:XR_EXT_spatial_container_self_rendering。
为了允许其他扩展程序为空间容器指定图形呈现方法,此扩展程序定义了 XrSpatialContainerGraphicsPresentationEXT 枚举。
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;
枚举说明
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SELF_RENDERING_EXT
空间容器使用 OpenXR 合成层(由 XR_EXT_spatial_container_self_rendering 扩展程序添加)
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_CONFORMANCE_AUTOMATION_EXT
空间容器是为一致性测试而创建的,没有渲染路径(由 XR_EXT_spatial_container_conformance_automation 扩展程序添加)
XR_SPATIAL_CONTAINER_GRAPHICS_PRESENTATION_SYSTEM_RENDERING_EXTX1
空间容器使用 OpenXR 系统渲染(由 XR_EXTX1_system_renderer 扩展程序添加)
空间容器状态
空间容器状态由运行时根据应用请求和用户需求进行管理。因此,空间容器状态的每个方面都会记录以下内容:
- 允许运行时更改空间容器状态。对于大多数空间容器状态,运行时可以随时更改状态。
- 应用如何请求更改状态。运行时可以推迟任何请求,直到它认为该请求合适为止。当请求被延迟时,运行时不会将事件加入队列,因此应用不应等待此类事件来执行不相关的逻辑。
- 空间容器状态发生变化时,事件运行时会排队。运行时会为所有更改(包括应用请求的更改和运行时发起的更改)将事件加入队列。运行时不得将未指示更改的状态更改事件加入队列,例如应用连续快速发出两个隐藏容器的请求。
- 拒绝应用更改请求时,事件运行时会排队。运行时可以出于任何原因拒绝请求,通常是由于与维持高质量用户体验相关的系统政策。
xrGetSpatialContainerStateEXT 函数用于查询空间容器的当前状态。
XrResult xrGetSpatialContainerStateEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerStateGetInfoEXT* getInfo,
XrSpatialContainerStateEXT* state);
参数说明
spatialContainer是要查询的 XrSpatialContainerEXT。getInfo是 XrSpatialContainerStateGetInfoEXT,其中包含了用于获取空间容器状态的信息。state是一个指向 XrSpatialContainerStateEXT 的指针,空间容器状态将通过该指针返回。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrGetSpatialContainerStateEXT -
spatialContainer必须是有效的 XrSpatialContainerEXT 句柄 - 如果
getInfo不是NULL,则getInfo必须是指向有效 XrSpatialContainerStateGetInfoEXT 结构的指针 -
state必须是指向 XrSpatialContainerStateEXT 结构的指针
返回代码
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
XrSpatialContainerStateGetInfoEXT 与 xrGetSpatialContainerStateEXT 搭配使用,可查询 XrSpatialContainerStateEXT。
typedef struct XrSpatialContainerStateGetInfoEXT {
XrStructureType type;
const void* next;
} XrSpatialContainerStateGetInfoEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerStateGetInfoEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_STATE_GET_INFO_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
typedef struct XrSpatialContainerStateEXT {
XrStructureType type;
void* next;
XrBool32 visible;
XrBool32 interactable;
XrSpatialContainerBoundsModeEXT boundsMode;
} XrSpatialContainerStateEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。visible表示空间容器是否可见。interactable表示空间容器当前是否能够接收任何类型的输入。这类似于桌面 2D 窗口系统的“焦点”,不同之处在于,多个空间容器可能同时可交互。boundsMode是空间容器的当前 XrSpatialContainerBoundsModeEXT。
空间容器状态的变化通过事件进行传达。
“字段已更改”事件
visible
XrEventDataSpatialContainerVisibleChangedEXT
interactable
XrEventDataSpatialContainerInteractableChangedEXT
boundsMode
XrEventDataSpatialContainerBoundsChangedEXT
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerStateEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_STATE_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
公开范围
应用通过 xrRequestSpatialContainerVisibleEXT 请求显示或隐藏空间容器。
XrResult xrRequestSpatialContainerVisibleEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerVisibleRequestInfoEXT* info);
参数说明
spatialContainer是要请求更改的 XrSpatialContainerEXT。info是一个指向 XrSpatialContainerVisibleRequestInfoEXT 的指针,其中包含请求的可见状态。
显示或隐藏空间容器是一项异步操作。
应用应在销毁空间容器之前请求将其隐藏,以便运行时显示平滑过渡。运行时应遵循隐藏空间容器的请求。
运行时可以拒绝显示空间容器的请求,在这种情况下,运行时必须将 XrEventDataSpatialContainerVisibleRequestDeniedEXT 事件加入队列。例如,如果用户通过与系统提供的“最小化”按钮互动隐藏了空间容器,某些运行时会拒绝显示该空间容器的请求。
在应用请求显示空间容器至少一次之前,运行时不得显示该空间容器。在应用首次请求显示空间容器后,运行时可以独立于应用的请求更改该空间容器的可见性。这样,应用就可以控制空间容器的初始状态和内容,而运行时则可以提供系统界面(例如任务栏),让用户能够选择哪些空间容器可见。
如果请求在 XrSystemSpatialContainerPropertiesEXT :: supportsBounded 和 XrSystemSpatialContainerPropertiesEXT :: supportsImmersive 不支持的边界模式下显示空间容器,运行时必须拒绝该请求。如果给定系统不支持默认边界模式 XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT,就可能会发生这种情况。
注意
在某些实现中,显示或隐藏空间容器需要与系统服务通信,并且可能会推迟到用户与系统对话框互动之后。请求可见性状态更改的异步设计旨在让运行时有时间完成这两项操作。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrRequestSpatialContainerVisibleEXT -
spatialContainer必须是有效的 XrSpatialContainerEXT 句柄 -
info必须是指向有效 XrSpatialContainerVisibleRequestInfoEXT 结构的指针
返回代码
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
XrSpatialContainerVisibleRequestInfoEXT 与 xrRequestSpatialContainerVisibleEXT 搭配使用,可更改空间容器的可见性。
typedef struct XrSpatialContainerVisibleRequestInfoEXT {
XrStructureType type;
const void* next;
XrBool32 visible;
} XrSpatialContainerVisibleRequestInfoEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。visible表示是否请求显示或隐藏空间容器。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerVisibleRequestInfoEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_VISIBLE_REQUEST_INFO_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
每次运行时更改空间容器的可见性时,运行时都必须将具有新状态的 XrEventDataSpatialContainerVisibleChangedEXT 事件加入队列。
typedef struct XrEventDataSpatialContainerVisibleChangedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
XrBool32 visible;
} XrEventDataSpatialContainerVisibleChangedEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是此事件所针对的 XrSpatialContainerEXT。visible是空间容器的新可见状态。
此事件会替换 XR_SESSION_STATE_VISIBLE,从而允许每个容器的值不同。对于所有更改(包括应用请求的更改和运行时发起的更改),事件都必须排队。
在将此事件排入队列并将 visible 设置为 XR_TRUE 后,运行时可以延迟几帧渲染容器,以避免显示空容器,并为应用提供时间来提交其初始内容。在此期间,XrSpatialContainerStateEXT ::visible 将为 XR_TRUE。运行时不应将容器渲染延迟超过 0.5 秒。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrEventDataSpatialContainerVisibleChangedEXT -
type必须为XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_VISIBLE_CHANGED_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
每当运行时拒绝显示容器的请求时,运行时必须将 XrEventDataSpatialContainerVisibleRequestDeniedEXT 事件加入队列。
typedef struct XrEventDataSpatialContainerVisibleRequestDeniedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrEventDataSpatialContainerVisibleRequestDeniedEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是此事件所针对的 XrSpatialContainerEXT。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrEventDataSpatialContainerVisibleRequestDeniedEXT -
type必须为XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_VISIBLE_REQUEST_DENIED_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
可互动
应用无法请求空间容器可交互。哪些空间容器可交互完全由运行时控制。可交互的空间容器也必须可见。
每当运行时更改空间容器的可交互状态时,运行时都必须将具有新状态的 XrEventDataSpatialContainerInteractableChangedEXT 事件加入队列。
typedef struct XrEventDataSpatialContainerInteractableChangedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
XrBool32 interactable;
} XrEventDataSpatialContainerInteractableChangedEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是此事件所针对的 XrSpatialContainerEXT。interactable是空间容器的新可交互状态。
此事件会替换 XR_SESSION_STATE_FOCUSED,从而允许每个容器的值不同。系统会将所有更改(包括运行时发起的更改)排入事件队列。
运行时可以随时启用或停用与空间容器的互动。如果运行时一次最多只支持一个空间容器可互动,那么当运行时更改可互动的空间容器时,运行时必须先将停止可互动的空间容器(interactable 设置为 false)的事件加入队列,然后再将开始可互动的空间容器(interactable 设置为 true)的事件加入队列。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrEventDataSpatialContainerInteractableChangedEXT -
type必须为XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_INTERACTABLE_CHANGED_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
边界
空间容器具有边界模式和边界框。空间容器的边界模式描述了边界的行为方式。空间容器会在其边界框内绘制内容。
XrSpatialContainerBoundsModeEXT 枚举用于标识空间容器边界可能处于的不同模式。
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;
枚举说明
XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT
空间容器是有界的。边界是一个有限的框。空间容器将仅在此区域中显示。
XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT
空间容器具有沉浸感,且边界无限。空间容器会显示在整个屏幕上。
处于边界模式 XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT 的空间容器有其他要求:
- 运行时必须将这些空间容器视为与未使用空间容器创建的全屏沉浸式应用相同,但会话状态的变化中指出的行为变化除外。
- 运行时可以提供额外的扩展程序,使沉浸式空间容器的行为与不使用此扩展程序创建的全屏和沉浸式应用不同。
- 运行时必须报告这些空间容器的无限边界。
- 当沉浸式空间容器可见时,运行时可以隐藏其他空间容器。由于不同运行时可能存在差异,应用不应依赖于空间容器根据沉浸式空间容器的可见性自动显示或隐藏。与所有其他可见状态转换一样,当空间容器因沉浸式容器可见而隐藏时,运行时必须将 XrEventDataSpatialContainerVisibleChangedEXT 事件加入队列。
注意
上述要求意味着,所有运行时都可以在不使用此扩展程序的情况下实现 OpenXR 1.x 路径,方法是隐式创建空间容器、将容器的边界模式设置为沉浸式,并请求将其设为可见。
应用会请求使用 xrRequestSpatialContainerBoundsModeEXT 更改空间容器的边界模式。
XrResult xrRequestSpatialContainerBoundsModeEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerBoundsModeRequestInfoEXT* info);
参数说明
spatialContainer是要请求更改的 XrSpatialContainerEXT。info是一个指向 XrSpatialContainerBoundsModeRequestInfoEXT 的指针,其中包含请求的边界模式。
更改空间容器的边界模式是一项异步操作,运行时可能会在应用请求更改后数秒内将更改或拒绝事件加入队列。这样一来,运行时便可弹出必要的界面,以便用户安全地进入沉浸模式。
运行时必须遵循更改不可见空间容器边界模式的请求。如果运行时会拒绝针对不可见容器的边界模式请求,则可能会拒绝或推迟显示此类空间容器的请求。这样,应用就可以将容器作为沉浸式容器启动。运行时可以拒绝更改可见空间容器边界模式的请求,在这种情况下,运行时必须将 XrEventDataSpatialContainerBoundsModeRequestDeniedEXT 事件加入队列。例如,如果用户未主动与某个可见的空间容器互动,某些运行时会拒绝更改该容器边界模式的请求。
如果应用请求的边界模式不受 XrSystemSpatialContainerPropertiesEXT :: supportsBounded 和 XrSystemSpatialContainerPropertiesEXT :: supportsImmersive 支持,运行时必须返回 XR_ERROR_VALIDATION_FAILURE。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrRequestSpatialContainerBoundsModeEXT -
spatialContainer必须是有效的 XrSpatialContainerEXT 句柄 -
info必须是指向有效 XrSpatialContainerBoundsModeRequestInfoEXT 结构的指针
返回代码
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
XrSpatialContainerBoundsModeRequestInfoEXT 与 xrRequestSpatialContainerBoundsModeEXT 搭配使用,可更改空间容器的边界模式。
typedef struct XrSpatialContainerBoundsModeRequestInfoEXT {
XrStructureType type;
const void* next;
XrSpatialContainerBoundsModeEXT boundsMode;
} XrSpatialContainerBoundsModeRequestInfoEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。boundsMode是空间容器所需的 XrSpatialContainerBoundsModeEXT。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerBoundsModeRequestInfoEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_BOUNDS_MODE_REQUEST_INFO_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针 -
boundsMode必须是有效的 XrSpatialContainerBoundsModeEXT 值
每当运行时更改空间容器的边界或边界模式时,运行时必须将包含新边界信息的 XrEventDataSpatialContainerBoundsChangedEXT 事件加入队列。
typedef struct XrEventDataSpatialContainerBoundsChangedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
XrExtent3Df bounds;
XrBool32 infiniteBounds;
XrSpatialContainerBoundsModeEXT boundsMode;
} XrEventDataSpatialContainerBoundsChangedEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是此事件所针对的 XrSpatialContainerEXT。bounds是空间容器边界的新宽度、高度和深度。- 如果容器具有无限边界,则
infiniteBounds为 true。 boundsMode是空间容器的新 XrSpatialContainerBoundsModeEXT。
系统会将所有更改(包括应用请求的更改和运行时发起的更改)排入事件队列。
当用户以交互方式调整空间容器的大小时,运行时必须采取以下行为之一:
- 在用户调整空间容器大小时,排队多个事件(可能以帧速率进行)
- 在调整大小结束时将单个事件加入队列
如果运行时在调整大小结束时仅将单个事件加入队列,则该运行时必须继续通过 xrGetSpatialContainerBoundsEXT 报告旧边界,直到运行时将调整大小事件加入队列。运行时必须合并多个未轮询的边界更改事件。换言之,如果在 XrEventDataSpatialContainerBoundsChangedEXT 事件仍在排队时边界或边界模式发生变化,运行时必须仅报告一个包含最后一次边界变化的事件。由于应用还可以使用 xrGetSpatialContainerBoundsEXT 直接轮询空间容器的边界,因此事件中的边界更改次数可能与轮询中的更改次数不同,具体取决于运行时生成的边界更改的时间、应用对 xrPollEvent 的调用以及应用对 xrGetSpatialContainerBoundsEXT 的调用。
当空间容器的边界发生变化时,空间容器的本地原点可能也会发生变化。例如,如果运行时允许用户通过拖动空间容器的某个边缘来调整其边界大小,那么当用户拖动单个边缘时,该容器的边界和本地原点都会发生变化。在这种情况下,运行时必须同时更改边界和本地原点。
运行时必须将 infiniteBounds 设置为 XR_TRUE,并将宽度、高度和深度设置为 0.0,以表示无限边界。运行时必须将 infiniteBounds 设置为 XR_FALSE,并将宽度、高度和深度设置为有限正数,以实现有限边界。
运行时必须按照与 XrSpatialContainerBoundsEXT 相同的规则设置 bounds 和 infiniteBounds。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrEventDataSpatialContainerBoundsChangedEXT -
type必须为XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_BOUNDS_CHANGED_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
每次运行时拒绝更改容器边界模式的请求时,运行时必须将 XrEventDataSpatialContainerBoundsModeRequestDeniedEXT 事件加入队列。
typedef struct XrEventDataSpatialContainerBoundsModeRequestDeniedEXT {
XrStructureType type;
const void* next;
XrSpatialContainerEXT spatialContainer;
} XrEventDataSpatialContainerBoundsModeRequestDeniedEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。spatialContainer是此事件所针对的 XrSpatialContainerEXT。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrEventDataSpatialContainerBoundsModeRequestDeniedEXT -
type必须为XR_TYPE_EVENT_DATA_SPATIAL_CONTAINER_BOUNDS_MODE_REQUEST_DENIED_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
XrSpatialContainerBoundsEXT 结构用于描述空间容器的边界框。
typedef struct XrSpatialContainerBoundsEXT {
XrStructureType type;
void* next;
XrExtent3Df bounds;
XrBool32 infiniteBounds;
} XrSpatialContainerBoundsEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。bounds是空间容器边界的宽度、高度和深度。边界以米为单位。- 如果容器具有无限边界,则
infiniteBounds为 true。
运行时必须将 infiniteBounds 设置为 XR_TRUE,并将宽度、高度和深度设置为 0.0,以表示无限边界。运行时必须将 infiniteBounds 设置为 XR_FALSE,并将宽度、高度和深度设置为有限正数,以实现有限边界。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerBoundsEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_BOUNDS_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
xrGetSpatialContainerBoundsEXT 函数用于查询空间容器的当前边界。
XrResult xrGetSpatialContainerBoundsEXT(
XrSpatialContainerEXT spatialContainer,
const XrSpatialContainerBoundsGetInfoEXT* getInfo,
XrSpatialContainerBoundsEXT* bounds);
参数说明
spatialContainer是要查询的 XrSpatialContainerEXT。getInfo是 XrSpatialContainerBoundsGetInfoEXT,其中包含了用于获取空间容器状态的信息。bounds是一个指向 XrSpatialContainerBoundsEXT 的指针,边界将通过该指针返回。
有界空间容器不得具有无限边界,而沉浸式空间容器必须具有无限边界。
在空间容器有边界时,运行时可以随时将空间容器的边界更改为任何正有限值。空间容器边界的更改通过 XrEventDataSpatialContainerBoundsChangedEXT 传达。
借助此扩展程序,应用无法请求更改边界,只能使用 xrRequestSpatialContainerBoundsModeEXT 在有边界和沉浸式之间切换。其他扩展程序将来可能会提供这种方式。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrGetSpatialContainerBoundsEXT -
spatialContainer必须是有效的 XrSpatialContainerEXT 句柄 - 如果
getInfo不是NULL,则getInfo必须是指向有效 XrSpatialContainerBoundsGetInfoEXT 结构的指针 -
bounds必须是指向 XrSpatialContainerBoundsEXT 结构的指针
返回代码
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
XrSpatialContainerBoundsGetInfoEXT 结构是一个输入结构,用于未来扩展。
typedef struct XrSpatialContainerBoundsGetInfoEXT {
XrStructureType type;
const void* next;
} XrSpatialContainerBoundsGetInfoEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSpatialContainerBoundsGetInfoEXT -
type必须为XR_TYPE_SPATIAL_CONTAINER_BOUNDS_GET_INFO_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
XrSpatialContainerVolumeClippingEXT 枚举用于标识空间容器的不同体积裁剪行为。
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;
枚举说明
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_NONE_EXT
任何内容都不会被剪裁到空间容器的边界体积。内容可以绘制在空间容器的边界之外。
XR_SPATIAL_CONTAINER_VOLUME_CLIPPING_STRICT_EXT
内容会被严格剪裁到空间容器的边界体积内。
此扩展程序中未使用此枚举。它旨在允许其他扩展程序指定所需的音量削波行为。例如,应用可能希望为有界空间容器绘制背景。单目立方体贴图是指定背景的一种便捷方式,但单目立方体贴图在概念上位于容器外部的无限远处。
系统功能
应用可以在调用 xrGetSystemProperties 时,将 XrSystemSpatialContainerPropertiesEXT 结构链接到 XrSystemProperties,从而检查系统功能。
typedef struct XrSystemSpatialContainerPropertiesEXT {
XrStructureType type;
void* next;
uint32_t maxSpatialContainerCount;
XrBool32 supportsBounded;
XrBool32 supportsImmersive;
} XrSystemSpatialContainerPropertiesEXT;
成员说明
type是此结构的 XrStructureType。next是NULL或指向结构链中下一个结构的指针。核心 OpenXR 或此扩展程序中未定义任何此类结构。maxSpatialContainerCount是可创建的空间容器数量上限。- 如果空间容器可以限定边界,则
supportsBounded为 true。 - 如果允许空间容器具有沉浸感,则
supportsImmersive为 true。
支持此扩展程序的运行时应支持应用创建多个空间容器,仅受内存分配限制。不同运行时对同时显示的空间容器数量的限制可能有所不同。无法在此扩展程序中查询同时显示的容器数量,因为运行时可能会根据所有正在运行的应用的状态来限制单个应用。我们假设,高度受限的设备和受限较少的设备在同时显示的容器数量方面会有不同的限制;高度受限的设备可能仅支持一次显示一个空间容器,而受限较少的设备可能支持同时显示大量空间容器,具体取决于渲染计算限制。
支持此扩展程序的运行时必须至少支持有界空间容器或沉浸式空间容器中的一种。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSystemSpatialContainerPropertiesEXT -
type必须为XR_TYPE_SYSTEM_SPATIAL_CONTAINER_PROPERTIES_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT 函数会返回系统支持的图形呈现方法。
XrResult xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT(
XrInstance instance,
XrSystemId systemId,
uint32_t graphicsPresentationCapacityInput,
uint32_t* graphicsPresentationCountOutput,
XrSpatialContainerGraphicsPresentationEXT* graphicsPresentations);
参数说明
instance是从中检索systemId的 XrInstance。systemId是要查询的XrSystemId。graphicsPresentationCapacityInput是graphicsPresentations数组的容量,或设为 0 以请求获取所需的容量。graphicsPresentationCountOutput是一个指针,指向写入的图形呈现数量;若graphicsPresentationCapacityInput为 0,则指向所需的容量。graphicsPresentations是指向 XrSpatialContainerGraphicsPresentationEXT 值数组的指针,但如果graphicsPresentationCapacityInput为 0,则可以为 null。- 如需详细了解如何检索所需的
graphicsPresentations大小,请参阅缓冲区大小参数部分。
对于给定的 systemId 以及在实例的生命周期内,运行时必须始终从此枚举中返回相同的缓冲区内容。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能调用 xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT -
instance必须是有效的 XrInstance 句柄 -
graphicsPresentationCountOutput必须是指向uint32_t值的指针 - 如果
graphicsPresentationCapacityInput不为0,则graphicsPresentations必须是指向graphicsPresentationCapacityInputXrSpatialContainerGraphicsPresentationEXT 值数组的指针
返回代码
XR_SUCCESS
XR_ERROR_FUNCTION_UNSUPPORTEDXR_ERROR_HANDLE_INVALIDXR_ERROR_INSTANCE_LOSTXR_ERROR_RUNTIME_FAILUREXR_ERROR_SIZE_INSUFFICIENTXR_ERROR_SYSTEM_INVALIDXR_ERROR_VALIDATION_FAILURE
会话状态的变化
如需为会话启用空间容器支持,请在调用 xrCreateSession 时链接 XrSessionCreateInfoSpatialContainersEXT。
typedef struct XrSessionCreateInfoSpatialContainersEXT {
XrStructureType type;
const void* next;
} XrSessionCreateInfoSpatialContainersEXT;
启用空间容器支持后,XrSession 的行为会有所不同。这是因为,使用空间容器时,会话不再在显示屏上呈现图片内容,而是由空间容器来呈现。因此,启用此扩展程序后,会话实际上是“无头”的。与其他无头扩展程序不同,应用可以通过空间容器提交图片数据。
启用空间容器支持会通过以下方式更改核心 OpenXR API。
运行时:丢失系统或设备
运行时:丢失系统或设备
xrDestroySession
xrDestroySession
IDLE
(正在运行)
闲置…
xrGetSystem
xrCreateSession
xrGetSystem…
xrCreateInstance
xrCreateIn…
xrDestroySession
xrDestroySession
LOSS_PENDING
(未运行)
LOSS_PENDING…
xrDestroyInstance
xrDestroyInstance
应用:可选择
重新启动 XR
app: optionally…
图 19. 新会话状态机
- 会话永远不会进入
XR_SESSION_STATE_VISIBLE、XR_SESSION_STATE_FOCUSED或XR_SESSION_STATE_EXITING状态。运行时绝不能将这些状态的事件加入队列。这些状态分别由每个空间容器事件 XrEventDataSpatialContainerVisibleChangedEXT、XrEventDataSpatialContainerInteractableChangedEXT 和 XrEventDataSpatialContainerClosedEXT 取代。 - 会话也永远不会进入
XR_SESSION_STATE_READY、XR_SESSION_STATE_SYNCHRONIZED、XR_SESSION_STATE_STOPPING状态。运行时绝不能将这些状态的事件加入队列。这些州没有替代方案。 - 当会话处于
XR_SESSION_STATE_IDLE状态时,运行时必须将其视为正在运行。 - 当会话处于
XR_SESSION_STATE_IDLE状态且至少有一个可交互的空间容器存在时,运行时必须将该会话视为处于聚焦状态。 - 不再需要 xrBeginSession 和 xrEndSession 函数。调用这些函数时,运行时必须返回
XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXT。其他扩展程序可能会提供这些函数的替代函数。 - xrRequestExitSession 函数也不再需要。调用此函数时,运行时必须返回
XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXT。想要退出正在运行的会话的应用可以改为调用 xrRequestSpatialContainerVisibleEXT 来隐藏其容器,并在所有容器都不再可见后销毁会话。 如果扩展程序会在会话开始运行时将其他事件加入队列,现在必须在会话创建后将这些事件加入队列。下面列出了此类扩展程序。
扩展程序事件
XR_EXT_user_presence
XrEventDataUserPresenceChangedEXT
XR_META_boundary_visibility
XrEventDataBoundaryVisibilityChangedMETA
- xrLocateViews 函数不适用于该会话。运行时必须从 xrLocateViews 返回
XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXT。其他扩展程序可能会提供方法来定位特定空间容器的视图。 - xrWaitFrame 函数必须始终将 XrFrameState ::
shouldRender设置为 false。其他扩展程序可能会提供一些方法,用于了解特定空间容器是否应更新其合成层。 - xrEndFrame 函数不是提交合成层的有效方式。如果应用将 XrFrameEndInfo ::
layerCount设置为非零值,则运行时必须返回XR_ERROR_VALIDATION_FAILURE。其他扩展程序可能会提供为特定空间容器提交合成层的方法。 - 进入
XR_SESSION_STATE_LOSS_PENDING状态后,系统还会关闭所有空间容器。在为XR_SESSION_STATE_LOSS_PENDING将会话状态更改加入队列之前,运行时必须为每个活跃的空间容器将 XrEventDataSpatialContainerClosedEXT 事件加入队列。 - xrCreateSession 函数不再需要图形 API 绑定结构。其他扩展程序可能需要图形绑定,例如,空间容器需要使用图形 API 进行渲染。
上述行为与 XR_MND_headless 中的行为略有不同。如果为某个会话启用了空间容器支持,则运行时不得从 XR_MND_headless 启用无头会话行为。
注意
启用空间容器后,会话仅在两种状态之间转换:XR_SESSION_STATE_IDLE(正在运行)和 XR_SESSION_STATE_LOSS_PENDING(未运行)。因此,运行时不再返回 XR_ERROR_SESSION_RUNNING 或 XR_ERROR_SESSION_NOT_RUNNING。相反,当会话未运行时,运行时会根据 OpenXR 核心中的规则返回 XR_ERROR_SESSION_LOST 或 XR_SESSION_LOSS_PENDING。此外,xrBeginSession 是唯一返回 XR_ERROR_SESSION_RUNNING 的函数,现在将始终返回 XR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXT。
有效用法(隐式)
- 必须先启用
XR_EXT_spatial_container扩展程序,然后才能使用 XrSessionCreateInfoSpatialContainersEXT -
type必须为XR_TYPE_SESSION_CREATE_INFO_SPATIAL_CONTAINERS_EXT -
next必须为NULL或指向结构链中下一个结构的有效指针
Android 清单条目
基于 AOSP 的运行时可能会根据在运行任何应用代码之前启动的初始空间容器状态而具有自定义行为。例如,运行时可以更改为 activity 分配的资源、启动动画或启动画面显示。为此,我们提供了以下属性。它们取代了 <category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" /> 标记,基于空间容器的应用不应指定该标记,除非是为了与基于 AOSP 的早期运行时兼容。
<property android:name="org.khronos.openxr.PROPERTY_ACTIVITY_HINT_XR_SPATIAL_CONTAINER_USED_BOUNDS_MODES"
android:value="list of modes" />
此属性会向运行时提示 activity 使用的边界模式。默认情况下,它是一个空列表,表示没有提示。
下列字符串对此属性有效。若有多个值,则使用 | 进行分隔,例如 "bounded|immersive"。
值
说明
"2d_panel"
该 activity 会使用 Android 的 2D 视图框架进行显示。
"bounded"
该活动使用 XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT。
"immersive"
该活动使用 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" />
此属性会向运行时提示 activity 首次创建时的初始 XrSpatialContainerBoundsModeEXT。默认情况下,它是字符串 XR_SPATIAL_CONTAINER_INITIAL_BOUNDS_MODE_UNDEFINED,表示没有提示。
运行时不得要求应用具有这些属性,否则应按照此规范运行。运行时不得根据这些属性更改应用可见行为。所有此类元数据必须可在 <activity> 级别或 <application> 级别指定。如果在 <application> 级别指定,则该属性会应用于应用中未指定其自身值的所有 activity。
示例代码
以下代码展示了如何在不进行任何渲染的情况下,将此扩展程序用于仅感知用例。
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));
新对象类型
新增命令
- xrCreateSpatialContainerEXT
- xrCreateSpatialContainerSpaceEXT
- xrDestroySpatialContainerEXT
- xrEnumerateSupportedSpatialContainerGraphicsPresentationsEXT
- xrGetSpatialContainerBoundsEXT
- xrGetSpatialContainerStateEXT
- xrRequestSpatialContainerBoundsModeEXT
- xrRequestSpatialContainerVisibleEXT
新结构
- XrEventDataSpatialContainerBoundsChangedEXT
- XrEventDataSpatialContainerBoundsModeRequestDeniedEXT
- XrEventDataSpatialContainerClosedEXT
- XrEventDataSpatialContainerInteractableChangedEXT
- XrEventDataSpatialContainerVisibleChangedEXT
- XrEventDataSpatialContainerVisibleRequestDeniedEXT
- XrSpatialContainerBoundsEXT
- XrSpatialContainerBoundsGetInfoEXT
- XrSpatialContainerBoundsModeRequestInfoEXT
- XrSpatialContainerCreateInfoEXT
- XrSpatialContainerSpaceCreateInfoEXT
- XrSpatialContainerStateEXT
- XrSpatialContainerStateGetInfoEXT
- XrSpatialContainerVisibleRequestInfoEXT
新枚举
- XrSpatialContainerBoundsModeEXT
- XrSpatialContainerGraphicsPresentationEXT
- XrSpatialContainerVolumeClippingEXT
新枚举常量
XR_EXT_SPATIAL_CONTAINER_EXTENSION_NAMEXR_EXT_spatial_container_SPEC_VERSION扩展 XrObjectType:
XR_OBJECT_TYPE_SPATIAL_CONTAINER_EXT
扩展 XrResult:
XR_ERROR_COMPATIBLE_SPATIAL_CONTAINER_MISSING_EXTXR_ERROR_SPATIAL_CONTAINERS_ENABLED_EXTXR_ERROR_SPATIAL_CONTAINERS_NOT_ENABLED_EXTXR_ERROR_SPATIAL_CONTAINER_CLOSED_EXT
扩展 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
问题
如何处理多个未完成的可见请求?应用应该收到一个更改/拒绝回调,还是多个?如果调用跨多个帧,则答案可能会有所不同。如果多个请求导致空操作(例如,请求让空间容器可见,然后又请求让原本不可见的容器不可见),答案也可能会有所不同。
- 已解决。针对更改事件和拒绝事件提供不同的选项。Noop 请求不会将更改事件加入队列,这只会给应用开发者带来干扰,并且运行时很容易将其过滤掉。如果多个可见请求被拒绝,则运行时必须分别为每个请求生成一个相应的拒绝事件。
如何定义一致性自动化扩展程序,以便 CTS 仍可测试政策行为的所有可选规范文本?
- 已解决。单独的测试扩展程序。系统会实现一个仅适用于 CTS 的测试扩展程序运行时,以便 CTS 控制所有系统政策。
当空间容器的位置发生变化时,是否需要触发事件?
- 已解决。否。空间容器空间是非世界锁定的,其他此类空间(例如
XR_REFERENCE_SPACE_TYPE_VIEW)在发生变化时不会触发事件。
- 已解决。否。空间容器空间是非世界锁定的,其他此类空间(例如
如果存在多个空间容器,xrSyncActions 如何运作?
- 已解决。无需更改。 xrSyncActions 将应用于会话中的所有空间容器。如果应用想要将输入操作定向到特定空间容器,则可以查看每个容器的可交互状态,以选择哪些容器是有效目标。如果应用只想同步单个空间容器的输入操作状态,则需要额外的扩展程序。不过,我们预计会改为专注于一个扩展程序,该扩展程序允许应用完全基于事件,并避免在帧循环中调用 xrSyncActions。
不经常更新的应用如何处理输入?
- 已解决。无需进行任何更改。虽然 EXT_spatial_container 很有价值,但在空间容器之外也很有价值。这可以通过事件渠道扩展程序进行处理,并且在两种情况下都有效。对于空间容器,我们将添加更多方法来过滤单个空间容器的事件。
对于输入和渲染循环分离的应用,我们是否需要等待来限制/控制输入循环的时间?
- 已解决。无需进行任何更改。这应该通过事件渠道和当前请求扩展程序来处理。Present 请求扩展程序允许基于事件进行渲染,并与帧循环分离。
空间容器能否获取其相对于其他空间容器的姿态?Key thoughts here: Do we have a use case for this? 如果是,空间容器空间如何连接到 LOCAL?
- 已解决。是。对于同一会话中的空间容器,已经可以通过
XR_REFERENCE_SPACE_TYPE_VIEW实现这一点,并且最好支持依赖于视图的内容。如需跨会话(例如向其他进程)共享空间容器姿态,预期路径是利用XR_EXT_spatial_anchor及其现有的持久性和共享模式。
- 已解决。是。对于同一会话中的空间容器,已经可以通过
如果空间容器的空间不可见,是否可以定位?
- 已解决。否。当空间容器不可见时,其空间无法定位。这意味着它没有空间音频,并且当 spatial_container 不可见时,应用无法“预热”依赖于视图的内容。这两种情况都可以接受,因为当空间容器不可见时,应用应停止该空间容器使用的所有 CPU/GPU 负载。
空间容器空间预计将放置在空间容器中的哪个位置?建议采用中心点或最小点 (minX, minY, minZ)。
- 已解决。在中心位置。在大多数情况下,空间容器调整大小的用户体验(移动边缘)都会导致位置发生变化。中心通常用于 OpenXR 的其他部分。我们没有与 2D 计算中的窗口对齐,因为 3D 模型查看器通常不遵循此惯例。
运行时何时应创建空间容器底层的资源?这有时会涉及与系统服务进行 IPC。
- 已解决。作为
xrCreateSpatialContainerEXT的一部分同步执行。虽然可能涉及 IPC,但容器的实际创建通常应该开销较低。一些供应商在管理容器方面有全局互斥量,但这些互斥量通常不会导致长时间等待。互斥量争用问题是特定于供应商的 bug,应由每个供应商自行解决。
- 已解决。作为
我们是否需要一个信号来表明 XrSession 将创建空间容器,因此不支持旧版渲染路径?
- 已解决。是。我们从根本上改变了会话状态机。
版本历史记录
修订版 1,2026 年 8 月 6 日(Jared Finder,Google)
- 初始扩展程序说明