Just ran into this issue and so far have isolated it to JUCE versions 8.0.8 and later, so I’m assuming whatever changed was in that version. I don’t see any breaking changes so not even sure where to begin, and no exceptions are thrown when debugging.
To clarify, the plugin windows still animate and respond to being moused over, but they can’t be clicked on and neither can anything else in the DAW, forcing me to force quit. This happens the same in REAPER and Ableton so far and only on windows, leading me to think it’s a Direct2D issue since I see a bunch of tweaks were added to that renderer in 8.0.8. Also of note is that it doesn’t happen with the blank template plugin UI, but it’s hard to know where the cause may be since debugging doesn’t cause any real red flags.
I haven’t been able to try isolating it further yet but will once our new product launch is over. For now I’ve just downgraded to 8.0.7.
And yeah to clarify it is a JUCE plugin that is the issue. VST3 and AAX on Windows both present the problem (VST3 in every DAW I tried).
I’ve checked for any static objects and there were none on the UI end, some static class member functions but inlining all of them didn’t change anything.
Will report back once I can nail down where the problem lies!
We’ve been experiencing this issue as well since we updated to 8.0.11 (we were on 8.0.3 with D2D disabled before that).
Having multiple opened UI instances of our plugin on Windows (tested in Ableton and Bitwig*) makes actions like clicks unresponsive (from few to many seconds delays, to completely unresponsive and having to force quit the DAW). The animations keep running smoothly however.
When all instances use the software renderer, (`getPeer()->setCurrentRenderingEngine(0);`), there’s no issue. But if one or more instance use OpenGL (we allow to choose that per instance at runtime with an option), we experience the issue again. If everything uses OpenGL, then everything freezes instantly.
All of those cases were working fine on 8.0.3 (with D2D disabled) or on previous versions.
I’ve profiled (cpu + gpu), used Thread Visualizer, used JUCE_DIRECT2D_METRICS=1 with D2D metrics app, and I couldn’t find the issue.
Could the JUCE team investigate this issue? This prevents us from updating and benefiting from other improvements and bug fixes (and from using D2D).
* In Bitwig, there was no issue if the plugins were running in separate processes.
What mechanism are you using to run your animations? Are you using the VBlankAttachment, or a Timer, or something else?
My best guess is that the message thread is spending all of its time handling paint commands, preventing any other messages from getting processed. However, I haven’t been able to reproduce the same behaviour so far (I tested with a few instances of the AudioPluginDemo, and with 8 instances of Surge XT built with JUCE 8.0.10, both in Live 12).
Are you able to provide an example project that demonstrates the problem?
I believe your guess is correct, but there’s clearly a regression compared to how previous JUCE versions handled this case.
In earlier versions (or with the software renderer), when running multiple instances under heavy paint load, the focused instance was prioritized. You could see the background windows lagging, but mouse clicks remained responsive. It seemed that non-focused instances were simply repainted less frequently.
With the latest JUCE, however—whether using OpenGL or D2D—the focused window no longer appears to be prioritized. Background instances continue to be repainted, causing the focused window to become completely unresponsive to clicks.
I hope these observations help identify the issue and restore the previous behavior for OpenGL and D2D, where background instances are rarely or never repainted under heavy load.
As for sharing a reproducible project, it would take significant time, since this issue only seems to occur with complex, animation-heavy UIs. If you’re unable to track it down, though, I’ll try to create a minimal reproducible example.
Please could you try applying that patch to the develop branch and check whether it fixes the issue and/or introduces any new problems in your project?
Thanks for the patch! I tested it for some time and it seems to solve the multiple instance issue for Direct 2D (for OpenGL the issue persists). The focused window seems to be prioritized again, like with the software renderer.
But it introduces some other drawing issues (only on D2D, regardless of the number of instances, even in standalone app), like not hiding some components / incorrect component z-order (I’m not sure, basically different components are shown on top of each other and they should not). Also mouseEnter / mouseExit does not seems to work for some of our components that trigger a highlight state. I don’t know why and when it happens though. It’s not everywhere, most of the UI looks fine, it’s only for specific things.
This editor has a continuously repainting background to show whether repaints are ongoing. It also has an interactive slider to check that mouse events are received and processed. The paint function contains a short sleep to simulate an expensive paint call.
Testing this with OpenGL enabled, I’m able to display 8 instances of the plugin comfortably in REAPER and Live. With OpenGL disabled (i.e. D2D enabled), things are very similar, although in REAPER the main host window stops repainting if more than 5 or 6 plugin editors are visible, although the host window still responds to mouse events.
I tried out the DemoRunner and Projucer with the linked patch applied and didn’t see anything like that. Maybe there’s a timing-related issue when the paint callback takes too long to complete.
Are you absolutely certain that you were testing the latest develop branch with the patch applied?
Are you able to modify the test plugin editor I shared to demonstrate the component visibility problems?
Is that in all windows, or only in background windows? I think that the WM_PAINT prioritisation will mean that repaints aren’t guaranteed to be triggered by hover interactions, scrolling etc. on windows that don’t have focus.
It would be really helpful if you could share a concrete example of a project that demonstrates these problems. If you’re not able to create a minimal example, are you able to share your full project with us? We can sign an NDA if necessary. A screen recording would also help to illustrate the faulty behaviour. If you’d prefer to contact us in private, you can do so by emailing info [at] juce [dot] com.
Yes, 100% sure. It’s on our fork but I doubled checked the diff with juce/develop, it only has some non-graphics related changes.
Yes, nothing about OpaqueLayers in juce_Component.
I’ll try your example later today, see if I experience the OpenGL issue first, and then if I can do something reproducing the drawing artifacts.
On focused instance.
I’ll send over email some screen recordings showing the multi-instance OpenGL freeze issue, and the D2D drawing artifacts. With that you’ll get a better idea of what I’m talking about.
I’ll do my best to get a minimal reproducible example if we can’t figure this out. I’ll also try to provide more context on what is called precisely when the artifacts occur.
I managed to get a reproducible example working. It’s here on the juce_8_0_11_experiment branch. It’s pretty similar to your example, but instead of waiting in paint(), it’s drawing a lot of paths. More info inthe readme.
With it, I’m able to reproduce the UI freeze with multiple Direct2D instances, but not with multiple OpenGL instances (which can happen in our plugin unfortunately).
When I apply the patch, the frame rate is dropping for some reason (even with single instance / standalone). I’m not experiencing the drawing artifact in there (did not try to reproduce it there, as the patch already introduce another issue).
Thanks for the demo code and screen recordings. I’ve been able to reproduce the new issues you described, apart from the problem with multiple OpenGL contexts causing the host app to freeze.
I’ve had another go at putting a patch together, and this version seems to behave better than the last one in your example plugin. There are two significant changes:
The SwapChainThread has been removed completely. This means that there are fewer threads active and fewer messages on the main message queue. There’s a small but finite chance this could improve matters with the OpenGL renderer. If nothing else, this change simplifies the D2D renderer implementation, so it’s probably worthwhile.
There was a bug in the code that retrieved invalidated screen areas in WM_PAINT, which I think meant that the renderer would only be able to retrieve small numbers of invalid rects at a time, and would fail for more complex invalidated regions.
As I wasn’t able to reproduce the OpenGL issue, I don’t know whether this patch will fix all the issues you reported. Even so, I’d appreciate if you could test the provided patch (based on the develop branch) in Current, and let us know if you’re still seeing any buggy behaviour.
Thank you for the patch. I’ve tested it, and it appears to resolve the issue with D2D! We’ll continue testing and let you know if anything else comes up.
Regarding OpenGL, I’m no longer able to reproduce the freezing bug as consistently as before, so there seems to be some improvement there as well. However, OpenGL’s handling of multiple instances still lags behind the other renderers. Specifically, the focused window isn’t prioritized, and everything becomes laggy—including clicks (especially when using different renderers at the same time), though not to the point of being unresponsive. All instances run at the same frame rate, which is tied to the overall paint load (can be seen in my reproducible example).
For clarity, this isn’t a regression; I’ve tested with older versions of JUCE, and OpenGL has always behaved this way. That said, it would be a significant improvement if OpenGL could handle multiple instances more like the other renderers. I believe that would solve our problem in Current. Do you see a way to do this?
Thanks for testing that out! It definitely sounds like this is an improvement over the current behaviour of develop, so I expect we’ll merge these fixes shortly.
Just to make sure, was the OpenGL freezing issue also present in JUCE 8.0.3 and previous versions? In your initial post it sounded like 8.0.3 did not exhibit the OpenGL freezing issue at all, and from your latest post it sounds like the issue is sometimes present even with the latest patch applied. If this is a regression from 8.0.3 then I’d like to work out what could have caused the change and attempt a fix.
I just did some testing targeting specifically OpenGL, and it seems the freeze bug on multiple instances was there already in JUCE 8.0.3. Sorry I said otherwise, this issue is harder to reproduce consistently than the 2D2 one before your patch (requires more instances and I usually don’t need to force quit). Probably I encountered it while having some instances on D2D.
OK, thanks. I might be able to investigate a little, but given that the freeze bug doesn’t seem to be a regression it might end up getting deprioritised a bit. I’m about to submit the other changes for review, so hopefully they’ll be on the develop branch in the next few days.