VkWriteDescriptorSet内存堆释放问题
Vulkan更新描述符集信息时需要填写VkWriteDescriptorSet结构体,然后调用vkUpdateDescriptorSets将其推送到GPU端。
创建VkWriteDescriptorSet时,一定要确保该VkWriteDescriptorSet与vkUpdateDescriptorSets调用位于同一个作用域!!
这里的同一个作用域,是指位于同一个函数作用域!!存在类成员变量中都不可以!!
举个例子:
假设有一个VulkanDescriptorFactory的工厂类,里面缓存了VkWriteDescriptorSet成员变量,假如在Add函数中添加对应的VkWriteDescriptorSet,在Build函数中构建DescriptorSet:
class VulkanDescriptorFactory
{
std::vector<VkWriteDescriptorSet> mWrite{ };
public:
void Add()
{
VkWriteDescriptorSet newWrite{};
// ...
mWrite.push_back(newWtire);
}
void Build()
{
// ...
vkUpdateDescriptorSets(*mAllocator->device,static_cast<uint32_t>(mWrite.size()),mWrite.data(),0,nullptr);
}
}
理论上看上去没什么毛病,但实际运行起来,Visual Studio会把mWrite中除了最后一项的所有VkWriteDescriptorSet中的Buffer Pointer数据都释放掉!也就是说,调用Build时mWrite中除了最后一项,前面的imgeInfo和BufferInfo全部堆内存地址都为0xdddddddddd。
正确的做法应该是在Add的时候用一个中间结构体Cache住VkWriteDescriptorSet的信息,在vkUpdateDescriptorSets前才构建VkWriteDescriptorSet,这样就不会有堆释放的问题了:
struct DescriptorWriteContainer
{
VkDescriptorImageInfo imgInfo;
VkDescriptorBufferInfo bufInfo;
uint32 binding;
VkDescriptorType type;
bool isImg = false;
};
void Add()
{
// ...
DescriptorWriteContainer descriptorWrite{};
descriptorWrite.isImg = false;
descriptorWrite.bufInfo = *bufferInfo;
descriptorWrite.type = type;
descriptorWrite.binding = binding;
mDescriptorWriteBufInfos.push_back(descriptorWrite);
// ...
}
void Build()
{
std::vector<VkWriteDescriptorSet> writes{};
for(auto& dc : mDescriptorWriteBufInfos)
{
VkWriteDescriptorSet newWrite{};
newWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
newWrite.pNext = nullptr;
newWrite.descriptorCount = 1;
newWrite.descriptorType = dc.type;
if(dc.isImg)
newWrite.pImageInfo = &dc.imgInfo;
else
newWrite.pBufferInfo = &dc.bufInfo;
newWrite.dstBinding = dc.binding;
newWrite.dstSet = *set;
writes.push_back(newWrite);
}
vkUpdateDescriptorSets(*mAllocator->device,static_cast<uint32_t>(writes.size()),writes.data(),0,nullptr);
return true;
}