Jump to content
  • Advertisement
Sign in to follow this  
GRAPHIC GEEK

OpenGL How does GLFlush() works?

This topic is 2406 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!