hid*_*yat 6 c++ graphics vulkan
假设我想用不同的材料渲染多个网格。我知道我可以push constants
在这个例子中使用,但这个问题更多地是为了理解 vkDescriptorset 是如何工作的。
struct Material {
vec4 color;
vkDescriptorset descriptorSet;
VkDescriptorBufferInfo descriptorBufferInfo;
};
Run Code Online (Sandbox Code Playgroud)
我只叫vkUpdateDescriptorSets
了_descriptorBufferInfo
对数据的缓冲区创建后。一切正常。
我测试了另一个解决方案。我不是vkDescriptorset
每种材料都有一个,而是所有材料都只有一个。而里面的rendepass
I call vkUpdateDescriptorSets
for each of the material 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
Run Code Online (Sandbox Code Playgroud)
但是当我这样做时,它不起作用。验证层表示您必须beginCommandBuffer
在为我渲染的第二个网格调用任何命令vkCmdBindDescriptorSets
、vkCmdBindPipeline
等之前调用。
那么这里的问题是什么,我不能在多个 VkDescriptorBufferInfo 之间共享一个 vkDescriptorset,或者我不能在 renderPass 内更新它吗?
来自 Vulkan 规范:
通过调用 vkCmdBindDescriptorSets 绑定的描述符集内容可能会在命令的主机执行期间、结果绘制的着色器执行期间或两者之间的任何时间被消耗。因此,在记录命令和命令在队列上完成执行之间,内容不得更改(被更新命令覆盖或释放)。
(强调)
据推测,您的renderMesh
调用将描述符集绑定到命令缓冲区。从那一刻起,在该命令缓冲区中的命令完成(或 CB 被破坏)之前,您不得以任何方式修改该描述符集。
这就是动态统一/存储缓冲区存在的原因。它们允许您更改统一/存储缓冲区的基本偏移量,而不会被视为对实际描述符集的修改。因此,您可以在具有不同缓冲区偏移量的多个位置使用相同的描述符集。