Vulkan教程翻译之十 创建 Descriptor Set

原文链接:https://vulkan.lunarg.com/doc/sdk/1.2.131.2/windows/tutorial/html/09-init_descriptor_set.html

创建 Descriptor Set

这一章节的代码文件是 09-init_descriptor_set.cpp

回到 pipeline_layout 例子中,你定义了 descriptor set layout,但是实际上没有分配它。回想一下,你定义 descriptor set 是用来通知 GPU 如何把 uniform buffer 包含的数据映射成 shader 程序的 uniform 变量。现在你可以进行分配和初始化了。

Descriptor Pool

像 command buffer 那样,descriptor set 也是从一个池里分配。所以你必须首先创建这个池。因为你已经知道只需要一个 descriptor set 来对应 uniform buffer,创建池就简单了:

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);

从池里分配 Descriptor Set

现在你可以从池里分配一个 descriptor set 了。注意你必须提供你在 pipeline_layout 例子中定义的 descriptor set layout。该layout 描述了 descriptor set 如何被分配:

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());

更新 Descriptor Set

注意你实际上还没有在任何地方使用这个 uniform buffer 的句柄。在你创建 uniform buffer 的时候,你把它的信息隐藏在一个命名为 info.uniform_data.buffer_info 的 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 buffer 的句柄。

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 到 descriptor,可能是在设备内存中。

这个 buffer info 包含了 uniform buffer 的句柄,还有偏移值和关联的数据大小。目前情况下,uniform buffer 只包含了 MVP 变换,所以偏移值是0,大小就是MVP的大小,按照 pipeline_layout 例子里设置的 info.uniform_data.buffer_info。一个 descriptor 确切的按字节的布局可能是特殊实现的,所以对你是不透明的。这也是为什么你要使用 Vulkan 驱动函数来操作 descriptor,而不是自己去映射写入。

你可能感兴趣的:(Vulkan教程翻译)