我正在尝试在Nexus 7(原始版本)上优化用OpenGLES2编写的图形演示。我在调用glDrawElements(...);
double before = doubleTime();
glDrawElements(GL_TRIANGLES, getIndexCount(), GL_UNSIGNED_SHORT, 0);
double after = doubleTime();
MyLog("%f", after-before);
doubleTime()
是我写的一个函数,用gettimeofday()
以秒为单位返回当前时间。
记录0.06附近的数字
这对我来说似乎非常漫长。我的理解是,除非OpenGL调用获取信息,即glReadPixels / glGetInteger,否则它是非阻塞的,并且它在CPU上所做的工作很少。
有人知道为什么会这样吗? glDrawElements阻止了什么?
答案 0 :(得分:2)
您的基本理解是正确的。 OpenGL实现尝试尽可能地从应用程序代码异步操作。主要动机当然是通过让CPU和GPU尽可能并行工作来获得最大的系统吞吐量,并且耦合最小。
实际上,如果您将OpenGL调用描述为提交工作到GPU的请求,而不是直接执行任何操作,那么它有助于理解性能特征和时序。除了您已经提到的一些调用,例如glReadPixel()
,调用将在GPU执行相应工作之前很久就返回。大部分时间,它都会排队等待以后提交给GPU。
但是,您可以异步运行,或者实际上想要运行是有限制的。想象一下GPU限制的应用程序。这意味着在持续状态下,应用程序可以使OpenGL调用比GPU执行它们更快。除非你减慢应用程序的速度,否则它将在GPU之前运行得越来越远,越来越多的工作将排队等候。如果你对此没有采取任何措施,你最终会使用无限量的内存来存储排队的GPU工作。对于像游戏这样的用例,您也不希望排队太多GPU渲染,因为这会增加响应用户输入的延迟。
基于此,对于GPU受限的用例,应用程序已在某些点被阻止,以防止它在GPU之前运行得太远。这种情况发生在何处以及如何发生的问题相当复杂且与系统有关。一个简单的选择是永远不要让CPU超过GPU之前的 n 帧,其中 n 可能类似于2.但实际策略可能相当大更复杂,可能还有其他原因可能需要阻止应用程序。
如果没有彻底的分析,为什么在这种情况下你的抽奖电话被阻止是不可能的。最可能的原因是你已经远远领先于GPU,并且驱动程序决定是时候阻止你让GPU赶上某一点了。驱动程序也可能在某些内部资源或可用内存上达到限制,并且必须阻塞,直到释放出来。