iPhone openGLES性能调优

时间:2010-01-16 00:42:11

标签: iphone opengl-es performance

我现在正在尝试一段时间来优化游戏的帧速率而不会取得进展。我正在运行最新的iPhone SDK并拥有iPhone 3G 3.1.2设备。

我调用了大约150个drawcalls,总共渲染了大约1900个三角形(所有对象都使用两个纹理层和多纹理进行纹理化。大多数纹理来自存储在pvrtc 2bpp压缩纹理中的相同textureAtlasTexture)。 这在我的手机上以30 fps的速度渲染,在我看来只有1900个三角形太低了。

我尝试了许多优化性能的方法,包括将对象批处理,转换CPU上的顶点以及在单个drawcall中渲染它们。这大概8个drawcalls(选择150个drawcalls),但性能大致相同(fps降至26fps左右)

我使用存储在交错数组中的32字节顶点(12字节位,12字节法线,8字节uv)。我正在渲染triangleLists,顶点按TriStrip顺序排序。

我做了一些分析,但我真的不知道如何解释它。

  1. 仪器采样 使用仪器和采样yelds这个结果: http://neo.cycovery.com/instruments_sampling.gif 告诉我在“mach_msg_trap”中花了很多时间。我用谷歌搜索它,似乎调用这个函数是为了等待其他一些事情。但等待什么??

  2. 仪器的OpenGL 使用openGL模块的仪器大喊这个结果: http://neo.cycovery.com/intstruments_openglES_debug.gif 但在这里我真的不知道这些数字告诉我的是什么

  3. 鲨鱼剖析: 用鲨鱼进行剖析并没有告诉我太多: http://neo.cycovery.com/shark_profile_release.gif DrawTriangles所花费的最大数字是10% - 其余部分用于非常小的百分比函数

  4. 任何人都可以告诉我还有什么办法可以解决瓶颈并帮助我解释这些分析信息吗?

    非常感谢!

4 个答案:

答案 0 :(得分:1)

你可能受CPU限制了。 OpenGL ES仪器中的平铺器/渲染器利用率统计显示,GPU的占空比在20-30 fps之间呈现20-30%,这表明如果足够快,GPU可以以60 fps运行。看起来你可以采取一些措施从仪器和鲨鱼那里获得更多的信息:

默认情况下,Sampler显示来自每个线程的每个样本,这意味着系统框架创建的大多数空闲辅助线程将主导您的视图。为了更好地了解CPU实际执行的操作,请确保显示详细信息视图(左下角左侧的第三个按钮)并将Sample Perspective更改为Running Sample Times以排除线程空闲/阻塞的示例

我从你的应用程序本身看不到Shark跟踪中的任何样本。这可能是因为您的代码足够快,以至于它不会出现在热门函数列表中的任何位置,但也可能是因为Shark无法为您的应用程序找到符号。您可能需要在其首选项中配置搜索路径,或者手动将Shark指向应用程序二进制文件。此外,Shark默认显示按照它们花费多少CPU时间排序的函数列表。将视图更改为更像常规调用树的内容可能很有用,因此您可以直观地了解整个渲染循环的时间。要执行此操作,请将右下角的“视图”选项更改为“树(自上而下)。”(如果您在此处未看到应用程序名称或功能,则Shark肯定会丢失您的符号。)

答案 1 :(得分:0)

遗憾的是,我并不精通OpenGL,但从以下三个结果中我可以看出一些事情:

1)从采样工具中,你可能会有某种背景网络连接吗?

2)渲染的利用率对我来说似乎很低(虽然我不知道如何改进它们)。

3)即使10%看起来很低,这似乎是一个很好的攻击点 - 然而几乎同样怀疑在memcpy上花了那么多时间。此外,ValidateState有点大,可能会让你退缩。

工具方面我认为您正在使用正确的工具来检查性能,您只需要更多地考虑这些对您的应用程序意味着什么。

答案 2 :(得分:0)

如果没有完整的来源,很难确切地说出发生了什么。仪器跟踪显示20%的渲染利用率,这有点低。这可能意味着你受CPU限制。但是,如果是这种情况,我希望在您的第一个跟踪中看到更多特定于应用程序的采样点。

我的建议是推出自己的计时课程。这样的东西(c ++):

#include <sys/time.h>

class Timer
{
public:
    Timer()
    {
        gettimeofday(&m_time, NULL);
    }
    void Reset()
    {
        gettimeofday(&m_time, NULL);
    }
    // returns time since construction or Reset in microseconds.
    unsigned long GetTime() const
    {
        timeval now;
        gettimeofday(&now, NULL);
        unsigned long micros = (now.tv_sec-m_time.tv_sec)*1000000+
                               (now.tv_usec-m_time.tv_usec);
        return micros;
    }
    protected:
        timeval m_time;
};

为您的代码部分计算时间,确切知道您的时间花在哪里。

另一个快速解决方法是禁用Thumb指令集。这可以帮助您的浮点性能达到20%或更高,但代价是可执行文件大小。

答案 3 :(得分:0)

如果您使用glFlush或glFinish,请删除所有这些。