Performance issue with OpenGL in multiple windows

Awesome! It’s nice to hear the multiple context opengl problem is being worked on. This is what prevents me from using OpenGL in plugins where multiple contexts have to be expected because multiple instances might be open at the same time.

2 Likes

Fabian,

Is the message manager lock required to protect the MM Thread from the OpenGL rendering thread, or is it also required to protect each OpenGL thread from each other?

RIght now (either with the workaround that I am using, or with your rework of the locking) the locking scheme has the effect of single-threading all the rendering threads (and blocking the MM thread while the rendering threads are actually rendering).

Ideally, the rendering would be able to do its thing while the MM thread continues to do its thing, but I understand why these threads need to be protected from each other.

I am less clear on why the individual OpenGL context rendering threads need to be protected from each other. Since they each have their own context, shouldn’t it be possible for the rendering threads to all be running in parallel while some coordinator holds the MMLock? If you have multiple OGL contexts in your app/plugin, right now they all contend for the MMLock and you wind up running the rendering single threaded, with the overhead of acquiring the lock. So if you are trying to get 30FPS, that 33ms needs to be shared by all the contexts.

If the rendering threads could run in parallel, then the lock would only be held for the max rendering time rather than the sum of the rendering times (or some division of the sum if there were more contexts than cores), which would keep the app responsive and the rendering smooth.

If it is isn’t possible to have the rendering threads running in parallel, then it seems like there should be some OGL coordinator that explicitly serializes the the rendering for all the contexts that require the MMLock rather than contending on the lock.

1 Like

This is only if you attach the OpenGLContext to a Component. The OpenGLContext will not try to get a message manager lock at all if you are simply interested in the OpenGLRenderer callbacks. You obviously, need the message manager lock if the OpenGLContext should also render JUCE components (i.e. if the OpenGLContext is attached to a component). You can’t have JUCE components resizing, deleting themselves etc. while they are being rendered.

Also, sorry for not having a fix for the performance problems you are experiencing. I’m still working on it and it’s nearly ready. I just want Jules to have another look once he is back from his holidays.

1 Like

Any update on this?

We’re getting reports from some Windows users that the frame rate drops massively when two plugin windows are open on their specific hardware. We have not been able to replicate this on any of our dev machines though: they all perform fine with 10+ instances at 60 Hz OpenGL rendering.

1 Like

We’re seeing here many bizzars with graphics and sadly I we have yet to find a “one fits all” solution.

Some machines would get better with OpenGL, others would feel much fluent with non-OpenGL.
Currently we have settings or flags for turning it on or off.
Windows is safest with off for broader compatibility.

I have yet to nail it but I think many of those behaviors related to juce message thread choking.
My next plan is to try and move some graphics code to background thread as suggested in the forum.
On my current project without OpenGL even a single meter makes UI sluggish. (and I don’t do any crazy redraws only using AudioProcessorValueTree attachments and sliders…)

1 Like

Yes, we’ve been working on fixing this. However, it needed some deep changes in the MessageManager locking implementation so we are still testing this.

Can you try the following branch and let me know if this improves performance for you? This would be super valuable information for us.

2 Likes

A fix for this is now on develop with commit b9b3439. Let me know how this fix works for you.

@IvanC

Hey Fabian, I am using the latest official download and still have this issue with a really lightweight plugin. I have 60fps, then when I drop another instance to the DAW, 30 fps, another instance 15fps… then crash :smiley: No problem if I keep open only one GUI of these plugin instances… then it’s simply 60fps for that instance.

Should your fix included in the latest release?

thanks, Kevin

Is that on macOS? Apple recommends using CVDisplayLink, which JUCE doesn’t, but we’ve found that it helps immensely with performance of multiple windows with OpenGL on macOS, and it’s implemented in the SR branch.

1 Like

It’s Win10 with an NVidia GTX card. But it’s definitely not openGL performance issue as even if I don’t draw just few lines it happens… I guess it’s something with blocking threads.

1 Like

We’ve seen similar issues as well. Do you have continuous repainting turned on?

1 Like

We have something similar happening on Linux, deadlocking as soon as you open a second window of the plugin

1 Like

Yes it’s on, and V-Sync is also on (setSwapInterval (1)). But even if V-Sync is off (0), then I get 4-500fps drop to 200fps with 2 instances, then something below 50fps with 3 instances , etc…

I think it would be helpful for the JUCE team to get some example source-code that can reproduce this.
Meanwhile there’s a lot of important feedback without a reproducible way that can be confirmed even on each of the participators of this thread.

I’d be more than happy to try and reproduce it here on Mac/Win & Linux VM

2 Likes

@fabian : I just made a minimal plugin to demonstrate that every new plugin instance is decreasing the FPS and after a while it leads to crash. With one instance it works perfectly tho. Here is a video demonstrating the issue: VIDEO

On the video you can see the FPS that I calculate in the RenderOpenGl() function is fixed to about 60FPS, so it is called nicely, but the real render FPS measured by the third party app FRAPS is dropping with every new plugin instance. Another interesting thing is that the more instances I drop into the DAW, the FPS I calculate in RenderOpenGl() is increasing by about 1 FPS/instance… so after a few plugins the original 60FPS is increased to 66-67FPS !!! It seems the function is called more frequently than the otherwise VSYNC-ed 60FPS.

On the video, it didn’t crash, but actually, if I would drop more plugins into the project it would crash for sure. Here is a crash debug picture if it makes any sense:

Please PM me, if you would like to see the source code too, but it’s pretty basic, I just made it from scratch in 20 mins.

Thanks in advance if you could look into the issue!
Attila

3 Likes

same issue reported to us on Windows when using OpenGL renderer

Can’t you just add it here or gist of the critical parts?

@ttg Here is a reduced code. Only the Editor class and I hope I didn’t made any mistake while rearranging some of the functions…

Bump :slight_smile:

1 Like

Hi @FineCutBodies, this code currently fails under macOS at least for me.

JUCE Assertion failure in juce_AudioProcessor.cpp:360
ERROR: 0:1: '' :  version '130' is not supported

JUCE Assertion failure in juce_OpenGLShaderProgram.cpp:90

It might be simpler to use JUCE own demo as a base for reproducing the problem.
I’ll try using the Demo. p.s - we saw decrease in performance (as we add more plug-ins) even by just using the JUCE OpenGL renderer with no direct OpenGL on our code.