glFlush in multi-thread.

I have two threads. The first one renders a texture while the second one renders the scene using the texture. Do I need call glFlush() after the first thread renders the texture to make sure the texture has been rendered before the second thread uses it?

No, but you do need to synchonize your multithreaded code so that while one piece of code is rendering, the other piece of code is not talking to OpenGL. However, once the commands are sent, you can release the lock on GL.

I thought an OpenGL rendering context cannot be shared between threads!?! :confused:

Yes but two rendering contexts can share textures…

Originally posted by lawrencelee:
I have two threads. The first one renders a texture while the second one renders the scene using the texture. Do I need call glFlush() after the first thread renders the texture to make sure the texture has been rendered before the second thread uses it?
glFlush() starts the rendering. glFinish() will make sure rendering is complete. On some or most drivers it is implemented as a busy loop. This is generally bad for multithreaded applications. I prefer to issue an occlusion query and poll it for completion in a millisecond sleep loop. This will synchronize the CPU with rendering completion within one millisecond of its actual completion without wasting CPU cycles. Don’t forget to rebind the texture each time in the other thread to pick up any attribute changes.

glFlush() forces any buffered commands to be sent to the server.

glFinish() blocks until all pending commands are completed.

So I believe your procedure would be:

Texture thread:
*Claims ownership of a mutex or something

Main thread:
*Blocks waiting for the mutex (or at least doesn’t make any OpenGL calls until then the texture thread releases it)

Texture thread:
*Acquire rendering context
*Do rendering
*glFlush();
*Releases the mutex

Main thread:
*Goes about its business. Move along. Move along.

Omaha, this will definitely fail. The glFlush sends the commands to the server, the rendering can still happen asynchronously at the time you release the mutex. You must use glFinish there (or try the occlusion trick from above).

It looks like that I got different opinions. So is there a specification to specify the behavior of multi-thread in OpenGL?

I see no practical reason of using the extra thread,
unless this is a programming exercise…

Since you may not be issuing commands to the GL from
different thread simultanuously, one of the threads
will have to wait its turn. The momment you have
realized this, you also abandon the idea of doing it
with two threads.

I am a fan of using threads for doing different things,
even on single CPU machines, but it seems very unatural
to want to send commands to the GL with different
threads. I could be dead wrong about this…

Originally posted by lawrencelee:
So is there a specification to specify the behavior of multi-thread in OpenGL?
No, it’s just logical. Consider every rendering command sent to the OpenGL API to run asynchronously in the background, then add what is necessary to synchronize the rendering to the texture in your case and the answer is, glFlush is insufficient to make sure the rendering has finished.

Originally posted by iznogoud:
I see no practical reason of using the extra thread,
unless this is a programming exercise…

If your application has multiple GL contexts on multiple windows or pbuffers then you must either switch GL contexts on a single thread or switch threads each with its own GL context. I have the impression that switching GL contexts is much more expensive than switching thread contexts. Does anyone have benchmark results?

Originally posted by lawrencelee:
I have two threads. The first one renders a texture while the second one renders the scene using the texture. Do I need call glFlush() after the first thread renders the texture to make sure the texture has been rendered before the second thread uses it?
Assuming you are using p-buffers, your second thread (with it’s own GL context) can’t use it unless you bind the p-buffer. Binding implies that the texture can be used.
The biggest issue is, you may get some major performance loss if you graphics card doesn’t perform well with multiple GL context.

In response to macarter and building on what
V-man said:

On certain (old and crappy) cards with very primative
drivers and poor performance (such as the Voodoo 3
which I use purposly), one has serious issues when
rendering on multiple contexts. In fact, I run into
trouble when running different hardware accelerated
applications simultanuously!

Switching contexts will give you a drop in performance
for sure. On the other hand, even with different
threads, I do not see how one can use a “state
machine” without having trouble. I could be naive,
but since I never even thought of using the GL with
two threads that are children of the same process,
I may be failing to put two and two together. I
guess the question is: “how can a state machine be
thread-safe?”

Originally posted by iznogoud:
[b]In response to macarter and building on what
V-man said:

I may be failing to put two and two together. I
guess the question is: “how can a state machine be
thread-safe?”[/b]
A GL context (state machine) is not thread safe. That is why it can only be bound to at most one thread at a time. Only the thread bound to a GL context can affect its state.

Originally posted by lawrencelee:
I have two threads. The first one renders a texture while the second one renders the scene using the texture. Do I need call glFlush() after the first thread renders the texture to make sure the texture has been rendered before the second thread uses it?
I think you don’t need to. If I understood correctly, your first thread created the texture (probably with TexImage2D) and the second uses this texture. You don’t call Flush anytimes after you create a new texture, even in single threaded apps, so there’s no real reason for doing that.

Just ensure you synchronize your both threads so that the second renders only when the first has finished to create the texture, and the first creates the texture only when the second has finished to draw.

I think it’s a safe way to do that.