Performance issue with OpenGL in multiple windows

I think, at least on windows, this problem can’t be fixed. Please correct me if I’m wrong. I wish there was a solution!

On Windows wgl is used to display OpenGL framebuffers to a windows surface/window.

The big problem is: OpenGL is not multithreaded. You can only use it if you claim the context. For this wglMakeCurrent is used. So naturally an OpenGL context is bound to ONE thread and only one thread can access it at a time.

In a plugin / multi window app environment this means, if one instance is using the context and another one wants to “makeCurrent”, it has to wait or otherwise synchronize it. How long does it take? Until the first instance uses makeCurrent(null).

It looks like this: The first instance claims it, does fancy OpenGLContext rendering and at some point wants to display it. SwapBuffers is called. If I understand this correctly. OpenGL does a lot of driver magic behind the scenes at this point. And the actual submit of most of the workload happens during SwapBuffers. So this call can take a long time! Even if you immediately call makeCurrent(null) after it, the thread will wait until SwapBuffers completes. Additionally to that, the makeCurrent is a very heavy operation.

In the end, the more complex your rendering is, and the more threads “fight” for the wglMakeCurrent, the slower your app gets.

Now what’s the solution? Say goodbye to OpenGL! Or somehow try to make the rendering single threaded, so there is no fight for a context. But then you have to synchronize your JUCE paint calls and do other dangerous and error prone stuff. Which in the end doesn’t even help because you just overload your SwapBuffers render loop and ruin your frame timings and animation smoothness.

Kind of hopeless. And if you look at the history of wgl, it’s not developed anymore. Microsoft probably focused their work on WPF, .NET and all the Windows 10 app stuff to offer better render performance. Alternative to all of this: Vulkan!

1 Like