8

假设我有多个要使用不同材质渲染的网格。我知道我可以使用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

但是当我这样做时,它不起作用。验证层说你必须在调用我渲染的第二个网格beginCommandBuffer的任何命令之前调用vkCmdBindDescriptorSetsvkCmdBindPipeline等等。

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

4

1 回答 1

6

来自 Vulkan 规范:

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

(重点补充)

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

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

于 2016-07-09T18:39:50.920 回答