简体   繁体   English

测量Android GLSurfaceView.Renderer的帧时间/帧速率

[英]Measuring Frametime/Framerate of an Android GLSurfaceView.Renderer

I have an application that uses OpenGL ES 2.0, and uses a GLSurfaceView and a Renderer class to draw to the screen. 我有一个使用OpenGL ES 2.0的应用程序,并使用GLSurfaceView和Renderer类绘制到屏幕上。 Originally, I set the rendermode to RENDER_WHEN_DIRTY , and then called requestRender() 60 times per second, timing how long it took to complete the function, but I was consistently getting incredibly short frametimes (high framerates), when the program was CLEARLY lagging on my phone. 最初,我将rendermode设置为RENDER_WHEN_DIRTY ,然后每秒调用requestRender() 60次,计算完成该函数需要多长时间,但是当程序明显滞后时,我一直得到令人难以置信的短帧时间(高帧率)我的手机。 I then assumed that this was because requestRender() only posts a render request, rather than actually calling onDrawFrame() , and so timing it would be pointless. 然后我假设这是因为requestRender()只发布一个渲染请求,而不是实际调用onDrawFrame() ,因此定时它将毫无意义。

I then decided to do the timing in the actual onDrawFrame() function. 然后我决定在实际的onDrawFrame()函数中进行计时。 I used SystemClock.elapsedRealtime() at the beginning and at the end of the function, and calculated the difference, and once again, I was getting framerates of over 70, when in actual fact, my phone was rendering over 1000 vertices and was lagging tremendously. 我在函数的开头和结尾使用了SystemClock.elapsedRealtime()并计算了差异,再一次,我得到超过70的帧率,实际上,我的手机渲染超过1000个顶点并且滞后极大。

So, how are you supposed to calculate frametime/framerate, and at which points should you start/stop timing? 那么,你应该如何计算帧时间/帧速率,以及你应该在哪些点开始/停止计时?

Timing the call to requestRender() is certainly meaningless. 定时调用requestRender()肯定是没有意义的。 You normally call that in the main thread, and it signals the rendering thread to wake up and render a frame. 您通常在主线程中调用它,它会通知渲染线程唤醒并渲染帧。 It will return as soon as it has done the signalling, so you would not measure anything rendering related at all. 它会在完成信号后立即返回,因此您根本不会测量任何渲染相关的内容。

Measuring from start to end of onDrawFrame() makes more sense, but it still won't give you what you're looking for. onDrawFrame()开始到结束测量更有意义,但它仍然不会给你你想要的东西。 OpenGL operates asynchronously from work you do on the CPU. OpenGL与您在CPU上的工作异步操作。 In most cases, when you make an OpenGL API call, it will only queue up work for later execution by the GPU. 在大多数情况下,当您进行OpenGL API调用时,它只会将工作排队等待以后由GPU执行。 The call then returns, mostly long before the GPU has completed the work, or before the driver even submitted the work to the GPU. 然后,呼叫返回,大部分时间早在GPU完成工作之前,或者在驱动程序甚至将工作提交给GPU之前。

So when you measure the time from start to end of onDrawFrame() , you measure how long it takes to make all your OpenGL calls, which includes time spent in your code, and time the driver takes to handle your calls. 因此,当您测量onDrawFrame()从开始到结束的时间时,您可以测量进行所有OpenGL调用所需的时间,包括在代码中花费的时间以及驱动程序处理调用所需的时间。 But it does not measure how long the GPU takes to complete the work. 但它并不能衡量GPU完成工作所需的时间。

The best you can do, while keeping things straightforward, is to render a sufficiently large number of frames (say a few 100 to a few 1000), and simply measure the elapsed time from start to finish. 你能做的最好的事情就是提供足够多的帧(比如几百到几千),并简单地测量从开始到结束所经过的时间。 Then divide the number of frames you rendered by the total elapsed time in seconds, and you have your overall average framerate. 然后将您渲染的帧数除以总耗用时间(以秒为单位),并获得总体平均帧速率。

Things get a little more difficult if you don't only want an average framerate, but you also want to observe variations. 如果您不仅想要平均帧率,而且还想观察变化,那么事情会变得更加困难。 If you need that, I would start by measuring the elapsed time between the start of one call to onDrawFrame() to the start of the next call to onDrawFrame() . 如果你需要,我会通过测量一个呼叫开始之间所经过的时间开始onDrawFrame()到下一个呼叫开始到onDrawFrame() This is not a scientifically accurate way to measure the time for each frame, but it will be a whole lot better than what you tried, and should give you at least useful numbers. 这不是一种科学准确的方法来衡量每一帧的时间,但它会比你尝试的更好,并且应该给你至少有用的数字。 The reason it is not accurate is that even the start of onDrawFrame() is not necessarily synchronized with the GPU completing frames. 它不准确的原因是即使onDrawFrame()的开始也不一定与完成帧的GPU同步。 I believe Android uses triple buffering, so there can be a couple of frames "in flight". 我相信Android使用三重缓冲,所以可以在飞行中有几帧。 In other words, the GPU can be 1-2 frames behind the rendering that your code is currently working on. 换句话说,GPU可能比您的代码当前正在处理的渲染落后1-2帧。

There is a mechanism called "timer queries" in OpenGL that allows you to more directly measure how much time the GPU spends for executing given sequences of commands. 在OpenGL中有一种称为“计时器查询”的机制,它允许您更直接地测量GPU花费多少时间来执行给定的命令序列。 But the feature was not added to ES until version 3.1. 但是直到版本3.1,该功能才被添加到ES。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM