我是Spooker的技术负责人。我们目前正在追求Steam Deck验证标签,花了几天时间深入研究优化。

我想分享我们的具体流程和优化步骤,希望能帮助一些人优化自己的本地Linux构建。

基准值(优化前)

为了设置基准值,我们从一开始就非常关注性能。我们使用Addressables进行手动内存加载/卸载,使用mipmap流式传输进行纹理流式传输,并且对代码进行了严格的审计。我们的代码库不使用重复循环,而是使用R3和VContainer进行注入,使用零分配库如UniTask来保持足迹低。

尽管如此,我们的Steam Deck(64GB LCD)仍然停留在以下位置:

  • FPS: 坚固的60
  • GPU:90% at 1520mhz
  • CPU:40% at 1949mhz
  • VRAM:2.9 GB
  • RAM:6.9 GB

虽然60fps很不错,但在90%GPU的状态下,我们没有任何余地。如果我们推动图形任何更硬的新特性,它将立即掉帧。

胜利之作 #1:CPU的降低

在解决GPU问题之前,我们做了一个快速的改变:我们移除了Amplify Imposters并用Unity 6.3中的新自动LOD系统替换了它。Amplify是一个很好的包,但它并不是我们的用例。

结果: 立即CPU下降到15–20%。这是一个巨大的胜利。

大狩猎:90%GPU瓶颈的定位

我们在隔离构建中运行了一系列测试来确定GPU瓶颈的确切位置。以下是我们遵循的确切顺序:

  1. 关闭后处理: 没有任何变化。
  2. 设置渲染比例为0.5: 巨大的下降。这立即告诉我们,我们很可能是填充率或像素着色器受限。我们通过将帧率限制为30fps来确认这一点,从而获得了类似的GPU负载降低。
  3. (STP/FSR的侧注:我们可以简单地在这里使用上采样,但这只是一个止痛剂。如果我们解决了根源问题,STP/FSR就变得多余或只是额外的装饰)
  4. Forward+ vs. Forward: 我们切换到Forward渲染以查看Steam Deck是否在计算操作上卡住。没有任何变化。
  5. “白色材料”测试: 我们用基本白色材料替换了游戏中的所有材料。这确认了我们是填充率受限——这意味着我们卡住在内存带宽,重绘,或者纹理上。
  6. 帧调试器 - 罗格摄像机: 我们打开了帧调试器并立即得到了一个击中。一个渲染纹理摄像机在错误的时间点开启并保持活动。它在我们的设置下是一个很小的影响,但是一个免费的胜利。修复。
  7. 帧调试器 - 主要凶手: 调试器捕捉到59个绘制调用,位于SSAO和Decals之间。Decals在移动硬件上并不是很棒的,且我们的SSAO设置在URP资产中已经被设置为最大值。
  8. 修复: 我们完全禁用了Decals(我们实际上不需要它们并且会用quad/sphere着色器来替换它们)。然后,我们对SSAO设置进行了激进的优化,直到我们只需要的视觉风格。

结果: 这是第一次我们移动了GPU的针对。它从一个顽固的90%下降到低70%

最后一搏

由于我们有了动力,我们就从其他地方开始清理:

  • 光晕: 关闭了高质量滤波。对于我们的外观来说并不是必要的。
  • 不透明纹理: 将不透明纹理的4倍方形下采样。这是一个巨大的交易,视觉影响很小(数学结果大约是256k像素下降到64k)。
  • 地形洞: 关闭了。我们甚至不使用Unity地形,但工具提示声称它会加快构建。我的一点疑虑,但为什么不试试呢?
  • 光照/反射: 关闭了MainLightShadows,Reflection Probes和Reflection Probe Atlases。我们不需要它们来呈现场景,而且我们已经禁用了个体光源上的阴影。

结果(优化后)

以下是Steam Deck的当前状态:

  • FPS: 仍然坚固的60
  • GPU: 舒适的55% – 70%(在一个更低的830mhz下)
  • CPU: 15% – 20%
  • VRAM: 2.4 GB(下降0.5 GB
  • RAM: 6.4 GB(下降0.5 GB

最好的部分: Steam Deck的电池报告在100%充电时从约2小时增加到4.5小时

总体而言,我们非常高兴。花时间真正定位瓶颈而不是简单地在问题上使用FSR给我们带来了巨大的热量和电池收益。仅供参考,我们没有使用Proton,而是选择了一个本地Linux构建。

希望这个诊断清单能帮助一些人从自己的项目中获得几个额外的电池寿命!