OpenXR架构简述及重要概念和组件的详解

对 OpenXR 原生开发 APP 的架构简述,并介绍了 XR 中一些重点概念。另注:本文涉及特定平台/制造商的内容均可从公开渠道获取,与相关平台/制造商的内部信息无关。

前言

本文是很久之前写的笔记,最近有时间,遂整理而公开于此。
由于文字篇幅过大,图片较少,建议使用护眼模式进行阅读。

读完本文,可以对如下内容有了解:

  • OpenXR 是如何诞生的
  • OpenXR 现状
  • OpenXR APP 的接入方式
  • Loader 与 Runtime 是什么关系
  • OpenXR 如何控制 APP 生命周期
  • Instance,Session,Swapchain,XRSpace是什么
  • 合成器(Composer)是什么,Layer 合并与 ATW 又是什么

本文不包含什么内容:

  • OpenXR 每个函数都是做啥用的(翻手册吧)
  • 如何实现 Runtime(请参阅开源项目 Monado)
  • 为什么 XXXXX

发展

首先,简单介绍下 OpenXR 诞生的契机以及目前现状。

旧时

上古时期,XR 设备制造商及软件提供商各自为战,导致各家平台的 XR 渲染及数据通信的方法各不相同(如各家的 Mobile VR SDK、Valve 的 OpenVR 等)。

虽然常见的游戏引擎一直在努力抹平开发差异,但这些抹平差异的做法也是碎片化的一部分(如 Unity XR SDK 需要设备生产商以 Provider plugin 的形式实现其内容)。

从原生开发角度来看,一个基于 OpenVR(SteamVR) 的 APP,想要移植到 Android 平台一体机上,需要先替换 SDK,再处理一堆报错及平台差异,如果应用没有自己封一层“差异抹平层”,那这个改动与大换血无异。

OpenXR 诞生

因此,OpenXR 诞生了,它是 Khronos 牵头、多家参与的通用 XR API,意图抹平硬件和平台差异(碎片化),使得 APP 不需要大变动即可跨多个设备生产商硬件运行。

用人话说就是规定了一套统一的结构体/函数/接口,使得 XR APP 接口调用、生命周期管理等遵循统一的标准,不管硬件设备如何,APP 与设备通信的函数签名(返回值、方法名、参数)都一样。

真正抹平差异的内部实现在 XR Runtime 里,XR Runtime 内置于各家 OS 中,APP 通过内置的 OpenXR Loader 程序在运行时与 XR Runtime 打交道。

XR Runtime 由硬件生产商负责实现,APP 开发者视角中底层的硬件交互、ATW、Composer 等是一个黑盒。

现状

理想是美好的,现实是残酷的,虽然各主流厂商都宣布支持 OpenXR,但 APP 开发离理想状态还差的远:

  • 移动平台 XR 设备的 OpenXR Loader 没有标准实现,强依赖硬件厂家。而 Loader 需要随应用打包分发,因此不能实现“一次编译、到处运行”。
  • 硬件制造商通过扩展(XR_[设备生产商]_FunctionName)将未标准化的硬件能力引入 OpenXR,构筑功能壁垒,以期望争夺未来标准化话语权(先斩后奏),加重碎片化。

另外,虽然 OpenXR 是一个免费(免版权费)标准,但 OpenXR Runtime 官方认证需要付费,否则硬件制造商不能称 Runtime 为“适配/conformant”,也不能使用 OpenXR LOGO 等标志。

当然,各厂商也在努力消除碎片化,以国内某厂商为例,去年的新版 SDK 废弃了某些专用扩展,转而 Include FB/Meta 扩展(但这在事实上也增加了 FB 的话语权,使得 FB 的扩展作为一个“实际通用标准”而存在)。

OpenXR APP 架构总览

传统 3D APP 的工作过程可以用如下简码概括:

OpenXR 的 3D APP 整体架构和上述简码大同小异,下图虽然看着复杂,本质也是一个大循环。

上图可以看出,OpenXR 的主要目的是规范 XR APP 的生命周期和调用接口,应用的逻辑、渲染穿插在生命周期的对应阶段中,由开发者自行实现。

换句话说,虽然 OpenXR Session 创建时需要指定图形 API,但 OpenXR 不负责教你怎么用图形 API 绘图,只是传递基本的环境。很多 VR 玩家有一个误区,认为“某某游戏换了 OpenXR,性能一定会好”,实际上应用的性能好不好,主要看应用开发者,次要看 Runtime 效率,和 OpenXR 这套 API 关系不大。

以 VD 为例,VDXR 下《微软模拟飞行 2020》串流性能有显著性能提升,这个是因为 VD OpenXR Runtime 专注于串流这一个场景,比 SteamVR 内置的 OpenXR Runtime 串流效率高。

