【问题标题】:Does any graphics API allow efficient per-primitive branching?是否有任何图形 API 允许高效的每个基元分支?
【发布时间】:2022-01-10 10:47:38
【问题描述】:

在 OpenGL 中编写片段着色器时,可以在编译时常量、uniform 变量或可变 变量上进行分支。

分支的性能取决于硬件和驱动程序的实现,但通常在编译时间常数上进行分支通常是免费的,并且在 uniform 上进行分支比在 variing 上进行更快 em>。

在 varying 的情况下,光栅化器仍然必须为每个片段插入变量,并且必须在每个族执行时决定分支,即使变化的值是相同的对于当前原语中的每个片段。

我想知道的是,是否有任何图形 API 或扩展允许某些片段着色器分支,每个光栅化图元仅执行一次(或者在平铺渲染的情况下,每个图元每个 bin 执行一次)?

【问题讨论】:

  • 当同一个 warp 中的所有线程都遵循相同的代码路径时,在变化上的分支(根据我的经验)与统一分支同样快。当同一个 warp 中的不同线程采用不同的分支时,性能会大幅下降,因为由于 SIMD 架构,不同的分支会一个接一个地执行。因此,您所要求的应该发生在任何相当新的硬件上的任何图形 API 中。
  • @BDL:请注意,波前中的所有片段是否都来自同一个原语,这取决于硬件。一些实现会这样做,而另一些则不会。在同一个波前运行多个图元会更快,特别是对于非常小的多边形。

标签: opengl rendering directx metal vulkan


【解决方案1】:

只有在导致divergence of instances executing at the same time 时,动态分支才会变得昂贵。插入“变化”的成本是微不足道的。

此外,不同的 GPU 以不同的方式处理原始光栅化。一些 GPU 确保片段着色器的波前仅包含在同一图元上执行的实例。在这些 GPU 上,基于不改变每个基元的值进行分支会很快。

但是,其他 GPU 会将来自不同基元的实例打包到相同的波前。在这些 GPU 上,如果不同基元的值不同,就会发生分歧。有多大的分歧?这取决于您在原语中获得多个实例的频率。如果您的许多图元在光栅化空间中都很小,那么您将获得比拥有大量大型图元时更大的差异。

将来自不同基元的实例打包到波前的 GPU 正试图最大限度地利用其内核。这是一个折衷:您正在最大限度地减少必须执行的波前总数,但发散的特定原因(数据在基元内保持不变但不在它们之间)将受到惩罚。

无论如何,尽量避免分歧。但是如果你的算法需要它……那么你的算法需要它,你得到的性能就是你得到的性能。您可以做的最好的事情是让 GPU 知道“变化”将通过使用 flat 插值在每个基元中保持不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-28
    • 2019-07-09
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    相关资源
    最近更新 更多