NVIDIA Forceware 75.90 => OpenGL 2.0.0 & fbo

Just out of curiosity, could you try the speed of the same scene without framebuffer switches? That is, rendering the reflection passes on screen instead of to the texture…

Originally posted by Overmind:
Just out of curiosity, could you try the speed of the same scene without framebuffer switches? That is, rendering the reflection passes on screen instead of to the texture…
quick hack of just skipping the BindFramebufferEXT with no other code changes looks to be about ~7-10% higher frame rate for the normal or clear only cases…
planning on doing a real pbuffer and copy from backbuffer version for more valid comparison at some point once I’m more awake, will depend on how much time I spend on optimizations or making it look nicer instead :slight_smile:

edit: more numbers to confuse the issue :slight_smile:
remembered that I was rendering to float textures, so tried GL_RGBA instead…
GL_RGBA16F: with BindFramebuffer = 35fps, without = 39
GL_RGBA: with bind = 41fps, without = 60fps…

actually, looks like without the BindFramebuffers, its wasting a lot of time doing glClears on the entire window instead of just the 256x256 area, so the above numbers are quite a bit lower than they should be, rough guess looks like about a factor of 2x…

Thanks for the test stuff 3B ! Keep on testing, I’d like to hear the difference with pbuffer in the same conditions :slight_smile:

Anybody have any idea how to use fbo with MRT (multiple render targets)? That is, if my fragment shader has multiple color outputs, how do I bind to them and display them as a texture? Previously this was done with pbuffers, but there must now be a better way through fbo correct?

Originally posted by potmat:
Anybody have any idea how to use fbo with MRT (multiple render targets)? That is, if my fragment shader has multiple color outputs, how do I bind to them and display them as a texture? Previously this was done with pbuffers, but there must now be a better way through fbo correct?
There is some psuedo code in the specification file on how to do this:
http://www.opengl.org/documentation/extensions/EXT_framebuffer_object.txt
just search for this line: Here is an pseudo-code example using option (E):

Other question, does the extension support the use of GL_TXTURE_RECTANGLE_NV instead of GL_TEXTURE_2D, cause I can’t get my test working…

Other question, does the extension support the use of GL_TXTURE_RECTANGLE_NV instead of GL_TEXTURE_2D, cause I can’t get my test working…
I don’t recall seeing anything in the spec to disallow rectangle textures. And they could be faster than regular textures as they may not be stored in a swizzled format. But, once again, the implementation is still not finished.

NVIDIA just posted a presentation regarding FBO, that was part of their GDC2005 GL talks.

[b]
In order of increasing performance:
– 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

– Single FBO, multiple texture attachments
• textures should have same format and dimensions
• use use FramebufferTexture() to switch between textures

– Single FBO, multiple texture attachments
• attach textures to different color attachments
• use glDrawBuffer() to switch rendering to different color attachments
[/b]

In a Geforce FX 5200 is not support ¿can anybody help me?.

Regarding the Nvidia presentation on FBO, has anybody actually got anything working with COLOR_ATTACHMENTn_EXT? Is is even supported or recognized by any drivers (even beta) yet? Would have been nice for Nvidia to give a complete working piece of code with this (if such a thing is even possible yet).

EDIT

I can get GL_COLOR_ATTACHMENT0_EXT to display as a texture using the sample code from the FBO spec. But getting GL_COLOR_ATTACHMENTn_EXT to display seems to turn up nothing.

Originally posted by potmat:
Regarding the Nvidia presentation on FBO, has anybody actually got anything working with COLOR_ATTACHMENTn_EXT? Is is even supported or recognized by any drivers (even beta) yet?
COLOR_ATTACHMENTn_EXT work for me (6800 GT, 75.90 and 76.10 drivers), at least 0-2, don’t remember if I’ve tried 3 or not, which is the highest supported on my card. Both one buffer at a time and multiples with ATI_DrawBuffers()…

Don’t forget to actually draw to more than ATTACHMENT0, either call DrawBuffer() and render a pass for each attachment, or DrawBuffers() and output to more than 1 at a time.

more FBO benchmarking results…

Simpler test, trying to isolate FBO overhead more…

  1. render quad to texture A
  2. render quad textured with A to texture B
  3. render quad textured with B to texture A
    repeat 2 and 3 for 2 seconds, optionally doing a glClear for each render, and/or generating mipmaps.
    (or same thing, but doing 64 textures in paralell)

