方法Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
花了太多时间,大约15毫秒
以下是代码示例:
long now = System.currentTimeMillis();
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
long end = System.currentTimeMillis() - now;//this is almost always > 15 ms
System.out.println("render time total: " + end);
这是在我的Android设备(nexus 5)上,在我的电脑上它的2-3毫秒
答案 0 :(得分:6)
这是预期的。您正在测量帧速率,而不是glClear()
的执行时间。
要了解这里发生的事情,您需要注意GPU与CPU代码异步操作。例如,当您调用glClear()
时,您将提交一个命令,告诉GPU清除帧缓冲区。描述其工作原理的最简单方法是将命令添加到队列中,该队列稍后由GPU处理。
一个结果是,当glClear()
调用返回时,帧缓冲区通常没有被清除。因此,测量在通话中花费的时间与实际清除帧缓冲所需的时间无关。
那你在测量什么?它基本上是帧速率。 Android不允许您生成比屏幕刷新率更快的帧,通常为60 Hz或稍高。在60 Hz时,显示屏每16.667 ms显示一个新帧,这几乎就是您测量的时间。
您的渲染需要受到限制以匹配显示刷新率,否则您将以更高的速率生成帧,并且会排队越来越多的工作。限制可能会发生在任何地方,但是当新的框架已经排队时,在新框架开始时阻止应用程序是相当常见的。
我相信大多数Android系统都使用三重缓冲。这意味着如果两个未显示的帧已经排队等待显示,并且您开始渲染另一个帧,则会阻止您的阻止,直到下一个屏幕刷新时显示两个待处理帧中的一个。
这实际上是非常理想的行为。根据系统和设置的不同,某些PC类型设备的渲染速度比屏幕刷新速度快。结果是您渲染的帧永远不会出现在显示器上,只是简单地删除。如果你考虑一下,这完全是浪费。特别是在电池供电和/或受热约束的设备上,您不希望做任何不必要的工作。限制渲染以匹配屏幕刷新率是完全合理的。
答案 1 :(得分:0)
接受的答案准确无误。我想使其更简单。
假设您的渲染功能如下:
onDrawFrame() {
time t1, t2;
t1 = getTime();
glClear();
t2 = getTime();
logOut(t2 - t1); // log time would be around 16 ms
}
如果刷新FPS为60Hz,则刷新裕量约为16.666毫秒。现在,如果您的渲染时间小于16毫秒,那将毫无意义,因为GPU将无法处理更新的调用(很好的GPU有一个队列来缓冲这些调用,但是无论如何该队列都不是无限的)。
因此,GPU 延迟了glClear()
调用的使用和返回,以避免无意义的GL调用。
如果您进行了以下类似的其他实验,则可能会发现记录的时间要短得多。
onDrawFrame() {
time t1, t2;
t1 = getTime();
glClear();
t2 = getTime();
sleep(10); // sleep 10 ms
logOut(t2 - t1); // log time would be around 5 to 6 ms now
}