Vulkan【10】创建描述符集合

  • Post author:
  • Post category:其他


创建描述符集合

本节的代码是

09-init_descriptor_set.cpp

回到“管线布局”示例,你定义了描述符集合布局,但并没有真正为它分配内存。回想一下,您定义的描述符集用于通知GPU如何将uniform 缓冲区中包含的数据映射到shader程序的统一变量。现在,您可以继续分配和初始化描述符集合。

描述符池

与命令缓冲区一样,描述符集合是从池中分配的。所以您必须首先创建池。因为您知道,对于uniform 缓冲区,您只需要一个描述符集,所以创建池是非常简单的:

VkDescriptorPoolSize type_count[1];
type_count[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
type_count[0].descriptorCount = 1;

VkDescriptorPoolCreateInfo descriptor_pool = {};
descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptor_pool.pNext = NULL;
descriptor_pool.maxSets = 1;
descriptor_pool.poolSizeCount = 1;
descriptor_pool.pPoolSizes = type_count;

res = vkCreateDescriptorPool(info.device, &descriptor_pool, NULL,
                             &info.desc_pool);

从池中分配一个描述符集合

现在您可以从池中分配一个描述符集。注意,您必须提供您在管道布局样例中定义的描述符集合布局。这个布局描述了如何分配描述符集。

VkDescriptorSetAllocateInfo alloc_info[1];
alloc_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info[0].pNext = NULL;
alloc_info[0].descriptorPool = info.desc_pool;
alloc_info[0].descriptorSetCount = NUM_DESCRIPTOR_SETS;
alloc_info[0].pSetLayouts = info.desc_layout.data();
info.desc_set.resize(NUM_DESCRIPTOR_SETS);
res = vkAllocateDescriptorSets(info.device, alloc_info, info.desc_set.data());

更新描述符集合

请注意,您还没有真正地在任何地方使用Uniform缓冲区的句柄。当你创建Uniform缓冲区时,你将Uniform缓冲区的信息保存在

VkDescriptorBufferInfo

结构体中,结构体变量名为

VkDescriptorBufferInfo

。 在函数

init_uniform_buffer()

来观察

info.uniform_data.buffer_info

是如何初始化的。


info.uniform_data.buffer_info

是一个下面结构体的实例:

typedef struct VkDescriptorBufferInfo {
    VkBuffer        buffer;
    VkDeviceSize    offset;
    VkDeviceSize    range;
} VkDescriptorBufferInfo;

其中

buffer

成员包含了Uniform缓冲区的句柄。

VkWriteDescriptorSet writes[1];
writes[0] = {};
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[0].pNext = NULL;
writes[0].dstSet = info.desc_set[0];
writes[0].descriptorCount = 1;
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
writes[0].pBufferInfo = &info.uniform_data.buffer_info;
writes[0].dstArrayElement = 0;
writes[0].dstBinding = 0;

vkUpdateDescriptorSets(info.device, 1, writes, 0, NULL);

上面的步骤本质上是将

VkDescriptorBufferInfo

复制到描述符中,描述符在设备内存中。

这个缓冲区信息包括对uniform 缓冲区的句柄,以及在uniform 缓冲区中访问的数据的偏移量和大小。在这种情况下,uniform 缓冲区只包含MVP转换,所以偏移量为0,大小是MVP的大小,这是由

info.uniform_data.buffer_info

中的管道布局示例设置的。

描述符的精确的字节布局可能是特定于实现的,因此对您来说是不透明的。这就是为什么您使用Vulkan驱动函数来操作描述符,而不是自己映射和编写它们。

© Copyright 2016 LunarG, Inc