【问题标题】:optimizing iPhone OpenGL ES fill rate优化 iPhone OpenGL ES 填充率
【发布时间】:2011-02-16 15:46:12
【问题描述】:

我在 iPhone 上有一个 Open GL ES 游戏。我的帧率非常糟糕,~20fps。在 iPhone 3G 上使用 Xcode OpenGL ES 性能工具,它显示:

渲染器利用率:95% 到 99%

Tiler 利用率:~27%

我正在绘制很多非常大的图像,并进行了很多混合。如果我减少绘制的图像数量,帧率会从 ~20 变为 ~40,尽管性能工具的结果保持大致相同(渲染器仍然最大化)。我认为我受到 iPhone 3G 填充率的限制,但我不确定。

我的问题是:如何更详细地确定瓶颈在哪里?这是我最大的问题,我只是不知道一直在做什么。如果是fillrate,除了少画,还有什么可以改进的吗?

我正在使用纹理图集。我试图最小化图像绑定,尽管这并不总是可能的(绘图顺序,并非所有内容都适合一个 1024x1024 纹理等)。每帧我做 10 个图像绑定。这看起来很合理,但我可能弄错了。

我正在使用顶点数组和 glDrawArrays。我真的没有很多几何。如果需要,我可以尝试更精确。每个图像都是 2 个三角形,我尝试批量处理,但通常(可能有一半时间)图像是使用单独的 glDrawArrays 调用绘制的。除了图像,我在 ~6 个 glDrawArrays 调用中渲染了 ~60 个三角形的几何图形。我经常在调用 glDrawArrays 之前先进行 glTranslate。

切换到 VBO 会提高帧率吗?我不认为它是大量的几何体,但也许由于其他原因它更快?

是否有一些需要注意的事项可能会降低性能?例如,我应该避免 glTranslate、glColor4g 等吗?

我在每帧 3 个位置使用 glScissor。每次使用都包含 2 个 glScissor 调用,一个用于设置它,一个用于将其重置为原来的样子。我不知道这里是否对性能有很大影响。

如果我使用 PVRTC,它的渲染速度会更快吗?目前我所有的图像都是 GL_RGBA。我没有内存问题。

我的全屏纹理之一是 256x256。使用 480x320 这样手机就不必进行任何缩放会更好吗?还有其他关于纹理大小的一般性能建议吗?

这里是我画的大致概念,按以下顺序:

1) 切换到透视矩阵。 2) 绘制全屏背景图片 3) 绘制一个半透明的全屏图像(这个有滚动纹理)。 4)画几个精灵。 5)切换到正交矩阵。 6)画一些精灵。 7)切换到透视矩阵。 8)绘制精灵和其他一些纹理几何。 9) 切换到正交矩阵。 10) 绘制一些精灵(例如,游戏 HUD)。

步骤 1-6 绘制一堆背景材料。 8 绘制了大部分游戏内容。 10 绘制 HUD。

如您所见,有很多层,其中一些是全屏的,而一些精灵非常大(屏幕的 1/4)。图层使用半透明,所以我必须以从后到前的顺序绘制它们。由于需要在正交和其他透视图中绘制各个层,这使情况变得更加复杂。

如果需要,我很乐意提供更多信息。提前感谢您针对我的问题提供的任何性能提示或一般性建议!

编辑:

我添加了一些日志来查看我正在执行多少个 glDrawArrays 调用,以及有多少数据。我每帧执行大约 20 个 glDrawArray 调用。通常其中大约 1 到 6 个具有大约 40 个顶点。其余的调用通常只有 2 个顶点(一个图像)。我只是在使用 glVertexPointer 和 glTexCoordPointer。

【问题讨论】:

  • 确定您是否受到填充限制的一个好方法是更改​​您要绘制的区域的大小。如果减小尺寸会提高帧速率,则表示填充受限。

标签: iphone performance optimization opengl-es rendering


【解决方案1】:

iPhone 平台上最大的性能杀手是绘图调用和状态更改的数量。如果您执行超过 20 次绘图调用或状态更改,您将遇到性能障碍。

批处理和纹理图集是您的朋友。

【讨论】:

  • 嗨,谢谢。我用关于我正在拨打的电话数量的附加信息编辑了我的问题的结尾。它似乎在你提到的合理范围的范围内。我会考虑批量处理更多的单个图像,但我不希望它可以进一步改进。
  • @NateS:如果您认为填充率有限,请尝试 PVRTC。
  • 在这种情况下,这可能不是最好的建议。减少绘图调用的数量是为了减少在 OpenGL 实现中花费的 CPU 时间。鉴于渲染器已被充分利用,绘图调用批处理可能不会改善这种情况。 Instruments 或 Shark 可用于分析 CPU 使用情况,并确定有多少 CPU 时间未使用,以及在 OpenGL 驱动程序中使用了多少。
  • 经过更多优化以减少绘制调用后,我获得了大约 6fps,这很重要。这很令人惊讶,因为我觉得自己的填充有限,所以我没想到会有太多收益。
【解决方案2】:

查看OpenGL ES Programming Guide for iPhone OS 的 Apple 的“Best Practices for Working with Texture Data”和“Best Practices for Working with Vertex Data”部分。他们强烈建议(和其他人一样)使用 PVRTC 来压缩纹理,因为它们可以提供比标准未压缩纹理 8:1 或 16:1 的压缩比。除了 mipmapping,您似乎还在使用纹理图集进行其他推荐的优化。

