Use of SecondaryCommandBuffer raises validation Layer debug info

Hi,

i am implementing a secondaryCommandBuffer, which shall be saved in the master (primaryCommandBuffer).
I want to create for every different mesh like a house, a animal etc a secondaryCommandBuffer.
The following method is raised at vkQueueSubmit(…) in the Draw method.


validation layer: Commandbuffer 0xa8c7750 was submitted with secondary buffer 0xa8cb400 but that buffer has subsequently been bound to primary cmd buffer 0xa8ccb80 and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. The spec valid usage text states 'If any secondary command buffers recorded into any element of the pCommandBuffers member of any element of pSubmits was not recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, it must not be in the pending state.' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkQueueSubmit-pCommandBuffers-00073)
validation layer: Commandbuffer 0xa8c7ca8 was submitted with secondary buffer 0xa8cb400 but that buffer has subsequently been bound to primary cmd buffer 0xa8ccb80 and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. The spec valid usage text states 'If any secondary command buffers recorded into any element of the pCommandBuffers member of any element of pSubmits was not recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, it must not be in the pending state.' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkQueueSubmit-pCommandBuffers-00073)

If I am changing the flag of the secondary Buffer to VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT. I get the following message:


No active render pass found at draw-time in Pipeline (0xd)!
validation layer: vkCmdDrawIndexed(): This call must be issued inside an active render pass. The spec valid usage text states 'This command must only be called inside of a render pass instance' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdDrawIndexed-renderpass)
validation layer: vkCmdExecuteCommands(): Secondary Command Buffer (0xab1eec8) executed within render pass (0x9) must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. The spec valid usage text states 'If vkCmdExecuteCommands is being called within a render pass instance, each element of pCommandBuffers must have been recorded with the VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdExecuteCommands-pCommandBuffers-00096)
validation layer: vkCmdExecuteCommands(): Secondary Command Buffer (0xab1eec8) executed within render pass (0x9) must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. The spec valid usage text states 'If vkCmdExecuteCommands is being called within a render pass instance, each element of pCommandBuffers must have been recorded with the VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdExecuteCommands-pCommandBuffers-00096)
validation layer: vkCmdExecuteCommands(): Secondary Command Buffer (0xab1eec8) executed within render pass (0x9) must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. The spec valid usage text states 'If vkCmdExecuteCommands is being called within a render pass instance, each element of pCommandBuffers must have been recorded with the VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdExecuteCommands-pCommandBuffers-00096)

But I am wondering about this message, because my vkCmdExecuteCommands() command is inside a active Render Pass. I don’t know what I am doing false.


void CVulkanDrawing::CreateCommandBuffers()
{
    commandBuffers.resize(swapChainFramebuffers.size());

    VkCommandBufferAllocateInfo allocInfo = {};
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    ...

    if (vkAllocateCommandBuffers(m_LogicalDevice.getDevice(), &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
        throw std::runtime_error("failed to allocate command buffers!");
    }

    for (size_t i = 0; i < commandBuffers.size(); i++) {
        VkCommandBufferBeginInfo beginInfo = {};
        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
        beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
        beginInfo.pInheritanceInfo = nullptr; // Optional

        if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) {
            throw std::runtime_error("failed to begin recording command buffer!");
        }

        VkRenderPassBeginInfo renderPassInfo = {};
        renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
        renderPassInfo.renderPass = m_Pipeline.GetRenderPass();
        renderPassInfo.framebuffer = swapChainFramebuffers[i];
        renderPassInfo.renderArea.offset = { 0, 0 };
        renderPassInfo.renderArea.extent = m_Presentation.GetSwapChainExtend();
        
        VkClearValue clearColor = { 0.0f, 0.0f, 0.0f, 1.0f };
        renderPassInfo.clearValueCount = 1;
        renderPassInfo.pClearValues = &clearColor;

        vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
                vkCmdExecuteCommands(commandBuffers[i], m_SecondaryCommandBuffer.size(), m_SecondaryCommandBuffer.data());
        vkCmdEndRenderPass(commandBuffers[i]);

        if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
            throw std::runtime_error("failed to record command buffer!");
        }

    }
}


