2

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'?

Yun
  • 3,056
  • 6
  • 9
  • 28
testman
  • 248
  • 3
  • 14

2 Answers2

4

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.

Bahbar
  • 17,760
  • 43
  • 62
  • 1
    Is there a possibility to determine if the read has finished? – testman Nov 30 '15 at 21:20
  • Thanks, so i could use glClientWaitSync or glWaitSync instructions. Is my application client or server to the GL and what would i use as the sync parameter? – testman Nov 30 '15 at 21:30
2

To add on to Bahbar's answer:

  • After glReadPixels, if you plan on reading back the data, I believe you should call glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);.

  • After glReadPixels and glMemoryBarrier, you can create a Fence Sync with glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0), then either check that the GPU has finished executing all instructions before the sync with glGetSynciv(fence_sync, GL_SYNC_STATUS, sizeof(GLint), NULL, &result), or wait for GPU to finish executing all instructions before the sync with glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, nanosecond_timeout).

serg06
  • 2,027
  • 1
  • 18
  • 26