Nested FBO's slowdown

I have recently rewritten some software from using pbuffers to using FBO’s for some offscreen rendering to textures.

In one case I render to an FBO texture and some of the objects in the scene contains textures generated by other FBO’s, i.e:

// Update texture1
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb1);
draw gl stuff to tex1
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, NULL);

// Update texture 2
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb2);
bind tex1

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, NULL);

Now, it seems that in the second texture update I sometimes get occational extreme slowdowns (everything stops for a couple of seconds).

Note that the framebuffers are not bound recursively, I only use the resulting texture from an earlier frame buffer operation in a new offscreen texture rendering.

This happens on an NVIDIA 6800 GTX under Ubuntu linux with NVIDIA 87.62 drivers.

Any ideas why this happens?

I have also runned into some strange performance problems with FBO on GeForce 6 series and into a bug in GeForce 6 and 7 series.

  1. Strange slowdowns
    On GeForce 7800GT my app runned fine - it was using multiple FBO’s.
    On GeForce 6600GT I had about 0,2s stalls in regular 1s offsets. Most of my frames were rendered in about 50ms, and one per ~20 frames took ~200ms to render.
    At first I thought I’m running out of video memory, but my game is constructed that way, that almost all textures and vertex arrays are used at least once every frame, so it was strange I’m not having slowdowns at every frame. Decreasing details and screen resolution down to 640x480 didn’t help - memory consumption and FBO size didn’t matter.
    I’ve solved this by removing depth render buffers from FBO’s that didn’t use them (at first I was attaching depth buffers to every FBO by default, which was a waste).

  2. Corrupted rendering & major slowdown
    This happens to my largest FBO - the main render target for HDR. It uses FLOAT16 texture and depth render buffer. FBO is always created successfully first time, but if I destroy it and create again it can go wrong (very often on GeForce 6600, sometimes on GeForce 7800). Of course, with all the textures and shaders loaded re-creating main FBO is not a wise thing to do, but FBO was reported as complete and no errors were returned.
    When I attached depth texture instead of render buffer to this target (I added depth of field to my game) I ended up in having problems on GeForce 6 - the FBO was sometimes corrupt when created for the first time (on GeForce 6600).
    The corruption causes a some sort of black chessboard to appear on screen, but I believe it’s not the color buffer that is corrupt, but it’s the depth buffer that causes some of the pixels not to be drawn. Screenshot here:
    http://ks-media.ehost.pl/images/bug/bug01.png (1,1 MB)
    It also causes the framerate to drop to 1 FPS (my game assumes that frame time can be no longer than 100ms, so it doesn’t show the actual FPS on this screen).
    As you can see it’s the main FLOAT16 texture that get’s corrupted. Everything that hapens later (downsampling, blurring, rendering HUD) works fine. Some of these corrupted pixels have a color of the sky, so It’s probably the depth test that goes wrong and prevent rendering on some pixels. I also mentioned that this bug is more probable when using depth texture instead of depth render buffer.
    This error only applies to GL_RGB_FLOAT16 FBO. With GL_RGB8 it works perfectly.

I get the feeling that error #2 is caused by some sort deadlock during depth test - after timeout the fragment processing is cancelled and no pixel is drawn. I don’t use depth test when I render the sky. That would explain why I see the sky at these pixels, and why the game slows down to 1 FPS.

So if you’re experiencing some slowdown/bugs with FBO on NVIDIA, then search for anything related to depth test:

  • don’t use depth textures if you don’t have to - use depth render buffers instead.
  • remove depth render buffers from FBO’s if you don’t need them
  • don’t enable depth test if you don’t need it

I see a similar checkerboard effect with fbo’s using the latest drivers but only if I have AA turned on…

I had FSAA disabled on both machines, but perhaps this bug is more likely to occur with FSAA.
Did you use FLOAT16 + depth render buffer or depth texture? Or was it other format?

I had the same problem with corrupted rendering and slowdowns when i was rendering to a cubemap face bound to an FBO, and i heard that the same thing happens when rendering to float textures.
To solve this problem I had to set the filtering modes for the cubemap faces to GL_NEAREST while rendering to them. I have no idea why, but this fixes the bug.
I think this solution should work for float textures as well.

About the topics original question: when exactly does the app stop for some time?
If you are changing the configuration of any of the FBOs, i assume that’s where the problem is

I had to set the filtering modes for the cubemap faces to GL_NEAREST while rendering to them
Thanks for this tip. I have GL_LINEAR filtering, since I’m downsampling this texture later, but I’ll try to switch to GL_NEAREST when rendering to it.


Ok, I tried it - no luck. Guess I’ll just stick to original plan that assumed you will have to restart the game if you switch to HDR rendering (it always works the first time)

I think the reason you all get intro rendering corruption is becouse you read from a buffer that the GPU is not finished with.

Try to insert a glFinish between each pass to check if this is the case. Of course the best thing to do is to interleave dependent rendering operations with independent.

So reducing filtering quality and render presicion seems to fix the problem, but in theese cases the GPU manages to finish the FBO operations in time.

Regards
Thor Henning Amdahl

I think the reason you all get intro rendering corruption is becouse you read from a buffer that the GPU is not finished with.
I cannot agree. Corruption is always at the same pixels and the same FBO. Besides, I’m not reading any pixels directly (but I am using this texture right away)

Try to insert a glFinish
The way I see it (although it’s just an assumption) glBindFramebuffer will be put to command queue just like any other GL command - it will not cause FBO switch until all previous commands are complete. So adding glFinish won’t help (and didn’t help - I’ve just checked this).

So reducing filtering quality and render presicion seems to fix the problem, but in theese cases the GPU manages to finish the FBO operations in time.
No, filtering of the texture shouldn’t and doesn’t have anything to do with the speed of rendering to this texture (unles you are using automatic mipmap generation, which is not the case here).

My bet is still on depth test timeouts. Thanks for your opinion anyway - every one counts :slight_smile:

OK, sorry that it not work.

Please let me know if you figure out what causes this.

I think I’ve found it (better never than late).

My FBO contained RGB_FLOAT16 texture and 24-bit depth renderbuffer.
My framebuffer support was missing a line that was deleting this depth renderbuffer when deleting FBO.
So my aplication leaved some unused depth renderbuffers and drivers went bananas causing newly created depth renderbuffer to produce timeouts when depth test was used. This could be connected to exceeding my GeForces onboard memory (I had plenty more available for GPU in my system).

So it looks like this is both my error (fixed) and a bug in NVIDIA drivers. I guess i’ll report it as soon as I find some time to make a small reproducer application.

Cheers.