如何正确使用decriptor集多个交错缓冲区?

时间:2018-02-19 14:09:48

标签: vulkan

我有一个统一的缓冲区,应该每帧更新一次。为了避免大的停顿,我想创建3个缓冲区(按我的帧缓冲区的数量),每个帧应该交错(0-1-2-0-1-2 -...)。但我无法理解如何创建描述符并绑定它们。这就是我现在这样做的方式:

  1. 我创建了一个VkDescriptorSetLayout,其中我指定我想在某个着色器阶段在绑定位置0使用统一缓冲区。
  2. 我创建了一个VkDescriptorPool,其大小为3个描述符,用于统一缓冲区。
  3. 接下来我需要分配描述符集,但这里需要多少个描述符集?我只有一个VkDescriptorSetLayout而且我希望得到一个VkDescriptorSet
  4. 接下来我需要更新创建的描述符集。由于我的着色器中只有一个绑定(0),因此我只能在VkDescriptorBufferInfo中使用一个缓冲区,该缓冲区将传递给VkWriteDescriptorSet,该缓冲区将传递给vkUpdateDescriptorSets。但是其他两个缓冲区呢?在哪里指定它们?
  5. 当我需要录制命令时,我需要绑定我的描述符集。但到目前为止,我有一个描述符集,只为一个缓冲区更新。其他人怎么样?
  6. 我是否需要创建3 VkDescriptorSetLayout - 每帧一个?接下来我需要使用相应的缓冲区分配和更新相应的描述符集吗?在此之后,我需要创建3个不同的命令缓冲区,我应该指定相应的描述符集。

    似乎它做了很多工作 - 数据几乎相同 - 所有绑定,状态保持不变,只有缓冲区发生变化。

    所有这一切听起来都很混乱,所以请不要犹豫澄清。

1 个答案:

答案 0 :(得分:5)

描述符集布局定义描述符集的内容 - 给定集合包含哪些类型的资源(描述符)。当您需要具有单个统一缓冲区的多个描述符集时,您可以使用相同的布局创建所有这些描述符集(布局仅是描述,规范)。这样你就告诉司机:“嘿,司机!给我3个描述符集。但是所有这些都应该完全相同”。

但是因为它们是从相同的布局创建的,所以并不意味着它们必须包含相同的资源句柄。所有这些(在您的情况下)必须包含一个统一的缓冲区。但是这个统一缓冲区将使用什么资源取决于你。因此,每个描述符集都可以使用单独的缓冲区进行更新。

现在,当你想在三个连续的帧中一个接一个地使用3个缓冲区时,你可以用几种不同的方式来做:

  1. 您可以设置一个描述符。然后在每个帧中,在开始准备命令缓冲区之前,使用下一个缓冲区更新描述符集。但是当您更新描述符集时,任何提交的(尚未完成的)命令缓冲区都不能使用它。因此,这需要额外的同步,并且与使用单个缓冲区没有太大区别。这样你也无法“预先记录”命令缓冲区。
  2. 您可以设置一个描述符。要更改其内容(在其中使用不同的缓冲区)您可以通过VK_KHR_descriptor_update_template扩展中添加的功能更新它。它允许将描述符更新记录在命令缓冲区中,因此同步应该更容易一些。它应该允许您预先记录命令缓冲区。但它需要支持扩展,因此它不适用于不支持它的平台。
  3. 您可能想到的方法 - 您可以拥有3个单独的描述符集。所有这些都使用相同的布局分配了统一缓冲区。然后用不同的缓冲区更新每个描述符集(可以使用第一个缓冲区和第一个描述符集,第二个缓冲区和第二个描述符集,第三个缓冲区和第三个描述符集)。现在,在记录命令缓冲区时,如果要使用第一个缓冲区,则只需绑定第一个描述符集。在下一帧中,您只需绑定第二个描述符集,依此类推。
  4. 方法3可能是最容易实现的,因为它不需要描述符的同步(如果你有这样的话,只需要每帧级同步)。它还允许您预先记录命令缓冲区,并且不需要启用任何其他扩展。但正如您所指出的,它需要更多的资源来创建和管理。

    不要忘记您需要创建一个足够大的描述符池来包含3个统一缓冲区但同时您还必须指定您要从中分配3个描述符集(每个描述符集一个统一缓冲区)

    您可以在英特尔API without Secrets: Introduction to Vulkan - Part 6教程中阅读有关描述符集的更多信息。

    关于你的问题:

      

    我是否需要创建3个VkDescriptorSetLayout - 每帧一个?

    否 - 单个布局就足够了(只要所有描述符集在同一个绑定中包含相同类型的资源。

      

    接下来我需要分配和更新相应的描述符集   用相应的缓冲区?

    根据选项3 - 是的。

      

    在此之后我需要在I中创建3个不同的命令缓冲区   应指定相应的描述符集。

    这取决于您是否每帧重新记录命令缓冲区,或者您是否预先记录它们。通常,每帧重新记录命令缓冲区。但是由于只有一个命令缓冲区需要等待其提交完成,因此您可能需要为每个帧设置一组命令缓冲区,这些缓冲区对应于您的帧缓冲区图像(和描述符集)。因此在第0帧中使用命令缓冲区#0(或为帧0保留的多个命令缓冲区)。在第1帧中,您使用命令缓冲区#1等。

    现在您可以为给定帧记录命令缓冲区并在录制期间提供与给定帧关联的描述符集。