更新renderPass中的VkDescriptorSet

时间:2016-07-09 18:01:15

标签: c++ graphics vulkan

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

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

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

我测试了另一个解决方案。而不是每种材料只有一个vkDescriptorset,我只有一个用于所有材料。在rendepass内,我为每个材料vkUpdateDescriptorSets调用VkDescriptorBufferInfo

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

但是当我这样做时,它不起作用。验证层表示您必须在调用任何命令beginCommandBuffervkCmdBindDescriptorSets等之前调用vkCmdBindPipeline以获取第二个我渲染的网格。

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

1 个答案:

答案 0 :(得分:2)

来自Vulkan规范:

  

通过调用vkCmdBindDescriptorSets绑定的描述符集内容可以在命令的主机执行期间消耗,或者在生成的绘制的着色器执行期间或其间的任何时间消耗。因此,在记录命令和命令在队列上完成执行之间,内容不得更改(由更新命令覆盖,或释放)。

(强调补充)

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

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