相关性能数据可见我上传的视频:https://www.bilibili.com/video/BV1Nz4y1N7Wu

OpenXR 重要组件及概念

主要讲一讲我认为重要的一些组件和概念。

Loader

一个包含在 APP 中的模块,负责加载 Runtime 库,并维护 APP 与 OS XR Runtime 的通信。

在开发者角度,我们使用的 OpenXR API,本质上都依赖 Loader 的工作。

合成器(Compositor)

这是一个属于 Runtime 的底层模块,不对开发者暴露,且没有统一的实现方式。

合成器负责的内容很多,但与 APP 开发者最紧密的是图像合成与 ATW(Asynchronous Timewarp)。

Quest 的 Composer 还有一些诸如 AppSpacewarp 的功能,略过不表。

图像合成

除了 Projection Layer 外,应用还可以同时提交其他 Layer(如 Quad Layer),甚至还可以使用 Overlay 扩展创建 Overlay Seesion 来提交 Overlay Layer(如 Quest 上的 Launcher 及输入法等全局面板)。

合成器负责将多 Layer 合并成一张图,并送给底层显示。

ATW(异步时间扭曲)

ATW 主要为了降低 MTP(motion-to-photon) 延迟。

假设应用完成一帧逻辑+图像渲染需要 8ms,那渲染开始时获取的设备 Pose,在 8ms 后大概率已经变了(虽然变化并不明显),因此渲染的图像会“微微”落后于真正的视角。如果游戏太卡,那么图像“跟不上”动作的现象会更加明显,从而加重玩家眩晕。

在 APP 绘制完成并提交帧图像后,合成器中的 ATW 将根据最新的 3D Pose 将图像做一些扭曲,使其尽量匹配当前的 Pose。

一个明显的现象:当游戏过于卡顿时,某些硬件在转头时会出现“黑边”,这个就是 ATW 在工作。

虽然 ATW 处理的图像会出现失真,但由于帧间隔时间很短,对于帧率正常的游戏,失真并不明显。

Composer 为什么重要

Composer 的作用非常重要,作为承上启下的中间层,各家厂商的 Compositor 优化都是核心技术点,也是最容易出现差异化的地方。

同样的游戏、同样的帧率,为啥在你家机器上体验很爽,在他家机器上就头昏眼花,除开 6dof 算法、电路、硬件设计等因素,Composer 的作用也不容忽视。

XrInstance

一个由 APP 持有的对象,用来和 OpenXR Runtime 通信,连接 APP 与 XR Runtime。

APP 中的 OpenXR Loader 一般会跟踪 XrInstance,并把函数调用转发到 XR Runtime 上。

XrSession

通过 XrInstance 创建的对象,APP 通过 XrSeesion 与 XR 打交道。

控制生命周期

APP 通过监听 Session 的状态来控制自己的生命周期

控制帧循环

当生命周期处于正常运行状态时,APP 利用xrWaitFrame/xrBeginFrame/xrEndFrame等方法,控制帧循环(FrameLoop)。

图中的xrWaitFrame理论上会阻塞线程(类似 Sleep),使应用释放 CPU 资源。

下一个 RenderLoop 到来时,阻塞会停止,应用逻辑继续执行。

阻塞的时间是一个预估值,由 XR Runtime 控制。

Swapchain

OpenXR Swapchain 的作用和常见的双缓冲/三缓冲没有太大区别。

通过 OpenXR 接口,以 Session 为媒,让 Runtime 为我们创建 Swapchain 资源。

创建 Swapchain 之后,通过 xrAcquireSwapchainImage 获取当前帧绘制所用图像的索引,并通过 xrWaitSwapchainImage等待图像被可能的读取任务所释放,之后便可以在图像上画图了。

完成渲染并绘制到图像上后,通过xrReleaseSwapchainImage释放图像的控制权。

XRSpace

OpenXR 的 XRSpace 即坐标系,核心的 Space 类型如下:

  • XR_REFERENCE_SPACE_TYPE_VIEW:视线坐标系
  • XR_REFERENCE_SPACE_TYPE_LOCAL:最常见的坐标系,随 ReCenter 变化(至于原点如何确定,依赖 Runtime:某些平台上,把 Instance 刚创建时的 Pose 作为坐标系原点)
  • XR_REFERENCE_SPACE_TYPE_STAGE:房间坐标系,如某些平台上划定的游玩区域(理论上不随手动 ReCenter 而变化)

还有一些平台相关的类型:

  • XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT
  • XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO

使用商业游戏引擎的开发者更熟悉的 Floor 坐标系:

  • XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT:与 LOCAL 类似,X,Z 相同,但 Y 坐标在地板上(游玩空间标定的地板或估算的地板)

参考资料

以下是本文部分的资料出处:

本文同时还利用了部分平台的 GPT 机器人能力,用以抽象/总结本人笔记内容。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/10307.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*