Vulkan 中的描述符集计数歧义
Descriptor Set count ambiguity in Vulkan
我想在 vulkan 中绘制两个对象。为实现这一点,我遵循为每个模型创建两个不同描述符集的过程。但是,我对指定所需描述符集计数的结构感到困惑。令我困惑的点如下:
在 VkDescriptorSetLayoutBinding
指定描述符计数
VkDescriptorSetLayoutBinding stagingLayoutBinding = {};
...
stagingLayoutBinding.descriptorCount = 1; <- i have one mat4 element for each descriptors
在 VkDescriptorPoolSize
指定描述符计数
VkDescriptorPoolSize stagingPoolSize = {};
...
stagingPoolSize.descriptorCount = static_cast<uint32_t>(model.size()); <- allocate two descriptor sets from one descriptor pool
在 VkDescriptorPoolCreateInfo
指定最大集合
VkDescriptorPoolCreateInfo poolInfo = {};
...
poolInfo.maxSets = model.size(); <- max descriptor sets = 2
最终在 VkDescriptorSetAllocateInfo
指定描述符集创建
VkDescriptorSetAllocateInfo allocInfo = {};
...
allocInfo.descriptorSetCount = static_cast<uint32_t>(model.size());
但是在vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data())
处抛出异常,验证层调试信息如下:-
validation Layer: Object: 0xcccccccccccccccc (Type = 20) | Invalid DescriptorSetLayout Object 0xcccccccccccccccc. The spec valid usage text states 'pSetLayouts must be a valid pointer to an array of descriptorSetCount valid VkDescriptorSetLayout handles' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-pSetLayouts-parameter)
我的描述符创建代码如下:
VkDescriptorSetLayout layouts[] = { descriptorSetLayout };
descriptorSet.resize(model.size());
VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool[0];
allocInfo.descriptorSetCount = static_cast<uint32_t>(model.size());
allocInfo.pSetLayouts = layouts;
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data()) != VK_SUCCESS)
{
throw std::runtime_error("failed to allocate descriptor set !");
}
我想我在某处提供了错误的描述符集计数。
问题大概出在这里:
allocInfo.descriptorSetCount = static_cast<uint32_t>(model.size());
如果您想绘制 2 个对象,而不是我假设的 model.size()
returns 2
。然而,您只提供一个描述符集布局:
VkDescriptorSetLayout layouts[] = { descriptorSetLayout };
如果您想分配2个(或更多)描述符集,您需要提供2个(或更多)描述符集布局。如果您希望描述符集共享布局,您只需多次提供相同的布局即可。
至于容易混淆的字段:
descriptorCount
VkDescriptorSetLayoutBinding
结构的成员是绑定中包含的描述符的数量,在着色器中作为数组访问。通常这里会提供1
,除非你想创建一个给定类型的描述符数组(例如采样图像数组),那么你需要提供一个更大的值。
descriptorCount
VkDescriptorPoolSize
的成员指定可以从给定池中分配多少给定类型的描述符。该值与描述符集总数无关,例如您可以创建一个描述符池,您可以从中总共分配 3 个描述符集,但总共只能分配 2 个存储映像。
maxSets
VkDescriptorPoolCreateInfo
结构的成员定义了可以从给定的池中分配多少个描述符集(可以从池中分配的集的总数)。同样,此值定义 "whole" 集,而前一个值(来自项目符号 2)定义特定描述符。
descriptorSetCount
VkDescriptorSetAllocateInfo
结构的成员指定在给定时刻(在 vkAllocateDescriptorSets()
函数调用期间)要分配多少个描述符集。例如,您可以创建一个池,您可以从中分配 10 个描述符集,但您希望一次只分配一个描述符集,方法是调用 vkAllocateDescriptorSets()
函数 10 次。
我想在 vulkan 中绘制两个对象。为实现这一点,我遵循为每个模型创建两个不同描述符集的过程。但是,我对指定所需描述符集计数的结构感到困惑。令我困惑的点如下:
在 VkDescriptorSetLayoutBinding
指定描述符计数VkDescriptorSetLayoutBinding stagingLayoutBinding = {}; ... stagingLayoutBinding.descriptorCount = 1; <- i have one mat4 element for each descriptors
在 VkDescriptorPoolSize
指定描述符计数VkDescriptorPoolSize stagingPoolSize = {}; ... stagingPoolSize.descriptorCount = static_cast<uint32_t>(model.size()); <- allocate two descriptor sets from one descriptor pool
在 VkDescriptorPoolCreateInfo
指定最大集合VkDescriptorPoolCreateInfo poolInfo = {}; ... poolInfo.maxSets = model.size(); <- max descriptor sets = 2
最终在 VkDescriptorSetAllocateInfo
指定描述符集创建VkDescriptorSetAllocateInfo allocInfo = {}; ... allocInfo.descriptorSetCount = static_cast<uint32_t>(model.size());
但是在vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data())
处抛出异常,验证层调试信息如下:-
validation Layer: Object: 0xcccccccccccccccc (Type = 20) | Invalid DescriptorSetLayout Object 0xcccccccccccccccc. The spec valid usage text states 'pSetLayouts must be a valid pointer to an array of descriptorSetCount valid VkDescriptorSetLayout handles' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-pSetLayouts-parameter)
我的描述符创建代码如下:
VkDescriptorSetLayout layouts[] = { descriptorSetLayout };
descriptorSet.resize(model.size());
VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool[0];
allocInfo.descriptorSetCount = static_cast<uint32_t>(model.size());
allocInfo.pSetLayouts = layouts;
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data()) != VK_SUCCESS)
{
throw std::runtime_error("failed to allocate descriptor set !");
}
我想我在某处提供了错误的描述符集计数。
问题大概出在这里:
allocInfo.descriptorSetCount = static_cast<uint32_t>(model.size());
如果您想绘制 2 个对象,而不是我假设的 model.size()
returns 2
。然而,您只提供一个描述符集布局:
VkDescriptorSetLayout layouts[] = { descriptorSetLayout };
如果您想分配2个(或更多)描述符集,您需要提供2个(或更多)描述符集布局。如果您希望描述符集共享布局,您只需多次提供相同的布局即可。
至于容易混淆的字段:
descriptorCount
VkDescriptorSetLayoutBinding
结构的成员是绑定中包含的描述符的数量,在着色器中作为数组访问。通常这里会提供1
,除非你想创建一个给定类型的描述符数组(例如采样图像数组),那么你需要提供一个更大的值。descriptorCount
VkDescriptorPoolSize
的成员指定可以从给定池中分配多少给定类型的描述符。该值与描述符集总数无关,例如您可以创建一个描述符池,您可以从中总共分配 3 个描述符集,但总共只能分配 2 个存储映像。maxSets
VkDescriptorPoolCreateInfo
结构的成员定义了可以从给定的池中分配多少个描述符集(可以从池中分配的集的总数)。同样,此值定义 "whole" 集,而前一个值(来自项目符号 2)定义特定描述符。descriptorSetCount
VkDescriptorSetAllocateInfo
结构的成员指定在给定时刻(在vkAllocateDescriptorSets()
函数调用期间)要分配多少个描述符集。例如,您可以创建一个池,您可以从中分配 10 个描述符集,但您希望一次只分配一个描述符集,方法是调用vkAllocateDescriptorSets()
函数 10 次。