Preventing the GPU from being idle..

Ok, i was wondering…

My current code looks like that:

while (!finished)
{
Setup_new_frame(); // GPU
Visibility_detection(); // CPU
Render(); // GPU
Input_physics_and_AI(); // CPU
Flip(); // GPU
}

Wouldn’t it be better (to avoid the GPU to be idle) if i do that:

Visibility_detection(); // CPU
while (!finished)
{
Setup_new_frame(); // GPU
Render(); // GPU
Visibility_detection(); // CPU
Input_physics_and_AI(); // CPU
Flip(); // GPU
}

Y.

It’s always depending on what you are doing e.g. after a glClear(GL_COLOR_BUFFER_BIT) the graphics pipeline is blocked untill its finished, so its sensible to do some CPU-calculations after a glClear

Look at the NV_fence extension, it has some relevance here, it’s an NV extension though. It turns your question on it’s head because it may seem to you like it tries to keep the CPU busy, but if you think about it, it’s the same question. You want to keep both busy and ballance the load.

In general though, you want to mix CPU with graphics, so it’s not exactly the case that you want to draw everything and then compute then swap.

Ideally you want to keep the graphics busy, while you compute but not waste time blocking of full graphics FIFO’s or starve graphics while your application runs. The former may be unlikely unless you have lot’s of data to draw, You’re thinking along the right lines but here’s some simple suggestions.

You can easily clear the screen then compute or poll input, then draw, I also like to try and block on swap to keep latency low before I call handle my input. Some don’t.

You could also try and interleave compute with draw, for example drawing a sky/background polygon then doing compute then drawing, but be warned on the coarse Z hardware like GeForce3 you may want to draw the backdrop last because it will be occluded and faster when drawn last.

Finally if you have a lot of compute you want to interleave it with graphics a lot, but you don’t want to starve graphics and this is what the NV_fence extension is for. Basically you send the pipe a token and can querry when the token is finished in graphics hardware without a glFinish or some other blocking command.

So pseudocode looks something like this:

While(Application_is_still_running)
{
Clear_screen();
Handle_input();
Do_latency_critical_updates();
// stuff some stuff down the pipe before
// first fence token
Draw_some_stuff();
While_Stuff_Left_To_Draw()
{
// set up fence and send stuff to
// keep GPU busy after fence token done
// we’ll only send more data when
// fence if finnished in hardware
glSendFenceNV();
Draw_Some_More_Stuff();
// this loop keeps CPU
// busy while GPU is drawing
while(!glTestFenceNV(GL_ALL_COMPLETED_NV))
{
// This could be compute for next frame
// or maybe some stuff for this frame
// such as on the fly culling, the more
// compute the more culling you can do
// while you’re waiting which is in a
// nice ballance
// note that compute has to
// be done is bite sized chunks
Do_Some_Compute_For_Next_Frame();
}
}

// swapbuffers and perhaps block
Complete_Frame();
// optional block to keep the input
// low latency
glFinish();
}

Cheers,Angus.

DaViper:
glClear blocks til it’s finished?! Are you sure of that? If true, why should this operation be blocking, i see no reason !?

Dorbie:
I like the idea to make CPU calculations when a fence is still in use. However, my theory was: make as much GPU work as possible just after the swap. That way the GPU starts to work just after the swap, and once all instructions have been sent to the card, i can start my CPU calculations ( in parallel, the GPU is drawing the scene ). This obviously assumes that there is no blocking call at all. I don’t see why you should interleave CPU & GPU work. In a perfect world, wouldn’t it be better if we swap, then render the scene with a unique and huge display list containing the whole scene ( just an example, so that render does not do CPU work ), and then do all CPU stuff ( input, AI, etc… ) ?
Is there a list of all OpenGL blocking calls somewhere ?

Y.

Do non-drawing work after a screen clear.
Clearing a full screen can take time. If you make additional drawing calls immediately after a screen clear, you may fill up the graphics pipeline and force the program to stall. Instead, do some non-drawing work after the clear.

this is from OpenGl Siggraphpaper from 98. http://www.sgi.com/software/opengl/advanced98/notes/notes.html