Что может быть в случае, когда VkCmdPipelineBarrier () не изменяет макет изображения - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь извлечь изображения из swapchain и конвертировать их, чтобы я мог создать из них видео.

Я пытаюсь переместить макет изображения с помощью буфера команд однократной отправки.После отправки буфера команд в очередь я получаю предупреждения и ошибки от слоев проверки о том, что макеты изображений неправильно отформатированы, но я четко установил барьер конвейера, используя все правильные параметры.

Это происходит, даже когда я перемещаю макеты текстур для своих объектов, но все прекрасно работает даже с этими предупреждениями.Я не могу прочитать содержимое извлеченного изображения из-за этой ошибки.

Что может быть причиной этого?Вот как я конвертирую макеты:

VkCommandBuffer cmdBuffer = commandBuffer == VK_NULL_HANDLE ? 
                            CommandBufferHandler::createOneTimeUsageBuffer(commandPool, device) : commandBuffer;
VkImageMemoryBarrier barrier = {};
VkPipelineStageFlags sourceStage = {};
VkPipelineStageFlags dstStage = {};

barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = mipLevels;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;

if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;

    if (hasStencilComponent(format)) {
        barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
    }
}
else {
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}

if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
    barrier.srcAccessMask = 0;
    barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;

    sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
    barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;

    sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
    dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
    barrier.srcAccessMask = 0;
    barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;

    sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
    barrier.srcAccessMask = 0;
    barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
    barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;;
    barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
    sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
    dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
    barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
    barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
    dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_GENERAL) {
    barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
    dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else {
    throw std::invalid_argument("unsupported layout transition!");
}

vkCmdPipelineBarrier(cmdBuffer, sourceStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);

if (commandBuffer == VK_NULL_HANDLE) {
    CommandBufferHandler::endOneTimeUsageBuffer(cmdBuffer, queue, commandPool, device);
}

А вот как я делаю снимок:

VkImageCreateInfo screenshotCreateInfo;
VkImage srcImage = images[activeImageSwapchainId];
VkDeviceMemory dstImageMemory;
VkImage dstImage = VK_NULL_HANDLE;

if (supportsBlit) {
    VkCommandBuffer cmdBuffer = CommandBufferHandler::createOneTimeUsageBuffer(
        mainWindow->getCommandHandler()->getCommandPool(), mainWindow->getRenderer()->getDevice());

    Util::createImage(sizeX, sizeY, 1, VK_FORMAT_B8G8R8A8_UNORM,
        VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
        &dstImage, &dstImageMemory, mainWindow->getRenderer()->getDevice(),
        mainWindow->getRenderer()->getPhysicalDeviceMemoryPropertiesPTR());

    Util::transitionImageLayout(dstImage,
        VK_FORMAT_B8G8R8A8_UNORM,
        VK_IMAGE_LAYOUT_UNDEFINED,
        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
        mainWindow->getCommandHandler()->getCommandPool(),
        mainWindow->getRenderer()->getQueueIndices()->getQueue(),
        mainWindow->getRenderer()->getDevice(),
        1,
        cmdBuffer);

    Util::transitionImageLayout(srcImage,
        VK_FORMAT_B8G8R8A8_UNORM,
        VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
        mainWindow->getCommandHandler()->getCommandPool(),
        mainWindow->getRenderer()->getQueueIndices()->getQueue(),
        mainWindow->getRenderer()->getDevice(),
        1,
        cmdBuffer);


    VkOffset3D offsets{};
    offsets.x = swapExtent.width;
    offsets.y = swapExtent.height;
    offsets.z = 1;

    VkImageBlit blit{};
    blit.srcSubresource.layerCount = 1;
    blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    blit.dstSubresource.layerCount = 1;
    blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    blit.srcOffsets[1] = offsets;
    blit.dstOffsets[1] = offsets;

    vkCmdBlitImage(cmdBuffer,
        srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
        dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
        1, &blit, VK_FILTER_NEAREST);

    Util::transitionImageLayout(dstImage, VK_FORMAT_B8G8R8A8_UNORM,
        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
        mainWindow->getCommandHandler()->getCommandPool(),
        mainWindow->getRenderer()->getQueueIndices()->getQueue(),
        mainWindow->getRenderer()->getDevice(),
        1,
        cmdBuffer);

    Util::transitionImageLayout(srcImage, VK_FORMAT_B8G8R8A8_UNORM,
        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
        mainWindow->getCommandHandler()->getCommandPool(),
        mainWindow->getRenderer()->getQueueIndices()->getQueue(),
        mainWindow->getRenderer()->getDevice(),
        1,
        cmdBuffer);

    CommandBufferHandler::endOneTimeUsageBuffer(cmdBuffer, mainWindow->getRenderer()->getQueueIndices()->getQueue(),
        mainWindow->getCommandHandler()->getCommandPool(), mainWindow->getRenderer()->getDevice());

    VkImageSubresource subresource{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
    VkSubresourceLayout subresourceLayout;
    vkGetImageSubresourceLayout(mainWindow->getRenderer()->getDevice(), dstImage, &subresource, &subresourceLayout);

    const char *data = nullptr;
    vkMapMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
    data += subresourceLayout.offset;

    std::ofstream file(filePath, std::ios::out | std::ios::binary);
    file << "P6\n" << swapExtent.width << "\n" << swapExtent.height << "\n" << 255 << "\n";     //File header

    for (uint32_t y = 0; y < swapExtent.height; ++y) {
        unsigned int *row = (unsigned int*)data;

        for (uint32_t x = 0; x < swapExtent.width; ++x) {
            file.write((char*)row, 3);
            row++;
        }

        data += subresourceLayout.rowPitch;
    }

    file.close();

    std::cout << "Screenshot saved to: " << filePath << std::endl;

    vkUnmapMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory);
    vkFreeMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory, nullptr);
    vkDestroyImage(mainWindow->getRenderer()->getDevice(), dstImage, nullptr);
}
else {
    assert(0 && "Swapchain error: Your device does not support image blitting. Cannot save image. Will be patched.");
    return;
}

