The curious case of how setBufferedToImage surprisngly made performance much worse

Have you ever had your UI run fast on small screens but slow on large retina screens?

Did you ever find when resizing the window that the performance degradation isn’t gradual or linear to the window size, but rather that at some specific threshold it starts being really slow all of a sudden?

Alternatively, did a setBufferedToImage which should had improved performance ever actually made it significantly worse?

This might be the cause:

Setting

  • Component::setBufferedToImage is used to avoid re-executing the paint methods of expensive-to-draw components
  • OpenGLContext::attachTo is used to speed up rendering (the OpenGL renderer is usually JUCE’s fastest renderer)
  • When combining both techniques, all usually works well
  • Under the hood the cached images are loaded into OpenGL textures, which is a bit expensive, but it only happens rarely when the component is actually invalidated

Problem

Sometimes JUCE has a mysterious behavior of recreating the OpenGL texture all the time (OpenGLTexture::loadImage), even though the image hasn’t changed!

Note that the image isn’t recreated, so breakpoints on your cached paint method you won’t pop up.

Mechanism

To support drawing Images in OpenGL without loading them into textures at each call, JUCE has a texture cache for them, Its size is limited, and is currently set by default to 8MB.

But this default may often not be enough.

A very simple way to work around it is to call setImageCacheSize with a more appropriate size. GPUs nowadays have a lot more memory to spare.

Ideal solution (feature request)

The setBufferedToImage/OpenGL combo can work better, by separately counting these cached images from normal images.

Even better would be if the cached images when using OpenGL would be textures to begin with! The OpenGL renderer would be used to draw into them for faster drawing, and setBufferedToImage won’t incur any texture uploading overhead at all!

Victory!

Fixing this problem made a huge difference for Pajam and in its latest version its UI is much smoother!

pajam

Did anyone else here also find that setImageCacheSize with higher values makes your apps quicker?

Cheers, Yair

20 Likes

8MB is very small for nowadays video card.
Should be around 32 or 64 no ?

2 Likes

This actually works! :smiley:
Just tried it. I set the buffer to 64MB.
Things are much smoother on my Retina MacBook now. Great!

Thanks Yair for finding!

5 Likes

Actually I’m just sharing, and should thank @danradix for finding the issue :love_letter:

6 Likes

Awesome tip!

1 Like

Nice! Got to try this out! Thanks for the tip.

1 Like

Is anyone aware if there is a downsize for setting a cache size which is too large?

If I understand correctly, downsize would be with machines with less GPU ram which would result crashing?

But… The JUCE was set years ago and higher values should be fine even for 10 years old machines…