为什么glClear在OpenGLES中被阻塞?

我试图描绘我的渲染器,我看到一些奇怪的分析行为,我无法解释。

我正在使用glSurfaceView,我已经设置了不断渲染。

这就是我的onDrawFrame()的结构

 public void onDrawFrame(GL10 unused) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); executeAllDrawCommands(); } 

这在轻负载下performance的很慢,所以我创build了一个计时器类,并开始分析这一些。 我对我所看到的很惊讶。

我把一些探测器放在我的onDrawFrame方法中,如下所示:

 public void onDrawFrame(GL10 unused) { swapTimer.end(); clearTimer.start(); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); clearTimer.end(); drawTimer.start(); executeAllDrawCommands(); drawTimer.end(); swapTimer.start(); } 

clearTimer测量调用glClear drawTimer的时间, drawTimer测量运行所有绘制调用所swapTimer的时间, swapTimer测量onDrawFrame退出时间和返回时间(调用eglSwapBuffers所用的时间)的时间。

当我跑了一个非常轻的场景,我得到了一些奇怪的数字,我无法解释:

 swapTimer : 20ms (average) clearTimer : 11ms (average) drawTimer : 2ms (average) 

我预计交换时间会稍微大一点,因为我相信这个设备的vsync强制启用的速度为30fps,不过我不知道为什么实际的“清除”通话会被阻塞11毫秒。 我以为它只是应该发出一个asynchronous命令并返回?

当我画一个更繁忙的场景时,数字发生了很大变化:

 swapTimer : 2ms (average) clearTimer : 0ms (average) drawTimer : 44ms (average) 

在这个场景中,我的平局电话花费了太多的时间,看起来像是隐藏了很多的vsync时间,而且清除电话中的块完全消失。

有什么解释为什么glClear阻止我的轻装载场景?

链接到我的'计时器'类源代码,以防有人怀疑我的测量技术: http : //pastebin.com/bhXt368W

Solutions Collecting From Web of "为什么glClear在OpenGLES中被阻塞?"

我把glFinish(和finishTimer.start()/ end())放在它的周围),它需要所有的时间远离glClear。 相反,现在glFinish需要几毫秒,glClear变为即时。

这解释了它。

当你的场景非常轻时,绘图渲染速度非常快,用新颜色清理和填充像素的时间将需要一些时间(这将总是需要时间,否则渲染器在后面,并且正在绘制新的东西)。 较新的Android设备具有填充限制。 例如,Nexus One在30赫兹时有一个填充locking – 无论您的实际图纸运行速度如何,屏幕将以该频率进行同步。 如果graphics在30 Hz以下完成,则渲染器将与屏幕同步。 这就是为什么你注意到这个延迟,即使你删除glClear()调用,你应该注意到这个延迟。 渲染器比屏幕的更新更快,更快。

当渲染器有许多要绘制的对象时,由于渲染器现在在屏幕更新之后,同步将停止(给定繁忙场景的configuration文件数据)。

当你使用glFinish() ,它会消除glClear()函数会导致的时间,通过遵循填充率逻辑,这意味着glFinish()现在是确保与屏幕同步的函数。

计算

F = 1 / T

简单的场景

F = 1 / T = 1 /((20 + 11 + 2)* 10 ^ -3)=〜30Hz

同步的延迟时间出现在您的分析器中。 渲染器正在与屏幕同步。 这意味着如果你删除glClear()或者glFinish()调用,那么延迟就会出现在别的地方。

重场景

F = 1 / T = 1 /((2 + 0 + 44)* 10 ^ -3))=〜22Hz

同步的延迟时间不会出现在您的分析器中。 渲染器在屏幕更新频率之后。

这似乎是所有相关的vsync

这似乎是正确的。