Предупреждения такие же, как на изображении ниже.Все остальные предупреждения приходят от того, что мой макет изображения не был переведен.

Mip levels are 0-9

Когда я использую Blit, я получаю эту ошибку.Я создаю dstImage в формате VK_FORMAT_R8G8B8A8_UNORM.

1 Ответ

0 голосов
/ 13 февраля 2019

Предупреждения, которые я получаю, не связаны с попыткой извлечь изображение.Они были от попытки создать текстурные мипмапы для моего объекта.Это то, что я не исправил.

Я исправил эту ошибку.Я просто избегал его использования и использовал вместо него vkCmdCopyImage().Вот как:

void Swapchain::saveScreenshot(std::string filePath) {
    VkImageCreateInfo screenshotCreateInfo;
    VkImage srcImage = images[activeImageSwapchainId];
    VkDeviceMemory dstImageMemory;
    VkImage dstImage = VK_NULL_HANDLE;

    if (supportsBlit) {
        VkCommandBuffer cmdBuffer = CommandBufferHandler::createOneTimeUsageBuffer(
            mainWindow->getCommandHandler()->getCommandPool(), mainWindow->getRenderer()->getDevice());

        Util::createImage(sizeX, sizeY, 1, VK_FORMAT_R8G8B8A8_UNORM,
            VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
            &dstImage, &dstImageMemory, mainWindow->getRenderer()->getDevice(),
            mainWindow->getRenderer()->getPhysicalDeviceMemoryPropertiesPTR());

        //NOVU Sliku prebacujemo u transfer destination
        Util::transitionImageLayout(dstImage,
            VK_FORMAT_R8G8B8A8_UNORM,
            VK_IMAGE_LAYOUT_UNDEFINED,
            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
            mainWindow->getCommandHandler()->getCommandPool(),
            mainWindow->getRenderer()->getQueueIndices()->getQueue(),
            mainWindow->getRenderer()->getDevice(),
            1,
            cmdBuffer);

        //Staru sliku prebacujemo iz prezentacije u transfer source
        Util::transitionImageLayout(srcImage,
            VK_FORMAT_R8G8B8A8_UNORM,
            VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
            VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
            mainWindow->getCommandHandler()->getCommandPool(),
            mainWindow->getRenderer()->getQueueIndices()->getQueue(),
            mainWindow->getRenderer()->getDevice(),
            1,
            cmdBuffer);

        VkExtent3D extent = { swapExtent.width, swapExtent.height, 1 };
        VkOffset3D offsets{};
        offsets.x = 0;
        offsets.y = 0;
        offsets.z = 0;

        VkImageSubresourceLayers layers{};
        layers.mipLevel = 0;
        layers.layerCount = 1;
        layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        layers.baseArrayLayer = 0;

        VkImageCopy regions{};
        regions.dstOffset = offsets;
        regions.extent = extent;
        regions.srcOffset = offsets;
        regions.srcSubresource = layers;
        regions.dstSubresource = layers;

        vkCmdCopyImage(cmdBuffer,
            srcImage,
            VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
            dstImage,
            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
            1,
            &regions);

        Util::transitionImageLayout(dstImage, VK_FORMAT_R8G8B8A8_UNORM,
            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
            mainWindow->getCommandHandler()->getCommandPool(),
            mainWindow->getRenderer()->getQueueIndices()->getQueue(),
            mainWindow->getRenderer()->getDevice(),
            1,
            cmdBuffer);

        Util::transitionImageLayout(srcImage, VK_FORMAT_R8G8B8A8_UNORM,
            VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
            mainWindow->getCommandHandler()->getCommandPool(),
            mainWindow->getRenderer()->getQueueIndices()->getQueue(),
            mainWindow->getRenderer()->getDevice(),
            1,
            cmdBuffer);

        CommandBufferHandler::endOneTimeUsageBuffer(cmdBuffer, mainWindow->getRenderer()->getQueueIndices()->getQueue(),
            mainWindow->getCommandHandler()->getCommandPool(), mainWindow->getRenderer()->getDevice());

        unsigned char *data = nullptr;
        vkMapMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);

        MagickCore::MagickWand *wand = MagickCore::NewMagickWand();
        MagickConstituteImage(wand, swapExtent.width, swapExtent.height, "BGRA", MagickCore::CharPixel, data);

        vkUnmapMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory);
        vkFreeMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory, nullptr);
        vkDestroyImage(mainWindow->getRenderer()->getDevice(), dstImage, nullptr);

        MagickCore::MagickBooleanType status = MagickWriteImage(wand, filePath.c_str());

        if (!status) {
            assert(0 && "ImageMagick error: Unable to save image to file.");
        }

        MagickCore::DestroyMagickWand(wand);
        MagickCore::MagickWandTerminus();
    }
    else {
        assert(0 && "Swapchain error: Your device does not support image blitting. Cannot save image. Will be patched.");
        return;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...