分配描述符集
译者注:示例代码点击此处
描述符集在一个容器对象中收集着色器资源(描述符)。其内容类型和资源数量由描述符集布局定义。我们可以从描述符池中分配描述符集。
怎么做...
- 获取逻辑设备并将其句柄村粗在名为logical_device的vkdevice类型变量中。
- 准备描述符池。使用池的句柄初始化名为descriptor_pool的VkDescriptorPool类型变量。
- 创建名为descriptor_set_layouts的std::vector<VkDescriptorSetLayout>类型变量。对于应该从池中分配的每个描述符集,添加一个描述符集布局的句柄,该布局定义了相应描述符集的结构。
- 创建一个名为descriptor_set_allocate_info的VkDescriptorSetAllocateInfo类型变量,并为其成员使用以下值:
·sType为VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO
·pNext为nullptr
·descriptorPool为descriptor_pool变量
·descriptorSetCount为descriptor_set_layouts的元素数量
·pSetLayouts为descriptor_set_layouts的第一个元素的指针 - 创建名为descriptor_sets的std::vector<VkDescriptorSet>类型变量并调整其大小以匹配descriptor_set_layouts向量的大小。
- 调用vkAllocateDescriptorSets( logical_device, &descriptor_set_allocate_info,
&descriptor_sets[0] )并提供logical_device变量、指向descriptor_set_allocate_info变量的指针以及指向descriptor_sets向量第一个元素的指针。
- 确保调用成功返回VK_SUCCESS值。
这个怎么运作...
描述符集用于为着色器提供资源。它们构成应用程序和可编程管线阶段之间的接口。该接口的结构由描述符集布局定义。当我们用图像或缓冲资源更新描述符集时,提供实际数据,然后在记录操作期间将这些描述符集绑定到命令缓冲区。
描述符集是从池中分配的。当创建一个池时,我们指定将在池中分配的所有描述符集中有多少描述符(资源)以及可以从中分配的类型。
当想要分配描述符集时,我们需要指定每个描述符的布局。此信息指定如下:
VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
nullptr,
descriptor_pool,
static_cast<uint32_t>(descriptor_set_layouts.size()),
descriptor_set_layouts.data()
};
接下来,我们按一下方式分配描述符集:
descriptor_sets.resize( descriptor_set_layouts.size() );
VkResult result = vkAllocateDescriptorSets( logical_device, &descriptor_set_allocate_info, descriptor_sets.data() );
if( VK_SUCCESS != result ) {
std::cout << "Could not allocate descriptor sets." << std::endl;
return false;
}
return true;
不幸的是,当我们分配和释放单独的描述符集时,池的内存可能会变得支离破碎。在这种情况下,我们可能无法从给定的池中分配新的集,即使我们没有达到指定的限制。这种情况如下图所示:
当我们第一次分配数据块集,绝对不会出现问题。此外,如果所有的描述符集使用的类型和数量都是相同的,也保证不会出现任何问题。
为了避免池碎片问题,我们可以一次释放所有描述符集(通过重置池)。否则,如果我们不能分配一个新的描述符集,并且不想重置池,需要创建另一个池。