How to update a buffer from multiple threads?

#1

I have a function which updates the contents of a GL buffer object. In simplified form it looks something like this:

void updateBuffer(GLint bufferName, float value)
{
    float *sumPtr = (float*)glMapNamedBuffer(bufferName, GL_READ_WRITE);
    *sumPtr += value;
    glUnmapNamedBuffer(bufferName);
}

This code is part of a plugin in for a 3rd-party application which has multiple threads, only one of which has a current rendering context. My function may be called from any of the application’s threads, not just the one with the context. Is there any way to make this work? Note that I have no control over the application’s rendering thread, so I cannot introduce any thread synchronization beyond what might be embedded within OpenGL.

From my reading of the OpenGL docs, I can create my own separate GL context which shares buffers with the application’s rendering context, but that context would be thread specific. So I would need a separate shared context for every thread. Is that right? Is there a simpler way of doing this?

Also, do I have to worry about synchronization between my contexts and the application’s if only mine ever use the buffer?

Can anyone point me to an example of this sort of usage?

#2

BTW: don’t map a buffer just to write 4 bytes to it. I mean, you should avoid writing such a minimal amount of data, but mapping for such a trivial write is not a good idea.

Since you’re able to use 4.5’s DSA, you should just persistent-map the buffer. Then, you never have to unmap it (so long as you follow the other rules of persistent mapped buffers).

Also, read/write mapping should be avoided.

No. If the application isn’t going to make the context current for you, then the application does not want you to directly manipulate OpenGL state.

You could only do that if you actually have access to the application’s rendering context. If you do, then I assume that you cannot make the context current in your thread, due to the possibility of breaking the application’s rendering.

Which again lends credence to the idea that the application doesn’t really want you to do this kind of thing.

Um… how exactly does that work? If you’re trying to put data into the buffer, then presumably some process is going to have to use it, right? And since you presently don’t have a rendering context and therefore cannot kick off a rendering process that uses the buffer, then the only conclusion is that you’re writing to the buffer so that the application can eventually use it.

#3

That was just a simplification. The actual buffer is much larger.

For some operations we need write access, for others not. Which is better: a persistent read/write mapping or temporary mappings which are read or read/write as needed?

I was working on the misapprehension that once a context is made current in a given thread, it remains locked to that thread thereafter. In actuality it’s okay to make the context current in a different thread so long as it isn’t current in any other. That shifts my problem from how to set up the sharing to how to handle the synchronization between threads.

It’s more that the application developers didn’t even think about plugins wanting to do what we’re doing.

You’re right. The buffer is used primarily in OpenCL kernels, but eventually it needs to be accessed by render code.

Thanks for your input, it was quite helpful in getting me sorted out.