#include namespace app { static constexpr uint32_t IMAGE_WIDTH = 256; static constexpr uint32_t IMAGE_HEIGHT = 64; static constexpr uint32_t IMAGE_DATA_SIZE = 4 * IMAGE_WIDTH * IMAGE_HEIGHT; static constexpr VkFormat IMAGE_DATA_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; VkContext vkContext; } int main() { using namespace app; initVulkan(); auto stagingBuffer = allocateStagingBuffer(IMAGE_DATA_SIZE); memset(stagingBuffer.mappedData, 0, IMAGE_DATA_SIZE); auto image = allocateColorAttachmentImage(IMAGE_DATA_FORMAT, IMAGE_WIDTH, IMAGE_HEIGHT); auto commandPool = createCommandPool(); VkCommandBufferAllocateInfo commandBufferAllocateInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .commandPool = commandPool, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1, }; VkCommandBuffer commandBuffer = VK_NULL_HANDLE; check(vkAllocateCommandBuffers(vkContext.d.device, &commandBufferAllocateInfo, &commandBuffer)); VkCommandBufferBeginInfo commandBufferBeginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = 0, .pInheritanceInfo = nullptr, }; check(vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo)); auto imageSubresouceRange = colorSubresourceRange(/* baseMipLevel */ 0, /* levelCount */ 1); auto preTransferImageMemoryBarrier = app::imageMemoryBarrier(image.handle, imageSubresouceRange, VK_ACCESS_NONE, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, /* dependencyFlags */ 0, nullptr, 0, nullptr, 1, &preTransferImageMemoryBarrier); VkImageSubresourceLayers imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = 0, .baseArrayLayer = 0, .layerCount = 1, }; VkBufferImageCopy region = { .bufferOffset = 0, .bufferRowLength = 0, .bufferImageHeight = 0, .imageSubresource = imageSubresource, .imageOffset = {0, 0, 0}, .imageExtent = {IMAGE_WIDTH, IMAGE_HEIGHT, 1}, }; vkCmdCopyBufferToImage(commandBuffer, stagingBuffer.handle, image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); #define SPLIT_BARRIER #ifdef SPLIT_BARRIER auto postTransferImageMemoryBarrier1 = app::imageMemoryBarrier(image.handle, imageSubresouceRange, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_NONE, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, /* dependencyFlags */ 0, nullptr, 0, nullptr, 1, &postTransferImageMemoryBarrier1); auto postTransferImageMemoryBarrier2 = app::imageMemoryBarrier(image.handle, imageSubresouceRange, VK_ACCESS_NONE, VK_ACCESS_NONE, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, /* dependencyFlags */ 0, nullptr, 0, nullptr, 1, &postTransferImageMemoryBarrier2); // Validation Error : [SYNC - HAZARD - WRITE - AFTER - WRITE] Object 0 : handle = 0xcb3ee80000000007, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x5c0ec5d6 | vkCmdPipelineBarrier: Hazard WRITE_AFTER_WRITE for image barrier 0 VkImage 0xcb3ee80000000007[]. Access info (usage: SYNC_IMAGE_LAYOUT_TRANSITION, prior_usage: SYNC_COPY_TRANSFER_WRITE, write_barriers: 0, command: vkCmdCopyBufferToImage, seq_no: 2, reset_no: 1). #else auto postTransferImageMemoryBarrier = app::imageMemoryBarrier(image.handle, imageSubresouceRange, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_NONE, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, /* dependencyFlags */ 0, nullptr, 0, nullptr, 1, &postTransferImageMemoryBarrier); #endif check(vkEndCommandBuffer(commandBuffer)); VkSubmitInfo submitInfo = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .waitSemaphoreCount = 0, .pWaitSemaphores = nullptr, .pWaitDstStageMask = 0, .commandBufferCount = 1, .pCommandBuffers = &commandBuffer, .signalSemaphoreCount = 0, .pSignalSemaphores = nullptr, }; check(vkQueueSubmit(vkContext.queue, 1, &submitInfo, /* fence */ nullptr)); vkDeviceWaitIdle(vkContext.d.device); }