OpenGL - Multi-threaded Texture Loading

James Fulop  —  2 months ago [Edited 1 hour, 17 minutes later]
Hey everyone. This week I had the strange itch to see if I could do any OpenGL work on worker threads, and if so, if it would actually have any benefits. TL:DR, yes it can happen without too much trouble (depending on your architecture), and it did help me get my load time down by ~5ms per 2048x2048 RGB glTexImage2D(...).

All you need to set this up is to create an OpenGL context for each thread, who has its context shared with your main thread's context. The process for doing this is surprisingly easy, it can just be one function call. Here's an example
HGLRC MainContext = wglCreateContextAttribsARB(WindowDC, 0, OpenGLAttribs);
HGLRC WorkerThreadContext = wglCreateContextAttribsARB(WindowDC, MainContext, OpenGLAttribs);
By passing the main context to the wglCreateContextAttribsARB function, it creates and shares all in one call. If for some reason you created your contexts separately, you can also use wglShareLists(...).

After creating the context, all you have to do is call wglMakeCurrent(WindowDC, WorkerThreadContext) from within your thread. You only have to call this once within the thread's life cycle.

Buyer beware, I wouldn't recommend multithreading OpenGL on a large-scale. Just keep it to simple things like this. This is also throwing a GL_INVALID_OPERATION for me 1/50 times so maybe its not shippable?
#12579 Mārtiņš Možeiko  —  2 months ago [Edited 6 minutes later]
I hope you have seen Handmade Hero stream about OpenGL context in multiple threads and issues with it. At the end Casey abandoned concept of multi-threaded GL because it was not worth it. The issues were just too serious.

If you care only about loading textures from threads then I suggest to go PBO route. In main thread map the pixel buffer object memory to your virtual address space. Pass the address to thread (which doesn't need to have GL context), do the texture decoding/copying to this memory location in thread. Then signal main thread that you're done (atomics/events/whatever). After that in main thread unmap memory and create GL texture from PBO object. Theoretically this should be faster because GL texture now will be created from PBO memory that should be uploaded to GPU in background.
#12580 James Fulop  —  2 months ago
Haven't seen it yet!
Log in to comment