Highlight
Apple 在 visionOS 上引入了始终渲染的显示管线,系统以 90Hz 持续渲染每一帧,开发者必须优化渲染、输入、ARKit、音视频和内存使用,否则应用会因错过渲染截止期限而被终止。
核心内容
空间计算的性能挑战
在 iPhone 或 iPad 上,应用不更新时屏幕内容保持不变,GPU 可以休息。在 visionOS 上,用户每次转头、动手、眨眼,画面都要更新。系统始终以 90Hz 渲染每一帧,无论应用是否在更新内容。
这意味着:
- 渲染开销从”动态内容”扩展到”静态内容”
- 系统同时运行空间算法处理多个应用
- 热管理成为性能瓶颈,而非电池续航
(00:39)
建立性能计划
开发阶段使用 Instruments 和 Xcode Gauges 分析。RealityKit Trace 是 Instruments 的全新模板,专门用于空间计算应用的性能和功耗分析。
关键原则:
- 必须在真机上分析,模拟器无法复现真实工作负载
- 测试多种交互场景:播放音视频、FaceTime、Personas
- 测试多应用同时运行时的资源竞争
- 使用 MetricKit 和 Xcode Organizer 收集线上数据
(03:34)
详细内容
渲染管线优化
visionOS 的渲染管线包含三个环节:
- 应用层:更新内容,主线程必须在时限内完成
- 渲染服务器:持续处理应用更新、用户输入和空间数据
- 合成器:以显示刷新率(通常 90Hz)向屏幕输出帧
如果应用渲染耗时过长,渲染服务器会错过最优渲染延迟的截止期限,导致视觉更新延迟一帧,用户感受到卡顿。严重的渲染停滞会导致应用被终止。
(06:28)
SwiftUI / UIKit 优化
// 使用 @Observable 替代 @StateObject,减少不必要的布局更新
import SwiftUI
@Observable
class TaskStore {
var tasks: [Task] = []
}
struct TaskListView: View {
let store: TaskStore
var body: some View {
List(store.tasks) { task in
TaskRow(task: task)
}
}
}
关键点:
@Observable提供更细粒度的变更追踪,减少无关的布局更新- 避免在重叠的 UI 视图上使用半透明效果,半透明会导致 overdraw
- 减少阴影、模糊、遮罩等视觉特效,这些会触发离屏渲染
- 考虑减小窗口默认尺寸,窗口占用的像素越多,渲染工作量越大
(08:33)
RealityKit 3D 渲染优化
import RealityKit
import SwiftUI
struct OptimizedSceneView: View {
var body: some View {
RealityView { content in
// 异步加载复杂资源,避免阻塞主线程
if let entity = try? await Entity(named: "optimized_scene", in: realityKitContentBundle) {
content.add(entity)
}
}
}
}
关键点:
- 使用 Reality Composer Pro 导出优化后的文件,自动获得纹理压缩
- 合并共享材质的网格部分,减少独立网格数量
- 使用较小的三角形和顶点数量
- 对大型或半透明内容使用 Custom material + unlit surface,避免昂贵的光照计算
- 提前创建实体,通过
isEnabled或场景层级控制显隐,避免频繁创建销毁
(10:58)
Metal 沉浸式体验优化
import Metal
import CompositorServices
// 每帧查询最新的 foveation map 和 pose prediction
func renderFrame(layerRenderer: LayerRenderer) {
guard let frame = layerRenderer.queryNextFrame() else { return }
// 在最后时刻查询输入数据
let timing = frame.predictTiming()
let pose = frame.posePrediction(at: timing.presentationTime)
let foveation = frame.queryFoveationMap()
// 编码 GPU 工作
encodeRenderWork(pose: pose, foveation: foveation)
// 确保合成器每帧都能收到新画面
frame.submit()
}
关键点:
- 使用 CompositorServices 绕过渲染服务器,直接向合成器提交渲染表面
- 每帧查询新的 foveation map 和 pose prediction
- 在编码 GPU 工作前的最后一刻查询输入数据
- 避免长时间帧停滞,否则系统会终止应用
(16:56)
输入性能
用户通过眼睛、手、语音和硬件输入与应用交互。输入更新在主线程处理,必须在 8 毫秒内完成(90Hz 刷新率下的最优延迟)。
优化建议:
- 为 RealityKit 内容添加物理碰撞体时,优先使用 static collider
- 减少重叠的交互内容,降低命中测试工作量
(18:57)
ARKit 优化
import RealityKit
// 使用 "once" 追踪模式避免持续追踪开销
let anchor = AnchorEntity(.head, trackingMode: .once)
entity.components.set(AnchorComponent(.head, trackingMode: .once))
关键点:
- 使用
AnchorComponent的"once"追踪模式,避免持续追踪成本 - 最小化持久锚点和临时锚点的总数
- 在需要使用前最后一刻查询 ARKit 数据
- 不需要场景理解网格的碰撞数据时,及时关闭
(20:17)
音视频优化
空间音频默认开启,系统实时处理用户位置、环境和音源信息。减少空间音频工作量的三个方向:
- 减少同时播放的音源数量
- 减少移动音源数量
- 缩小 soundstage 尺寸
视频播放建议:
- 使用 24 或 30fps 视频获得最佳性能和功耗
- 减少同时播放和渲染的视频数量
- 视频播放期间最小化 UI 或 3D 内容更新
(22:16)
热管理与内存压力
import Foundation
// 监听热状态变化,动态调整内容
NotificationCenter.default.addObserver(
forName: ProcessInfo.thermalStateDidChangeNotification,
object: nil,
queue: .main
) { _ in
let state = ProcessInfo.processInfo.thermalState
switch state {
case .serious, .critical:
reduceVisualQuality()
lowerUpdateRate()
default:
break
}
}
关键点:
- 订阅
thermalStateDidChangeNotification,根据热压力动态调整内容 - 使用 Xcode 的 thermal inducers 模拟高热状态
- 减少离屏渲染、窗口数量和媒体内容以降低渲染内存分配
- 降低纹理分辨率、网格几何尺寸和粒子数量以减少 RealityKit 内存
(25:19)
核心启发
-
做什么:为 visionOS 应用建立性能基准测试套件
- 为什么值得做:空间计算平台始终渲染的特性意味着性能回归会直接影响用户体验,甚至导致应用被终止
- 怎么开始:使用 RealityKit Trace 模板在 Instruments 中记录关键场景的帧时间、GPU 使用率和系统功耗,将数据纳入 CI 流程
-
做什么:实现动态质量降级系统
- 为什么值得做:热压力会随时发生,主动降级比被系统终止更好
- 怎么开始:监听
thermalStateDidChangeNotification,在.serious状态时降低材质复杂度、减少粒子数量、降低渲染分辨率
-
做什么:优化 3D 资产的加载策略
- 为什么值得做:复杂资产会阻塞主线程并增加内存压力
- 怎么开始:使用
Entity(named:in:)异步加载 Reality Composer Pro 导出的优化文件,共享相同资产的实体实例
-
做什么:为沉浸式体验实现 Metal 渲染管线
- 为什么值得做:CompositorServices 可以绕过渲染服务器,直接控制帧提交时机
- 怎么开始:使用
LayerRenderer查询帧时机、pose prediction 和 foveation map,确保每帧都向合成器提交新画面
-
做什么:设计多应用共存友好的资源使用策略
- 为什么值得做:visionOS 用户会同时使用多个应用,资源竞争是常态
- 怎么开始:在测试时主动运行其他应用,监控共享空间下的渲染延迟和系统功耗,确保应用在资源受限时仍能维持 90Hz
关联 Session
- Meet RealityKit Trace — 全新的 Instruments 模板,用于分析空间计算应用的性能和功耗
- Discover Metal for immersive apps — 使用 Metal 和 CompositorServices 构建沉浸式体验
- Explore rendering for spatial computing — 深入了解空间计算中的渲染机制
- Design for spatial input — 优化空间输入的交互设计
评论
GitHub Issues · utterances