Alright, I’m currently trying to do that.
Do I need to have some sort of synchronisation security when copying data between images ?
Here is what I did now:
- I’m setting up memory barriers for the compute Image to be written to by shader. Then I change its layout to transfer & prepare the swap chain image as transfer destination.
- Copy data from compute image to swap chain image
- change swap chain image from transfer destination to presentation
But now when I try to present the current image or sometimes when submitting the queue, I just get a critical exception.
The validation layers don’t throw anything, just the compiler says critical exception.
This is what my 3 steps look like:
1. step
std::vector<VkImageMemoryBarrier> barriers = {};
// Compute Image
VkImageMemoryBarrier compWrite = {};
compWrite.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
compWrite.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
compWrite.newLayout = VK_IMAGE_LAYOUT_GENERAL;
compWrite.image = computeImage;
compWrite.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
compWrite.srcAccessMask = 0;
compWrite.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
// Compute Image
VkImageMemoryBarrier compTransfer = {};
compTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
compTransfer.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
compTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
compTransfer.image = computeImage;
compTransfer.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
compTransfer.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
compTransfer.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
// Current Swap chain image
VkImageMemoryBarrier swapTransfer = {};
swapTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
swapTransfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
swapTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
swapTransfer.image = swapChainImages[curImageIndex];
swapTransfer.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
swapTransfer.srcAccessMask = 0;
swapTransfer.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
barriers.push_back(compWrite);
barriers.push_back(compTransfer);
barriers.push_back(swapTransfer);
vkCmdPipelineBarrier(buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
0, 0, nullptr, 0, nullptr, barriers.size(), barriers.data());
2. step
// Compute Image
VkImageSubresourceLayers source;
source.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
source.mipLevel = 0;
source.baseArrayLayer = 0;
source.layerCount = 1;
// Current Swap chain image
VkImageSubresourceLayers dest;
dest.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
dest.mipLevel = 0;
dest.baseArrayLayer = 0;
dest.layerCount = 1;
VkImageCopy copy;
copy.srcSubresource = source;
copy.dstSubresource = dest;
copy.extent = { WIDTH, HEIGHT, 1 };
vkCmdCopyImage(buffer, computeImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapChainImages[curImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
3. step
// Current Swap chain image
VkImageMemoryBarrier swapPres = {};
swapPres.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
swapPres.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
swapPres.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapPres.image = swapChainImages[curImageIndex];
swapPres.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
swapPres.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
swapPres.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
vkCmdPipelineBarrier(buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
0, 0, nullptr, 0, nullptr, 1, &swapPres);
Sorry for throwing so much code in here
There’s no other synchronisation between those steps, just the pipeline barriers.