Vulkan多网格独用纹理绘制报错:描述符集已销毁或更新
解决Vulkan中「descriptorset is destroyed or updated」报错问题
兄弟,你这明显踩了Vulkan里Descriptor Set同步的经典坑了!咱们先把问题掰碎了说:
为什么原来的流程没问题?
之前你先调用UpdateDescriptorSets(texture)把全局纹理绑定到同一个Descriptor Set,再遍历网格录制Draw命令——这时候整个命令缓冲录制过程中,这个Set的内容是完全稳定的,所有Draw命令引用的都是同一个“固定版本”的Set,Vulkan完全认可这种操作,自然不会报错。
你的修改错在哪?
现在你把UpdateDescriptorSets(textures[meshindex])塞进了命令缓冲录制的循环里,这就犯了Vulkan的大忌:
- 第一次循环:绑定UBO → 更新Set → 录制Draw命令(此时命令缓冲已经记下了对这个Set的引用)
- 第二次循环:你又去更新同一个Set——这直接让之前命令缓冲里的引用失效了!Vulkan规定:一旦一个Descriptor Set被记录到命令缓冲中,在这个命令缓冲执行完成之前,绝对不能修改它的内容,否则就会触发你看到的「descriptorset is destroyed or updated」错误。
说白了就是:你给GPU递了一份“操作清单”(命令缓冲),清单里说要用某份文件(Descriptor Set),结果GPU还没执行到那一步,你就把文件内容改了,系统当然要报错。
正确的解决办法
方案1:为每个网格分配独立的Descriptor Set(首推)
这是最贴合Vulkan设计思路的做法,操作也清晰:
- 提前基于同一个Descriptor Set Layout,为每个纹理分配一个独立的Descriptor Set
- 录制命令缓冲时,遍历每个网格:
- 绑定该网格的Transform UBO
- 用
vkCmdBindDescriptorSets绑定这个网格专属的Descriptor Set - 执行Draw命令
每个网格用自己的Set,互相完全不干扰,再也不会出现修改已被引用的Set的问题。
方案2:用Descriptor Set模板(适合纹理极多的场景)
如果你的场景里纹理数量特别大,不想提前分配大量Set,可以试试VK_EXT_descriptor_template扩展。它允许你在录制命令缓冲时快速更新Set的内容,但必须做好同步(比如用Fence确保上一帧的命令完全执行完后,再更新Set)。不过这个方案复杂度高,新手还是优先选方案1。
额外提醒
- 分配Descriptor Set前,要确保你的Descriptor Pool有足够的容量,不然会分配失败
- 所有网格的Descriptor Set必须基于兼容的Descriptor Set Layout,不然没法绑定到同一个Pipeline
内容的提问来源于stack exchange,提问作者IAS0601
相关产品推荐
相关产品推荐

