Juce constantly freezes and is not suitable for animations (both native OpenGL and software renderer)

Hello,
Creating a new animated project via the projucer and copying the paint implementation from https://docs.juce.com/master/tutorial_animation.html
Give you the right result :
https://docs.juce.com/master/tutorial_animation_screenshot3.png

BUT

The animation is not fluent at all and gives the feeling to get repeatedly freezed which is absolutly horrible for me as a user point of view.

So I did the same with open GL thinking the only way to get proper animations in Juce was to do the painting by yourself. Unfortunatly, running shaders into Juce gives you exactly the same result, with quick freezes which makes it totally unsuitable to do any kind of fluent animation movement. While in shadertoy.com or vertexshaderart.com this same shaders are running smoothly without effort.

A really wonder if itā€™s only on my machine, if itā€™s me who is doing something wrong, or itā€™s just because those freezes are too subtile and people donā€™t care.

The fact is, for now, I didnā€™t find any way to just do one simple fluent animation in Juce.
Itā€™s not something new, itā€™s something I always experienced with Juce.

Cheers,

Setup : Windows 10, i7-9750h, Juce 6.0.4

With my experience with OpenGL animation and Juce, while developinng my plug-in, UpStereo Pro : https://www.quikquak.com/ (I designed the display shader in Shadertoy, which was a lot of fun!)

You have to remember that itā€™s a plug-in and you have a lot of competition for graphics. Youā€™re sharing the rendering with possibly over a dozen other things, all wanting the #1 slot!

Only have one OpenGL context, and calling the other renders when the main ā€˜renderOpenGLā€™ is called, not forgetting to set the viewport in each. This sped things up nicely for me with multiple panels.
I did this because Iā€™ve had hang crashes in the swap buffers in Cubase and Logic when using multiple contexts. Especially recently.

If you still have slow-downs then set setContinuousRepainting to false, and openGLContext.setSwapInterval(0) using a timer to call repaint() at about 30 frames a second to stop getting in the way of the host rendering and other plug-ins etc. (Itā€™s also a reasonable frame rate and a good compromise in most situations) - it reduced judder and felt a lot smoother when I tried this. You could try using 60 fps of course, but that depends on many things I donā€™t know about what you are rendering.

A another answer would be to use Metal and the latest DirectX, but thatā€™s another storyā€¦ :slight_smile:

*edit - I wasnā€™t aware of the AnimatedAppComponent. You could use that instead of using a timer like I suggested above, itā€™s pretty much the same thing.

3 Likes

Hi Dave,

Thanks for the advice about having a single openGL instance.
Currently Iā€™m looking at other alternatives like IPlug2 that claims to be 60 fps ready and embeds the Skia graphical backend from google, It runs fine on my side and I need to benchmark it to compare it with the Juce performances drawing, how the text renders, how the antialias performs, cpu perfs, etcā€¦

Also I really like your plugins especially the pitch shifter one, glad to know UpStereo Pro animation has been done with a shader. :slight_smile:

Many thanks,

1 Like

Iā€™m no expert at animations, but are you compiling in debug mode? If so, try it in release mode and see if itā€™s any better.

Yes, I built everything in release mode.

that is a really cool use of a shader in a plugin @DaveH, but you should have called it ā€œeye of mordorā€. Iā€™m probably not the first to say that !

2 Likes

@olilarkin Hey thanks, yeah it means you only need 2 polygons, as the GPU can ray-march whole scenes in the fragment shader alone :grinning: GPUs are insanely fast, even oneā€™s on Apple machineā€™s these days! :innocent:

Hereā€™s an ā€œeye of mordorā€ I did seven years ago(!)ā€¦ (it might be buggy on iOS as it only supports WebGL1)

2 Likes

sauron! I remember seeing your stuff on shadertoy. great work!

1 Like

I just did a really simple test.
A white square moving from the left to the right. with iPlug2 and Juce frameworks.

With Juce the animation is not fluent at all and the square seems to have spasms while moving.
With Iplug2/skia cpu rendering, those animations are quite fluid and smooth, I noticed some rare cases when it jerked, but with Juce itā€™s like 2 jerks per second, which is quite unsuitable.

It could be great if the juce team could look up at this issueā€¦

Thanks,

TBH I made even more complicated animations that are running fluid.
So chances are you are doing something in your code that is not compatible with the way juce works or is buggy.

So without the code to replicate the issue it is probably impossible to comment.

Addition: Have a look at the DemoRunner: Browse demos -> GUI -> AnimationExample

1 Like

Well I just created a new animated project from the projucer, then added the following paint function

void MainComponent::paint (juce::Graphics& g)
{
    g.fillAll(juce::Colours::black);
    g.setColour(juce::Colours::white);
    g.drawRect(3 * getFrameCounter() % 400 + 10, 10, 100, 100);
}

Then building in release mode.

I can reproduce the issue here with Juce 6, Visual Studio 2019 and Windows 7.

However, I wonder if the issue is because of using the getFrameCounter call to calculate the rectangle positionā€¦One should probably instead use a clock time difference calculation for that.

edit : Unfortunately, an initial test without using the getFrameCounter didnā€™t solve the issue. It still looks like some frames are ā€œskippedā€. I need to test a bit more, in case I did some mistake with the alternative implementation.

2 Likes

I was looking at the source (am on mac). The getFrameCount() is incremented in the timerCallback().
This could only be different from the clock, if the Timer is set so fast that it cannot finish.

May I ask what timer interval you set?
I would be surprised if a value below 100 (actually 30 should be ideal) makes those problems, but I might be wrongā€¦

The default is 60 timer callbacks per second. I also tested with 30, but that didnā€™t help.

I wonder, could Juce on Windows be doing some kind of ā€œhiddenā€ heavy processing occasionally in the GUI thread? :thinking:

Very strange. Seems the timer accuracy is to blame thenā€¦
I have no idea, good luck!

I tested back the IPlug2 version and now I get those ā€œjerksā€ issue on it too, where before it was quite 100% perfect.
Honnestly I donā€™t know too much if itā€™s an issue of Juce or if itā€™s related to the OS itself, or even the screen.
Thanks for the help anyway :slight_smile: Iā€™ll invest.

Maybe itā€™s some issue with hardware interrupts or something? I suppose more people on Windows should test this, so we could start to understand this issue. (On my part, I can say it isnā€™t the classic ā€œturn off your WIFIā€-issue, because this desktop PC I am on at the moment, doesnā€™t have WIFI. :wink: )

1 Like

When animating ideally you should never rely on the frame rate to do animations you should always calculate animations based on time otherwise it will behave differently on different machines. I can see the tutorial is using getFrameCounter(). I would suggest the tutorial is updated to prevent people making this mistake.

3 Likes

I already tested that alternative approach, like I explained above. It didnā€™t help. The issue is apparently something that prevents the component painting from working reliably. Itā€™s probably something in Juceā€™s Windows implementation that does something heavy in the GUI thread every 2 seconds or so, or a Windows system issue.

@xenakios oh sorry totally missed that. How odd! To be clear youā€™re using the time since the app or animation started to calculate a position? It doesnā€™t surprise me much if the odd frame is missed but I wouldnā€™t expect it to be noticeable.

1 Like