with texture size = 32x32 GL_RGBA
CopyTexSubImage from front buffer = ~50k/sec without mipmaps, ~10kwith mipmaps
FBO per texture = ~15k/sec without mipmaps, ~5k/sec with both
single FBO switching with FramebufferTexture = 80k/sec with no mipmaps, no clear. ~35k/sec with clear, ~30k/sec with mipmaps, ~20k with mipmaps and clear
Pbuffer = ~3-6k/sec
GenerateMipmaps called repeatedly by itself = ~35k /sec

above 128x128, the single FBO/no clear/no mip case starts to slow down : 79k/sec at 128x128, ~40k at 256x256

at 512x512:
CopyTexSubImage from front buffer = ~6k/sec without mipmaps or clear, ~2.7k with both
FBO per texture = ~10k/sec without mipmaps or clear, ~3.2k/sec with both
single FBO switching with FramebufferTexture = 12k/sec with no mipmaps, no clear. ~5.5k/sec with clear, ~5k/sec with mipmaps, ~3.3k with mipmaps and clear
Pbuffer = ~4-5k/sec with 1 texture, ~2-3k with 64
GenerateMipmaps called repeatedly by itself = ~8k /sec

–
didn’t test using FBO and DrawBuffers to switch textures yet, seems like that would probably end up being the same as the single FBO case once you render to much more than 4 textures, but will probably try it soon anyway…

great tests, thanks ! :slight_smile:

Wow, thats a huge difference between FBO switching and binding another texture…

Regarding the case with DrawBuffers: What happens when I bind more than 4 color attachments? Will I get an unsupported error, or am I just unable to render to more than 4 in one pass?

Originally posted by Overmind:
[b]Wow, thats a huge difference between FBO switching and binding another texture…

Regarding the case with DrawBuffers: What happens when I bind more than 4 color attachments? Will I get an unsupported error, or am I just unable to render to more than 4 in one pass?[/b]
It should fail to bind if you try a higher numbered attachment point. Also, don’t rely on the number 4, check the value of MAX_COLOR_ATTACHMENTS_EXT, minimum according to the spec is 1 (and it looks like it could change with the format of the texture, so to be completely correct, I think you would need to do the check after binding the first texture to the fb).
The number you can render at once is a different value, from the Draw_Buffers spec(s), which could theoretically be less than the number that can be bound at once, but we’ll have to wait and see what the driver dev’s decide on that :slight_smile:

Can anyone post some code for using multiple color attachments? Both the code to set up the attachments and then how to display them. It would be greatly appreciated.

Originally posted by potmat:
Can anyone post some code for using multiple color attachments? Both the code to set up the attachments and then how to display them. It would be greatly appreciated.
simple example : (with no error checking, etc. in particular, should check # of valid attachments and draw buffers, currently 4 on my 6800GT, dunno about older cards. Also, verify the framebuffer is valid before trying to render to it, see the example macro in the spec. )

  ////////////////////////////////////////////////////////////////////////
  GLuint fb,rb,tex[4];
  //misc setup
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0,1,0,1,0,16);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(0,0,-1);
  glDisable(GL_CULL_FACE);
  glDisable(GL_LIGHTING);
  glDisable(GL_BLEND);
  glDisable(GL_DEPTH_TEST);

  //allocate space for the textures
  glGenTextures(4,tex);
  for (int i=0;i<4;i++) {
    glBindTexture(GL_TEXTURE_2D,tex[i]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,256,256,0,GL_RGBA,GL_INT,0);
    //glGenerateMipmapEXT(GL_TEXTURE_2D); //add if using mipmaps
  }
  //create and bind the framebuffer, and add the textures
  glGenFramebuffersEXT(1,&fb);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fb);
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,tex[0],0);
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT1_EXT,GL_TEXTURE_2D,tex[1],0);
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT2_EXT,GL_TEXTURE_2D,tex[2],0);
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT3_EXT,GL_TEXTURE_2D,tex[3],0);
  //optional, add a depth buffer (stencil is similar, but doesn't work on nv 75.90 or 76.10 drivers)
  //glGenRenderbuffersEXT(1,&rb);
  //glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,rb);
  //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,256,256);
  //glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0);

  //set up for rendering
  glViewport(0,0,256,256); //set viewport to size of texture
  GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT,GL_COLOR_ATTACHMENT2_EXT,GL_COLOR_ATTACHMENT3_EXT};
  glDrawBuffersARB(4,buffers); //enable all 4 attachments for drawing
  glsl.activate(); //enable the shader
  glBegin(GL_QUADS); //draw something
  glVertex3f(0,0,0);
  glVertex3f(1,0,0);
  glVertex3f(1,1,0);
  glVertex3f(0,1,0);
  glEnd();
  glsl.off();
  //switch to OS provided framebuffer (aka the window)
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
  glViewport(0,0,512,512); //and reset the viewport
  //set up for drawing
  glEnable(GL_TEXTURE_2D);
  glClearColor(1,0,1,1);
  glClear(GL_COLOR_BUFFER_BIT);
  glColor4f(1,1,1,1);
  //bind each texture and draw it as a quad
  for (int i=0;i<4;i++) {
    float x1 = (i&1)*0.5;
    float y1 = (i&2)*0.25;
    float x2 = x1+0.5,y2=y1+0.5;
    glBindTexture(GL_TEXTURE_2D,tex[i]);
    glBegin(GL_QUADS);
    glTexCoord2f(0,0);
    glVertex3f(x1,y1,0);
    glTexCoord2f(1,0);
    glVertex3f(x2,y1,0);
    glTexCoord2f(1,1);
    glVertex3f(x2,y2,0);
    glTexCoord2f(0,1);
    glVertex3f(x1,y2,0);
    glEnd();
  }    
  //swap buffers as needed for display...

