我有一个使用OpenGL ES 2.0的应用程序,并使用GLSurfaceView和Renderer类绘制到屏幕上.本来,我中将renderMode设置为RENDER_WHEN_DIRTY,然后叫requestRender()每秒60次,时间过了多长时间才能完成的功能,但我一直获得极短的frametimes(高帧速率),当程序显然落后于我的手机.然后我假设这是因为requestRender()只发布一个渲染请求,而不是实际调用onDrawFrame(),因此定时它将毫无意义.
然后我决定在实际的onDrawFrame()函数中进行计时.我在函数的开头和结尾使用了SystemClock.elapsedRealtime()并计算了差异,再一次,我得到超过70的帧率,实际上,我的手机渲染超过1000个顶点并且滞后极大.
那么,你应该如何计算帧时间/帧速率,以及你应该在哪些点开始/停止计时?
解决方法:
定时调用requestRender()肯定是没有意义的.您通常在主线程中调用它,它会通知渲染线程唤醒并渲染帧.它会在完成信号后立即返回,因此您根本不会测量任何渲染相关的内容.
从onDrawFrame()的开始到结束测量更有意义,但它仍然不会给你你想要的东西. OpenGL与您在CPU上的工作异步操作.在大多数情况下,当您进行OpenGL API调用时,它只会将工作排队等待以后由GPU执行.然后,呼叫返回,大部分时间早在GPU完成工作之前,或者在驱动程序甚至将工作提交给GPU之前.
因此,当您测量onDrawFrame()从开始到结束的时间时,您可以测量进行所有OpenGL调用所需的时间,包括在代码中花费的时间以及驱动程序处理调用所需的时间.但它并不能衡量GPU完成工作所需的时间.
你能做的最好的事情就是提供足够多的帧(比如几百到几千),并简单地测量从开始到结束所经过的时间.然后将您渲染的帧数除以总耗用时间(以秒为单位),并获得总体平均帧速率.
如果您不仅想要平均帧率,而且还想观察变化,那么事情会变得更加困难.如果你需要,我首先测量一次调用onDrawFrame()到下一次调用onDrawFrame()的开始之间经过的时间.这不是一种科学准确的方法来衡量每一帧的时间,但它会比你尝试的更好,并且应该给你至少有用的数字.它不准确的原因是即使onDrawFrame()的开始也不一定与完成帧的GPU同步.我相信Android使用三重缓冲,所以可以在飞行中有几帧.换句话说,GPU可能比您的代码当前正在处理的渲染落后1-2帧.
在OpenGL中有一种称为“计时器查询”的机制,它允许您更直接地测量GPU花费多少时间来执行给定的命令序列.但是直到版本3.1,该功能才被添加到ES.