与像素缓冲区对象异步从GPU读取数据



如果您想与应用程序的其他部分同步读取数据,那么从GPU获取数据似乎是一项非常缓慢的任务。一种可能性是在像素缓冲区对象的帮助下异步读取。不幸的是,我不知道这是怎么做到的。

首先,我创建了一个像素缓冲区对象:

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);

然后我想从帧缓冲区对象读取像素:

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);

但这是如何异步的呢?在GPU"准备就绪"之前,glReadPixels或glMapBufferRange是否会阻止应用程序?

glReadPixels调用应该启动到cpu可见缓冲区的复制。(无论何时提交到GPU。您可以使用glFlush强制提交)。您正在异步启动读取。

glMapBufferRange将强制glReadPixels调用完成(因为您现在正在访问CPU上的指针,所以没有办法绕过它)。

所以。。。不要背靠背进行2次,而是要晚一点。

添加到Bahbar的答案:

  • glReadPixels之后,如果您计划读回数据,我认为您应该致电glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);

  • glReadPixelsglMemoryBarrier之后,您可以创建与glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)的围栏同步,然后检查GPU在与glGetSynciv(fence_sync, GL_SYNC_STATUS, sizeof(GLint), NULL, &result)同步之前是否已完成所有指令的执行,或者等待GPU在与glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, nanosecond_timeout)同步之前完成所有指令。

最新更新