Yes, we’re looking at synchronising repaint calls to screen FPS on all platforms for JUCE 7.
Could we get a
Component::setContinuousRepainting() with that, so we don’t have to keep using timers everywhere where we want animated components? Would nicely match
I will upgrade if Juce 7 implements the unicode font fallback
Alright – I just played with this for a few hours and here was my finding.
In Standalone: – metal on or off – the framerate is amazing (to be expected kinda – it always was) - CVLink calls 60FPS – and it certainly looks 60FPS, it is smooth as butter, eye wateringly good. If I could get my plugins to look this all the time I would cry.
In Ableton No Metal: - CVLink calls 60fps – but drawRect calls drop by about 10 FPS (no idea why) – it definitely is still an improvement and looks much better. Quartz Debug show the 1 merged rectangle flashing.
In Ableton With Metal: - CVLink calls 60fps – yay, no more drawRect, so it gets really hard to measure, but it definitely feels the best, i see rectangles rendering across split calls in 400 - 500 renders a second depending how many things I have animating with seemingly no problem – it seems somehow like it’s not quite as smooth as standalone, but it is damn damn good. It looks as smooth as OpenGL, and I didn’t need to do shit. We see the entire screen flashing with Quartz, but that’s similar to other apps I realized use this rendering style while playing around (ableton you see the same CVLink prints we now see with JUCE). Obviously we’re painting less internally because of the repaint debugging and the split rect drawing which YAY – we can manage again. No idea if Quartz is even relevant anymore.
Overall thought: this is incredibly freeing. I didn’t measure any actual CPU performance in these tests, it was just prints and looking at visuals, but it’s is a MASSIVE improvement for me.
Some thing I’d hope/love to see before release:
1 - Turn on / off metal & multiple paint calls separately.
Why: It will be easier to measure performance, and I’ve previously tuned my graphics for the 1 big rect – I’m not sure if this is helping or hurting without being able to turn it on or off – in some cases it makes sense a single paint over the merged rect may be more performant. IMO the flags now are a bit awkward and not doing what they say honestly.
2 - Async flag is gone?
Why - I’ve noticed some strange behavior with Async on previously.
Is metal always async? How are we meant to turn this on / off now?
3 - Some way to measure actual true FPS
Why – not sure if this is even possible, but currently we can only track when we actually tell the OS to update a rect – it would be amazing if there was a way to get notified when it truly re-renders.
I say this cause everything is calling at 60FPS now, but are we actually rendering at 60FPS? It would be so much easier to debug if we could see how our actions changed this. With all the async and metal now, it just feels like painting is totally free and non-blocking – I’d like to not be an idiot and overdo it without being able to tell how or why.
It’s really wizard level shit and I love this, thanks so much JUCE team. Trying to figure out these Native APIs with the amount of crap information out there online still seems like magic to me in a world of Xcode drag & drop UIs & swift do-it-all-for-you approaches. I can tell some elbow grease went into figuring this out – at least it would’ve been hard as hell for me! Grateful!
This won’t be very helpful.
- Multiple paint calls and no Metal layer doesn’t work at all, as described in the linked posts
- The Metal layer and no multiple calls will be slower than no Metal and no multiple calls. The extra layer of indirection won’t be doing anything useful.
The default renderer is async. The Metal layer renderer is not async.
See the breaking changes doc for more info about both 1. and 2.: JUCE/BREAKING-CHANGES.txt at juce7 · juce-framework/JUCE · GitHub
Now that JUCE_COREGRAPHICS_DRAW_ASYNC is no longer meaningful, I think it would beneficial to give a warning during compilation if it is found to be defined in a project, to give the developer an heads up in case they missed the BREAKING-CHANGES doc.
In general, I think it would be good practise to give such warning for every macro when it is no longer used by JUCE. That would give us developers a chance to clean up our #defines with increased confidence.
(Same idea already mentioned here: Ouch! kAudioUnitParameterFlag_IsHighResolution problem, fix needed! - #3 by yfede)
JUCE_COREGRAPHICS_DRAW_ASYNC wont have any effect on backwards compatibility.
- If you previously had this set, then the new default is also async rendering, no change there.
- If you had this set, but you wanted to selectively disable how it was used, this would now be a compilation failure and you would need to move to the new
Nice to see that async layer drawing is now the default option. I’ve been using that trick on certain areas of the UI in native iOS apps since 2013
As others mentioned here, it would be really great if you guys could improve rendering on Windows now, I’d absolutely love to ditch the OpenGLContext in some cases.
So am I right in thinking that the best approach on macOS now is to remove any previously set values of
JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS and rely on the defaults?
I remember when the DRAW_ASYNC feature was added, some plugins rendered with a blank window (Waves and MeldaProduction at least IIRC), has any testing been done to that extent or is the advise to use the new
windowRequiresSynchronousCoreGraphicsRendering flag for plugin hosting windows?
The effectiveness of
JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS will depend on the form of your GUI. If you have something like a plug-in with meters on each side causing large sections of the window to be redrawn constantly then you should opt for enabling
JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS. However, if you’re not suffering from this, then the defaults will likely perform much better.
We have fixed one blank-window async rendering issue, but I suspect there might be a few more. I’d use
windowRequiresSynchronousCoreGraphicsRendering for plug-in windows.
FWIW, I have tested on an intensive UI plugin (UVI Shade - Creative Filter and EQ) and async redraw performs better than multiple paint calls, so it’s really a per plugin decision.
Just wanted to report that “Safari seems snappier” — er, I mean, running my painting-heavy plugin on the juce7 branch is happy on MacOS so far. No hiccups, and it does seem smoother/snappier (I had JUCE_COREGRAPHICS_DRAW_ASYNC on beforehand).
Wow! This is amazing, so excited for JUCE 7!! Definitely looking forward to seeing the improvements you guys have planed for graphics rendering on Windows.
Exciting! Can’t wait to try out the new version and check out all the graphics improvements!
Yeah confirmed – I don’t really get how to set the flag from within a plugin UI – I thought those flags get added when you add the window to desktop, but we don’t add the window to desktop to ourselves in the plugins?
Just building on Windows to see if something breaks -everything seems to work. Clang warns about a couple missing initializers in constructor calls: ConfiguredArrangement::transform and CachedGlyphArrangement::cachePosition.
I’m unsure whether this was intended as a response to my suggestion of giving a warning in case client code still #defines that macro.
My point is, that once JUCE no longer cares about that value, issuing a warning if client code still defines it one way, prevents clutter and “dogmatic” behavior, like: “for better performance, thou shalt define JUCE_COREGRAPHICS_DRAW_ASYNC”, where in practice it doesn’t matter the least bit.
Source: I’ve been blindly setting JUCE_DISABLE_WIN32_DPI_AWARENESS in my projects with confidence, until a couple months ago when I realized that JUCE doesn’t care about that macro any longer since August 2018…
Furthermore it is a time sink, if people start to investigate if setting or unsetting this flag helps or hurts in their project.
If a flag that has been used by JUCE and is now removed/do nothing, it might be nice if JUCE would add compiler warnings exactly as now we get nice deprecated heads up.
These are great things for you to be working on. Really core stuff the UI performance and unicode stuff.