10

在 Vulkan 中,您可以使用vkCreateGraphicsPipelinevkCreateComputePipeline创建管道派生类,以及/的basePipelineHandlebasePipelineIndex成员。该文档指出,出于性能原因,此功能可用:VkGraphicsPipelineCreateInfoVkComputePipelineCreateInfo

衍生管道的目标是使用父级作为起点创建它们更便宜,并且在同一父级的子级之间切换/绑定更有效(在主机或设备上)。

这对我提出了很多问题:

  1. 有没有办法指示父管道和子管道之间共享哪个状态,或者由实现决定?
  2. 有什么方法可以知道实现是否真的从使用派生管道(分析除外)中获得了任何好处?
  3. 需要使用创建父管道VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT。始终使用此标志是否有不利之处(例如,如果您将来可能从该标志创建派生管道)?
4

3 回答 3

6

我来到这个问题调查管道衍生品是否提供好处。以下是我从供应商那里找到的一些资源:

提示和技巧:Vulkan 的注意事项,Nvidia,2019 年 6 月 6 日

不要期望 Pipeline Derivatives 会加速。

Vulkan 使用建议,三星

管道衍生品让应用程序将“子”管道表示为类似“父”的增量状态变化;在某些架构上,这可以降低在相似状态之间切换的成本。许多移动 GPU 主要通过流水线缓存获得性能,因此流水线衍生产品通常不会为便携式移动应用程序带来任何好处。

建议

  • 在应用程序执行的早期创建管道。避免在绘制时创建管道。
  • 为所有管道创建使用单个管道缓存。
  • 在应用程序运行之间将管道缓存写入文件。
  • 避免管道衍生品

面向移动开发人员的 Vulkan 最佳实践 - 管道管理,Arm 软件,2019 年 7 月 11 日

  • 在没有管道缓存的情况下在绘制时创建管道(引入性能卡顿)。
  • 使用管道衍生产品,因为它们不受支持。

Vulkan 样本、LunarG、API-Samples/pipeline_derivative/pipeline_derivative.cpp

/*
VULKAN_SAMPLE_SHORT_DESCRIPTION
This sample creates pipeline derivative and draws with it.
Pipeline derivatives should allow for faster creation of pipelines.
In this sample, we'll create the default pipeline, but then modify
it slightly and create a derivative.  The derivatve will be used to
render a simple cube.
We may later find that the pipeline is too simple to show any speedup,
or that replacing the fragment shader is too expensive, so this sample
can be updated then.
*/

似乎没有任何供应商实际上建议使用管道衍生产品,除非可能是为了加快管道创建速度。

对我来说,这在理论上似乎是一个好主意,理论上的实现在实践中并不重要。

此外,如果驱动程序应该从多个管道的共同父级中受益,它应该完全能够自动化该祖先检测。“共同祖先”可以基于提供最佳加速的任何特定共同管道状态来合成。为什么要通过 API 明确指定它?

于 2019-12-12T20:40:42.293 回答
5

有没有办法指示在父管道和子管道之间共享哪个状态

不; 管道创建 API 无法告诉它什么状态会改变。这个想法是,由于实现可以看到父母的状态,它可以看到你对孩子的状态提出的要求,它可以告诉你有什么不同。

此外,如果有这样的方式,它只会代表一种方式,让您意外地误导实现以了解更改的内容。最好让实现找出变化。

有什么方法可以知道实现是否真的从使用派生管道(分析除外)中获得了任何好处?

不。

需要使用创建父管道VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT。始终使用此标志是否有不利之处(例如,如果您将来可能从该标志创建派生管道)?

大概。由于#1,实现需要至少存储某种形式的父管道状态,以便可以将其与子管道的状​​态进行比较。它必须以易于阅读的形式存储此状态,这可能与要复制到命令流中的 GPU 内存和令牌不同。因此,父管道很有可能会为此类数据分配额外的内存。尽管它们在绑定/命令执行时变慢的可能性很低。

您可以通过将分配器传递给管道创建函数来轻松地测试这一点。如果它分配的内存量与没有标志的情况相同,那么它可能没有存储任何东西。

于 2016-05-10T14:39:16.083 回答
0

我不是计算机图形学方面的专家,但我的理解(部分包括直觉)如下:

有没有办法指示父管道和子管道之间共享哪个状态,或者由实现决定?

管道的某些方面在渲染时未指定(因此是固定的),例如要使用哪些着色器。我的猜测是,派生管道和派生管道可能共享这些“只读”信息(或者在 C 术语中,它们指向同一个对象)。这就是为什么派生管道的创建速度更快的原因。

在这些管道之间切换也会更快,因为在更改管道时更改资源的需求较少,因为某些资源是共享的且相同的。

需要使用 VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT 创建父管道。始终使用此标志是否有不利之处(例如,如果您将来可能从该标志创建派生管道)?

这很可能取决于实现。我的猜测是,当您允许衍生时,您启用资源(例如着色器)共享,这意味着实现可能会对这些资源进行引用计数。如果不共享资源,那将是不必要的成本。此外,在更改管道时,驱动程序不需要检查每个资源是否共享并且可以保留在 GPU 上,或者是否需要更改。如果没有共享,所有资源都将被更改,并且没有检查开销。这些都不是那么大的开销,所以要么 Vulkan 保持安全,要么还有另一个我不知道的原因。

于 2016-05-12T17:23:57.663 回答