使用多个PBO异步从OpenGL前缓冲区读取数据

5
我正在开发一个应用程序,需要从OpenGL应用程序的前缓冲区中读取整个帧。我可以劫持应用程序的OpenGL库,并在swapbuffers上插入我的代码。目前,我成功地使用了一个简单但极其缓慢的glReadPixels命令而没有使用PBO。
现在我了解到使用多个PBO可以加速处理速度。虽然我认为我已经找到足够的资源来实际编程(不是很难),但我还有一些操作问题。我会做如下步骤:
1.创建一系列(例如3个)PBO;
2.在我的swapBuffers覆盖中使用glReadPixels将数据从前缓冲区读取到PBO中(应该快速且非阻塞,对吗?);
3.创建一个单独的线程调用glMapBufferARB,在每个PBO上执行一次glReadPixels之后,因为这会阻止像素进入客户端内存;
4.处理第3步中的数据。
现在我的主要关注点当然是步骤2和步骤3。我了解到在PBO上使用glReadPixels是非阻塞的,如果我在此之后立即发出新的OpenGL命令,这会成为一个问题吗?那些OpenGL命令会阻塞吗?还是它们会继续执行(我猜是这样),如果是这样,我猜只有swapbuffers可能会成为一个问题,这个命令会停止还是glReadPixels从前缓冲区读取数据的速度要快得多(每15->30ms),或者最坏的情况是在glReadPixels仍然在将数据读取到PBO时执行swapbuffers?我的当前猜测是这个逻辑将执行以下操作:将FRONT_BUFFER复制到VRAM的通用位置,将VRAM->RAM复制。但我不知道这两者哪一个是真正的瓶颈以及对正常OpenGL命令流的影响。
然后,在第3步中,将它异步地放在与正常OpenGL逻辑分开的线程中是否明智?目前我认为不是,因为似乎在执行此操作后必须将缓冲区操作恢复为正常状态,而我无法在原始代码中安装同步对象来暂时阻塞它们。所以,我认为最好的选择是在读取它们之前定义一定的swapbuffer延迟,例如在同一线程中调用PBO i%3上的glReadPixels和PBO(i + 2)%3上的glMapBufferARB,从而导致2帧的延迟。此外,当我调用glMapBufferARB使用客户端内存中的数据时,这是否是瓶颈,还是glReadPixels(异步)是瓶颈?
最后,如果您有更好的想法来加速从OpenGL中读取帧,请告诉我,因为这是我当前系统中痛苦的瓶颈。

我希望我的问题足够清晰,我知道答案可能也可以在互联网上找到,但我大多数都是得到使用PBO将缓冲区保留在视频内存中并在那里进行处理的结果。我真的需要将前端缓冲区读回RAM,并且我没有找到关于在这种情况下性能的清晰解释(我需要这个,我不能依赖“它更快”,我需要解释为什么它更快)。

谢谢

1个回答

4

您确定要从前缓冲区读取吗?您没有拥有此缓冲区,根据您的操作系统,它可能会被销毁,例如,被另一个在其上方的窗口所覆盖。

针对您的用例,人们通常会执行以下操作:

  • 绘制N
  • 从后缓冲区开始PBO读取N
  • 绘制N+1
  • 从后缓冲区开始PBO读取N+1
  • 同步PBO读取N
  • 处理N
  • ...

以上操作都应该在单个线程中执行。


我知道我想要从前缓冲区读取(或在调用之前从后缓冲区读取),这实际上并不是问题所在。你的答案帮助了我关于线程的问题,这其实我已经有点怀疑了。但我真的很想知道当你这样做时GPU屏幕后面发生了什么,什么被阻塞了,什么没有被阻塞,尝试使用超过两个PBO是否合理等等。无论如何,感谢你的回答 :)! - KillianDS
1
使用后备缓冲区是更好的选择。幕后发生的事情取决于驱动程序。通常,异步读取会被发布到GPU fifo中,在GPU按顺序处理时进行处理。完成后,GPU将发送一个令牌告诉驱动程序操作已完成 - 这将取消阻止mapBuffers。对于任何更具体的内容,您需要与nVidia / AMD工程师交谈。根据您想要有多少帧“在飞行”可能有意义使用超过两个缓冲区。只需实现可配置,并进行基准测试即可。 - eile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接