稀疏 VkDescriptorSetLayoutBinding 的用例是什么?
What are the use cases of sparsed VkDescriptorSetLayoutBinding?
我无法找出 VkDescriptorSetLayoutBinding::binding 的任何用例,这是结构:
struct VkDescriptorSetLayoutBinding
{
uint32_t binding;
VkDescriptorType descriptorType;
uint32_t descriptorCount;
VkShaderStageFlags stageFlags;
const VkSampler* pImmutableSamplers;
};
此处用于创建 DescriptorSetLayout:
struct VkDescriptorSetLayoutCreateInfo
{
VkStructureType sType;
const void* pNext;
VkDescriptorSetLayoutCreateFlags flags;
uint32_t bindingCount;
const VkDescriptorSetLayoutBinding* pBindings;
};
我想知道为什么 "binding" 变量不是从 pBindings 数组中的索引推导出来的。
经过一些研究,我发现 vulkan 规范说:
The above layout definition allows the descriptor bindings to be specified sparsely such that not all binding numbers between 0 and the maximum binding number need to be specified in the pBindings array. Bindings that are not specified have a descriptorCount and stageFlags of zero, and the value of descriptorType is undefined. However, all binding numbers between 0 and the maximum binding number in the VkDescriptorSetLayoutCreateInfo::pBindings array may consume memory in the descriptor set layout even if not all descriptor bindings are used, though it should not consume additional memory from the descriptor pool.
我找不到在什么情况下可以使用那些稀疏绑定,为什么要留下一个空的未使用的space?
绑定索引被硬编码到着色器中(您可以通过专门化常量定义绑定索引,但除此之外,它们是着色器代码的一部分)。因此,让我们假设您拥有着色器阶段的代码。并且您想在两个不同的管道(A 和 B)中使用它。假设这些管道的描述符集布局不兼容;我们只想重用着色器。
嗯,着色器中的绑定索引没有改变;他们不能改变。因此,如果此着色器在集合 0 的绑定 3 中有一个 UBO,那么它与 一起使用的任何描述符集布局必须 在集合 0 的绑定 3 中有一个 UBO。
也许在管线 A 中,除我们重用的着色器之外的某些着色器可能会使用集合 0 中的绑定 0、1 和 2。但是,如果管线 B 的其他着色器 none 需要绑定索引 2 怎么办?可能流水线A中的片段着色器使用了3个描述符资源,而流水线B中的片段着色器只需要2个。
具有稀疏描述符绑定允许您重用已编译的着色器模块而无需在着色器中重新分配绑定索引。哦,是的,您必须确保所有此类着色器彼此兼容(它们不以不同方式使用相同的设置+绑定索引),但除此之外,您可以自由混合和匹配。
而且应该注意的是,连续绑定几乎从来都不是任何 API 的要求。在 OpenGL 中,您的着色器管道可以使用纹理单元 2、40 和 32,这 100% 没问题。
为什么 Vulkan 会有所不同,只是因为它的资源绑定模型更抽象?
我无法找出 VkDescriptorSetLayoutBinding::binding 的任何用例,这是结构:
struct VkDescriptorSetLayoutBinding
{
uint32_t binding;
VkDescriptorType descriptorType;
uint32_t descriptorCount;
VkShaderStageFlags stageFlags;
const VkSampler* pImmutableSamplers;
};
此处用于创建 DescriptorSetLayout:
struct VkDescriptorSetLayoutCreateInfo
{
VkStructureType sType;
const void* pNext;
VkDescriptorSetLayoutCreateFlags flags;
uint32_t bindingCount;
const VkDescriptorSetLayoutBinding* pBindings;
};
我想知道为什么 "binding" 变量不是从 pBindings 数组中的索引推导出来的。 经过一些研究,我发现 vulkan 规范说:
The above layout definition allows the descriptor bindings to be specified sparsely such that not all binding numbers between 0 and the maximum binding number need to be specified in the pBindings array. Bindings that are not specified have a descriptorCount and stageFlags of zero, and the value of descriptorType is undefined. However, all binding numbers between 0 and the maximum binding number in the VkDescriptorSetLayoutCreateInfo::pBindings array may consume memory in the descriptor set layout even if not all descriptor bindings are used, though it should not consume additional memory from the descriptor pool.
我找不到在什么情况下可以使用那些稀疏绑定,为什么要留下一个空的未使用的space?
绑定索引被硬编码到着色器中(您可以通过专门化常量定义绑定索引,但除此之外,它们是着色器代码的一部分)。因此,让我们假设您拥有着色器阶段的代码。并且您想在两个不同的管道(A 和 B)中使用它。假设这些管道的描述符集布局不兼容;我们只想重用着色器。
嗯,着色器中的绑定索引没有改变;他们不能改变。因此,如果此着色器在集合 0 的绑定 3 中有一个 UBO,那么它与 一起使用的任何描述符集布局必须 在集合 0 的绑定 3 中有一个 UBO。
也许在管线 A 中,除我们重用的着色器之外的某些着色器可能会使用集合 0 中的绑定 0、1 和 2。但是,如果管线 B 的其他着色器 none 需要绑定索引 2 怎么办?可能流水线A中的片段着色器使用了3个描述符资源,而流水线B中的片段着色器只需要2个。
具有稀疏描述符绑定允许您重用已编译的着色器模块而无需在着色器中重新分配绑定索引。哦,是的,您必须确保所有此类着色器彼此兼容(它们不以不同方式使用相同的设置+绑定索引),但除此之外,您可以自由混合和匹配。
而且应该注意的是,连续绑定几乎从来都不是任何 API 的要求。在 OpenGL 中,您的着色器管道可以使用纹理单元 2、40 和 32,这 100% 没问题。
为什么 Vulkan 会有所不同,只是因为它的资源绑定模型更抽象?