glReadPixels OR glGetTexImage crash application

Using an FBO with two color attachments and a depth texture attachment, I can’t seem to read back the data from one of the color textures without crashing the application. This happens when I try to use either glReadPixels when the FBO is bound, or glGetTexImage on the texture directly.

I’ve checked the size of the texture, which seems to the be size I’d expect and I’ve also tried significantly expanding the allocated memory I’ve read into, which I’ve checked to make sure is correctly being allocated. I’ve also read that glReadPixels and glGetTexImage are affected by previous bind calls (I’m using VBOs, too) where it turns the pointer into an offset, so I tried to make sure I’m setting everything back to 0. Still either read function crashes.

I know the texture is getting the correct data. If I render my scene to the FBO and then render the texture to the screen, I get what I’d expect. Are there any other debugging tips I can use for working this out?

Looking at this example, it seems glReadPixels works without problem, so I don’t know if it’s my texture setup, messed up state, or something else.

http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial.html

Here’s my code to setup the FBO, which works for rendering to the color attachments.


    glGenFramebuffersEXT(1, &_fbo);
    glGenTextures(1, &_beautyTexture);
    glGenTextures(1, &_indexTexture);
    glGenTextures(1, &_depthTexture);

    glBindFramebufferEXT(GL_FRAMEBUFFER, _fbo);

    // setup beauty texture
    glBindTexture(GL_TEXTURE_2D, _beautyTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, _beautyTexture, 0);

    // setup index texture
    glBindTexture(GL_TEXTURE_2D, _indexTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _indexTexture, 0);

    // setup depth texture
    glBindTexture( GL_TEXTURE_2D, _depthTexture);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, _depthTexture, 0);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, _depthTexture, 0);

    glBindTexture( GL_TEXTURE_2D, 0);

    switch (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) {
    case GL_FRAMEBUFFER_COMPLETE_EXT:
        break;
    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
        std::cerr << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" << std::endl;
        break;
    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
        std::cerr << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" << std::endl;
        break;
    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
        std::cerr << "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" << std::endl;
        break;
    case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
        std::cerr << "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" << std::endl;
        break;
    case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
        std::cerr << "GL_FRAMEBUFFER_UNSUPPORTED_EXT" << std::endl;
        break;
    }

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

And here’s the code where I try to read back the data after I render out the scene.


        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        GLuint* ack = new GLuint(width()*height()*4*4);
        //glBindTexture(GL_TEXTURE_2D, _beautyTexture);
        GLint val;
        glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &val);
        std::cout << "Texture width: " << val << std::endl;
        glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &val);
        std::cout << "Texture height: " << val << std::endl;
        std::cout << width() << std::endl;
        std::cout << height() << std::endl;
        //glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, ack);
        glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
        glReadPixels(0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_BYTE, ack);

        //glReadPixels(0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_INT, _selectionBuffer.data());

        delete ack;
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

Do you have a buffer object bound to PIXEL_PACK_BUFFER? If so it will be reading into that buffer (likely at a huge offset) instead of into client memory.
Try:


  glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

I don’t actually do anything iwth PIXEL_PACK_BUFFER anywhere in my code. Adding that code in just in case still crashes my app.

I’m not fluent in c/c++, but looking at new and delete (C++) - Wikipedia should:


GLuint* ack = new GLuint(width()*height()*4*4);

be


GLuint* ack = new GLuint[width()*height()*4*4];

Also, use delete[] when you use new[].

That indeed was my problem.