在性能方面比较 multiDrawArrays、使用原始重启和 multiDrawElements?

Comparing the multiDrawArrays, using primitive restart and multiDrawElements in terms of performance?

我想画一团形状各异的树枝,每个树枝由4个三角条组成。 (使用 OpenGL)

所以现在我正在考虑使用其中一种方法调用(multiDrawArrays,使用原语重启和 multiDrawElements)。

我想知道哪个更有效率。 multiDrawArrays()方法在速度上是否等同于多个drawArrays()方法?

VAO 是否将顶点信息存储在 RAM 中,而 SSBO 将顶点信息存储在 VRAM 中?如果是这样,考虑到性能,使用 SSBO 比 VAO 更好吗?

正如@derhass 已经在评论中指出的那样,您的一些术语混淆了。 VAO(顶点数组对象)包含定义顶点数据如何与顶点属性相关联的状态。它是包含实际顶点数据的 VBO(顶点缓冲区对象)。

我怀疑对顶点数据使用 SSBO 是否有益。通常,缓冲区类型主要定义数据的使用方式。图形管道专为从 VBO 获取顶点数据而定制,许多 GPU 具有专用的固定功能硬件来从 VBO 获取数据并将其馈送到顶点着色器。我看不出如何在顶点着色器中使用显式代码从 SSBO 中提取顶点数据会更有效率。

数据存储在VRAM 还是SRAM 是不同的考虑因素。您对此唯一的控制是 glBufferData() 的最后一个参数。它提供了有关您计划如何使用数据的提示。例如,如果您指定 GL_STATIC_DRAW,您是在告诉驱动程序您不打算修改数据,这表明将它放在 VRAM 中可能是个好主意。它是否真的在 VRAM 中取决于驱动程序,它可能会根据各种标准来决定。

在功能上,glMultiDrawArrays() 等同于多次调用 glDrawArrays()。但它肯定可以更有效率。如果不出意外,它可以节省进行多次 API 调用的开销。每个 API 调用都有一定的开销,例如:

  • 它可能会通过几个软件层,导致在幕后调用额外的函数。
  • 它需要从线程本地存储中获取当前上下文。
  • 需要进行错误检查。
  • 它可能需要某种形式的锁定来处理来自多个线程中的多个上下文的访问(绘制调用可能不需要)。
  • 它需要检查挂起的状态更改。

引入 MultiDraw 调用是为了减少所需的 API 调用次数。

现在,glMultiDrawArrays()还是glDrawElements()原始重启效率更高,一般来说是不可能的。如果您还没有使用索引缓冲区,我会有点犹豫是否要介绍一个,以便您可以使用原始重启。所以我的直觉是:

  • 如果您正在使用索引缓冲区,请将 glDrawElements() 与原始重启一起使用。
  • 如果您不使用索引缓冲区,请使用 glMultiDrawArrays()

真正的答案,一如既往,只能通过对标来获得。它当然可以 platform/hardware 依赖。我的预测是在大多数情况下您不会看到显着差异,因为这两种方法都允许您通过单个 API 调用绘制大量几何图形,这应该可以避免这方面的瓶颈。