8

Lets say I have multiple meshes I want to render with different materials. I know I can use push constants for this example, but this question is more to understand how vkDescriptorset is suppose to work.

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

I only call vkUpdateDescriptorSets for _descriptorBufferInfo after the buffer for the data has been created. Everything works fine.

I tested another solution. Instead of having one vkDescriptorset per material, I have only one for all of them. And inside the rendepass I call vkUpdateDescriptorSets for the 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

But when I do this, it does not work. The validation layer says you have to call beginCommandBuffer before calling any of the commands, vkCmdBindDescriptorSets, vkCmdBindPipeline etc for second mesh I render.

So what is the problem here, can I not share an vkDescriptorset between multiple VkDescriptorBufferInfo, or can I not update it inside a renderPass?

hidayat
  • 9,493
  • 13
  • 51
  • 66

1 Answers1

6

From the Vulkan specification:

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.

(emphasis added)

Presumably, your renderMesh call binds the descriptor set to the command buffer. From that moment forward, you are not allowed to modify that descriptor set in any way until the commands in that command buffer have completed (or the CB was destroyed).

This is why dynamic uniform/storage buffers exist. They allow you to change the base offset of a uniform/storage buffer without being considered a modification of the actual descriptor set. So you can use the same descriptor set in multiple places with a different buffer offset.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982