Multiple contexts, multiple threads, loading thread degrading render thread

I am currently implementing a feature that allows loading a new scene in a background thread while the primary thread continues to draw. To do this I have created two contexts (c-main and c-load). I have a class within my project that encapsulates an entire scene (all vbos, textures, shaders, etc, everything that is currently loaded into the opengl context which is used to draw that scene). When I want to load a new scene, I kick off creation of a new scene to a separate thread and make c-load the current context on that thread. Once loading is complete, I swap contexts turning c-load into c-main on the main render thread and the previous c-main into c-load (empty and not current on any thread until next scene is loaded).

This works for the most part, but I have noticed that when loading textures and mipmaps within the secondary thread, my framerate will drop substantially causing a jerkiness to be visible.

Therefore my question to anyone generous enough to be reading this is: Why do I experience this degradation on my primary render thread when loading these textures into a separate opengl context on a separate thread?

After some investigation the theory I have come up with is that since all opengl calls are added to opengl’s command queue regardless of what cpu thread made the call, that once the glGenerateMipmap or glTexImage2D calls are executed by the drivers, all other commands including glDrawElements being called from the main thread from within a separate context, are blocked until they finish generating mipmaps or uploading data. Is this correct? Or have I wildly misunderstood something?

glTexImage functions shouldn’t take up the same resources as rendering calls. glGenerateMipmaps is another matter entirely.

This function is as rendering function; to do its job, it has to perform a rendering operation or something near-enough to it. So it’s going to have to use the same rendering resources your other thread is using. As such, synchronization will be needed, which is bad.

It would be better for you to just pregenerate the mipmaps and load them from disk rather than generating them in-situ. If that’s not possible, consider doing the generation on the CPU.

Removing the call to glGenerateMipmaps and setting GL_TEXTURE_MIN_FILTER to GL_LINEAR has resolved the major stutter (will look into pregenerating mipmaps). However, there’s still something going on that’s degrading the render thread which I’m attempting to track down.

If I’m calling glDrawElements on my main thread, and then on the secondary thread calling glTexImage2D, would the call to glDrawElements not block until glTexImage2D has completed?

That’s far too implementation-dependent to know with any certainty. It probably shouldn’t block, since they don’t conceptually use the same resources. But at the same time, there’s nothing to say that it’s impossible for them to block.

I doubt the blocking is particularly function-specific. It’s more likely to be how the driver submits batches of work to the GPU.

That makes sense. Thank you for the clarification.