Clearing an INTEGER framebuffer

I’m implementing picking by rendering integer IDs into a framebuffer (FBO). As the buffer format, I’m using GL_RGBA32UI, which is an INTEGER format. My shaders correctly write the integer IDs into the buffer and I can read them back with glReadPixels. However, the problem is clearing the buffer with non-zero integer numbers using glClearBuffer. When I clear with 1, I would expect to read back 1. On NVIDIA cards clearing works as expected. However, on AMD, when I clear with 1, I read back 1065353216. Interestingly, bit-wise speaking 1065353216 INT corresponds to 1.0 FLOAT.

In any case, when I clear a buffer with 1 INT, I expect to read back 1 INT (and neither 1065353216 INT nor 1.0 FLOAT).

  1. What is the correct way to clear an integer framebuffer?
  2. Is the behavior on AMD cards a driver problem?

A corresponding test case is below. Tests have been made on Windows 7 and Ubuntu 12.10. It works correctly on NVIDIA, but fails on AMD.


#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut.h>

GLuint fbo = 0;

void Display()
{
    // Clear buffer
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    GLuint in[4] = {0, 1, 2, 3};
    glClearBufferuiv(GL_COLOR, 0, in);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

    // Read back from the buffer, expect to find the same values as used for clearing
    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
    unsigned int out[4] = {0, 0, 0, 0};
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &out);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

    printf("IN  %d %d %d %d
", in[0], in[1], in[2], in[3]);
    printf("OUT %d %d %d %d
", out[0], out[1], out[2], out[3]);

    glutSwapBuffers();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
    glutInitWindowSize(1024, 768);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("OpenGL");
    glutDisplayFunc(Display);

    GLenum status = glewInit();
    if (status != GLEW_OK) {
        printf("Error: %s
", glewGetErrorString(status));
        return EXIT_FAILURE;
    }

    // Create the FBO
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    GLuint tex = 0;

    // Create a texture object for the picking buffer
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1024, 768, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, NULL);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);

    // Create a texture object for the depth buffer
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 768, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex, 0);

    // Verify that the FBO is correct
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        printf("Error: status 0x%x
", status);
        return EXIT_FAILURE;
    }

    // Restore the default framebuffer
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glutMainLoop();
    
    return 0;
}

I am facing the same issue with AMD, when i clearcolor with integer texture fbo, everytime i get color values of max intensity. I am implementing render to texture and not using readpixels. I think that is probably a bug.

I have had several issues with the AMD driver - you may need to clear it with your own shader.

Thanks for the comments and suggestions.

So it appears there is a BUG on AMD when clearing and integerbuffer using glClearBuffer. Hopefully AMD recognizes this problem soon and corrects it.