c – 更新renderPass中的VkDescriptorSet

假设我有多个网格我想用不同的材质渲染.我知道我可以在这个例子中使用推式常量,但这个问题更多的是要了解vkDescriptorset是如何工作的.

struct Material {
    vec4 color;
    vkDescriptorset descriptorSet;
    VkDescriptorBufferInfo descriptorBufferInfo;
};

在创建数据缓冲区后,我只为_descriptorBufferInfo调用vkUpdateDescriptorSets.一切正常.

我测试了其他解决方案而不是每个材料都有一个vkDescriptorset,我只有一个用于所有材料.在rendepass中,我为每个材质VkDescriptorBufferInfo调用vkUpdateDescriptorSets.

vkDescriptorset globalDescriptorSet;
struct Material {
  vec4 color;
  VkDescriptorBufferInfo descriptorBufferInfo;
};

beginCommandBuffer
beginRenderPass
for (auto &mesh : meshes) {
    ...
    writeDescriptorSets.dstSet = globalDescriptorSet;
    writeDescriptorSets.pBufferInfo = &mesh.material.descriptorBufferInfo;
    ....
    vkUpdateDescriptorSets(device, 1, &writeDescriptorSets, 0, nullptr);
    renderMesh(mesh);
}
endRenderPass
endCommandBuffer

但是当我这样做时,它不起作用.验证层表示你必须在调用任何命令之前调用beginCommandBuffer,vkCmdBindDescriptorSets,vkCmdBindPipeline等为第二个网格渲染.

那么这里有什么问题,我可以不在多个VkDescriptorBufferInfo之间共享vkDescriptorset,还是不能在renderPass中更新它?

最佳答案 从Vulkan规范:

The descriptor set contents bound by a call to vkCmdBindDescriptorSets may be consumed during host execution of the command, or during shader execution of the resulting draws, or any time in between. Thus, the contents must not be altered (overwritten by an update command, or freed) between when the command is recorded and when the command completes executing on the queue.

(重点补充)

据推测,您的renderMesh调用将描述符集绑定到命令缓冲区.从那一刻起,在命令缓冲区中的命令完成(或CB被销毁)之前,不允许以任何方式修改该描述符集.

这就是存在动态统一/存储缓冲区的原因.它们允许您更改统一/存储缓冲区的基本偏移量,而不会被视为对实际描述符集的修改.因此,您可以在具有不同缓冲区偏移量的多个位置使用相同的描述符集.

点赞