How does GLFlush() works?

Started by
10 comments, last by Promit 12 years, 1 month ago
Hi everyone,
I am a newbie to OpenGL programming. I've started learning OpenGL very recently
can anyone please explain me how the function GLFlush works in simple terms with an example
that can help me understand it better?

Thankyou
Advertisement
When you issue a drawcall (or any other opengl command) the implementation can keep it in a buffer instead of sending it to the driver (and the driver can buffer things before sending them to the GPU), this allows the implementation to merge drawcalls into batches to reduce context switches and other nice things.

The problem with this is that your drawcalls might not get sent immediatly, Most of the time this is a good thing (Buffering is good) but in some situations you might want the implementation to flush its buffers early.

The main usecase i can think of for this is if you have a render function that looks something like this:

1) bunch of opengl drawcalls
2) do some time consuming calculations or i/o
3) more drawcalls
4) more time consuming cpu stuff
4) swap the buffers

In this case it can be a good idea to flush the buffers before you do the time consuming calculations to get the GPU working on the drawcalls. (if you don't flush then the implementation might keep some or all commands buffered until you try to swap the buffers as it is expecting you to send more data its way).

Its important to note that the buffer swap will not only flush the buffers, it will also stall until all rendering is complete and thus it can be beneficial to have a game loop that does something like:

1) issue render calls
2) flush
3) update gamestate (This can take quite some time in complex games)
4) swap buffers

This way the GPU will process the drawcalls while you update the gamestate. (Some implementations will use triple buffering or pre-rendered frames to get a similar effect with a update->render->swap loop but you can't always count on that)

(With double buffering and no pre-rendering a update->render->swap loop will leave the GPU idle while you update the gamestate and the CPU idle while the GPU finishes rendering and swapping which is fairly inefficient)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
I don't think you'll ever need to use glFlush. When you call swap buffers, it automatically does a flush in any case, so if you're double buffering (as almost all use cases do these days), calling glFlush won't gain you anything. So in Simon's example, you can replace 4 steps with 3:

1) Issue render calls
2) Swap buffers
3) Update game state

, which is pretty much what you'd do if you didn't know glFlush existed.

I don't think you'll ever need to use glFlush. When you call swap buffers, it automatically does a flush in any case, so if you're double buffering (as almost all use cases do these days), calling glFlush won't gain you anything. So in Simon's example, you can replace 4 steps with 3:

1) Issue render calls
2) Swap buffers
3) Update game state

, which is pretty much what you'd do if you didn't know glFlush existed.


The problem with a render->swap->update or update->render->swap loop (they are identical really) is that the swap waits for the render to finish completely which in turn means that the GPU will be idle during the update (after the swap all drawcalls will be completely processed) glFlush doesn't wait for the render to finish, it returns immediatly allowing you to send off all commands to the GPU without swapping the buffers. (This way you can squeeze in all non-rendering related CPU work while the GPU is working by putting it between a flush and the swap)

Once you start pushing the limits of the hardware a bit it will pay off to have the GPU and CPU work at the same time instead of constantly waiting for eachother. (a multithreaded approach is even better these days but also significantly more complex and thus error prone)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Thankyou all for replying,

but still i am unable to understand how GLFlush works,

is it mandatory to write GLFlush after all the drawing functions between glBegin and glEnd?

i've written a sample code please go through it

#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glut.h>
#include<stdio.h>
#include<stdlib.h>
void display1()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(0.25,0.25,0.0);
glVertex3f(0.75,0.25,0.0);
glVertex3f(0.75,0.75,0.0);
glVertex3f(0.25,0.75,0.0);
glEnd();

glFlush();

}
void display2()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE);
glVertex3f(0.25,0.25,0.0);
glVertex3f(0.75,0.25,0.0);
glVertex3f(0.75,0.75,0.0);
glVertex3f(0.25,0.75,0.0);
glEnd();


glFlush();

}
void display3()
{
glColor3f(0.0,1.0,1.0);
glBegin(GL_TRIANGLES);
glVertex3f(0.25,0.25,0.0);
glVertex3f(0.75,0.25,0.0);
glVertex3f(0.75,0.75,0.0);
glEnd();
//glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
}
int main(int argc,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500 , 500);
glutCreateWindow("My First OpenGL program");
init();
glutDisplayFunc(display1);
glutDisplayFunc(display2);
glutDisplayFunc(display3);
glutMainLoop();
return 0;
}


In the above code in 3 functions display1,2 and 3,
when i specify GLFlush then only i am able to see the object
or else i am unable to see anything why is it like that?

can you explain me in detail why GLFLUSH is being used here
with a small lucid example?

thanks in advance
Commands are typically not executed immediately but stored in a command buffer. A flush is implied when you swap buffers in a double buffered environment, which is why you don't need ti flush it yourself. But in a single buffered environment like your code, the commands are waiting in the command buffer until it is flushed, and only you can flush it since there is no implied flush point anymore (swapping double buffers is an implied flush point). If you don't flush the buffer, the commands are still in the buffer waiting to be executed, so nothing is drawn.

Unless you're using single buffering, you should never have to use glFlush or glFinish.
Thankyou Brother Bob for replying,

how long will the commands stay in command buffer?

why because even after the complete execution of program, will the commands still stay there?

please tell me
Why are you so concerned with glFlush GG? It's honestly not something you should worry about or need to use until you spot an opportunity to optimise there. As has been pointed out, it will automatically be flushed when the buffers are swapped. Otherwise, how long it remains buffered depends on many things, including the driver implementation defined size of the buffers.

And no, I have no idea why flush is being used in that example, unless it isn't double buffering and needs to draw something directly to a front buffer, i.e. no swap buffers.

Unless you're using single buffering, you should never have to use glFlush or glFinish.


Thankyou all for replying,

but still i am unable to understand how GLFlush works,

is it mandatory to write GLFlush after all the drawing functions between glBegin and glEnd?

i've written a sample code please go through it

#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glut.h>
#include<stdio.h>
#include<stdlib.h>
void display1()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f(0.25,0.25,0.0);
glVertex3f(0.75,0.25,0.0);
glVertex3f(0.75,0.75,0.0);
glVertex3f(0.25,0.75,0.0);
glEnd();

glFlush();

}
void display2()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE);
glVertex3f(0.25,0.25,0.0);
glVertex3f(0.75,0.25,0.0);
glVertex3f(0.75,0.75,0.0);
glVertex3f(0.25,0.75,0.0);
glEnd();


glFlush();

}
void display3()
{
glColor3f(0.0,1.0,1.0);
glBegin(GL_TRIANGLES);
glVertex3f(0.25,0.25,0.0);
glVertex3f(0.75,0.25,0.0);
glVertex3f(0.75,0.75,0.0);
glEnd();
//glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
}
int main(int argc,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500 , 500);
glutCreateWindow("My First OpenGL program");
init();
glutDisplayFunc(display1);
glutDisplayFunc(display2);
glutDisplayFunc(display3);
glutMainLoop();
return 0;
}


In the above code in 3 functions display1,2 and 3,
when i specify GLFlush then only i am able to see the object
or else i am unable to see anything why is it like that?

can you explain me in detail why GLFLUSH is being used here
with a small lucid example?

thanks in advance


In this case its used because you are using a single buffer (and thus no buffer swap that forces a flush), if you switch
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
to
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
you no longer have to flush to get things on screen (as a glFinish is implied on the swap). (As i said above though, flushing can still be useful for performance reasons if you run a single threaded application)
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
The commands stays in the buffer for as long as necessary. If there is nothing that flushes it, they may even stay there forever and you will never get your triangle on the screen.

This topic is closed to new replies.

Advertisement