Validation error on attemp to use vkCmdCopyImage

Hello,

Firstly, i need to describe what exactly i attempt to do:

  1. I need to read data from my depth buffer (actually, i need store data from my depth buffer into .png file).

  2. i can not read data from depth buffer directly, because depth image is not visible from host and because depth image has OPTIMAL_TILING (i can create host visible image for depth, but can not create depth image with linear tiling, because linear tiling is not compatibly with depth features flags (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)).

  3. so, i’ve created an empty image with the same format and linear tiling to copy depth data into this image.

  4. but every time, i attempts to submit vkCmdCopyImage in command buffer, i take an error:
    DS(ERROR): object: 0x1e33690 type: 6 location: 4471 msgCode: 6: Cannot submit cmd buffer using image (0x47) [sub-resource: aspectMask 0x2 array layer 0, mip level 0], with layout VK_IMAGE_LAYOUT_UNDEFINED when first use is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.


image create info for my depth image looks like (source image for copy command):


imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
                imageCreateInfo.extent.width = width;
                imageCreateInfo.extent.height = height;
                imageCreateInfo.extent.depth = 1;
                imageCreateInfo.mipLevels = 1;
                imageCreateInfo.arrayLayers = 1;
                imageCreateInfo.format = format; // in my case always VK_FORMAT_D32_SFLOAT
                imageCreateInfo.tiling =VK_IMAGE_TILING_OPTIMAL;
                imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT  | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
                imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

image create info for empty image (destination image for copy command):


imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
                imageCreateInfo.extent.width = width; // the same as for depth
                imageCreateInfo.extent.height = height; // the same as for depth
                imageCreateInfo.extent.depth = 1;
                imageCreateInfo.mipLevels = 1;
                imageCreateInfo.arrayLayers = 1;
                imageCreateInfo.format = format; // the same, VK_FORMAT_D32_SFLOAT
                imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
                imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
                imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

and finally copy command:


VkImageCopy imageCopy = {};

        imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
        imageCopy.srcSubresource.baseArrayLayer = 0;
        imageCopy.srcSubresource.layerCount = 1;
        imageCopy.srcSubresource.mipLevel = 0;
        imageCopy.srcOffset.x = 0;
        imageCopy.srcOffset.y = 0;
        imageCopy.srcOffset.z = 0;
        imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
        imageCopy.dstSubresource.baseArrayLayer = 0;
        imageCopy.dstSubresource.layerCount = 1;
        imageCopy.dstSubresource.mipLevel = 0;
        imageCopy.dstOffset.x = 0;
        imageCopy.dstOffset.y = 0;
        imageCopy.dstOffset.z = 0;
        imageCopy.extent.width = frameSize[0];
        imageCopy.extent.height = frameSize[1];
        imageCopy.extent.depth = 1;

        vkCmdCopyImage(commandBuffer->handle(),
                       frameBuffer->attachments()[0].imageView().image().handle(), // depth buffer image
                       VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                       depthDebugImage->handle(),  // my empty image for debug
                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                       1,
                       &imageCopy);

and as result:
DS(ERROR): object: 0x1e33690 type: 6 location: 4471 msgCode: 6: Cannot submit cmd buffer using image (0x47) [sub-resource: aspectMask 0x2 array layer 0, mip level 0], with layout VK_IMAGE_LAYOUT_UNDEFINED when first use is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.


Validation error says that initialLayout of destination image does not correspond with dstImageLayout in copy command, but they can’t correspond - i can not create image with initialLayout TRANSFER_DST, and can set dstImageLayout to LAYOUT_UNDEFINED.

So, how i can copy data from depthBuffer to another image? And what is the best way to extract data from depthBuffer (depth image)?

Maybe, i’ve missed some impotent detail to understand my problem (there are tons of code hidden in wrappers and abstractions - so, i can not post whole code at once)- let me know if i need to post some additional info to describe my issue.

Validation error says that initialLayout of destination image does not correspond with dstImageLayout in copy command, but they can’t correspond - i can not create image with initialLayout TRANSFER_DST, and can set dstImageLayout to LAYOUT_UNDEFINED.

That’s not what the validation error is saying.

Your copy command tells Vulkan, very clearly, that at the time the command executes, the destination image will be in the layout TRANSFER_DST_OPTIMAL. We’re not talking about the initial layout it was created in. We’re talking about the layout when you issue the copy.

The validation layer is telling you that it was actually paying attention to the sequence of commands you sent Vulkan, and you never actually changed the image’s layout to TRANSFER_DST_OPTIMAL. Therefore, you lied to Vulkan when you told it that the image’s layout would be TRANSFER_DST_OPTIMAL.

The solution is to perform a image layout transition on the destination image. So you would need a vkCmdPipelineBarrier to change from LAYOUT_UNDEFINED to TRANSFER_DST_OPTIMAL. And that needs to happen before calling the copy command.

Thanks!

My mistake, Image layout transition chapter has avoided from my attention, when i read synchronization part of specification last time.