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 10 of 10

Thread: Framebuffer outputs black on resize

  1. #1
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    9

    Framebuffer outputs black on resize

    Hi, I`m trying to resize my framebuffer which uses Multisample Textures with 4 samples.
    When I call my resize method, the framebuffer just outputs a black color.

    Here is my resize method:

    Code :
        GL.DeleteFramebuffer(id);
        foreach (GLXTexture texture in colorAttachments)
        {
            texture.Resize(width, height, 0);
         }
         if (depthAttachment != null)
         {
              depthAttachment.Resize(width, height, 0);
         }
         if (stencilAttachment != null)
         {
              stencilAttachment.Resize(width, height, 0);
         }
         id = GL.GenFramebuffer();
         Create(colorAttachments, depthAttachment, stencilAttachment);

    You can see a "Create" method at the bottom. I can include the source code but it is working fine, because if I dont use "Resize" on a Texture, the framebuffer renders ok. It then renders to a texture, which is not the same size and, because of this, distorted.

    The interesting stuff happens in the Textures "Resize" method. If I use any openGL texture operations like "GL.BindTexture" and "GL.TexImage2DMultisample" in my case, the output is turns black. No error is generated.

    Here is the code (INFO: IsMutable is true, which means that I`m using GL.TexImage2DMultisample):
    Code :
            public override void Resize(int width, int height, int depth)
            {
                if (!IsReserved)
                {
                    throw new NotSupportedException("This texture has to be created before resizing!");
                }
                if (width == 0 || height == 0)
                {
                    throw new NotSupportedException("You can`t resize this image to 0 width or height!");
                }
                this.width = width;
                this.height = height;
                if (!IsMutable) // If the texture is not mutable it has to be destroyed completely
                {
                    Destroy();
                    ReserveTextureID();
                }
                GL.BindTexture(TextureTarget.Texture2DMultisample, id);
                if (IsMutable)
                {
                    // TexTarget is GL_TEXTURE_2D_MULTISAMPLE in this class
                    GL.TexImage2DMultisample((TextureTargetMultisample)TexTarget, samples, internalFormat, width, height, fixedSampleLocations);
                }
                else
                {
                    GL.TexStorage2DMultisample((TextureTargetMultisample2d)TexTarget, samples, (SizedInternalFormat)internalFormat, width, height, fixedSampleLocations);
                }
                //ApplyOptions(IsMutable); Dont apply any options to a 2D Multisample Texture
                GetError(false); // Print errors 
                GL.BindTexture(TextureTarget.Texture2DMultisample, 0);
            }

    Here is the desired output, which I get if I dont resize the screen. (Only these Gray blocks)
    Click image for larger version. 

Name:	des.jpg 
Views:	30 
Size:	12.0 KB 
ID:	2468

    After window resize:
    Click image for larger version. 

Name:	des.jpg 
Views:	29 
Size:	6.2 KB 
ID:	2466

    And here I have removed the GL.BindTexture and GL.TexImage2DMultisample lines and then resized the window:
    Click image for larger version. 

