【发布时间】:2018-11-09 08:47:18
【问题描述】:
This 文章在任何人询问 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 处理到纹理,暂时只有第三个?
cmets 似乎建议 OpenGL 驱动程序在内部能够创建第二个缓冲区 IF 并且仅在需要避免停止管道时才创建。正在使用的缓冲区正在被 DMA 处理,我对 map 的调用会产生一个新的缓冲区供我写入。
那篇文章的作者在这方面的知识似乎比我自己还要多。我完全误解了重点吗?
【问题讨论】:
-
我不知道我在说什么,但我的盲目猜测是:您使用两个缓冲区,以便随时可以写入另一个可以读取而不会读写干扰,内存与避免竞争条件的成本相比,它相当便宜
-
恕我直言,我认为它是这样的:想象一下,其中一个 PBO 被发送到渲染缓冲区以绘制到屏幕上。虽然此操作在当前帧期间发生,但如果 PBO 中的信息要在下一帧或绘制调用之前更改怎么办......而不是等待帧完成绘制,取回信息,然后更新它并将其发送回渲染缓冲区,更新可以在当前绘制帧期间在后台进行,然后一旦该帧完成绘制,它几乎可以立即交换缓冲区以绘制更新的信息。
-
不要完全引用我的话,因为我没有使用过 PBO,因为我主要使用的是 vbo、vba 和 rbo,但我认为这就是原因。
-
@FrancisCugler 谢谢。但是,PBO 中的信息不能更改。任何更改它的尝试都会使 GPU 停止工作,直到它不再被使用。或者,如果缓冲区已被 glBufferData(...NULL) 孤立,那么任何修改它的尝试都只会提供一个全新的缓冲区。
-
@cds84 你不是在那儿回答你自己的问题吗? “任何改变它的尝试都会停止 GPU 直到它不再被使用”即你需要 2 个这样你就不会停止 GPU