void CVulkanDrawing::CreateSecondaryCommandBuffers()
{
    VkCommandBuffer secondaryCommandBuffer;
    VkCommandBufferAllocateInfo allocInfo = {};
    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
    ...

    if (vkAllocateCommandBuffers(m_LogicalDevice.getDevice(), &allocInfo, &secondaryCommandBuffer) != VK_SUCCESS) {
        throw std::runtime_error("failed to allocate command buffers!");
    }

    VkCommandBufferInheritanceInfo inheritanceInfo;
    inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
    inheritanceInfo.pNext = nullptr;
    inheritanceInfo.renderPass = m_Pipeline.GetRenderPass();
    inheritanceInfo.subpass = 0;
    inheritanceInfo.occlusionQueryEnable = VK_FALSE;
    inheritanceInfo.framebuffer = VK_NULL_HANDLE;
    inheritanceInfo.pipelineStatistics = 0;
    //inheritanceInfo.framebuffer = 

    VkCommandBufferBeginInfo beginInfo = {};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
    beginInfo.pInheritanceInfo = &inheritanceInfo; // Optional

    if (vkBeginCommandBuffer(secondaryCommandBuffer, &beginInfo) != VK_SUCCESS) {
        throw std::runtime_error("failed to begin recording command buffer!");
    }

    vkCmdBindPipeline(secondaryCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_Pipeline.GetGraphicsPipeline());

    VkBuffer vertexBuffers[] = { vertexBuffer };
    VkDeviceSize offsets[] = { 0 };
    vkCmdBindVertexBuffers(secondaryCommandBuffer, 0, 1, vertexBuffers, offsets);
    vkCmdBindIndexBuffer(secondaryCommandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);

    vkCmdDrawIndexed(secondaryCommandBuffer, static_cast<uint32_t>(m_Indices.size()), 1, 0, 0, 0);

    if (vkEndCommandBuffer(secondaryCommandBuffer) != VK_SUCCESS) {
        throw std::runtime_error("failed to record command buffer!");
    }

    m_SecondaryCommandBuffer.push_back(secondaryCommandBuffer);
}


void CVulkanDrawing::Draw()
{
    vkWaitForFences(m_LogicalDevice.getDevice(), 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
    vkResetFences(m_LogicalDevice.getDevice(), 1, &inFlightFences[currentFrame]);

    uint32_t imageIndex;
    vkAcquireNextImageKHR(m_LogicalDevice.getDevice(), m_Presentation.GetSwapChain(), std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);

    VkSubmitInfo submitInfo = {};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

    VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };

    VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
    submitInfo.waitSemaphoreCount = 1;
    submitInfo.pWaitSemaphores = waitSemaphores;
    submitInfo.pWaitDstStageMask = waitStages;

    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = &commandBuffers[imageIndex];

    VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };

    submitInfo.signalSemaphoreCount = 1;
    submitInfo.pSignalSemaphores = signalSemaphores;

    vkResetFences(m_LogicalDevice.getDevice(), 1, &inFlightFences[currentFrame]);

    if (vkQueueSubmit(m_LogicalDevice.GetGraphicsQueue(), 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
        throw std::runtime_error("failed to submit draw command buffer!");
    }

    ...
    
}

Best regards

Dennis

sorry, because of the double post. I haven’t found an edit Button.
I’ve read the spec and edited the the beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT and the beginInfo flag of the secondary Buffer to VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT.
But, now the folowing message is thrown every time at executing point vkQueueSubmit in Draw Method:

validation layer: Commandbuffer 0xa771a40 was submitted with secondary buffer 0xa75ca78 but that buffer has subsequently been bound to primary cmd buffer 0xa771f98 and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. The spec valid usage text states ‘If any secondary command buffers recorded into any element of the pCommandBuffers member of any element of pSubmits was not recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, it must not be in the pending state.’ (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkQueueSubmit-pCommandBuffers-00073)
validation layer: Commandbuffer 0xa759018 was submitted with secondary buffer 0xa75ca78 but that buffer has subsequently been bound to primary cmd buffer 0xa771f98 and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. The spec valid usage text states ‘If any secondary command buffers recorded into any element of the pCommandBuffers member of any element of pSubmits was not recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, it must not be in the pending state.’ (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkQueueSubmit-pCommandBuffers-00073)

I don’t know what does pending state means.

I got it. :slight_smile:
The Solution was changing SecondaryCommandBuffers flags to VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT.
Now, the warnings are disappeared.