Name:	des.jpg 
Views:	30 
Size:	9.8 KB 
ID:	2467


    I tried this with Multisampled 2D Textures and only 2D Textures, both have the same effect.

    Additional informations:
    - The openGL context which created the textures and framebuffer is bound properly in the resize method.
    - I`m using multiple draw buffers from GL_COLOR_ATTACHMENT0 to 3 which are bound using glDrawBuffers
    - There is no Framebuffer error generated
    - This PC has Intel(R) HD Graphics | Driver Version 9.17.10.2884

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,176
    Are you checking for GL errors? Do you see any?

    You don't actually show many of the GL calls you're making here. Showing a bit about how you're doing the downsample might help.

    When I first saw your problem, I suspected you might be trying to downsample and resize your MSAA render target with one glBlitFramebuffer call (which you can't do; you have to use two). However, you didn't show this code so you might check that.

  3. #3
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    9
    Quote Originally Posted by Dark Photon View Post
    Are you checking for GL errors? Do you see any?
    No errors =/

    Quote Originally Posted by Dark Photon View Post
    You don't actually show many of the GL calls you're making here. Showing a bit about how you're doing the downsample might help.
    I`m doing downsampling using a shader.
    Code :
        void main(){
             vec4 color = vec4(0.0);
             ivec2 coords = ivec2(texCoords.x * samplerResolution.x, samplerResolution.y - texCoords.y * samplerResolution.y);
             for(int i = 0; i < 4; i++)
             color += texelFetch(finalImage, coords, i);
             fragColor = color / samples;
         }

    But this should`nt be the problem, because it works before I resize.

    Here is the complete resizing procedure captured by GLIntercept:

    Code :
    //Begin Resize (width = 710, height = 307)
    glIsFramebuffer(1)=true 
    glDeleteFramebuffers(1,108FF014)
     
    // For each Texture: Resize(710, 307, 0); // 0 is ignored
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,4)
    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,4,34837,710,307,true)
    glGetError()=GL_NO_ERROR 
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,0)
     
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,5)
    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,4,33323,710,307,true)
    glGetError()=GL_NO_ERROR 
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,0)
     
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,3)
    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,4,32856,710,307,true)
    glGetError()=GL_NO_ERROR 
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,0)
     
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,6)
    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,4,34843,710,307,true)
    glGetError()=GL_NO_ERROR 
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,0)
     
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,7)
    glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,4,35056,710,307,true)
    glGetError()=GL_NO_ERROR 
    glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,0)
     
    // Continue with the framebuffer creation
    glGenFramebuffers(1,108FF014)
    glBindFramebuffer(GL_FRAMEBUFFER,1)
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D_MULTISAMPLE,4,0)
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,GL_TEXTURE_2D_MULTISAMPLE,5,0)
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT2,GL_TEXTURE_2D_MULTISAMPLE,3,0)
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT3,GL_TEXTURE_2D_MULTISAMPLE,6,0)
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_TEXTURE_2D_MULTISAMPLE,7,0)
    glDrawBuffers(4,02A150A8)
    glCheckFramebufferStatus(GL_FRAMEBUFFER)=GL_FRAMEBUFFER_COMPLETE

    Thanks in advance for any hint!

  4. #4
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,176
    As a test, try setting the GL_TEXTURE_MIN_FILTER on all of your textures to GL_NEAREST.

  5. #5
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    9
    Quote Originally Posted by Dark Photon View Post
    As a test, try setting the GL_TEXTURE_MIN_FILTER on all of your textures to GL_NEAREST.
    This generates the error: 1280-'InvalidEnum'
    I`m using GL_TEXTURE_2D_MULTISAMPLE as Target.

    I found this on the khronos`OpenGL documentation(https://www.khronos.org/registry/Ope...tisample.txt):

    (2) What commands may be used on multisample textures?

    RESOLVED: Multisample textures can be bound for rendering and texturing,
    but they cannot be loaded/read with SubImage commands (TexSubImage,
    CopyTexSubImage, GetTexImage), they don't support compressed formats,
    and they don't need TexParameters since they can only be fetched with
    texelFetchMultisample.

    The screen is still black after resizing =/ Nothing changed even with the generated error.

    #EDIT

    I also tried to detach the textures from the framebuffer using:
    Code :
    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + i, texture.TexTarget, 0, 0);

    But still the same error.
    Also, what may be interesting: if I delete the framebuffer after resizing any textures, It causes an AccessViolationException. This means that I`m writing to protected memory.
    Is this normal behavior? I have to delete the framebuffer before resizing textures to avoid the exception.

    Thanks in advance!
    Last edited by McStones; 08-31-2017 at 02:14 AM.

  6. #6
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,176
    Quote Originally Posted by McStones View Post
    This generates the error: 1280-'InvalidEnum'
    I`m using GL_TEXTURE_2D_MULTISAMPLE as Target.
    Sorry about that. That error makes sense. I guess I was remembering having issues when using 2D textures with render-to-texture, not 2D MSAA textures, and needing to reset the MIN_FILTER so that it wouldn't try to access MIPmap levels that didn't exist. That's not an issue for MSAA textures.

    Also, what may be interesting: if I delete the framebuffer after resizing any textures, It causes an AccessViolationException. This means that I`m writing to protected memory.
    Is this normal behavior? I have to delete the framebuffer before resizing textures to avoid the exception.
    No, it's not normal. That indicates either 1) a bug in your code, and/or 2) a bug in your GL drivers.

    At this point, I'd suggest you post a short, stand-alone GLUT text program that illustrates your problem. With that, folks here can build/run it, skim it, and give you feedback both on what you're doing as well as if/how it works on various GPUs and drivers.

    Here's a shell to copy/paste your code into:

    Code cpp:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <GL/glew.h>
    #include <GL/glut.h>
     
    void checkGLError( const char hdr[] )
    {
      int err = glGetError();
      if( err )
      {
        fprintf(stderr, "ERROR %s: %s\n", hdr, gluErrorString(err));
        exit(1);
      }
    }
     
    void reshape(GLsizei w, GLsizei h)
    {
      glViewport(0, 0, w, h);
      glutPostRedisplay();
    }
     
    void keyboard( unsigned char key, int x, int y )
    {
      // Key Bindings
      switch( key )
      {
        case 27 : exit(0);                    break;
      }
    }
     
    void display()
    {
      glClearColor( 0,0,1,1 );
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
      glutSwapBuffers();
      checkGLError( "display() end" );
    }
     
    main( int argc, char *argv[] )
    {
      glutInit( &argc, argv );
      glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB ); 
      glutCreateWindow( "window title" );
      checkGLError( "Create window" );
     
      glutReshapeFunc ( reshape  );
      glutDisplayFunc ( display  );
      glutKeyboardFunc( keyboard );
     
      glutPostRedisplay();
      glutMainLoop();
    }
    Last edited by Dark Photon; 08-31-2017 at 06:23 AM.

  7. #7
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    9
    Quote Originally Posted by Dark Photon View Post
    Sorry about that. That error makes sense. I guess I was remembering having issues when using 2D textures with render-to-texture, not 2D MSAA textures, and needing to reset the MIN_FILTER so that it wouldn't try to access MIPmap levels that didn't exist. That's not an issue for MSAA textures.



    No, it's not normal. That indicates either 1) a bug in your code, and/or 2) a bug in your GL drivers.
    Hello Dark Photon, thanks for these hints and sorry, I was very busy, this is why I can answer only today.

    I recently solved this issue. The problem was, that I tried to delete the framebuffer and resize the textures while one of these textures was still bound.

    In my post processing unit, I`m using the latest framebuffer color result and bind it for MSAA resolving. But I dont unbind it... I've had some luck, because the resizing code gets executed right after the post processing and swap buffers, so I know there are no other texture binds. I could have run into the same issue some day and throw my hands up in horror, when it gets more complex.


    Does it make sense to unbind all framebuffer targets before deleting the actual framebuffer?
    Well, this is what makes it work for me.

  8. #8
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,176
    Quote Originally Posted by McStones View Post
    Hello Dark Photon, thanks for these hints and sorry, I was very busy, this is why I can answer only today.

    I recently solved this issue. The problem was, that I tried to delete the framebuffer and resize the textures while one of these textures was still bound.
    No problem. I understand. Thanks for following up.

    If we assume that the driver operates per-spec, I don't immediately see how your solution fixes the problem though. Could be you've hit a driver bug.

    If you still have the version of your app that produces the artifact, it would be interesting to add a glFinish() right before you do all the FBO deletes and texture resizes to see if that magically fixes the artifact. If not, then try binding 0 for the active FBO and 0 to all the texture units and see if that fixes it. Could be the driver isn't properly synchronizing when you start making changes to a texture or FBO that it's currently using in the pipe.

    Does it make sense to unbind all framebuffer targets before deleting the actual framebuffer?
    I think it makes sense to do sufficient resource tracking to ensure you don't lose track of resources. However, it's not necessary to unbind textures from texture units before you delete the containing framebuffer.

    Now if you have any internal state tracking that keeps track of your last bound texture(s) and you delete a texture that is bound, you need to make sure you update your state. However, you still don't need to manually unbind textures from texture units.

    I also think it probably makes sense to: after you've rendered to or with a texture, don't resize the texture by just binding it and changing the format/size. Instead, just delete the texture, and recreate it from scratch. That should make it harder to hit strange driver bugs with changing the format of resources that are already in-flight. I could see where implementing that change might have fixed your problem.

  9. #9
    Junior Member Newbie
    Join Date
    Aug 2017
    Posts
    9
    Quote Originally Posted by Dark Photon View Post
    If you still have the version of your app that produces the artifact, it would be interesting to add a glFinish() right before you do all the FBO deletes and texture resizes to see if that magically fixes the artifact. If not, then try binding 0 for the active FBO and 0 to all the texture units and see if that fixes it. Could be the driver isn't properly synchronizing when you start making changes to a texture or FBO that it's currently using in the pipe.
    Yes, I can reproduce the problem simply by removing the line, where I unbind a framebuffer texture before resizing. I tried the to use glFinish() but this did not work... Also deleting all textures and recreating them does not work. It only works if I unbind the textures before deleting the framebuffer in the resize process...
    But at least it works with unbinding the textures. So I have a way of working around this.

    Thanks!

  10. #10
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,176
    Thanks for the follow-up! That's interesting. It sounds like your driver may have some problems tracking and synchronizing changes to GL objects.

Tags for this Thread

Posting Permissions

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