opengl: glFlush() vs. glFinish()

I'm having trouble distinguishing the practical difference between calling glFlush() and glFinish().

The docs say that glFlush() and glFinish() will push all buffered operations to OpenGL so that one can be assured they will all be executed, the difference being that glFlush() returns immediately where as glFinish() blocks until all the operations are complete.

Having read the definitions, I figured that if I were to use glFlush() that I would probably run into the problem of submitting more operations to OpenGL than it could execute. So, just to try, I swapped out my glFinish() for a glFlush() and lo and behold, my program ran (as far as I could tell), the exact same; frame rates, resource usage, everything was the same.

So I'm wondering if there's much difference between the two calls, or if my code makes them run no different. Or where one should be used vs. the other. I also figured that OpenGL would have some call like glIsDone() to check whether or not all the buffered commands for a glFlush() are complete or not (so one doesn't send operations to OpenGL faster than they can be executed), but I could find no such function.

My code is the typical game loop:

while (running) {
    process_stuff();
    render_stuff();
}

Solution 1:

Mind that these commands exist since the early days of OpenGL. glFlush ensures that previous OpenGL commands must complete in finite time (OpenGL 2.1 specs, page 245). If you draw directly to the front buffer, this shall ensure that the OpenGL drivers starts drawing without too much delay. You could think of a complex scene that appears object after object on the screen, when you call glFlush after each object. However, when using double buffering, glFlush has practically no effect at all, since the changes won't be visible until you swap the buffers.

glFinish does not return until all effects from previously issued commands [...] are fully realized. This means that the execution of your program waits here until every last pixel is drawn and OpenGL has nothing more to do. If you render directly to the front buffer, glFinish is the call to make before using the operating system calls to take screenshots. It is far less useful for double buffering, because you don't see the changes you forced to complete.

So if you use double buffering, you probably won't need neither glFlush nor glFinish. SwapBuffers implicitly directs the OpenGL calls to the correct buffer, there's no need to call glFlush first. And don't mind stressing the OpenGL driver: glFlush will not choke on too many commands. It is not guaranteed that this call returns immediately (whatever that means), so it can take any time it needs to process your commands.

Solution 2:

As the other answers have hinted, there really is no good answer as per the spec. The general intent of glFlush() is that after calling it, the host CPU will have no OpenGL-related work to do -- the commands will have been pushed to the graphics hardware. The general intent of glFinish() is that after it returns, no remaining work is left, and the results should be available too all appropriate non-OpenGL APIs (e.g. reads from the framebuffer, screenshots, etc...). Whether that is really what happens is driver-dependent. The specification allows a ton of latitude as to what is legal.

Solution 3:

I was always confused about those two commands too, but this image made it all clear to me: Flush vs Finish Apparently some GPU drivers don't send the issued commands to the hardware unless a certain number of commands has been accumulated. In this example that number is 5.
The image shows various OpenGL commands (A, B, C, D, E...) that have been issued. As we can see at the top, the commands don't get issued yet, because the queue isn't full yet.

In the middle we see how glFlush() affects the queued up commands. It tells the driver to send all queued up commands to the hardware (even if the queue isn't full yet). This doesn't block the calling thread. It merely signals the driver that we might not be sending any additional commands. Therefore waiting for the queue to fill up would be a waste of time.

At the bottom we see an example using glFinish(). It almost does the same thing as glFlush(), except that it makes the calling thread wait till all commands have been processed by the hardware.

Image taken from the book "Advanced Graphics Programming Using OpenGL".

Solution 4:

If you did not see any performance difference, it means you're doing something wrong. As some others mentioned, you don't need to call either, but if you do call glFinish, then you're automatically losing the parallelism that the GPU and CPU can achieve. Let me dive deeper:

In practice, all the work you submit to the driver is batched, and sent to the hardware potentially way later (e.g. at SwapBuffer time).

So, if you're calling glFinish, you're essentially forcing the driver to push the commands to the GPU (that it batched till then, and never asked the GPU to work on), and stall the CPU until the commands pushed are completely executed. So during the whole time the GPU works, the CPU does not (at least on this thread). And all the time the CPU does its work (mostly batching commands), the GPU does not do anything. So yeah, glFinish should hurt your performance. (This is an approximation, as drivers may start having the GPU work on some commands if a lot of them were already batched. It's not typical though, as the command buffers tend to be big enough to hold quite a lot of commands).

Now, why would you call glFinish at all then ? The only times I've used it were when I had driver bugs. Indeed, if one of the commands you send down to the hardware crashes the GPU, then your simplest option to identify which command is the culprit is to call glFinish after each Draw. That way, you can narrow down what exactly triggers the crash

As a side note, APIs like Direct3D don't support a Finish concept at all.