【问题标题】:Comparing the multiDrawArrays, using primitive restart and multiDrawElements in terms of performance?比较 multiDrawArrays,在性能方面使用原始重启和 multiDrawElements?
【发布时间】:2015-03-07 15:22:17
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你我们的术语是错误的。您可能指的是 VBO 和 SSBO,而不是 VAO 和 SSAO。 VAO 至少存在于 GL 中,而图形领域的 SSAO 仅代表“屏幕空间环境光遮蔽”
  • 哦,刚刚更正了,谢谢提醒!!@derhass
  • 我假设 SSBO 表示 Shader Storage Buffer Objects。

标签: opengl glsl jogl


【解决方案1】:

正如@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()

与往常一样,真正的答案只能通过基准测试获得。它当然可以依赖于平台/硬件。我的预测是,在大多数情况下您不会看到显着差异,因为这两种情况都允许您通过一次 API 调用绘制大量几何图形,这应该可以避免该领域的瓶颈。

【讨论】:

  • 我还想补充一点,应该考虑 [GL_ARB_multi_draw_indiriect]](opengl.org/registry/specs/ARB/multi_draw_indirect.txt) 变体。根据我的经验,它们比旧的、非间接的变体更受欢迎,只要有客户端缓冲区。
  • @Reto Koradi 我搜索了一些与该主题相关的其他讨论。现在似乎不建议使用 multiDraw* 调用。我还在最新的蓝皮书 6th 上查了一下,除了 glMultiDrawArraysIndirect() 之类的东西,我没有发现任何关于 multiDrawArrays() / multiDrawElements() 的信息。
  • 我不认为 glMultiDrawArrays() 已被弃用。因此,如果它满足您的需求,我看不出您不应该使用它的充分理由。 glMultDrawArraysIndirect() 如果您想通过单个调用进行的绘制调用数量非常多,则可能会有所帮助。我一直认为他们主要针对绘制调用参数由计算着色器生成的用例。它确实需要 OpenGL 4.3,这意味着它只能在相当新的硬件上运行。
  • 据我所知,glMultiDrawArrays 的实现很差,并且没有明显的加速。此外,对 glDrawArrays 做同样的事情是微不足道的。也许 GL_ARB_multi_draw_indirect 值得一试。为什么不尝试网格实例化?您只有 4 个三角形条带,单个静态 VBO 会更有效。
  • 如果使用 WebGL,这是有效使用 ubershader 的唯一方法。
猜你喜欢
  • 1970-01-01
  • 2017-09-26
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
  • 1970-01-01
  • 2012-12-12
相关资源
最近更新 更多