即使我刚刚交换了缓冲区,在1个单个像素上使用glReadPixels也会使管道停滞。
我不需要同步,我可以做这样的事情:
pixel=DEFAULT_VALUE;
while (1){
draw(pixel);
swapBuffers();
pixel=glRead???;
}
如何以一种优化的方式(而不是停顿)来做到这一点?
最佳答案
您可以通过Pixel Buffer Objects (PBOs)异步像素传输。当您发出不带PBO的读取调用时,流水线将被刷新,CPU必须等待GPU完成渲染和传输数据。使用PBO,您需要事先提供一个缓冲区,并且在GPU准备就绪时,数据将被复制到该缓冲区中,因此不会停止。当您尝试在未准备好访问该缓冲区时(例如通过glGetBufferSubData()
或映射该缓冲区以进行读取等),它当然会停顿。因此,理想情况下,在回读数据之前,您可以先排队其他一些渲染命令,然后再执行其他一些CPU工作,然后再访问缓冲区。我链接的扩展规范中有一个示例部分,这很有趣。
这些东西也可以与sync objects结合使用。在这种情况下,您可以在读取调用之后添加篱笆同步,这会将数据复制到PBO中。然后,您实际上可以在CPU上检查操作是否已经完成。如果没有,您可以做一些其他工作然后再检查。
所有这些异步传输的主要问题是您将吞吐量与延迟进行了交换。因此,如果您立即需要该像素值,并且在GPU和CPU之间没有其他可完成的工作,则没有太多收获。这样,您就无法真正避免停滞。