Create command buffers

In order to feed the GPU with instructions, we will need to create command buffers. The core object creating command buffers is a command pool. The command pool is assigned a queue family index. All command buffers allocated from this command pool are only to be used on any command queue with that family index, in our case, the graphics queue we identified earlier.

Command buffers allocated from a command pool need to be in a recording state in order to allow rendering commands to be added to the command list, which can be done using vkBeginCommandBuffer and can be stopped using vkEndCommandBuffer.

While in the recording state, the command buffer can not be submitted for execution by the GPU. Similarly, while the command buffer is being executed by the GPU, the command buffer can not be recorded. As a result, when the GPU is still executing, we would like to record commands into another command buffer on the CPU for submission as soon as the other command buffer is done.

VkCommandPool commandPool;
result = vkCreateCommandPool (
        .pNext            = NULL,
        .queueFamilyIndex = graphicsQueueIndex,
if ( result != VK_SUCCESS )
    RETURN_ERROR(-1,"vkCreateCommandPool failed (0x%08X)", (uint32_t)result);

for ( uint32_t i = 0; i < FRAME_BUFFER_COUNT; i++ )
    result = vkAllocateCommandBuffers (
            .pNext              = NULL,
            .commandPool        = commandPool,
            .level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
            .commandBufferCount = 1,
    if ( result != VK_SUCCESS )
        RETURN_ERROR(-1,"vkAllocateCommandBuffers failed (0x%08X)", (uint32_t)result);