本文介绍性能对混合现实应用的重要性。 如果应用程序未以最佳帧速率运行,则用户体验可能会受到影响。 全息影像看起来不稳定,并且环境的头部跟踪变得不准确,导致用户体验不佳。 将性能视为混合现实开发的一流功能,而不是一项精美的任务。
下表列出了每个目标平台的性能帧速率值。
| 平台 | 目标帧速率 |
|---|---|
| HoloLens | 60 FPS |
| Windows Mixed Reality Ultra电脑 | 90 FPS |
| Windows Mixed Reality电脑 | 60 FPS |
下面的框架概述了达到目标帧速率的最佳做法。 有关在Unity环境中测量和提高帧速率的提示,请参阅Unity的性能建议一文。
了解性能瓶颈
如果应用的帧速率性能不佳,则第一步是分析和了解应用程序在计算密集型的位置。 两个主要处理器处理渲染场景的工作:CPU 和 GPU。 每个处理器处理混合现实应用的不同方面。 可能出现瓶颈的三个关键位置是:
- 应用线程 - CPU - 负责应用逻辑,包括处理输入、动画、物理和其他应用逻辑。
- 呈现线程 - CPU 到 GPU - 负责将绘图调用提交到 GPU。 当应用想要呈现对象(如多维数据集或模型)时,此线程会向 GPU 发送执行作的请求。
- GPU - 通常处理应用程序的图形管道,以将 3D 数据 (模型、纹理等) 转换为像素。 它最终会生成 2D 图像以提交到设备的屏幕。
通常,HoloLens 应用程序是 GPU 绑定的,但并非总是如此。 使用以下部分中的工具和技术来了解特定应用出现瓶颈的位置。
如何分析应用程序
有许多工具可用于了解混合现实应用程序中的性能配置文件和潜在瓶颈。
下面是一些常见工具,可帮助你为应用程序收集深层分析信息:
- Intel Graphics Performance Analyzers
- Visual Studio 图形调试器
- Unity Profiler
- Unity帧调试器
- Unreal Insights
- PIX
- Unreal 中的 GPU 分析
如何在任何环境中分析
确定应用是受 GPU 还是 CPU 限制的一种方法是降低呈现目标输出的分辨率。 通过减少要计算的像素数,可以降低 GPU 负载。 设备将呈现为较小的纹理,然后向上采样以显示最终图像。
降低呈现分辨率后,如果:
- 应用程序帧速率 增加,那么你很可能已 绑定 GPU
- 应用程序帧速率 不变,则你可能已 受 CPU 限制
注意
Unity可以通过 XRSettings.renderViewportScale 属性在运行时轻松修改应用程序的呈现目标分辨率。 设备上显示的最终图像具有固定分辨率。 平台将采样较低分辨率的输出,以生成更高分辨率的图像,以便在显示器上呈现。
UnityEngine.XR.XRSettings.renderScale = 0.7f;
如何改进应用程序
CPU 性能建议
通常,在 CPU 上的混合现实应用程序中,大多数工作都涉及执行场景的“模拟”和处理应用程序逻辑。 以下区域是优化的目标:
- 动画
- 物理
- 内存分配
- 复杂算法 (即反向运动学、路径查找)
GPU 性能建议
了解带宽与填充速率
在 GPU 上呈现帧时,应用程序受内存带宽或填充速率的约束。
-
内存带宽 是 GPU 可从内存中读取和写入的速率
- 若要确定带宽限制,请降低纹理质量,并在帧速率提高时检查。
- 若要确定填充速率限制,请降低显示分辨率并查看帧速率是否提高。
注意
如果使用Unity,检查特定于Unity GPU 性能建议。 - 在 Unity 中,使用 XRSettings.renderViewportScale 属性
内存带宽通常涉及以下任一优化:
- 较低的纹理分辨率
- 使用较少的纹理 (法线、镜面等)
填充率侧重于减少需要为最终呈现的像素计算的作数,包括:
- 要呈现/处理的对象数
- 每个着色器的作数
- 最终结果 (几何着色器、后处理效果等的 GPU 阶段数)
- 要呈现的像素数 (显示分辨率)
减少多边形计数
多边形计数越高,GPU 的作就越多,因此 减少场景中的多边形数量 会缩短呈现时间。 还有其他一些因素会使几何图形着色变得昂贵,但多边形计数是确定渲染场景需要多少工作量的最简单指标。
限制过度绘制
当多个对象呈现但在屏幕上未显示时,它们被遮挡对象隐藏时,会发生高过度绘制。 想象一下,看着一堵墙后面有物体。 将处理所有几何图形以用于呈现,但只需要呈现不透明的墙,这会导致不必要的作。
着色
着色器是在 GPU 上运行的小型程序,在呈现中执行两个重要步骤:
- 确定应绘制哪些顶点以及它们位于屏幕空间中的位置 (顶点着色器)
- 每个网格的每个顶点执行顶点着色器。
- 确定像素着色器 (每个像素的颜色)
- 像素着色器按像素执行,并由几何图形呈现到目标呈现纹理。
通常,着色器执行许多转换和照明计算。 虽然复杂的照明模型、阴影和其他作可以产生出色的效果,但它们也有一个价格。 减少着色器中计算的作数可以大大减少每个帧 GPU 所需的工作量。
着色器编码建议
- 尽可能使用双线性筛选
- 重新排列表达式,以使用 MAD 内部函数同时执行乘法和加法
- 在 CPU 上尽可能多地进行预计算,并将常量作为常量传递给材料
-
支持将作从像素着色器移动到顶点着色器
- 通常,顶点数远小于像素数, (720p 为 921,600 像素,1080p 为 2,073,600 像素,依此)
删除 GPU 阶段
后期处理效果可能成本高昂,并增加应用程序的填充率,包括 MSAA 等抗锯齿技术。 在 HoloLens 上,我们建议避免这些技术和其他着色器阶段,例如几何图形、外壳和计算着色器。
内存建议
过多的内存分配和解除分配作可能会导致性能不一致、帧冻结和其他有害行为。 在 Unity 中开发时,了解内存注意事项尤其重要,因为内存管理由垃圾回收器控制。
对象池
对象池是一种常用的技术,用于降低连续分配和解除分配对象的成本。 这是通过分配包含相同对象的大型池并重用此池中的非活动可用实例来完成的,而不是随着时间的推移不断生成和销毁对象。 对象池非常适合在应用期间具有可变生存期的可重用组件。