shaders :

//vertex prog
void main() {
  gl_Position = ftransform();
}
//fragment prog
void main() {
//draw something to each of the output targets
  gl_FragData[0] = vec4(1.0,0.0,0.0,1.0);
  gl_FragData[1] = vec4(0.0,1.0,0.0,1.0);
  gl_FragData[2] = vec4(0.0,0.0,1.0,1.0);
  gl_FragData[3] = vec4(1.0,1.0,1.0,1.0);
}

should draw 4 quads to the screen, red,green,blue and white…

I tried to assign my FBO to a float texture but I obviously forgot something:

	glGenTextures(1, &FBOTexture);
	glBindTexture(GL_TEXTURE_RECTANGLE_NV, FBOTexture);

	glTexImage2D ( 
		GL_TEXTURE_RECTANGLE_NV,
		0,
		GL_FLOAT_RGBA16_NV,
		256,
		256,
		0,
		GL_RGBA,
		GL_FLOAT,
		0
	);

	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glGenFramebuffersEXT(1, &FBOObject);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOObject);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, FBOTexture, 0);

It only produces NULL values to the target float texture (though I end my fragment program with gl_FragColor = vec4(1.,1.,1.,1.); )

Should I initialize something specific ?
3B, can you paste the way you worked with FBO and float textures ?

By the way, is GL_TEXTURE_RECTANGLE_NV format obligatory when working with float textures ? couldn’t it be a classic power of two texture ?

divide,

You’re assigning the texture rectangle as a texture2D color attachment, that won’t work. You have to attach it as GL_TEXTURE_RECTANGLE_NV.

It’s also possible to use the TEXTURE_2D target, but then you have to initialize a floating point texture according to the ATI_texture_float spec.

Nico

Right. I corrected this but it still doesn’t work :-/
Tried the ATI method, doesn’t work either.

	glGenTextures(1, &FBOTexture);
	glBindTexture(GL_TEXTURE_2D, FBOTexture);

	glTexImage2D ( 
		GL_TEXTURE_2D,
		0,
		GL_RGBA_FLOAT32_ATI,
		256,
		256,
		0,
		GL_RGBA,
		GL_FLOAT,
		0 
	);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glGenFramebuffersEXT(1, &FBOObject);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOObject);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, FBOTexture, 0);

try the arb FP extension: GL_RGBA32F_ARB, GL_RGBA16F_ARB, etc. Those are what I’ve been using, and they work for me…hmm, looks like those are actually the same value as the ATI extension (and apple as well).

changing my sample above to
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F_ARB,256,256,0,GL_RGBA,GL_INT,0);
or
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB,256,256,0,GL_RGBA,GL_INT,0);
works here…

Are you checking for errors?

Random things to try:
if using 32bit floats, disable blending and whatever else NV doesn’t support for those…

make sure the texture isn’t bound when you render

did you call DrawBuffer(GL_COLOR_ATTACHMENT0_EXT) before you draw anything to the FBO? (don’t remember if it defaults to that automatically or not)