[Interest] 60FPS and FBO

Samuel Rødal samuel.rodal at digia.com
Tue Nov 27 10:12:58 CET 2012

On 11/26/2012 05:50 PM, Thomas Senyk wrote:
> Hi,
> the context of this is mail is:
>   - scenegraph
>   - FBO based effects
>   (plain shader-effects, qtgraphicaleffects, qt3d)
>   - embedded hardware / opengl es 2.0
> I've noticed that on a lot of embedded systems the FPS drops rather
> drastically (e.g. from 60 to 30 with one effect, from 30 to 10-15 with two
> effects) when using FBO based effects.
>    ... even simple effects, sometimes even if they have 'visible: false'
> Is this somewhat expected?
> It does sound like a vsync vs. fbo problem ... doesn't it?
> Is this a fault/bug in the embedded opengl drivers?

As Florian also commented I've noticed that the FPS very easily drops to 
30 when not using the threaded renderer.

But even if that's not the case, I guess FBOs can be heavy on the GPU, 
especially if they're large (screen sized) as it basically implies 
another full-screen render pass, plus some synchronization overhead 
depending on the architecture; when rendering to the main framebuffer 
some GPUs have a deep pipeline of several frames being in flight at the 
same time, this pipeline might not be possible to utilize for FBOs since 
the result of rendering to the FBO is typically used quite immediately 
for rendering into another FBO or the main framebuffer. An interesting 
experiment might be to do double buffering by keeping two FBOs and only 
using the FBO that was rendered to during the last frame as a source 
during the current frame. That would mean the FBO content and non-FBO 
content would not be completely in sync though (unless you used 
predictive timing for the FBO content or introduced extra latency). It 
would have significant implications for memory use and its effectiveness 
would depend highly on the driver and GPU architecture.

I would be surprised if rendering to an FBO involved a vsync, since 
there's no eglSwapBuffers() call involved in the process. You simply 
bind an FBO, render to it, release it, and use it as a texture (this 
step is where you get the synchronization hit).

> Did anyone ever had a setup, using one or multiple FBO based effects did still
> result in 60fps? (as it should be for simple(!) effects?)

At least on the Raspberry Pi I believe I've gotten 60 fps performance 
out of ShaderEffects on ShaderEffectItems or layers. Not sure they were 
fullscreen though.

There are some general tricks you can use to get better performance when 
using ShaderEffects:

If you're applying effects on a sub-tree that is not animating, and the 
ShaderEffect involves some heavy fragment program computation (such as a 
nice blur effect), you can trade memory for performance by caching the 
result of the ShaderEffect in a texture. This can be done simply by 
setting "layer.enabled: true" on the ShaderEffect. Careful though, if 
the sub-tree that is a source for the shader effect _is_ animating, this 
will instead cause a drop in performance since the layer would need to 
be updated each frame.

In some cases you might get away with applying the effect at a lower 
level in the Item hierarchy, for example instead of applying an effect 
on a Rectangle that contains a rotating Image, separate the effect into 
two components, one that applies to the Rectangle and one that applies 
to the Image, cache the result of applying the effect to the image with 
the "layer.enabled: true", and apply the rotation animation on the 
effect instead of the source Image. This assumes that the effect is 
rotation independent though, for example if it's doing a pure color 
transform (gray-scale or sepia etc). Of course, even better would be to 
have a PNG with the effect pre-applied :)

In general, shader effects or not, you can always use "layer.enabled: 
true" on non-animating sub-trees to trade memory for performance.


More information about the Interest mailing list