使用PBO实现异步的glReadPixels

8

我想使用两个PBO以交替方式读取像素。我认为使用PBO的方式会更快,因为使用PBO时glReadPixels会立即返回,并且可以重叠很多时间。

奇怪的是似乎没有太多好处。考虑以下代码:

    glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
    Timer t; t.start();
    glReadPixels(0,0,1024,1024,GL_RGBA, GL_UNSIGNED_BYTE, buf);
    t.stop(); std::cout << t.getElapsedTimeInMilliSec() << " ";

    glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo);
    t.start();
    glReadPixels(0,0,1024,1024,GL_RGBA, GL_UNSIGNED_BYTE, 0);
    t.stop(); std::cout << t.getElapsedTimeInMilliSec() << std::endl;

结果是:
1.301 1.185
1.294 1.19
1.28 1.191
1.341 1.254
1.327 1.201
1.304 1.19
1.352 1.235

PBO的方式会稍微快一些,但是即时返回效果并不理想。

我的问题是:

  • 影响glReadPixels性能的因素是什么?有时候它的成本达到了10毫秒,但是这里只有1.3毫秒。
  • 为什么即时返回花费了1.2毫秒?这太大了还是正常的?

===========================================================================

通过与演示进行比较,我发现两个因素:

  • GL_BGRA优于GL_RGBA,1.3毫秒=>1.0毫秒(没有PBO),1.2毫秒=>0.9毫秒(使用PBO)
  • glutInitDisplayMode(GLUT_RGB|GLUT_ALPHA)而不是GLUT_RGBA,0.9毫秒=>0.01毫秒。这就是我想要的性能。在我的系统中,GLUT_RGBA=GLUT_RGB=0。GLUT_ALPHA=8

然后又有两个问题:

  • 为什么GL_BGRA优于GL_RGBA?这只是特定平台还是所有平台都适用?
  • 为什么GLUT_ALPHA如此重要,以至于它会极大地影响PBO的性能?

我刚在我的系统上测试了一下 GLUT_RGBA 330 fps GLUT_RGB|GLUT_ALPHA 630fps 这增加了2倍,我错过了GLUT_ALPHA很重要的因素。 - ColacX
对我而言,在macOS上,我必须确保我的缓冲区大小是2的幂次方!否则,使用PBO的glReadPixels会被阻塞。 - Luke
2个回答

6
我不熟悉glutInitDisplayMode,但通常是因为内部和外部格式不匹配。例如,当组件数量不匹配时,您将不会注意到异步行为,因为此转换仍会阻止glReadPixels。所以最可能的问题是,使用glutInitDisplay(GLUT_RGBA)实际上会创建一个默认帧缓冲区,其内部格式实际上是RGB或甚至是BGR。传递GLUT_ALPHA参数可能会使其在内部成为RGBABGRA,与您想要的组件数匹配。编辑:我找到了一个nvidia文档,解释了一些有关像素打包和性能影响的问题。编辑2:使用BGRA的性能增益很可能是因为内部hw缓冲区是BGRA,没有太多其他的原因。

如果您读取DEPTH_COMPONENT而不是RGBA,您能否获得异步的glReadPixels()?因为当使用PBO时,我无法立即获得glReadPixels的返回。 - Bram

3

BGRA是最快的,因为它是现代GPU的本地格式。RGBA、RGB和BGR在读取时需要进行“重新格式化”。


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