背景:我们正在开发的游戏在我们更新到iOS 10或11的设备上进行了性能下降。两款运行10.3.3的iPhone 6s只能达到20-30fps,而iPhone 5s仍在运行8.0以60fps的速度轻松上架。
最近我将iPod6从ios 9更新到ios 11,它也从60到20-30 fps下降,运行完全相同的游戏版本。
注意:最初,GPU分析器让我相信这是一个与着色器相关的问题,但这是一个虚假的痕迹。感谢所有在此基础上发表评论的人。
以下是我如何缩小问题:
正常运行,我们的游戏每帧生成以下屏幕外纹理:
在iPhone5上,这一切都以平稳的60fps发生。在iPod6和iPhone6s上,由于更新到iOS10 / 11,它很难达到30fps。
作为测试,我将所有屏幕外渲染重定向到主帧缓冲区,禁用深度检查并在所有内容上启用Alpha混合,以确保平铺渲染器不会对任何内容进行优化。
结果是游戏被迫渲染的像素数量超过以前的10倍(因为填充256x256纹理的渲染现在都填充了640x1136的屏幕),所有都使用alpha混合(在很多之前)它没有混合),它很高兴在iPod6上以60fps的速度完成。
我知道我仍然可以对屏幕外渲染进行优化(我目前没有在阴影纹理上标记深度缓冲区以进行丢弃),但这不是非常重要的是:5s正在处理未经优化的渲染,iPod6也是如此,所以在iOS 10/11下有什么变化?
重现的步骤:
答案 0 :(得分:1)
根据我的测试,似乎某些iOS OGLES实现(特别是10.3.3和11)在将交错渲染优化到屏幕和屏幕外纹理方面做得非常糟糕。
理想情况下(1),从基于图块的硬件上的帧期间渲染到多个目的地的角度来看,OpenGL实现会尽可能长时间地在主帧缓冲区上执行渲染命令,具有解交织请求的序列的效果:
进入这个视觉上等效的执行的序列:
后一个序列效率更高,因为它避免了重复逻辑加载的需要,并存储了主帧缓冲区内容的(2)。
然而,从一个简单的基准测试中可以明显看出,iOS的更新版本中的实现在执行此优化方面比过去更糟糕。
我的基准分配了10个256x256纹理和10个512x512纹理,并为每个纹理分配了一个帧缓冲区。然后每个帧将为每个纹理绘制一些大的alpha混合精灵,然后将这些纹理渲染到屏幕上(也是alpha混合的)。我将其设置为默认情况下以交错顺序进行设置,然后在触摸屏幕时进行反交错。
以下是一系列测试设备的未触及/触摸(差异)结果:
如您所见,所有设备都受益于手动更正渲染顺序。然而,没有这样做的惩罚从iOS8下的2.5ms上升到类似硬件上iOS11下的7.2ms(在iPod上安装iOS11之前,它平稳地运行我们的游戏,所以我觉得有理由得出推断)。在iPhone6s上,惩罚甚至更高,毫无疑问是因为屏幕分辨率更高。
似乎可能是惩罚部分归因于逻辑加载和存储,部分归因于在可以将渲染到画面之前完成渲染到纹理之间的依赖性引入的停顿。再次:在推迟指向主帧缓冲区的命令的实现中,这些停顿不会发生。
拒绝替代方案
逻辑加载和存储本身的成本大幅增加。
这将解释观察到的减速,但不能解释当手动解交错渲染顺序时iPod和iPhone5之间的性能相似性。更正的订单仍然需要大量的逻辑存储(10mb),并且没有明显额外成本的证据。
参考文献: