这时候有人问关于OpenGL的视频流纹理文章经常引用.
它说:
要最大化流传输性能,可以使用多个像素缓冲区对象.该图显示同时使用2个PBO; 当纹理源被写入另一个PBO时,glTexSubImage2D()从PBO复制像素数据.
对于第n帧,PBO 1用于glTexSubImage2D(),PBO 2用于获得新的纹理源.对于第n + 1帧,2个像素缓冲区正在切换角色并继续更新纹理.由于异步DMA传输,可以同时执行更新和复制过程.CPU将纹理源更新为PBO,而GPU从其他PBO复制纹理.
它们提供了一个简单的基准程序,允许您在没有PBO的情况下在单个PBO之间循环纹理更新,并且如上所述使用两个PBO.
启用一个PBO时,我看到性能略有改善.但第二个PBO没有真正的区别.
在代码glMapBuffer的PBO之前,它调用glBufferData并将指针设置为NULL.这样做是为了避免同步停顿.
// map the buffer object into client's memory
// Note that glMapBufferARB() causes sync issue.
// If GPU is working with this buffer, glMapBufferARB() will wait(stall)
// for GPU to finish its job. To avoid waiting (stall), you can call
// first glBufferDataARB() with NULL pointer before glMapBufferARB().
// If you do that, the previous data in PBO will be discarded and
// glMapBufferARB() returns a new allocated pointer immediately
// even if GPU is still working with the previous data.
Run Code Online (Sandbox Code Playgroud)
所以,这是我的问题......难道这不会使第二个PBO完全无用吗?只是浪费记忆!
使用两个PBO,纹理数据存储3次.纹理中的1,每个PBO中的一个.
只有一个PBO.有两份数据副本.在glMapBuffer创建新缓冲区的情况下暂时只有第3个,因为现有的缓冲区目前正在对纹理进行DMA处理?
评论似乎表明OpenGL驱动程序内部能够创建第二个缓冲区IF,并且只有在需要时才能避免使管道停滞.正在使用的缓冲区是DMA,我对map的调用产生了一个新的缓冲区供我写入.
该文章的作者似乎比我自己更了解这方面的知识.我完全误解了这一点吗?
回答我自己的问题...但我不会接受它作为答案...(还)。
问题中链接的基准程序存在很多问题。它使用立即模式。它使用过剩!
该程序大部分时间都花在做我们对分析不感兴趣的事情上。主要通过GLUT渲染文本,并在纹理上写入漂亮的条纹。所以我删除了这些功能。
我将纹理结果提高到 8K,并添加了更多PBO 模式。
无 PBO(产生 6fps)
1 个 PBO。孤立的前一个缓冲区。(产生 12.2 fps)。
2 个 PBO。Orpha 之前的缓冲区。(产生 12.2 fps)。
1 个 PBO。不要孤立以前的 PBO(可能的停顿 - 由我自己添加。产生 12.4 fps)。
2 个 PBO。不要孤立以前的 PBO(可能的停顿 - 由我自己添加。产生 12.4 fps)。
如果其他人想检查我的代码,可以在这里找到
我尝试过不同的纹理大小...以及不同的 updatePixels 函数...尽管我尽了最大努力,但我还是无法让双 PBO 实现比单 PBO 实现更好。
此外...不孤立以前的缓冲区,实际上会产生更好的性能。与文章声称的完全相反。
也许现代驱动程序/硬件不会遇到此设计试图解决的问题......
也许我的图形硬件/驱动程序有问题,并且没有利用双 PBO...
也许经常引用的文章是完全错误的?
谁知道。。。。我的测试硬件是 Intel(R) HD Graphics 5500 (Broadwell GT2)。
编辑:许多年后,在 @Heiner 评论说集成不是一个好的测试,因为它与 CPU 共享 RAM 后,我在新硬件(独立 GPU)上重复了这个测试。
新硬件是 AMD Radeon RX 6800M (Navi22)。
所以...是的,在独立 GPU 上,我能够使用第二个 PBO 观察到 0.4% 的帧速率提升...然而,PBO 性能的最大提升是孤立以前的缓冲区 (2%)。