Concurrent buffer data store creation and drawing in OpenGL 3.3

Hi there everyone!

I’m currently designing an engine for my game and I want it to be able to load or stream data on one thread while drawing on another. I have encountered a problem where it hinders me from doing this. Here is the problem:

I’m doing the SOP for loading data into buffers (binding a buffer into a target, calling glBufferData, unbind). However, the rendering thread may be at that time is also binding a buffer into the same target. It may not be obvious at first (as it is to me at first), but the rendering thread may be using the wrong buffer in its draw calls.

Please note that I don’t want to solve this using thread synchronization as it would cause too much overhead. Also note that I am not using vertex array objects and uses only one vbo for drawing.

You cannot use one OpenGL context from two threads, even if you use thread synchronization. You may create a second GL context, make it current in your background thread and use that to fill the VBO.

Isn’t creating another context a bit expensive?

I also want to ask if there are “generic buffer targets” extensions in 3.3. This would somehow solve the problem.

Isn’t creating another context a bit expensive?

Yes. But you only do it once, at initialization time. There’s also the fact that you don’t have a choice. OpenGL does not allow you to make the same context current in two different threads.

In any case, you should be far more concerned about the fact that you are creating a race condition on the buffer object. OpenGL isn’t thread-safe in the sense that you can use the same object from two different threads.

You should use an appropriate mutex or other synchronization primitive to be sure that you are only modifying the object when the other thread isn’t using it. It’s OK if OpenGL internally is still using it, but you can’t have one thread bind the object and render while the other thread is doing a data transfer.

[QUOTE=Alfonse Reinheart;1238295]Yes. But you only do it once, at initialization time. There’s also the fact that you don’t have a choice. OpenGL does not allow you to make the same context current in two different threads.

In any case, you should be far more concerned about the fact that you are creating a race condition on the buffer object. OpenGL isn’t thread-safe in the sense that you can use the same object from two different threads.

You should use an appropriate mutex or other synchronization primitive to be sure that you are only modifying the object when the other thread isn’t using it. It’s OK if OpenGL internally is still using it, but you can’t have one thread bind the object and render while the other thread is doing a data transfer.[/QUOTE]

Thanks very much! I think I’ll go on creating multiple contexts. Using another context in creating and initializing a buffer will not use buffer targets in the rendering thread’s OpenGL context.

About your last paragraph, I’m designing the engine to create and initialize the buffer once then use it as many times in rendering without further modifications by other threads. There is no need for synchronization and will therefore have no additional overheads (I hope I’m right!).

Again, thanks very much everyone!

Whatever happened to glMapBuffer and glUnmapBuffer ???

Whatever happened to glMapBuffer and glUnmapBuffer ???

In regard to what? Modification from different threads?

Well, yes. You can map it on your main thread and just pass the mapped pointer to the worker thread. That way, there’s no need for an explicit synchronization, except for the worker to tell the main thread that it’s finished uploading data.

I am no expert on OpenGL, but are you sure you need parallel access from more than one thread to the driver?

I believe OpenGL in itself will do a lot of things in parallel, as long as you know how to not change states too often. So it may be you spend a lot of efforts on this, not giving you any extra performance.

For example, if the pipelines are already saturated somewhere, you will not gain anything.