2

如果我调用glDrawElements绘制目标作为后台缓冲区,然后调用glReadPixels,是否保证我会读取绘制的内容?

换句话说,是glDrawElements阻塞调用吗?

注意:我在这里观察到一个奇怪的问题,可能是由于glDrawElements没有被阻塞引起的......

4

1 回答 1

8

换句话说, glDrawElements 是阻塞调用吗?

这不是 OpenGL 的工作方式。

OpenGL 内存模型建立在“好像”规则之上。除了某些例外,OpenGL 中的所有内容都会您发出的所有命令都已完成一样运行。实际上,一切都会像每个命令在完成之前都被阻塞一样工作。

但是,这并不意味着 OpenGL 实现实际上是这样工作的。它只需要尽一切努力使其看起来以这种方式工作。

因此,glDrawElements一般不是阻塞调用;但是,glReadPixels(当读取客户端内存时)一个阻塞调用。因为直接传输到客户端内存的像素传输结果必须在返回时可用glReadPixels,所以实现必须检查是否有任何未完成的渲染命令进入正在读取的帧缓冲区。如果有,那么它必须阻塞,直到那些渲染命令完成。然后它可以执行读取并将数据存储在您的客户端内存中。

如果您正在读取缓冲区对象,则无需glReadPixels阻塞。该函数不会修改客户端可访问的内存,因为您正在读取缓冲区对象。因此驱动程序可以异步发出回读。但是,如果您发出一些依赖于此缓冲区内容的命令(例如映射它以供读取或使用glGetBufferSubData),则 OpenGL 实现必须停止直到读取操作完成。

简而言之,OpenGL 尝试尽可能长时间地延迟阻塞。为了确保性能,你的工作是帮助OpenGL 做到这一点,除非绝对必要,否则不要强制进行隐式同步。同步对象可以帮助解决这个问题。

于 2013-03-01T04:23:42.387 回答