Specific Multi Threading usage in OpenGL

Hi! I know that by design OpenGL is not designed for multi threading.
However, I want to ask if some operations are supposed to work.

First of all, is it possible to use OpenGL so while one thread renders polygons, sets materials, matrices, and stuff, the other thread allocates and deallocates textures/arrays (that of course are not in use by the rendering thread)?

I know Direct3D can do this fine, but I was wondering if it can be properly done in OpenGL, and if its safe. Of course, I’d be having to specifically lock between objects drawn or something, so i can bind textures and arrays safely, but then again, is this possible?

Cheers!

yes

See Parallel OpenGL FAQ and GDC2005_OpenGL_Performance.pdf pages 33-37.

The basic problem with multithreading in OGL is the fact that OGL context, which contains entire state of the OGL, can be at one time bound to only one thread. Because of this you can not simultaneously modify it from two threads. You basically have three options.
[ul][li]You can create one context for each thread and enable sharing of display lists and textures between them. It is likely that this path is not too well supported by the drivers.[]You can load and prepare the resources by the second thread and let the main thread do the creation call into OGL.[]If the resource type supports it (e.g. VBO), you can map its memory by the main thread. Fill it in the second thread and unmap it by the main thread.[/ul][/li]

I’m curious. What kind of benefits can be expected by accessing GL from more than one thread?

CatDog

In points 2 and 3 of Komat’s post, it is interesting to prepare data in a separate thread from the rendering one. That way you can parallelize dynamic texture creation, CPU skinning, particle engine etc, along with driver thread.
It “could” be interesting to have multithread driver in cases when driver has non-negligible work to do, such as converting formats, exploring VBO indexes, compiling shaders …

It’s me again.

I’d like to fill my VBOs from a worker thread, like explained above. Map the buffer in main thread, resume worker thread that fills it, finally unmap in main thread when finished. No GL calls done from within the worker thread, just moving and processing data.

The spec says:

A mapped data store must be unmapped with glUnmapBuffer before its buffer object is used.

So is it correct that I can do everything in the main thead while the buffer is mapped and being filled - as long as I don’t touch it (=not “use” it)? Including for example SwapBuffers and glFinish?

With other words: is it possible to continue rendering and displaying frames while a buffer is mapped?

CatDog

With other words: is it possible to continue rendering and displaying frames while a buffer is mapped?

As far as I understand the specs: Yes!

As long as you don’t actually use the VBO while it is mapped, you are allowed to do anything else.

Yes, a mapped buffer can be modified however you want in a 2nd thread, and you can make any OpenGL calls you want in the main thread while this happens (except ones that directly pertain to the mapped buffer, unbind in particular).

is it possible to continue rendering and displaying frames while a buffer is mapped?

In fact a vbo can be mapped if the GPU don’t use it. So If I understand well the specification, the vbo is not used by the gpu until you unmap it.
Then when you map a vbo, this one could be in use by the gpu and this last one will force the driver to wait until gpu finishes its task.
That is why it is necessay to invalidate the vbo data calling glBufferDataARB with a NULL data pointer which will allocate a new data buffer in memory that you can then map with glMapBufferARB.

This way, the gpu is still rendering with the buffer you have invalidated and in parallel you are allocating and filling another buffer that will be used by the gpu after unmap it.

Great! Thanks a lot!

CatDog

Is there a good resource somewhere available that details what exactly happens when the state is toggled during a context change? Something that would help me answer the following questions myself.

I have read through the FAQ and the AMD presentation that were mentioned in this thread. I’m currently playing around with the following multi-threading scenario:

  • Multiple rendering contexts
  • 1 thread per context
  • Each thread renders into a separate FBO
  • I’m using shader programs. One set of shaders is bound to each context (the same programs, but nothing is shared at this point).

I don’t need sharing between contexts unless I can get any performance benefit from it.

There were two points in the AMD presentation that were particularly interesting to me: “Toggling states costs CPU time”
and “Shader changes expensive”.

Is it true for any architecture that states get back written back to the CPU or is it also possible to keep the state on the GPU? Also what does this state include, also things like textures that are bound to a context? All my threads work with a significant amount of 3d texture data (e.g. stacks of CT images).

Would it make sense (and would it be possible) to attach the same shader to different contexts to minimize the expensive shader changes?

Thanks,
Mark

Actually, I’ve tried something like that. When I make changes I often see the impact. It helped me to consider that however many contexts and threads I make, and however much I juggle CPU use, the GPU commands always end up serialized (before they go massively parallel, that is!).

I think a rough guide is to only bother if it’s going to save you CPU time, or offer some other advantages.

Bruce