与iOS9(OGLES2.0)相比,iOS10/11下的屏幕外渲染性能大幅下降

与iOS9(OGLES2.0)相比,iOS10/11下的屏幕外渲染性能大幅下降,ios,iphone,performance,opengl-es,fragment-shader,Ios,Iphone,Performance,Opengl Es,Fragment Shader,背景:我们正在开发的游戏在我们升级到iOS 10或iOS 11的设备上性能急剧下降。两台运行10.3.3的iPhone6s只能达到20-30fps,而一台运行8.0的iPhone5s只能以60fps的速度轻松前行 最近,我将iPod6从ios 9升级到ios 11,运行完全相同版本的游戏时,速度也从60 fps下降到了20-30 fps NB:最初,GPU分析器让我相信这是一个与着色器相关的问题,但这是一个错误的线索。感谢所有在此基础上发表评论的人。 以下是我如何缩小问题的范围: 正常运行时,我

背景:我们正在开发的游戏在我们升级到iOS 10或iOS 11的设备上性能急剧下降。两台运行10.3.3的iPhone6s只能达到20-30fps,而一台运行8.0的iPhone5s只能以60fps的速度轻松前行

最近,我将iPod6从ios 9升级到ios 11,运行完全相同版本的游戏时,速度也从60 fps下降到了20-30 fps

NB:最初,GPU分析器让我相信这是一个与着色器相关的问题,但这是一个错误的线索。感谢所有在此基础上发表评论的人。

以下是我如何缩小问题的范围:

正常运行时,我们的游戏会在每一帧生成以下屏幕外纹理:

  • 256x256处的十个玩家阴影(不涉及alpha混合)
  • 十一个128x256到256x256动画“电视屏幕”纹理
  • 256x512“世界反射”纹理包含场景中模型的一小部分
在iPhone5s上,所有这些都以60帧/秒的速度顺利完成。在iPod6和iPhone6s上,自从更新到iOS10/11后,它的速度很难达到30fps

作为测试,我将所有的屏幕外渲染重定向到主帧缓冲区,禁用深度检查并在所有内容上启用alpha混合,以确保平铺渲染器不会优化任何内容

结果是,游戏被迫渲染的像素数是以前的十倍多(因为填充256x256纹理的渲染现在都填充640x1136屏幕),所有渲染都启用alpha混合(之前很多渲染都没有混合),并且在iPod6上以60fps的速度愉快地完成了这一操作

我知道我仍然可以对屏幕外渲染进行优化(我目前没有在阴影纹理上标记深度缓冲区以丢弃),但这并不是问题的关键:5s处理未优化渲染的效果很好,iPod6也很好,所以在iOS 10/11下有什么变化

复制步骤:

  • 生成20个小(256x256)纹理并为其指定帧缓冲区
  • 在每个帧中,为每个纹理渲染几个精灵,然后将纹理渲染到屏幕上
  • OpenGL配置此设置
  • 将所有精灵渲染重定向到屏幕(但也保留“将纹理渲染到屏幕”步骤)
  • 配置此设置。在我的测试中,尽管sprite渲染必须覆盖更多的像素,但第二次设置要快10毫秒

根据我的测试,某些iOS OGLES实现(尤其是10.3.3和11)在优化屏幕和屏幕外纹理的交错渲染方面做得非常糟糕

理想情况下(1),从在基于平铺的硬件上的帧期间渲染到多个目的地的角度来看,OpenGL实现将尽可能长时间延迟在主帧缓冲区上执行渲染命令,其效果是取消交错该请求序列:

  • 绘制到主帧缓冲区
  • 绘制到纹理1
  • 将纹理1绘制到主帧缓冲区
  • 绘制到纹理2
  • 将纹理n绘制到主帧缓冲区
进入该视觉等效执行序列:

  • 绘制到纹理1
  • 绘制到纹理2
  • 绘制纹理
  • 将纹理1绘制到主帧缓冲区
  • 将纹理2绘制到主帧缓冲区
  • 将纹理n绘制到主帧缓冲区
后一种序列效率更高,因为它避免了对主帧缓冲区内容的重复逻辑加载和存储(2)

然而,从一个简单的基准测试中可以明显看出,较新版本的iOS在执行此优化方面比过去差得多

我的基准测试分配了十个256x256纹理和十个512x512纹理,并为每个纹理分配了一个帧缓冲区。每一帧,它将为每个纹理绘制大量的alpha混合精灵,然后将这些纹理渲染到屏幕上(也是alpha混合)。我将其设置为默认情况下以交错顺序进行,然后在触摸屏幕时取消交错

以下是经过测试的一系列设备的未接触/接触(差异)结果:

  • iPhone 5s(iOS 8.0):14毫秒/11.5毫秒(2.5毫秒)
  • iPod 6gen(iOS11):19ms/11.8ms(7.2ms)
  • iPhone6s(iOS10.3.3):17ms/8.2ms(8.8ms)
如您所见,所有设备都受益于手动更正渲染顺序。然而,在类似的硬件上,不这样做的惩罚从iOS8下的2.5ms上升到iOS11下的7.2ms(在将iOS11安装到iPod上之前,它平稳地运行了我们的游戏,所以我觉得得出这样的推论是合理的)。在iPhone6s上,惩罚甚至更高,这无疑是因为它的屏幕分辨率更大

这似乎部分是由于逻辑加载和存储造成的,部分是由于在将纹理绘制到屏幕之前完成渲染到纹理之间的依赖关系导致的暂停。同样:在延迟定向到主帧缓冲区的命令的实现中,这些暂停不会发生

被拒绝的备选方案

逻辑负载和存储本身的成本大幅增加

这可以解释观察到的速度减慢,但不能解释当渲染顺序手动去交错时iPod和iPhone5s在性能上的相似性。正确的顺序仍然需要大量的逻辑存储(10mb),并且没有证据表明会有大量额外成本

参考资料:

1:


2:

你说的是opengl es,对吗?你的目标是哪个版本?OGLES2.0-现在添加到主帖子中。有两件事需要尝试:1。用两个单独的vec2替换vec4 texcoord,这样可以避免依赖纹理读取(尽管