当有人询问 OpenGL 中的视频流纹理时,通常会参考这篇文章。
它说:
为了最大限度地提高流传输性能,您可以使用多个像素缓冲区对象。该图显示同时使用了 2 个 PBO;glTexSubImage2D() 从一个 PBO 复制像素数据,同时将纹理源写入另一个 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.
所以,这是我的问题……这不是让第二个 PBO 完全没用吗?只是浪费内存!?
使用两个 PBO,纹理数据存储 3 次。纹理中有 1 个,每个 PBO 中有 1 个。
使用单个 PBO。数据有两个副本。如果glMapBuffer创建一个新的缓冲区,因为现有的缓冲区目前正在被DMA到纹理中,暂时只有第三个?
评论似乎表明 OpenGL 驱动程序内部能够创建第二个缓冲区 IF 并且仅在需要避免停止管道时才创建。正在使用的缓冲区正在被 DMA 处理,我对 map 的调用会产生一个新的缓冲区供我写入。
那篇文章的作者在这方面的知识似乎比我自己还要多。我完全误解了这一点吗?