Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: How to resolve integer multisampled texture attached to a framebuffer?

  1. #1
    Junior Member Newbie
    Join Date
    Sep 2013
    Posts
    3

    How to resolve integer multisampled texture attached to a framebuffer?

    Hi,

    I'm having some troubles in resolving integer multisampled textures.
    I have a simple questions which although, don't seem to get strong answers so far.

    I already know that I can define integer multisample textures, I can attach them to a FBO and I can draw on them from a fragment shader. The question is, can they be resolved coherently? The problem occurs when I try to resolve the integer draw buffer onto a singlesample FBO, because the texture data I get is filled with zeroes.

    So, I'm using a multiple render target framebuffer, on which, the first color attachment is a color texture (RGBA8), while the second draw buffer (color attachment 1) is an index texture (R32UI).

    Code :
    gl::BindTexture(gl::TEXTURE_2D_MULTISAMPLE, m_Textures[eTEXTURE_COLORBUFFER]);
    gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_BASE_LEVEL, 0);
    gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_MAX_LEVEL, 0);
    gl::TexImage2DMultisample(gl::TEXTURE_2D_MULTISAMPLE, m_Multisample,gl::RGBA8,width,height,gl::FALSE_);
     
    gl::BindTexture(gl::TEXTURE_2D_MULTISAMPLE, m_Textures[eTEXTURE_CLASSBUFFER]);
    gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_BASE_LEVEL, 0);
    gl::TexParameteri(gl::TEXTURE_2D_MULTISAMPLE, gl::TEXTURE_MAX_LEVEL, 0);
    gl::TexImage2DMultisample(gl::TEXTURE_2D_MULTISAMPLE, m_Multisample,gl::R32UI,width,height,gl::FALSE_);

    Both textures are multisampled, and I would like to download them on CPU once the render has been completed.
    The code I use to download the image is listed down here.

    Code :
    uint32_t* tex_data = new uint32_t[query.m_FrameDims*query.m_FrameDims];
    memset(tex_data,0,sizeof(uint32_t)*query.m_FrameDims*query.m_FrameDims);
    gl::BindTexture(gl::TEXTURE_2D,query.m_DestColorTexture);
    {
        // Copy color texture
        gl::ReadBuffer(gl::COLOR_ATTACHMENT0);
        gl::ReadPixels(0,0,query.m_FrameDims,query.m_FrameDims,
            gl::RGBA,gl::UNSIGNED_BYTE,tex_data);
        gl::TexSubImage2D(gl::TEXTURE_2D,0,0,0,query.m_FrameDims,query.m_FrameDims,
            gl::RGBA,gl::UNSIGNED_BYTE,tex_data);
    }
     
    gl::BindTexture(gl::TEXTURE_2D,query.m_DestClassTexture);
    {
        // Copy class texture
        gl::ReadBuffer(gl::COLOR_ATTACHMENT1);                      
        gl::ReadPixels(0,0,query.m_FrameDims,query.m_FrameDims,
                gl::RED_INTEGER,gl::UNSIGNED_INT,tex_data);
        gl::TexSubImage2D(gl::TEXTURE_2D,0,0,0,query.m_FrameDims,query.m_FrameDims,
                gl::RED_INTEGER,gl::UNSIGNED_INT,tex_data);
    }
     
    delete[] tex_data;

    With no multisampling everything works fine, and the integer texture is filled with correct data, but as soon as I call the glBlitFramebuffer() function the second color attachment (the integer texture) is zeroed.

    I don't see any docs that says that integer texture can note be multisampled, but even though, I'm not sure they make sense at all.

    Hope someone can shed some light on it.

  2. #2
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    782
    Current spec says that LINEAR blit of integer formats results in INVALID_OPERATION (because filtering of integer pixels is undefined.) This was not specified in earlier spec versions (and several implementations report MAX_INTEGER_SAMPLES as zero.)

    So, if you're attempting to do a LINEAR resolve, no, it shouldn't work. If you do a NEAREST resolve it should work, but it will simply throw away all of the samples but one (in which case, why did you bother multisampling in the first place?)

  3. #3
    Junior Member Regular Contributor tksuoran's Avatar
    Join Date
    Mar 2008
    Location
    Cambridge, UK
    Posts
    224
    Quote Originally Posted by arekkusu View Post
    Current spec says that LINEAR blit of integer formats results in INVALID_OPERATION (because filtering of integer pixels is undefined.) This was not specified in earlier spec versions (and several implementations report MAX_INTEGER_SAMPLES as zero.)

    So, if you're attempting to do a LINEAR resolve, no, it shouldn't work. If you do a NEAREST resolve it should work, but it will simply throw away all of the samples but one (in which case, why did you bother multisampling in the first place?)
    That is not what the latest spec says on multisample resolve. When doing multisample resolve, filter is ignored. For integer attachments, a single sample is selected when multisample resolve is performed.

  4. #4
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    782
    Hm, you are correct. Prior to GL4.4 the spec indicated integer formats would simply error with LINEAR. In 4.4 the new language clarifies multisample cases.


    Too bad these issues weren't more carefully specified back in 2006, when EXT_texture_integer, EXT_framebuffer_multisample, EXT_framebuffer_blit were contemporaneously authored.

  5. #5
    Junior Member Newbie
    Join Date
    Sep 2013
    Posts
    3
    Quote Originally Posted by arekkusu View Post
    Current spec says that LINEAR blit of integer formats results in INVALID_OPERATION (because filtering of integer pixels is undefined.) This was not specified in earlier spec versions (and several implementations report MAX_INTEGER_SAMPLES as zero.)
    I'm checking with glGetError() and/or the KHR_debug and I don't get any error.

    Quote Originally Posted by arekkusu View Post
    So, if you're attempting to do a LINEAR resolve, no, it shouldn't work. If you do a NEAREST resolve it should work, but it will simply throw away all of the samples but one (in which case, why did you bother multisampling in the first place?)
    It doesn't work for me on both cases. Although, it would make sense to me getting the nearest values on integer multisample textures, I can always blit the color with the LINEAR option and the indexes with the NEAREST. It would be anyway faster than repaint the entire scene again.

    This is the code I use to blit the framebuffer before downloading textures on CPU.
    Code :
    // Resolve multisampling
    if ( m_Multisample > 0 )
    {
    	gl::BindFramebuffer(gl::READ_FRAMEBUFFER, m_Framebuffers[eFBO_RENDERBUFFER]);
    	gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, m_Framebuffers[eFBO_RESOLVEBUFFER]);
    	gl::BlitFramebuffer(0, 0, m_FrameDims, m_FrameDims, 0, 0, m_FrameDims, m_FrameDims, 
    		gl::COLOR_BUFFER_BIT, gl::NEAREST);
     
    	gl::enum_t blit_error = gl::NO_ERROR_;
    	blit_error = gl::GetError();
    	if ( blit_error != gl::NO_ERROR_ )
    	{
    		throw framebuffer_error(string::format<128>(
    			"BlitFramebuffer failed with error: %d",blit_error));
    	}
     
    	gl::BindFramebuffer(gl::READ_FRAMEBUFFER, m_Framebuffers[eFBO_RESOLVEBUFFER]);
    }

    My context version is 4.3 with nVidia drivers 326.80 and a GeForce660GTX on Windows 7.
    Last edited by Fabio_3Nu; 09-17-2013 at 12:57 AM. Reason: Better formatting code

  6. #6
    Junior Member Newbie
    Join Date
    Sep 2013
    Posts
    3
    So, I have resolved the mistery.

    You can only read from a single color buffer at a time when you do a framebuffer blit; you can write to many draw buffers (technically up to GL_MAX_DRAW_BUFFERS at once). The problem here is that I want to read from two different color buffers, and writing with a single blit.

    OpenGL 4.4 Core Specification - 18.3. Copying Pixels - (pp. 483)

    When the color buffer is transferred, values are taken from the read buffer of the read framebuffer and written to each of the draw buffers of the draw framebuffer.

    The correct way to blit my multisample MRT FBO is:

    Code :
    // Resolve multisampling
    if ( m_Multisample > 0 )
    {
      //
      // Do the first resolve (COLOR_ATTACHMENT0)
      //
      gl::BindFramebuffer(gl::READ_FRAMEBUFFER,m_Framebuffers[eFBO_RENDERBUFFER]);
      gl::ReadBuffer     (gl::COLOR_ATTACHMENT0); // Read:  Attachment 0 (MSAA)
     
      gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER,m_Framebuffers[eFBO_RESOLVEBUFFER]);
      gl::DrawBuffer     (gl::COLOR_ATTACHMENT0); // Write: Attachment 0 (Resolve)
     
      gl::BlitFramebuffer(0, 0, m_FrameDims, m_FrameDims, 0, 0, m_FrameDims,
          m_FrameDims, gl::COLOR_BUFFER_BIT, gl::NEAREST);
     
      //
      // Do the second resolve (COLOR_ATTACHMENT1)
      //
      gl::BindFramebuffer(gl::READ_FRAMEBUFFER,m_Framebuffers[eFBO_RENDERBUFFER]);
      gl::ReadBuffer     (gl::COLOR_ATTACHMENT1); // Read:  Attachment 1 (MSAA)
     
      gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER,m_Framebuffers[eFBO_RESOLVEBUFFER]);
      gl::DrawBuffer     (gl::COLOR_ATTACHMENT1); // Write: Attachment 1 (Resolve)
     
      gl::BlitFramebuffer(0, 0, m_FrameDims, m_FrameDims, 0, 0, m_FrameDims,
          m_FrameDims, gl::COLOR_BUFFER_BIT, gl::NEAREST);
     
      gl::BindFramebuffer(gl::READ_FRAMEBUFFER,m_Framebuffers[eFBO_RESOLVEBUFFER]);
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •