vkCmdClearColorImage не может очистить изображение, макет которого - PullRequest
1 голос
/ 11 июня 2019

Я пытаюсь очистить экран, но я получаю сообщение об ошибке при вызове vkCmdClearColorImage ().Он (уровень проверки) сообщает, что текущим макетом изображения является VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, в то время как vkCmdClearColorImage использует VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (это то, что предполагается использовать)является).Когда я заканчиваю запись в буфер команд, я получаю исключение.

Вот запись в буфер команд

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);
    }

Это должно очистить экран до определенного цвета.Вот ошибка, которую я получаю от проверки

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

Ответы [ 2 ]

1 голос
/ 13 июня 2019

Не делайте vkCmdClearColorImage(), если вы можете избежать этого;на многих архитектурах (в частности, мобильных) гораздо эффективнее использовать clear loadOp на проходе рендеринга.

1 голос
/ 12 июня 2019

Ваш srcStage в первом барьере "настоящее для очистки" равен VK_PIPELINE_STAGE_TRANSFER_BIT.

Это было бы правильно только в том случае, если в командный буфер передается семафор ожидания с pWaitDstStageMask, равным VK_PIPELINE_STAGE_TRANSFER_BIT, для того, чтобы этот барьер зацепил ожидание семафора, которое получает сигналы изображения swapchain.

...