1

I'm trying to clear the screen, but i get an error when calling vkCmdClearColorImage(). It (The Validation layer) reports that the current image layout is VK_IMAGE_LAYOUT_PRESENT_SRC_KHR while vkCmdClearColorImage uses VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (this is the one that's supposed to be used)

I checked so that VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL is available in the swap chain creation (which it is). When I end the command buffer recording i get an exception.

Here's the command buffer recording

VkCommandBufferAllocateInfo allocationInfo = {};
    allocationInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocationInfo.commandPool = m_ContextPtr->commandPool;
    allocationInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocationInfo.commandBufferCount = (uint32_t)commandBuffers.size();

    VkCommandBufferBeginInfo beginInfo = {};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
    beginInfo.pInheritanceInfo = nullptr;

    if (vkAllocateCommandBuffers(m_ContextPtr->device, &allocationInfo, commandBuffers.data()) != VK_SUCCESS)
        Utils::Logger::logMSG("Failed to allocate command buffers\n", "Rendering", Utils::Severity::Error);

    uint32_t presentQueueFamily = VulkanPhysicalDevice::getQueueFamilyIndices(m_CurrentWindow->m_Surface, m_ContextPtr->mainPhysicalDevice.physicalDevice).presentFamily;

    VkClearColorValue clearColor = { m_ClearValue.x, m_ClearValue.y, m_ClearValue.z, 1.0f };

    VkImageSubresourceRange subResourceRange = {};
    subResourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    subResourceRange.baseMipLevel = 0;
    subResourceRange.levelCount = 1;
    subResourceRange.baseArrayLayer = 0;
    subResourceRange.layerCount = 1;

    for (size_t i = 0; i < commandBuffers.size(); i++)
    {
        VkImageMemoryBarrier presentToClearBarrier = {};
        presentToClearBarrier.sType                 = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        presentToClearBarrier.srcAccessMask         = VK_ACCESS_MEMORY_READ_BIT;
        presentToClearBarrier.dstAccessMask         = VK_ACCESS_TRANSFER_WRITE_BIT;
        presentToClearBarrier.oldLayout             = VK_IMAGE_LAYOUT_UNDEFINED;
        presentToClearBarrier.newLayout             = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
        presentToClearBarrier.srcQueueFamilyIndex   = presentQueueFamily;
        presentToClearBarrier.dstQueueFamilyIndex   = presentQueueFamily;
        presentToClearBarrier.image                 = m_CurrentWindow->m_SwapChain.swapChainImages[i];
        presentToClearBarrier.subresourceRange      = subResourceRange;

        VkImageMemoryBarrier clearToPresentBarrier = {};
        presentToClearBarrier.sType                 = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
        presentToClearBarrier.srcAccessMask         = VK_ACCESS_TRANSFER_WRITE_BIT;
        presentToClearBarrier.dstAccessMask         = VK_ACCESS_MEMORY_READ_BIT;
        presentToClearBarrier.oldLayout             = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
        presentToClearBarrier.newLayout             = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
        presentToClearBarrier.srcQueueFamilyIndex   = presentQueueFamily;
        presentToClearBarrier.dstQueueFamilyIndex   = presentQueueFamily;
        presentToClearBarrier.image                 = m_CurrentWindow->m_SwapChain.swapChainImages[i];
        presentToClearBarrier.subresourceRange      = subResourceRange;

        vkBeginCommandBuffer(commandBuffers[i], &beginInfo);

        vkCmdPipelineBarrier
        (
            commandBuffers[i],
            VK_PIPELINE_STAGE_TRANSFER_BIT,
            VK_PIPELINE_STAGE_TRANSFER_BIT,
            0, 0, nullptr, 0, nullptr, 1,
            &presentToClearBarrier
        );
        vkCmdClearColorImage
        (
            commandBuffers[i],
            m_CurrentWindow->m_SwapChain.swapChainImages[i],
            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
            &clearColor, 1,
            &subResourceRange
        );
        vkCmdPipelineBarrier
        (
            commandBuffers[i],
            VK_PIPELINE_STAGE_TRANSFER_BIT,
            VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
            0, 0, nullptr, 0, nullptr, 1,
            &clearToPresentBarrier
        );

        if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS)
            Utils::Logger::logMSG("Failed to record command buffer\n", "Rendering", Utils::Severity::Error);
    }

It's supposed to clear the screen to a specific color. Here's the error i get from the validation

vkCmdClearColorImage(): Cannot clear an image whose layout is 
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and doesn't match the current layout 
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
  • It might depend on something before your posted code. Your `srcStage` is `VK_PIPELINE_STAGE_TRANSFER_BIT`. Does anything before the `vkCmdPipelineBarrier` form a dependency chain to that stage? – krOoze Jun 11 '19 at 17:37
  • Sounds like a variation on this problem: https://stackoverflow.com/questions/37524032/how-to-deal-with-the-layouts-of-presentable-images – Jherico Jun 11 '19 at 17:48
  • TBF, the error msg could perhaps use some improvements. I would encourage people to write Issues at https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues. If a msg confuses a trained engineer, chances are it could be improved... I think at least 5 similar Qs could be found on SO. – krOoze Jun 11 '19 at 17:56
  • @krOoze I don't disagree. I think understanding barriers is probably one of the biggest obstacles to new developers learning Vulkan. On the other hand over-specifying the validation layer message can send a dev off in the wrong direction. – Jherico Jun 11 '19 at 23:47
  • @Jherico You make a good case for just-right-specifying the msg. :D In this case if I am right I would say the msg is misleading; It forces user to white-box know the layer to know why they think an Image is in layout X. I think the actual error is that the image may be in two layouts at the point of consumption by `vkCmdClearColorImage`, and it would be more clear if the layers said so. Also what's the difference between "image's layout" and "current layout"; unfortunate error msg wording.. – krOoze Jun 12 '19 at 12:54

2 Answers2

2

Your srcStage in the first "present-to-clear" barrier is VK_PIPELINE_STAGE_TRANSFER_BIT.

That would only be correct if the command buffer is submitted with a wait Semaphore with a pWaitDstStageMask of VK_PIPELINE_STAGE_TRANSFER_BIT, in order for that barrier to chain off the semaphore wait which acquiring swapchain image signals.

krOoze
  • 12,301
  • 1
  • 20
  • 34
1

Don't do vkCmdClearColorImage() if you can avoid it; on many architectures (in particular mobile) it's much more efficient to use a clear loadOp on the render pass.

solidpixel
  • 10,688
  • 1
  • 20
  • 33