Search code examples
graphicsrenderingvulkan

Is it able to call multiple drawcalls of vkCmdDrawIndexed in one render pass containing one pipeline?


I have two meshes, containing same material template but with different paramters. I want to draw these two meshes one by one. For example, the pseudocode likes

BeginRenderPass
BindPipeline

for(auto& mesh : meshes)
{
    BindVertexBuffers(mesh.vertexBuffer)
    AddUniformBufferDescriptorSet(mesh.material)
    UpdateDescriptorSets
    BindIndexBuffer(mesh.indexBuffer)
    DrawIndexed(mesh.indexCount, 1, 0, 0, 0)
}

vkCmdEndRenderPass

I bind vertex buffers of all mesh to same binding index, and use same descriptor set for all uniform object. There are some validation errors:

validation layer: Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkDescriptorSet ] Object 0: handle = 0x40b43c0000000049, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; Object 1: handle = 0x1c40e53df48, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0xe8616bf2 | You are adding vkCmdBindVertexBuffers() to VkCommandBuffer 0x1c40e53df48[] that is invalid because bound VkDescriptorSet 0x40b43c0000000049[] was destroyed or updated.

How can I implement the above pseudocode ?


Solution

  • There is my finding(WRONG). ~~First, the conclusion is I can not implment mulitple draw calls like the above pseudocode.~~ Because, according to vkUpdateDescriptorSets , it will invalid the command buffer used to bind the descriptor sets, which will disenable record next call. Therefore, the validation error appears.

    What I can implement to draw multiple meshes with seperate material parameters.

    There are two ways:

    • Use push_constant in shader to config material parameters, and set the corresponding parameter values by vkCmdPushConstants before draw call.
    • Use uniform buffer array in shader, where each element is a set of material parameters. Add an additional input attribute named “material id” to index the corresponding uniform buffer. Then update the uniform buffer array in one call of vkUpdateDescriptorSets. The current command buffer still can record next draw call command.

    The first way is inspired by Sascha_Willems, the second way is what I have successfully implemented.

    Supplement(CORRECTION)

    I also try to update and bind the corresponding descriptor set before each of two draw calls insider one render pass. Finally, it works. Note that two seperate descriptor sets with same layout bindings need to be created, but the graphics pipeline need to be decleared to contain only one descriptor set.