我应该使用多个glBufferSubData()调用更新多个VBO,还是使用一个glBufferSubData()调用更新单个VBO?

时间:2017-02-15 00:03:31

标签: opengl vbo

我有38个具有不同着色器的粒子系统,并且每个粒子系统在世界上的不同位置(发射器)可以渲染多达200次。 我需要更新(上传到GPU)的每一帧都是发射器位置(在某些系统中可能还有一些其他属性), 当且仅当任何粒子系统处于活动状态且在视锥体中可见时。

我应该像这样分配和更新所有内容: - 为每个可处理多达200个发射器的粒子系统分配单个VBO。使用glBufferSubData()为每个粒子系统更新每帧0到200个发射器。 对每个粒子系统执行单次绘制调用。

我们需要在最坏的情况下用这种方法执行38次glBufferSubData()调用!

或者,我应该这样做(共享VBO): - 分配一个非常大的VBO,可以处理多达38个(粒子系统)* 200(每个粒子系统的发射器)。使用单个更新所有粒子系统 调用glBufferSubData()。在这种情况下,我们需要为每个粒子系统分组所有发射器, 因为每个绘图调用必须知道每个粒子系统及其发射器的起始偏移量。 对每个粒子系统执行单次绘制调用。

我们只需要调用一次glBufferSubData()!

很明显,案例nr 2是胜利者,但我有些怀疑。我们知道38个粒子系统共享一个VBO, 但是如何阻止GPU管道呢? 当且仅当所有38个粒子系统都完成了渲染,即不从VBO读取任何数据时,图形驱动程序才能执行VBO更新。

我发现了这个:考虑使用多个缓冲区对象来避免在数据存储更新期间停止渲染管道。如果管道中的任何渲染引用glBufferSubData正在更新的缓冲区对象中的数据,特别是来自正在更新的特定区域,则在更新数据存储之前,该渲染必须从管道中消失。

此处:https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml

对于案例nr 2,我应该使用双倍甚至三倍缓冲吗?

1 个答案:

答案 0 :(得分:2)

就图形方面的许多优化而言,这是一种权衡。通过将所有缓冲区合并为一个缓冲区,您可以减少为平均情况绘制粒子系统所需的状态更改次数。但是,当系统不在平截头体中时,如果你跳过glBufferSubData(),那么你就会错失总线带宽。

我不会担心拖延GPU管道,除非整个缓冲区大于几MB(想想一个或两个高分辨率视频流的大小)。与更改着色器或帧缓冲区相比,更改VBO是一种更便宜的状态更改。

它主要归结为您需要更多的东西:GPU处理/同步时间(以状态更改的形式)或PCI-e总线带宽。