framebuffer_blit with multisample inverts the blit

BlitFrameBufferEXT is throwing INVALID_OPERATION, with a READ_FRAMEBUFFER of my valid color-only FBO, and a DRAW_FRAMEBUFFER of 0, the window.

0 is also NONE, and the spec argues that nothing should happen if either buffer is NONE.

Clearly I’m confused here, and could use some enlightenment. You should be able to blit from a framebuffer object to the default unnamed framebuffer, right?

glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, 0 );
CHECKGL;

glBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, rt.fbo->_handle );
CHECKGL;

GL_CHECK_FRAMEBUFFER_STATUS( GL_DRAW_FRAMEBUFFER_EXT );
GL_CHECK_FRAMEBUFFER_STATUS( GL_READ_FRAMEBUFFER_EXT );
CHECKGL;
	
glBlitFramebufferEXT( 0, 0, rt.width, rt.height,
		      0, 0, appWindow.width, appWindow.height,	  
                      GL_COLOR_BUFFER_BIT, GL_NEAREST );

CHECKGL is a macro for glGetError

Only the blit causes an error, if I comment it out, everything goes on its invisible-but-seeming-to-work way.

What mistakes should I be looking for? My old FBO path w/ Texture2D still works.

That’s because GL_NONE is not a valid buffer. You need something like “GL_BACK” rather than “GL_NONE”. GL_NONE means, “Don’t draw stuff to me.”

Thanks Korval.

So
1.) the DRAW framebuffer should be GL_BACK only during the blit?

2.) glReadBuffer does not need to be called in this situation, as BlitFramebuffer only cares about what is specified by the bound READ_FRAMEBUFFER?

Now I’m getting INVALID_FRAMEBUFFER_OPERATION, and the spec says this only happens if either the draw or read buffer is incomplete.

However, glCheckFramebufferStatus returns framebuffer complete for both.

I’ll look at this with a fresh brain tomorrow.

Okay, blitting works with a DRAW_FRAMEBUFFER of 0, not GL_BACK, and a READ_FRAMEBUFFER with my user-specified object.

Now it’s time to get a multisample READ_FRAMEBUFFER framebuffer blitted to the default window.

CatAtWork, you didn’t say what GPU and driver version you’re using.

glBindFramebuffer takes a uint framebuffer name, not a draw buffer name such as GL_BACK. GL_BACK is a valid DRAW_BUFFER (glDrawBuffer) or READ_BUFFER (glReadBuffer) for framebuffer zero.

In CatAtWork’s example there are two framebuffers. Each of the framebuffers contains both DRAW_BUFFER and READ_BUFFER state. Pixels will be blitted from the READ_FRAMEBUFFER’s READ_BUFFER to the DRAW_FRAMEBUFFER’s DRAW_BUFFER(s). The blit operation ignores the READ_FRAMEBUFFER’s DRAW_BUFFER state, and ignores the DRAW_FRAMEBUFFER’s READ_BUFFER state.

In a slight digression, note that if the BlitFramebuffer’s <mask> value were specified as (only) DEPTH_BUFFER_BIT, then both READ_BUFFER and DRAW_BUFFER would be ignored. Pixels would blit from one depth buffer to the other, similar to a GL_DEPTH CopyPixels.

8800GTX, 97.02.

What are valid items to pass to ReadBuffer and DrawBuffer when a framebuffer is not zero?

Blitting from a non-multisample framebuffer to zero works now, but I’m struggling with the multisample version. The framebuffer_multisample spec is a joy to read.

Are either of these statements correct?

Regardless of framebuffer zero’s multisample format generated by SetPixelFormat, any valid multisample framebuffer may be blitted to zero.

OR

Only a framebuffer with the same number of samples as the window may be blitted to framebuffer zero?

I’m making sure that the blit rectangles are the same size in the multisample case, and I’m only blitting color for now.

The value values of ReadBuffer and DrawBuffer are defined in the EXT_framebuffer_object spec. They are GL_NONE and names such as COLOR_ATTACHMENT0_EXT. See table 10.nnn, as well as references to this table in the FBO spec.

