14

当您使用交错的 VBO 而不是使用多个 VBO 时,通常会加快速度。这在使用 VAO 时也有效吗?

因为为位置设置一个 VBO,为法线设置一个 VBO 更方便。您可以在多个 VAO 中使用一个 VBO。

4

2 回答 2

18

VAO

  • 对于共享更大的数据集,包含单个顶点(属性)数组的专用缓冲区肯定是一种方法,而人们仍然可以在另一个缓冲区中交错特定数组并使用 VAO 将它们组合起来。

  • VAO 处理所有这些缓冲区和顶点(属性)数组状态的绑定,例如数组缓冲区绑定和带有(缓冲区)指针和启用/禁用标志的属性条目。除了方便之外,它还旨在快速完成这项工作,更不用说简单的 API 调用了,它可以一次更改所有状态,而无需繁琐的启用和禁用属性数组。它基本上可以,我们之前必须手动执行的操作。但是,使用我自己的类似 VAO 的实现,我无法测量任何性能损失,即使在进行大量绑定时也是如此。从我的角度来看,主要优点是它的方便。

因此,VAO 不会根据 glDraw* 来决定绘图性能,但它会对状态更改的开销产生影响。

交错数据格式...

  • ...减少 GPU 缓存压力,因为单个顶点的顶点坐标和属性不会分散在内存中。它们连续地适合几个缓存行,而分散的属性可能会导致更多的缓存更新并因此被驱逐。最坏的情况可能是每个缓存行一次一个(属性)元素,因为内存位置较远,而顶点以非确定性/非连续方式被拉取,可能没有预测和预取作用。GPU非常在这件事上类似于 CPU。

  • ...对于满足已弃用的交错格式的各种外部格式也非常有用,其中兼容数据源的数据集可以直接读取到映射的 GPU 内存中。正是出于这些原因,我最终用当前的 API 重新实现了这些交错格式。

  • ...应该像简单的数组一样布局对齐友好。混合具有不同大小/对齐要求的各种数据类型可能需要填充以对 GPU 和 CPU 友好。这是我所知道的唯一缺点,除了更困难的实施。

  • ...不要阻止您指向其中的单个属性数组进行共享。

交错很可能会提高绘制性能。

结论:

根据我的经验,最好为顶点数据源和“编译”的 VAO 设计干净的接口,这样可以适当地封装 VAO 工厂。然后可以更改此工厂以从数据源初始化交错、分离或混合的顶点缓冲区布局,而不会破坏任何内容。这对于分析特别有用。

经过这么多唠叨,我的建议很简单:在优化之前和优化之前进行适当且充分抽象的设计。

于 2013-09-17T17:32:18.660 回答
3

VAO保存任何顶点属性数据。它是一组顶点数组的容器对象,描述如何从零个、一个或多个缓冲区对象中提取数据(这些是您使用VertexAtrribPointer()(pre-GL43) 或VertexAttribFormat()和(GL43+) 定义的实际顶点数组) VertexAttribBinding()BindVertexBuffer()启用状态表示顶点数组,可能还有一个ELEMENT_ARRAY_BUFFER_BINDING. 有关详细信息,请参见 GL 4.4 核心规范的表 23.3 和 23.4。

ARRAY_BUFFER_BINDING为每个顶点数组单独记录,即每个属性索引的每个调用VertexAttribPointer()通过这种方式,您可以将 VAO 的属性索引与多个缓冲区对象相关联,并在要从中提取的缓冲区之间切换,{Enable|Disable}VertexAttribArray()或者通过跨属性索引分配缓冲区并为着色器选择适当的属性位置 - 使用glBindAttribLocation()或使用您内部的显式属性位置着色器(后者更胜一筹)。

为什么所有这些关于 VAO 的喋喋不休?因为使用 VAO 没有不利影响,VBO 缓冲存储的布局以及拉取顶点的速度与 VAO 无关。VAO 是状态容器,仅此而已。您仍然需要缓冲存储来支持任何顶点拉动,您可以像没有 VAO 一样交错数据。您需要做的就是用您的顶点数组反映交错的内存布局。所以本质上,除了记录顶点数组状态之外,没有任何变化。

使用 VAO 获得的是一种或多或少在状态集和关联缓冲区对象之间快速切换的方法,而无需在每次切换缓冲区对象时都设置顶点数组。因此,您可以节省 API 调用。此外,在绑定 VAO 时,每个顶点数组仍然有自己的ARRAY_BUFFER_BINDING,无需BindBuffer()再次调用,从而节省了进一步的 API 调用。就是这样。

由于 VAO,您不会获得也不会失去任何关于顶点拉动性能的东西,至少在理论上不会。但是,当您疯狂地随意切换 VAO 时,您确实会损失整体性能。

顺便说一句,在使用 GL32 和更高的核心上下文时,使用 VAO 也是强制性的,所以如果你不打算兼容,你的问题就没有实际意义。

一般来说,当您不确定性能时:不要猜测,总是配置文件!在使用 OpenGL 时尤其如此。

于 2013-09-17T16:06:26.607 回答