假设我有多个网格,我想用不同的材质渲染。我知道我可以在这个例子中使用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
,vkCmdBindDescriptorSets
等之前调用vkCmdBindPipeline
以获取第二个我渲染的网格。
那么这里有什么问题,我可以不在多个VkDescriptorBufferInfo之间共享vkDescriptorset,还是不能在renderPass中更新它?
答案 0 :(得分:2)
来自Vulkan规范:
通过调用vkCmdBindDescriptorSets绑定的描述符集内容可以在命令的主机执行期间消耗,或者在生成的绘制的着色器执行期间或其间的任何时间消耗。因此,在记录命令和命令在队列上完成执行之间,内容不得更改(由更新命令覆盖,或释放)。
(强调补充)
据推测,您的renderMesh
调用将描述符集绑定到命令缓冲区。从那一刻开始,在命令缓冲区中的命令完成(或CB被销毁)之前,不允许以任何方式修改该描述符集。
这就是存在动态统一/存储缓冲区的原因。它们允许您更改统一/存储缓冲区的基本偏移量,而不将视为实际描述符集的修改。因此,您可以在具有不同缓冲区偏移量的多个位置使用相同的描述符集。