I recently implemented a worker thread in my application to upload large vertex buffers to the GPU asynchronously. Therefore, I first tried to just call sf::Context context; as first command in the thread, before entering a loop that calls functions where OpenGL calls are used inside.
void Worker()
{
sf::Context context;
while (running) {
Buffer(); // uses OpenGL calls
}
}
But I got undefined results. The uploaded meshes were drawn distorted, completely empty, or correct sometimes. So I moved the context creation inside the Buffer() function and that solved my issue.
However, it might be slow to create a new context every time the function gets called, where I only need one. Do I have the pass context object as function parameter to be visible in scope of the function body? Why can't I used it as I first intended?
That's right. I called glFinish() from the worker thread after glBufferData() calls to wait for the buffers to be uploaded completely. After that I swap the buffer ids of the model instance that the main thread reads. So it should use the old buffer until then. Here is a short code example to illustrate.
struct Model {
GLuint positions, normals, texcoords;
};
// worker thread
void Load(Model &model)
{
Model loaded;
// generate buffers and fill them from disk
// ...
// wait for buffer upload to finish
// main thread shouldn't be affected
glFinish();
// swap buffers
Model old = model;
model = loaded;
// delete old buffers
glDeleteBuffers(1, old.positions);
glDeleteBuffers(1, old.normals);
glDeleteBuffers(1, old.texcoords);
}