CatAtWork, does your multisample renderbuffer have an internalFormat that is “equivalent” to the window’s format?

I’m passing GL_RGBA as the internalFormat:

All blitting works until I create a multisample framebuffer object. No errors are generated, but the blit is not shown. I just use a different ClearColor for framebuffer zero and the user-specified one.

R_ComputeFBODimensions( rt );


// Detach color _renderBuffer_, if there was one
//
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0 );

// Detach color _texture_ if there was one
//
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, rt.textureTargetType, 0, 0 );

rt.fb_colorRB = 0;

glGenRenderbuffersEXT( 1, &rt.fb_colorRB );
	
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rt.fb_colorRB );

//////////////////////////////////////////////////////////////////////////
//
if( glrimp.exts.EXT_framebuffer_multisample ) {
    glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, multisamplesRequested, GL_RGBA, rt.width, rt.height );
    
    GLint givenSamples = -1;
    glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &givenSamples );

    if( givenSamples == multisamplesRequested ) {
        Printf(  COM_GREEN("%d multisample color format given
"), givenSamples );
    }
    else {
        Printf( COM_YELLOW("%d multisample color format given, different from request
"), givenSamples );
    }
}
else {
    // glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, /*NOTE ZERO*/ 0, internalDepthFormat, rt.width, rt.height );
    // Is the same thing as
    //
    glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_RGBA, rt.width, rt.height );
   
}

// attach renderbuffer to framebuffer color buffer
glFramebufferRenderbufferEXT( GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, rt.fb_colorRB );

Well, I re-enabled my scene drawing, and it looks like an error in my code led to a wrong glClear when a multisample framebuffer was being drawn to.

Right now the blitted image is upside down if the source is a multisample framebuffer, and right-side-up if framebuffer is non-multisample.

Stripping down to a single test case at the moment.

EDIT: test case flips the blit when multisampled, and nothing is blitted if the default framebuffer is already multisample-enabled.

EDIT2: I modded my Quadro FX 1500M to use the 97.02 drivers, and I see the same flipped blit when reading from a multisample framebuffer.

Grab the FBO test out of http://www.effloresce.com/cat/opengl.org/

Choose your monitor # from the console window.
Bring down the GL console with ~.

Enter
r_usePostProcess 1 (should turn one triangle green.)

Enter
r_postProcessMultisamples 2 (should flip the screen)

Enter
r_multisamples 2

followed by
r_restart
and a multisample window should not blit anything if the read framebuffer is multisampled.

Both issues (steps 2 and 4 above) will be fixed in a future driver release. Thank you for taking the time to produce a simple repro app, this greatly helped us.

This issue is caused by a problem that could sometimes happen when doing a downsample blit directly into the window. To work around the issue on the current drivers, you could modify your application to perform the downsample blit into a second single-sample FBO, and then do a 1:1 blit from the single-sample FBO to the window.

This issue is caused by a problem that could sometimes happen when doing a downsample blit directly into the window.
since this is a while ago, i assume this has been fixed?

as the following gives me invalid operation, bliting from a fbo to the main window (FBO is multisampled)
glBlitFramebufferEXT(0, 0, W, H, 0, 0, W/2, H/2, GL_COLOR_BUFFER_BIT, GL_LINEAR );
theres no probs if both are the same size

gf7600gs with XP + 162.18 drivers

ok further info, sorry i should of tested this before


glBlitFramebufferEXT(0, 0, W, H, 0, 0, W/2, H/2, GL_COLOR_BUFFER_BIT, GL_LINEAR );

works fine if the FBO is NOT multisampled


glBlitFramebufferEXT(0, 0, W, H, 0, 0, W, H, GL_COLOR_BUFFER_BIT, GL_LINEAR );

works fine if the FBO IS multisampled


but
glBlitFramebufferEXT(0, 0, W, H, 0, 0, W/2, H/2, GL_COLOR_BUFFER_BIT, GL_LINEAR );

doesnt work if the FBO is multisampled


i assume this is a driver bug, btw in all 3 cases
CheckFramebufferStatusEXT == GL_FRAMEBUFFER_COMPLETE_EXT