当您使用交错的VBO而不是使用多个VBO时,通常会加快速度。 这在使用VAO时也有效吗?
因为对于位置有一个VBO,对于法线等有一个VBO要方便得多。 并且您可以在多个VAO中使用一个VBO。
答案 0 :(得分:18)
<强> VAOs 强>
为了共享更大的数据集,包含单个顶点(attrib)数组的专用缓冲区肯定是一种方法,而人们仍然可以在另一个缓冲区中交错特定数组并使用VAO将它们组合。
VAO处理所有缓冲区和顶点(attrib)数组状态的绑定,例如数组缓冲区绑定和attrib条目与(缓冲区)指针和启用/禁用标志。除了方便之外,它还可以快速完成这项工作,更不用说简单的API调用,它可以立即更改所有状态,而无需繁琐的启用和禁用attrib数组。它基本上是,我们之前必须手动完成的。但是,通过我自己的类似VAO的实现,我无法衡量任何性能损失,即使在进行大量绑定时也是如此。从我的角度来看,主要的优点是它的便利性。
因此,VAO不会根据glDraw *决定绘制性能,但它会对状态变化的开销产生影响。
交错数据格式......
...导致较少的GPU缓存压力,因为单个顶点的顶点坐标和属性并未遍布内存。它们连续适应几个缓存行,而分散的属性可能会导致更多的缓存更新,从而导致驱逐。由于远程内存位置,最坏的情况可能是每个高速缓存行一个(属性)元素,而顶点以非确定性/非连续方式被拉动,可能没有预测和预取开始.GPU非常与此事件中的CPU类似。
...对于各种外部格式也非常有用,这些格式满足不推荐使用的interleaved formats,其中兼容数据源的数据集可以直接读入映射的GPU内存。最后,我最终使用当前的API重新实现了这些交错格式。
...应该像简单数组一样对齐友好。混合具有不同大小/对齐要求的各种数据类型可能需要填充为GPU和CPU友好。这是我所知道的唯一不利因素,从较难实施来看。
...不要阻止您指向其中的单个attrib数组进行共享。
交错很可能会提高拉丝性能。
<强>结论:强>
根据我的经验,最好为顶点数据源和“编译的”VAO设计干净的界面,可以适当地封装VAO工厂。然后可以更改此工厂以从数据源初始化交错,单独或混合的顶点缓冲区布局,而不会破坏任何内容。这对于分析特别有用。
在所有这些bab呀学语之后,我的建议很简单:在优化之前进行适当且充分抽象的设计。
答案 1 :(得分:3)
VAO 不保存任何顶点属性数据。它是一组顶点数组的容器对象,它描述了如何从零,一个或多个缓冲区对象中提取数据(这些是您使用VertexAtrribPointer()
定义的实际顶点数组(前GL43) )或VertexAttribFormat()
,VertexAttribBinding()
和BindVertexBuffer()
(GL43 +)),为所述顶点数组启用状态,并可能启用ELEMENT_ARRAY_BUFFER_BINDING
。有关详细信息,请参阅GL 4.4核心规范的表23.3和23.4。
每个顶点数组分别记录ARRAY_BUFFER_BINDING
,即每个属性索引的每个VertexAttribPointer()
调用。这样,您可以将VAO的属性索引与多个缓冲区对象相关联,并在使用{Enable|Disable}VertexAttribArray()
之间切换哪些缓冲区,或者在attrib索引之间分配缓冲区并为着色器选择适当的attrib位置 - 使用{{ 1}}或在着色器中使用显式的attrib位置(后者优越)。
为什么所有这些都是关于VAO的喋喋不休?因为使用VAO和VBO缓冲存储器的布局没有不利影响,并且拉动顶点的速度与VAO无关。 VAO是国家容器,仅此而已。您仍然需要缓冲存储来支持任何顶点拉动,您可以像没有VAO一样交错数据。您需要做的就是用您的顶点数组反映交错存储器布局。所以从本质上讲,除了记录顶点数组状态外,没有任何变化。
使用VAO获得的是一种在每次切换缓冲区对象时都可以在不设置顶点数组的情况下或多或少地快速切换状态集和相关缓冲区对象的方法。因此,您可以保存API调用。此外,绑定VAO时,每个顶点数组仍然具有glBindAttribLocation()
,并且无需再次调用ARRAY_BUFFER_BINDING
,从而节省了更多的API调用。而已。
由于VAO,你不会因为顶点拉动性能而失去任何,至少在理论上是这样。但是,如果你不小心将VAO切换到疯狂状态,你就会失去整体性能。
BTW,在使用GL32和更高级的核心环境时,使用VAO也是强制性的,所以如果你不打算进行比赛,你的问题就没有用了。一般情况下,当你不确定性能时:不要猜测,总是分析!使用OpenGL时尤其如此。