从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);
但这是如何异步的呢?是glReadPixels或glMapBufferRange阻止应用程序,直到GPU“准备好”吗?
2条答案
按热度按时间hxzsmxv21#
glReadPixels
调用应该开始复制到一个cpu可见的缓冲区。(每当它被提交到GPU时。你可以用glFlush
强制提交)。你正在异步地开始读取。glMapBufferRange
将强制glReadPixels
调用完成(因为您现在访问的是CPU上的指针,所以没有办法)。所以......不要连续做两次,而要明显晚一点。
1yjd4xko2#
在Bahbar的回答中补充一点:
glReadPixels
之后,如果您打算阅读回数据,我认为您应该调用glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
。glReadPixels
和glMemoryBarrier
之后,您可以使用glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)
创建围栏同步,然后在与glGetSynciv(fence_sync, GL_SYNC_STATUS, sizeof(GLint), NULL, &result)
同步之前检查GPU是否已完成执行所有指令,或者在与glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, nanosecond_timeout)
同步之前等待GPU完成执行所有指令。