【问题标题】:iPhone OpenGL ES glFlush() inconsistently slowiPhone OpenGL ES glFlush() 始终慢
【发布时间】:2011-08-17 09:43:18
【问题描述】:

看似随机(但在任何给定程序运行期间通常保持一致),我的presentRenderBuffer 调用非常慢。我追踪到调用presentRenderBuffer 调用glFlush(),所以现在我在presentRenderBuffer 之前调用glFlush()。我在glFlush() 上设置了一个计时器,它会做两件事之一,似乎是随机的。

glFlush() 要么

1) 始终需要 0.0003 秒

2) 在大约 0.019 到 0.030 秒之间交替

最奇怪的是,这与绘图代码无关。即使我注释掉所有绘图代码以便它所做的只是调用glClear(),我仍然只是随机得到两个结果之一。

绘图方法由CADisplayLink 调用,设置如下:

dLink = [[UIScreen mainScreen] displayLinkWithTarget:viewController selector:@selector(drawFrame)];
dLink.frameInterval = 1;
[dLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

我发现无法确定导致其中一个结果发生的原因。任何人都可以提供想法吗?

【问题讨论】:

    标签: iphone ios performance opengl-es cadisplaylink


    【解决方案1】:

    一般来说,在 iOS OpenGL ES 调用上执行精确计时有点棘手,因为设备使用了基于 tile 的延迟渲染器。状态更改、绘图和其他操作可以推迟到呈现场景之前。

    这通常会使glFlush() 或上下文的-presentRenderBuffer: 之类的东西看起来很慢,而实际上它只是导致所有延迟渲染都在该点执行。

    您注释掉所有绘图代码但glClear() 的情况不会受此影响。您在交替示例中呈现的不同时间大致对应于 1/53 或 1/33 秒,这似乎表明它可能只是阻塞了足够长的时间以匹配屏幕刷新率。 CADisplayLink 应该让您与屏幕刷新保持同步,但我可以看到您的绘图有时会略微偏离。

    你是在主线程上运行这个测试吗?可能有一些东西导致主线程轻微阻塞,让你稍微偏离屏幕刷新时间。当我将渲染移到后台线程时,我发现这种振荡有所减少,但它仍然由 CADisplayLink 触发。当我这样做时,渲染速度也提高了,尤其是在多核 iPad 2 上。

    最后,我认为在 iOS 上使用 OpenGL ES 时不需要显式使用 glFlush()。您的 EAGLContext 的 presentRenderbuffer: 方法应该是将您的框架渲染到屏幕所需的全部内容。我在这里的 OpenGL ES 应用程序中没有看到 glFlush() 的单个实例。在你的情况下它可能是多余的。

    【讨论】:

    • 我确实在主线程上渲染。要将渲染转移到另一个线程,我是否创建一个新线程并将显示链接添加到另一个线程的运行循环?我想我读到从主线程以外的线程更新 UI 是不可取的,但我会试一试。谢谢!
    • 另外,我知道调用 glFlush() 是多余的,但这是一个测试,看看究竟是什么导致了巨大的减速。我发现 glFlush() 是缓慢的部分。如果在 presentRenderBuffer 之前调用它,那么 presentRenderBuffer 几乎不需要任何时间。
    • @pinerd314159 - 我为此使用了 GCD 队列,正如我在这里描述的那样:stackoverflow.com/questions/5944050/…。这让我可以在一个单宽队列中包含对 OpenGL ES 上下文的所有访问(调整帧缓冲区大小、渲染等),以保证在不使用昂贵锁的情况下不会同时访问。您只需要记住在每个块中设置当前上下文,因为它们运行的​​线程可能会改变,并且您需要在使用之前向给定线程注册上下文。
    • @pinerd314159 - 你看到glFlush() 很慢然后-presentRenderBuffer: 很快,如果你按照这个顺序运行它们的原因是glFlush() 将强制呈现所有延迟项目。稍后当您点击-presentRenderBuffer: 时,将没有任何事情要做。你会看到类似glReadPixels() 的行为,它会在继续之前停止渲染管道以执行所有待处理的任务。
    • @pinerd314159 - 我会再看一下 GCD,因为我觉得它是一个用于执行多线程任务的优雅框架。它与标准多线程中的范例不同,因此需要一点时间来适应,但是当我说它值得学习时请相信我。我教了一门课程,您可以在 iTunes U 上看到该主题(转到多线程会话):itunes.apple.com/WebObjects/MZStore.woa/wa/…,而 WWDC 2010 会议“iPhone 上的 Blocks 和 Grand Central Dispatch 简介”是关于该主题的一个很好的教程。
    【解决方案2】:

    我发现了我认为的问题。附加到 EAGLView 的视图控制器未按应有的方式设置为窗口的根视图控制器。相反,视图被手动添加为窗口的子视图。解决此问题后(以及其他一些相关修复),drawFrame 方法现在似乎与屏幕刷新完美同步。成功!

    【讨论】:

    • 有趣的是,如果您在 iPad 上以 x2 模式运行 iPhone 应用程序,您会得到这种行为
    猜你喜欢
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    相关资源
    最近更新 更多