17

I wonder since a long time what would be the best way to handle OpenGL FrameBuffer Objects (FBO). Switching FBOs can be costly but defining new attachments too.

How do you do it fast ?

I hesitate between these 3:

  • 1 FBO for everything, change attachment but don't switch between FBOs

  • 1 FBO for each render target (size + format) in the rendering path. That means i will reuse the same FBO for similar render targets. But this way a custom blur would cost 4+ FBOs.

  • 1 FBO for each render target, set attachments only once and then switch between FBOs

Also, should I minimize the number of FBO switches (like I minimize the number of texture bindings) ?

ponce
  • 919
  • 5
  • 15
  • first... what is a FBO? If you're to use an acronym multiple times it's recommended to use it unexpanded the first time. – fortran Feb 04 '10 at 09:46
  • 6
    FBO = Framebuffer Object – ponce Feb 04 '10 at 09:59
  • Nice question.However the first part of the answer given below contradicts what is said in the book "OpenGL Insights".The book states that switching between multiple FBOs is costly and the best thing to increase the performance is using multiple attachments to the same FBO. – Michael IV Aug 28 '12 at 10:11
  • That's why he said "In order of increasing performance". – ponce Sep 12 '12 at 14:56

2 Answers2

16

Updated references:


NVIDIA 2005 (probably outdated): The last official performance recommendation by NVIDIA I know is almost five years old. In his GDC presentation, Simon Green recommends the following (slide 29):

In order of increasing performance:

  1. Multiple FBOs
    • create a separate FBO for each texture you want to render to
    • switch using BindFramebuffer()
    • can be 2x faster than wglMakeCurrent() in beta NVIDIA drivers
  2. Single FBO, multiple texture attachments
    • textures should have same format and dimensions
    • use FramebufferTexture() to switch between textures
  3. Single FBO, multiple texture attachments
    • attach textures to different color attachments
    • use glDrawBuffer() to switch rendering to different color attachments

In my experience, the second case is really faster than the first (ATI Radeon HD4850, Geforce 8800GT). I've not tried the third case, as it would have complicated my code.

Malte Clasen
  • 5,637
  • 1
  • 23
  • 28
  • The [GDC presentation here](https://developer.nvidia.com/sites/default/files/akamai/gamedev/docs/Porting%20Source%20to%20Linux.pdf) mentions to not switch attachments because it apparently leads to bad performance. So it contradicts this performance order. – Erunehtar Oct 08 '16 at 14:42
  • Please note that the presentation I mentioned is from 2005, and my results are from 2009. I wouldn't be surprised if the order of performance changed over the last decade. – Malte Clasen Oct 09 '16 at 12:53
  • I would also add this [link](https://software.intel.com/en-us/articles/opengl-performance-tips-swap-frame-buffer-objects-fbo-instead-of-surfaces-using-a-single), which mention better performance to switch FBOs (#1) instead of switching attachments (#2 and #3). It would be a good idea to update the answer to this question. – Erunehtar Feb 15 '17 at 19:42
  • Thanks Deathicon, I've just updated the answer including your links – Malte Clasen Feb 16 '17 at 19:39
4

As a matter of philosophy, modifying an object state requires that it be re-validated. Instead, simply changing the object binding (that's already valid from the previous frame) should be faster for the driver [1].

So as a first implementation, I'd go for 1 FBO for each render target (or more precisely, render target set. You usually render to multiple buffers at once).

That said, nothing beats benchmarking your app against multiple implementations.

[1] I mention for the driver, because an FBO change can force a GPU flush, depending on architecture. It will introduce bubbles in most cases. So it is definitely something that you don't want to do often. It's more important than optimizing the texture bindings, e.g.

Bahbar
  • 17,760
  • 43
  • 62