使用像素缓冲区对象从 gpu 异步读取数据

Posted

技术标签:

【中文标题】使用像素缓冲区对象从 gpu 异步读取数据【英文标题】:Reading data from gpu asynchronously with Pixel Buffer Objects 【发布时间】:2015-11-30 21:11:04 【问题描述】:

如果您想与您的应用程序同步读取数据,从 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 '准备好'?

【问题讨论】:

【参考方案1】:

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

glMapBufferRange 将强制 glReadPixels 调用完成,如果不是(因为您现在正在访问 CPU 上的指针,所以没有办法解决这个问题)。

所以...不要背靠背进行 2 次,而是更晚进行。

【讨论】:

是否有可能判断读取是否完成? 谢谢,所以我可以使用 glClientWaitSync 或 glWaitSync 指令。我的应用程序客户端或服务器是 GL 的吗?我将使用什么作为同步参数?【参考方案2】:

补充巴巴尔的回答:

glReadPixels之后,如果你打算读回数据,我相信你应该打电话给glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);

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

【讨论】:

以上是关于使用像素缓冲区对象从 gpu 异步读取数据的主要内容,如果未能解决你的问题,请参考以下文章

WebGL - 从渲染缓冲区读取像素数据

将 WebGL 2 中的像素读取为浮点值

读取 WebGLTexture 中的像素(将 WebGL 渲染到纹理)

angular读取文件

OpenGL ES 学习教程(十五) 从 颜色缓冲区(FBO的颜色附着)中 读取颜色数据 保存到图片(FreeImage)

WebGL:读取缓冲区对象的内容?