Bug report: OpenGL swapBuffers not swapping?

Hi there !

(Sorry in advance for the loooong post)

We’re starting to have some customers complaining that our plugins (using JUCE) display only a black and empty UI on their setups.
We’ve had a hard time trying to reproduce the bug, but it seemed to happen mostly with customers using Display Link USB hubs.
We finally got one and were able to reproduce with a 2019 Intel macBook Pro with an ADM graphic card, and this hub.

Of course the bug doesn’t happen on this computer unless the hub is connected… I don’t know what those hubs are doing, but they surely mess something up. Though, all the other apps are working fine and only our plugins are displaying black-empty windows. Still, I was able to reproduce the bug with plugins from other brands using JUCE (like Vital), and even with the OpenGL app template from the Projucer. So I’m pretty confident there’s something in JUCE colliding with whatever the hub is doing.

From what I was able to dig, this empty-UI issue only happens when using the OpenGL renderer (the native ones are ok, but we use OpenGL for our plugins).

The issue seems to come from bufferSwapper.swap() (in OpenGLContext::CachedImage::renderFrame()), which somehow fails to flush.
I’ve checked for OpenGL errors before and after the swap, but nothing showed up. I’ve also checked with a glReadPixel the content of the main framebuffer before the swap, and the UI was all drawn in it, so the swap really seems to fail. I guess the reason of this failure is elsewhere, maybe in the way JUCE setups the context, but I couldn’t find any obvious leads.

So I’ve setup a small project that uses the Projucer’s OpenGL app template to illustrate the bug. The app simply displays a red triangle over a grey background The project can either use JUCE’s standard OpenGL renderer, or a custom quick’n’dirty OpenGL renderer. Here are the results :

With JUCE’s OpenGL rendering

With custom OpenGL rendering

So I definitely think there’s one little detail somewhere in the way JUCE setups the OpenGL context that causes this bug, and we would appreciate some help from the JUCE’s team on this one :slightly_smiling_face:
I agree this might seem as a corner case, but since we have more and more users reporting it, it felt important to share it with you.

The demo project can be found here if needed (it’s a macOS only project): GitHub - Lyoks38/TestOpenGLApp: A basic JUCE OpenGL that can either use the standard OpenGL renderer of JUCE or a light-weight custom one

Thanks !

1 Like

Unfortunately we don’t have access to one of these hubs at the moment, so it’s going to be difficult for us to diagnose the issue on our side.

Some things to check:

  • Is swapBuffers actually getting called on every vblank? You could try putting a breakpoint on the triggerRepaint() call in refreshDisplayLinkConnection(), and on bufferSwapper.swap(), and make sure that the breakpoint gets hit repeatedly. You mentioned that you’ve debugged GL errors before and after the swap() call, so I assume this is hit at least once. However, it would be good to confirm that subsequent swaps are being correctly triggered by each monitor vblank.
  • If component painting is enabled, the JUCE GL context will render components into a persistent framebuffer, and will draw this buffer onto the screen after invoking any custom renderer. I can imagine that a black frame might be drawn if the framebuffer is misconfigured somehow, e.g. it has no alpha component. Do you see the same drawing issue if you disable component repainting with setComponentPaintingEnabled (false) on the main context?
  • Have you tried changing the GL versions used by the JUCE context (setOpenGLVersionRequired()) and/or your example? Does switching the version affect the observed behaviour?
  • After ruling out the points above, my only idea would be to minimise the differences between the JUCE context and your working minimal example, by gradually removing/simplifying the OpenGLContext code. In this way it should be able to work out what’s causing the problem.

This seems like it could be related and that issue is still a problem.

Hi @reuk !

Thanks for your answer. TBH, I wasn’t expecting you to have one of those hubs :smile:
Thanks for the different leads, I can already answer to some of them:

  • Enabling/disabling component drawing doesn’t change anything unfortunately.
  • Setting an higher version of OpenGL doesn’t change anything either.

I’ll check the other suggestions you gave me, and will get back to you if I find anything suspicious.

@asimilon This is indeed very similar :thinking:

1 Like