我正在尝试剖析渲染器,并且看到了一些我无法解释的奇怪的分析行为。

我正在使用glSurfaceView,它已设置为连续渲染。

这就是我的onDrawFrame()的结构

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

这在轻负载下表现缓慢,因此我创建了一个计时器类并开始对此进行概要分析。我对看到的东西感到非常惊讶。

我像这样在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度量运行所有我的绘制调用所花费的时间,swapTimer度量从onDrawFrame退出到返回之间的时间(调用eglSwapBuffers所花费的时间)。

当我运行一个非常轻载的场景时,我得到了一些我无法解释的非常奇怪的数字:
swapTimer  : 20ms (average)
clearTimer : 11ms (average)
drawTimer  :  2ms (average)

我预计交换时间会比较长,因为我相信设备已将vsync强制启用为〜30fps,尽管我不知道为什么实际的“清除”调用会阻塞11毫秒?我以为它只是应该发出一个异步命令并返回?

当我绘制一个更加繁忙的场景时,数字变化很大:
swapTimer  :  2ms (average)
clearTimer :  0ms (average)
drawTimer  : 44ms (average)

在这个场景中,我的绘画调用花费了很多时间,看起来好像隐藏了很多vsync周期,而清除调用上的块完全消失了。

关于glClear为什么会在我的轻载场景中阻塞,有什么解释吗?

如果有人怀疑我的测量技术,请链接到我的“Timer”类源代码:http://pastebin.com/bhXt368W

最佳答案



这就解释了。

当您的场景非常明亮且图形绘制速度非常快时,清除和填充新颜色像素的时间将花费一些时间(它将始终需要时间,否则渲染器将落后并且当前正在绘制新内容)。较新的Android设备具有填充率限制。例如,Nexus One的填充率锁定为30 Hz-无论实际的绘图速度有多快,屏幕都将以该频率同步。如果图形以30 Hz以下的频率结束,则渲染器将与屏幕同步。这就是为什么您会注意到此延迟的原因,即使您删除了glClear()调用,也应注意该延迟。渲染器比屏幕更新的更新速度快。

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

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

计算:

F = 1/吨

易场景:

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

同步的延迟时间出现在您的探查器中。渲染器正在与屏幕同步。这意味着,如果删除glClear()glFinish()调用,则延迟将出现在其他位置。

重场景:

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

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



这似乎是正确的。

10-07 22:18