openglbuffer-objects

Reading data from the GPU asynchronously with Pixel Buffer Objects


Getting data from the GPU seems to be a very slow task if you want to read it synchronized with the rest of your application. One possibility is to read asynchronously with the help of Pixel Buffer Objects. Unfortunately, I am not able to see how this is done.

First, I create a Pixel Buffer Object:

glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, pbo_size, 0, GL_DYNAMIC_READ);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

Then I want to read pixels from a Frame Buffer Object:

glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, 0);
GLfloat *ptr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pbo_size, GL_MAP_READ_BIT);
memcpy(pixels, ptr, pbo_size);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

But how is this asynchronous? Is glReadPixels or glMapBufferRange blocking the application until the GPU is 'ready'?


Solution

  • The glReadPixels call should start the copy to a cpu-visible buffer. (whenever it gets submitted to the GPU. You can force the submission with glFlush). You're starting the read asynchronously.

    glMapBufferRange will force the glReadPixels call to finish if it wasn't (since you're now accessing the pointer on the CPU, there's no way around that).

    So... don't do the 2 back-to-back, but rather significantly later.