我是否需要为每个缓冲区创建一个新的描述符集?

Do I need to create a new descriptor set for every buffer?

我是图形编程和 Vulkan 的新手。 我知道我们需要将缓冲区绑定到一个描述符集,但我想知道我是否需要为我拥有的每个缓冲区设置一个新的描述符集,或者我是否可以将 descriptorSet 绑定 2 个/更多缓冲区? 如果是,这有什么经验法则?

每个描述符集可能有多个相同或不同类型的资源。什么类型的资源可以通过描述符集绑定在描述符集布局中定义。在那里,通过 VkDescriptorSetLayoutBinding 结构,您可以指定给定类型的资源(例如采样器、存储图像或统一缓冲区)以及作为着色器内部数组访问的此类资源的数量。但是您也可以指定多个相同类型的资源作为单独的布局条目(在布局创建期间指定的多个 VkDescriptorSetLayoutBinding 条目)。每个这样的描述符必须使用一个单独的、不同的绑定。并且必须在着色器内部使用相同的绑定来访问给定资源:

layout( set=S, binding=B ) uniform <variable_type> <variable_name>;

至于你问题的第二部分 - 视情况而定。每种情况、绘制的场景、渲染资源的类型、资源数量、内存使用,甚至图形硬件供应商都会影响在渲染期间用于创建和绑定描述符集的方法。一般规则是您应该在渲染过程中尽量减少状态变化。因此,您应该使 vkCmdBindDescriptorSets() 函数调用的次数尽可能少。但这限制了场景的灵活性和动态性。因此,在许多情况下,您将需要更改描述符,或者一次绑定多个描述符,每个描述符都有多个描述符。但是,正如我所写的,这完全取决于给定的情况。

不,您不需要为每个资源设置单独的描述符。

VkDescriptorSetLayout 的文档似乎清楚地说明了正在发生的事情。在同一章中还有很好的代码示例演示了这一点。

所以,总结一下:

  • 您可以拥有单一描述符类型的(同质)数组
  • 您可以有多个 "bindings",每个都可以包含任何描述符类型的资源(或其数组)
  • 作为间接层,您可以拥有多个描述符集,每个描述符集都有自己的绑定

经验法则可能是 "less is more"。如果您不需要资源具有单独的类型或名称,请使用数组。如果不需要单独的一套,就只用一套。