Problem with offline rendering

Hello.

I have a problem that I don’t know how to approach after trying to deal with it for the last week.

In a nutshell – I am developing a Vulkan v1.00 based engine for a game and its custom content editor. Currently, it works fine with the usage of swap chain images for color attachment and a depth image for depth testing. Nothing fancy, just glue between my code and shader programs. Currently, I need to create an offscreen renderer to create UI icons for content created in this editor.
My thinking was that I was just going to replace the swap chain obtained image used in VkFramebuffer creation with an image I made myself but otherwise re-use all the machinery I have set up so far.

The steps I’ve done so far:

  1. Create an image of an appropriate size. Image usage is set to:

VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT

  1. Immediately transition the image to:

layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
access: VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
stage: VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT

  1. Create VkFramebuffer, do my drawing, wait for the device to finish – as I do with swap chain images

  2. Transition the image to:

layout: VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
access: VK_ACCESS_TRANSFER_READ_BIT
stage: VK_PIPELINE_STAGE_TRANSFER_BIT

  1. Create a staging vkBuffer

  2. call vkCmdCopyImageToBuffer

  3. transition the image back to the same status as 2, because I might want to reuse it as a render target

Each transition in steps 2, 4, and 7 is done in a temporary buffer and submitted immediately after a call to ‘vkCmdPipelineBarrier’, so I assume that the image is, indeed, in that layout.

I get the black image as a result of this reading. If I do steps 4-7 on an image meant to be used as a texture for sampling in a fragment shader – I get the texture back as I uploaded it. Validation layers are silent.

I tried to follow a few examples for offline/headless rendering and from what I saw those, roughly, follow the same path as I did, but I get lost in minutia of which flag to use and when. In one example the layout transitions 2 and 4 were done using subpass dependancies, which I so far had not used. I’m just using one subpass in one render pass. As I said – I’m doing nothing fancy. However the ‘stage’ flags in that example were set differently, but when I cargo-culted them I got validation errors.