I have a simple OpenGL test app in C which draws different things in response to key input. (Mesa 8.0.4, tried with Mesa-EGL and with GLFW, Ubuntu 12.04LTS on a PC with NVIDIA GTX650). The draws are quite simple/fast (rotating triangle type of stuff). My test code does not limit the framerate deliberately in any way, it just looks like this:
while (true)
{
draw();
swap_buffers();
}
I have timed this very carefully, and I find that the time from one eglSwapBuffers()
(or glfwSwapBuffers
, same thing) call to the next is ~16.6 milliseconds. The time from after a call to eglSwapBuffers()
to just before the next call is only a little bit less than that, even though what is drawn is very simple. The time that the swap buffers call takes is well under 1ms.
However, the time from the app changing what it's drawing in response to the key press to the change actually showing up on screen is >150ms (approx 8-9 frames worth). This is measured with a camera recording of the screen and keyboard at 60fps.
Therefore, the questions:
Where are draws buffered between a call to swap buffers and actually showing up on screen? Why the delay? It sure looks like the app is drawing many frames ahead of the screen at all times.
What can an OpenGL application do to cause an immediate draw to screen? (ie: no buffering, just block until draw is complete; I don't need high throughput, I do need low latency)
What can an application do to make the above immediate draw happen as fast as possible?
How can an application know what is actually on screen right now? (Or, how long/how many frames the current buffering delay is?)
Answer
Any drawing API function called from the CPU will be submitted to the GPU command ring buffer to be executed later by the GPU. This means that OpenGL functions are mostly non-blocking functions. So the CPU and the GPU will be working in parallel.
The most important thing to note is that your application can be CPU or GPU bound. once you call glFinish the CPU should will wait the GPU to complete it's drawing commands, if the GPU is taking more time and may/is causing the CPU to stall then your applications is GPU bound. If the GPU finishes it drawing commands and the CPU is taking too long to glFinish then your application is CPU bound.
And note that there is a difference between glFlush
and glFinish
.
glFlush
:indicates that all commands that have previously been sent to the GL must complete in finite time.
glFinish
: forces all previous GL commands to complete. Finish does not return until all effects from previously issued commands on GL client and server state and the framebuffer are fully realized."
glXSwapBuffers performs an implicit glFlush before it returns. Subsequent OpenGL commands may be issued immediately after calling glXSwapBuffers, but are not executed until the buffer exchange is completed.
The actual frame time will most likely be determined by which of the two CPU/GPU is taking more time to complete its work.
No comments:
Post a Comment