申请VkDescriptorSet。
继续写绘制多边形的demo。
在SceneWidget.h中添加一个bool CreateDescriptorSet()函数,在SceneWidget.cpp中实现这个函数。还需要在头文件中先声明一个成员变量,来记录生成VkDescriptorSet。
由于每一帧都会有一个VkDescriptorSet与之对应,所以申请的数量应该是和缓存中的帧数一样。即m_swapchainImages.size()。所以添加成员变量:std::vector<VkDescriptorSet> m_descriptorSets。
还是老样子,从创建函数写起,VkDescriptorSet的申请函数为:
vkAllocateDescriptorSets(),申请也同样可以判断返回值。即:
VkResult result = vkAllocateDescriptorSets()
其参数:
第一个参数:m_device。
第二个参数:需要再定义一个VkDescriptorSetAllocateInfo descriptorSetInfo = {}的变量,然后传入这个变量的引用即:&descriptorSetInfo。
第三个参数:m_descriptorSets.data()。保存申请好的VkDescriptorSet对象。记得要在使用之前进行初始化,即m_descriptorSets.resize(m_swapchainImages.size());
descriptorSetInfo属性赋值:
结构体的类型,固定写法。
descriptorSetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
保持默认
descriptorSetInfo.pNext = nullptr;
指向已创建好的m_descriptorPool
descriptorSetInfo.descriptorPool = m_descriptorPool;
下面的两个属性,一个VkDescriptorSetLayout数组的数量,一个VkDescriptorSetLayout数组的指针。具体的赋值,需要定义一个VkDescriptorSetLayout的数组,可以这样定义:
std::vector<VkDescriptorSetLayout> descriptorSetLayouts。那么下面的属性值为:
descriptorSetInfo.descriptorSetCount = descriptorSetLayouts.size();
descriptorSetInfo.pSetLayouts = descriptorSetLayouts.data();
关于descriptorSetLayouts的赋值,在开头也提到过了,每一帧都对应一个VkDescriptorSet,也就对应一个VkDescriptorSetLayout,所以descriptorSetLayouts赋值为:
descriptorSetLayouts(m_swapchainImages.size(),m_descriptorLayout),将descriptorSetLayouts初始化为m_swapchainImages.size()个m_descriptorLayout。
下面开始给每帧绑定DescriptorSet。
要在每一帧里里更新,需要循环设置每一帧,来更新描述符。
for (size_t I = 0; I < m_swapchainImages.size(); ++I)
{
vkUpdateDescriptorSets();
}
vkUpdateDescriptorSets();的参数:
第一个参数:m_device。
第二个参数:要更新(写入)的描述符数组的数量。这里需要定义一个VkWriteDescriptorSet类型的数组变量std::vector<VkWriteDescriptorSet> writeDescriptorSets;这个值就是writeDescriptorSets.size();
第三个参数:writeDescriptorSets.data()
第四个参数:对描述符的拷贝,这里不需要。所以设置为0.
第五个参数:设置为nullptr.
先定义一个VkWriteDescriptorSet uniformDescritorSet = {};
其属性赋值:
固定写法
uniformDescritorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
不用扩展,设为nullptr.
uniformDescritorSet.pNext = nullptr;
之前申请的对象,与每一帧对应一个。
uniformDescritorSet.dstSet = m_descriptorSets[i];
从0开始。
uniformDescritorSet.dstBinding = 0;
数据不用特殊处理,从0开始。
uniformDescritorSet.dstArrayElemnt = 0;
使用一个,并且类型为uniformBuffer的类型。
uniformDescritorSet.descriptorCount = 1;
uniformDescritorSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
这里存放的应该是具体的数据,即:mvp。所以需要VkDescriptorBufferInfo类型的变量uniformBuffer = {};
uniformDescritorSet.pBufferInfo = &uniformBuffer;
由于类型是uniform buffer类型,所以下面的这两个赋值为nullptr .
uniformDescritorSet.pImageInfo = nullptr;
uniformDescritorSet.pTexelBufferView = nullptr;
然后将
writeDescritorSets.push_back(uniformDescritorSet);
同样还需要定义一个变量VkWriteDescriptorSet imageDescritorSet = {};
其属性赋值:
固定写法
imageDescritorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
imageDescritorSet.pNext = nullptr;
imageDescritorSet.dstSet = m_descriptorSets[i];
imageDescritorSet.dstBinding = 1;
imageDescritorSet.dstArrayElement = 0;
imageDescritorSet.descriptorCount = 1;
imageDescritorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
imageDescritorSet.pBufferInfo = nullptr;
补充一个变量:VkDescriptorImageInfo imageInfo = {};
imageDescritorSet.pImageInfo = &imageInfo;
imageDescritorSet.pTexelBufferView = nullptr;
再看uniformBuffer属性的赋值:
对应与之前申请好的VkBuffer:m_uniformBuffers[i]
uniformBuffer.buffer = m_uniformBuffers[i];
偏移为0.
uniformBuffer.offset = 0;
buffer的大小,为整个数据的大小。
uniformBuffer.range = sizeof(UniformData);
imageInfo的赋值属性
imageInfo.sampler = m_sampler;
imageInfo.imageView = m_colorImageView;
只从shader里读取。
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
在SceneWidget::Init函数添加调用的代码,以及在SceneWidget::Uninit中添加清理的代码。
执行代码如下:
没有报错:)