在 DirectX 12 中,切换管道状态对象的性能如何?

In DirectX 12, how performant is it to switch Pipeline State Objects?

我正在研究 DirectX 12,我想知道切换管道状态对象的性能如何。我从我正在阅读的来源获得相互矛盾的报告,即有些人说它非常慢还有人说速度挺快的

使用的 "slow" 参数是:每当您使用 SetPipelineState().

时,GPU 必须在幕后做一些事情,例如重新编译等

使用的"fast"论点是:管道状态的所有计算都是在创建管道状态对象时完成的,因此GPU只需交换一些指针就可以了。

哪个是真的? SetPipelineState() 性能如何,使用时应注意什么?

真正的问题是:你用 SetPipelineState() 做什么?没有它你不能改变着色器。您可以更改资源绑定配置。否则您无法更改拓扑。理论上 PipelineState 具有对 GPU 进行编程所需的所有内容,并且您不能在此处交换块,因此您有点受困于现有内容。

现在回答:这取决于GPU和驱动程序。是的,有一些东西在后台完成。但是,体面的图形驱动程序应该优化并缓存已经完成的工作。含义 - 如果您已经使用了给定的 PipelineState,使用不同的 PipelineState 并返回到原始状态应该很快。

为了快速回答,您可能永远不会遇到切换 PSO 的性能问题,这就是它们最初的设计方式。

对于更长一点的答案,管道状态对象的更改成本将主要取决于三个标准:

  • 硬件和驱动效率。
  • 即将打开或关闭的流水线阶段,例如曲面细分单元。
  • 根签名,因为它很接近但仍然是一个抽象,驱动程序可能需要一些工作来准备它的映射。

PSO 旨在尽可能快地切换,它是自我满足的,并且至少在 nVidia 和 AMD 上,唯一的着色器编译发生在创建时,而不是在使用时。在 AMD 上,甚至可以通过一些 hack 从 ID3D12PipelineState::GetCachedBlob 的结果中提取真正的微码程序集。一项观察是,他们不再像 DX11 那样使用获取着色器系统来处理不同的输入布局,因为它现在是 PSO 描述的一部分。

不得不提的是,DX12的一大优势还在于提供了对无绑定资源的访问。使用该功能,可以将 material 刷​​新的数量减少十倍左右,使用巧妙的实例化和 ExecuteIndirect,您可以让 GPU 决定 materials 和几何而不互动多

因为信息是 public 不知何故 (http://www.wihlidal.ca/Presentations/GDC_2016_Compute.pdf)。

On Xbox One, ExecuteIndirect has some incredible extensions where PSOs can be switched by indirect arguments, meaning we can issue a single ExecuteIndirect for our entire scene, regardless of state or
resource changes.

Xbox One 上的 PSO 更改在 CPU 上几乎是免费的,因为它们能够直接从 GPU 消耗它们。遗憾的是它在 PC 上不可用,但它应该可以帮助您降低对 PSO 开关的担忧。