您似乎不受几何限制,因为(正如我在this question 中发现的那样)Tiler Utilization 统计数据似乎表明几何大小造成了多少瓶颈。但是,iPhone 3G S(以及第三代 iPod touch 和 iPad)支持硬件加速的 VBO,因此您可以试一试,看看它们如何影响性能。它们可能没有压缩纹理的效果那么大,但它们并不难实现。

【讨论】:

    【解决方案3】:

    鉴于 Renderer Utilization 基本上是 100%,这表明瓶颈是填充、纹理和混合像素。旨在优化顶点处理(VBO 和顶点格式)或 CPU 使用率(绘图调用批处理)的技术可能无济于事,因为它们不会加速像素处理。

    最好的办法是减少要填充的像素数量,并查看不同的纹理格式,以便更好地利用第一代设备上非常有限的内存带宽。尽可能使用 PVRTC 纹理,否则使用 16 位未压缩纹理。

    【讨论】:

    • 谢谢。将全屏纹理切换到 PVR 获得了 ~4fps,这很好。我知道他们使用的内存更少,但不确定是否会有任何性能提升。此外,我将图像更改为 GL_NEAREST 并获得了另外 2-3 fps。
    • 更新:使用 CADisplayLink 也有所帮助。
    【解决方案4】:

    在类似情况下(将 2D 冒险游戏移植到 iPad)。我的 3GS 版本运行时或多或少锁定在 60FPS,把它放在 iPad 上(和我的下巴)掉到 20fps。

    事实证明,其中一个小问题是 PVR 卡讨厌 GL_ALPHA_TEST;在实际上有轻微积极影响的 PC 上(尤其是在较旧的英特尔芯片上),但它们在 iPhone 上的填充率上已经死亡。将其更改为

     glDisable(GL_ALPHA_TEST);
    

    让我的 FPS 立即提高了 100%(最高 40 FPS)。一行代码还不错.. :)

    艾伦

    【讨论】:

    • 哇。这很有趣。通过关闭 alpha 测试将 iPad 上的帧速率提高一倍。根据记录,我们一直在进行 alpha 混合,而且我们的游戏是 alpha 重,所以我们在任何地方都使用混合,你甚至看不到 alpha 测试。
    • 给我一个 Apple 未记录的错误“1280”。不管什么意思。谢谢,苹果。
    【解决方案5】:

    (主要用于)3G 的一大胜利也将是您使用的纹理过滤。检查您是否使用“TRILINEAR”过滤,并将其更改为“BILINEAR”。

    确保您像这样设置纹理:

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    

    不是这样的:

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    

    哈利

    【讨论】:

      【解决方案6】:

      我想补充一个答案,将 Framebuffer 支持更改为 16 位格式,而不是 32 位格式。

      if ((self = [super initWithCoder:coder])) 
          {
          eaglLayer = (CAEAGLLayer *)self.layer;
          eaglLayer.opaque = YES;
          eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                                  [NSNumber numberWithBool:NO], 
                                                  kEAGLDrawablePropertyRetainedBacking, 
                                                  kEAGLColorFormatRGB565,  //kEAGLColorFormatRGBA8 = large frame buff 32bit  // kEAGLColorFormatRGB565 = 16bit frame buffer.
                                                  kEAGLDrawablePropertyColorFormat, 
                                                  nil];        
      }
      

      让我意识到这一点的是 XCode 分析器。它一直抱怨使用大的帧缓冲区,最终我在我的 init 部分找到了它。 http://developer.apple.com/library/ios/#documentation/iPhone/Reference/EAGLDrawable_Ref/EAGLDrawable/EAGLDrawable.html . 这一变化让我在 iPad、Retina 和 iPod 上的游戏速度达到了 60 FPS。 我还没有重新发布它们,因为我在 3 天前才发现它 :) 但我不认为我打算以 60fps 发布,30fps 对于休闲游戏来说就很好了,我发现我的声音效果被削减了如果我决定使用 60fps,请重新采样、在另一个线程中播放 sfx 或其他解决方案以保持该帧速率。
      不要忘记丢弃不用于显示的缓冲区..

      if (fiOSver >= 4.0f) {
          const GLenum discards[]  = {GL_DEPTH_ATTACHMENT_OES};
          glDiscardFramebufferEXT(GL_FRAMEBUFFER_OES,1,discards);
      }
      
      [m_oglContext presentRenderbuffer:GL_RENDERBUFFER_OES];
      

      【讨论】:

        【解决方案7】:

        根据我过去在处理速度约为 600mhz 的旧 Windows 移动设备上使用 openGL ES 的经验 通常降低渲染窗口分辨率会提高渲染速度。

        在我最近的测试中,我发现我需要在逐帧渲染时进行性能监控,以收集当前性能可以显示多少 fps 以及当前应用的分辨率

        我希望在运行游戏渲染引擎时使用监控算法代替渲染视图以平衡分辨率和帧速率是一种很好的做法。

        根据您想要的帧速率数量,您应该牺牲渲染视图分辨率,以在大多数硬件和软件性能不同的设备上表现最佳并平稳降级。

        您可能需要像本文中解释的那样通过菜单控制分辨率。

        http://www.david-amador.com/2010/09/setting-opengl-view-for-iphone-4-retina-hi-resolution/

        【讨论】:

          猜你喜欢
          • 2018-07-12
          • 2011-03-08
          • 2011-07-07
          • 1970-01-01
          • 1970-01-01
          • 2013-07-11
          • 1970-01-01
          • 2011-04-21
          • 2011-09-16
          相关资源
          最近更新 更多