From da7c110e5d0d5efc3689e568c5a8cf469765bf9d Mon Sep 17 00:00:00 2001 From: asuessenbach Date: Mon, 31 Jul 2023 15:02:11 +0200 Subject: [PATCH] cleanup on image layout transition functions --- framework/api_vulkan_sample.cpp | 66 ++--- framework/common/hpp_vk_common.h | 37 ++- framework/common/vk_common.cpp | 275 ++++++++---------- framework/common/vk_common.h | 129 ++++---- framework/core/command_buffer.cpp | 31 +- framework/hpp_api_vulkan_sample.cpp | 36 +-- .../hpp_texture_mipmap_generation.cpp | 59 +--- .../texture_mipmap_generation.cpp | 67 ++--- .../descriptor_indexing.cpp | 17 +- .../dynamic_rendering/dynamic_rendering.cpp | 42 +-- .../fragment_shading_rate.cpp | 26 +- .../fragment_shading_rate_dynamic.cpp | 80 ++--- .../open_gl_interop/open_gl_interop.cpp | 71 +---- .../ray_tracing_reflection.cpp | 60 ++-- .../raytracing_basic/raytracing_basic.cpp | 63 ++-- .../raytracing_extended.cpp | 63 ++-- .../multi_draw_indirect.cpp | 39 +-- .../texture_compression_basisu.cpp | 32 +- .../texture_compression_comparison.cpp | 19 +- samples/tooling/profiles/profiles.cpp | 18 +- 20 files changed, 497 insertions(+), 733 deletions(-) diff --git a/framework/api_vulkan_sample.cpp b/framework/api_vulkan_sample.cpp index 2be6bfc9c9..f3089f4c0a 100644 --- a/framework/api_vulkan_sample.cpp +++ b/framework/api_vulkan_sample.cpp @@ -1024,12 +1024,11 @@ Texture ApiVulkanSample::load_texture(const std::string &file, vkb::sg::Image::C // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy - vkb::set_image_layout( - command_buffer, - texture.image->get_vk_image().get_handle(), - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresource_range); + vkb::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresource_range); // Copy mip levels from staging buffer vkCmdCopyBufferToImage( @@ -1041,12 +1040,11 @@ Texture ApiVulkanSample::load_texture(const std::string &file, vkb::sg::Image::C bufferCopyRegions.data()); // Change texture image layout to shader read after all mip levels have been copied - vkb::set_image_layout( - command_buffer, - texture.image->get_vk_image().get_handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresource_range); + vkb::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + subresource_range); device->flush_command_buffer(command_buffer, queue.get_handle()); @@ -1128,12 +1126,11 @@ Texture ApiVulkanSample::load_texture_array(const std::string &file, vkb::sg::Im // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy - vkb::set_image_layout( - command_buffer, - texture.image->get_vk_image().get_handle(), - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresource_range); + vkb::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresource_range); // Copy mip levels from staging buffer vkCmdCopyBufferToImage( @@ -1145,12 +1142,11 @@ Texture ApiVulkanSample::load_texture_array(const std::string &file, vkb::sg::Im buffer_copy_regions.data()); // Change texture image layout to shader read after all mip levels have been copied - vkb::set_image_layout( - command_buffer, - texture.image->get_vk_image().get_handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresource_range); + vkb::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + subresource_range); device->flush_command_buffer(command_buffer, queue.get_handle()); @@ -1229,12 +1225,11 @@ Texture ApiVulkanSample::load_texture_cubemap(const std::string &file, vkb::sg:: // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy - vkb::set_image_layout( - command_buffer, - texture.image->get_vk_image().get_handle(), - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresource_range); + vkb::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresource_range); // Copy mip levels from staging buffer vkCmdCopyBufferToImage( @@ -1246,12 +1241,11 @@ Texture ApiVulkanSample::load_texture_cubemap(const std::string &file, vkb::sg:: buffer_copy_regions.data()); // Change texture image layout to shader read after all mip levels have been copied - vkb::set_image_layout( - command_buffer, - texture.image->get_vk_image().get_handle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - subresource_range); + vkb::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + subresource_range); device->flush_command_buffer(command_buffer, queue.get_handle()); diff --git a/framework/common/hpp_vk_common.h b/framework/common/hpp_vk_common.h index c23464fac6..a3ecd4b146 100644 --- a/framework/common/hpp_vk_common.h +++ b/framework/common/hpp_vk_common.h @@ -95,21 +95,28 @@ inline vk::ShaderModule load_shader(const std::string &filename, vk::Device devi return static_cast(vkb::load_shader(filename, device, static_cast(stage))); } -inline void set_image_layout(vk::CommandBuffer command_buffer, - vk::Image image, - vk::ImageLayout old_layout, - vk::ImageLayout new_layout, - vk::ImageSubresourceRange subresource_range, - vk::PipelineStageFlags src_mask = vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlags dst_mask = vk::PipelineStageFlagBits::eAllCommands) -{ - vkb::set_image_layout(command_buffer, - static_cast(image), - static_cast(old_layout), - static_cast(new_layout), - static_cast(subresource_range), - static_cast(src_mask), - static_cast(dst_mask)); +inline void image_layout_transition(vk::CommandBuffer command_buffer, + vk::Image image, + vk::ImageLayout old_layout, + vk::ImageLayout new_layout) +{ + vkb::image_layout_transition(command_buffer, + static_cast(image), + static_cast(old_layout), + static_cast(new_layout)); +} + +inline void image_layout_transition(vk::CommandBuffer command_buffer, + vk::Image image, + vk::ImageLayout old_layout, + vk::ImageLayout new_layout, + vk::ImageSubresourceRange subresource_range) +{ + vkb::image_layout_transition(command_buffer, + static_cast(image), + static_cast(old_layout), + static_cast(new_layout), + static_cast(subresource_range)); } // helper functions not backed by vk_common.h diff --git a/framework/common/vk_common.cpp b/framework/common/vk_common.cpp index 03f66d4ed0..4e5fb8cb5b 100644 --- a/framework/common/vk_common.cpp +++ b/framework/common/vk_common.cpp @@ -388,184 +388,165 @@ VkShaderModule load_shader(const std::string &filename, VkDevice device, VkShade return shader_module; } -// Create an image memory barrier for changing the layout of -// an image and put it into an active command buffer -// See chapter 11.4 "Image Layout" for details - -void set_image_layout( - VkCommandBuffer command_buffer, - VkImage image, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkImageSubresourceRange subresource_range, - VkPipelineStageFlags src_mask, - VkPipelineStageFlags dst_mask) +VkAccessFlags getAccessFlags(VkImageLayout layout) { - // Create an image barrier object - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.image = image; - barrier.subresourceRange = subresource_range; - - // Source layouts (old) - // Source access mask controls actions that have to be finished on the old layout - // before it will be transitioned to the new layout - switch (old_layout) + switch (layout) { case VK_IMAGE_LAYOUT_UNDEFINED: - // Image layout is undefined (or does not matter) - // Only valid as initial layout - // No flags required, listed only for completeness - barrier.srcAccessMask = 0; - break; - + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return 0; case VK_IMAGE_LAYOUT_PREINITIALIZED: - // Image is preinitialized - // Only valid as initial layout for linear images, preserves memory contents - // Make sure host writes have been finished - barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - break; - + return VK_ACCESS_HOST_WRITE_BIT; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - // Image is a color attachment - // Make sure any writes to the color buffer have been finished - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - // Image is a depth/stencil attachment - // Make sure any writes to the depth/stencil buffer have been finished - barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - break; - + return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR: + return VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - // Image is a transfer source - // Make sure any reads from the image have been finished - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - break; - + return VK_ACCESS_TRANSFER_READ_BIT; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - // Image is a transfer destination - // Make sure any writes to the image have been finished - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - // Image is read by a shader - // Make sure any shader reads from the image have been finished - barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - break; + return VK_ACCESS_TRANSFER_WRITE_BIT; + case VK_IMAGE_LAYOUT_GENERAL: + assert(false && "Don't know how to get a meaningful VkAccessFlags for VK_IMAGE_LAYOUT_GENERAL! Don't use it!"); + return 0; default: - // Other source layouts aren't handled (yet) - break; + assert(false); + return 0; } +} - // Target layouts (new) - // Destination access mask controls the dependency for the new image layout - switch (new_layout) +VkPipelineStageFlags getPipelineStageFlags(VkImageLayout layout) +{ + switch (layout) { + case VK_IMAGE_LAYOUT_UNDEFINED: + return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + case VK_IMAGE_LAYOUT_PREINITIALIZED: + return VK_PIPELINE_STAGE_HOST_BIT; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - // Image will be used as a transfer destination - // Make sure any writes to the image have been finished - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - // Image will be used as a transfer source - // Make sure any reads from the image have been finished - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - break; - + return VK_PIPELINE_STAGE_TRANSFER_BIT; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - // Image will be used as a color attachment - // Make sure any writes to the color buffer have been finished - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - break; - - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - // Image layout will be used as a depth/stencil attachment - // Make sure any writes to depth/stencil buffer have been finished - barrier.dstAccessMask = barrier.dstAccessMask | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - break; - + return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: + return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR: + return VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - // Image will be read in a shader (sampler, input attachment) - // Make sure any writes to the image have been finished - if (barrier.srcAccessMask == 0) - { - barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - } - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - break; + return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + case VK_IMAGE_LAYOUT_GENERAL: + assert(false && "Don't know how to get a meaningful VkPipelineStageFlags for VK_IMAGE_LAYOUT_GENERAL! Don't use it!"); + return 0; default: - // Other source layouts aren't handled (yet) - break; + assert(false); + return 0; } +} + +// Create an image memory barrier for changing the layout of +// an image and put it into an active command buffer +// See chapter 12.4 "Image Layout" for details + +void image_layout_transition(VkCommandBuffer command_buffer, + VkImage image, + VkPipelineStageFlags src_stage_mask, + VkPipelineStageFlags dst_stage_mask, + VkAccessFlags src_access_mask, + VkAccessFlags dst_access_mask, + VkImageLayout old_layout, + VkImageLayout new_layout, + VkImageSubresourceRange const &subresource_range) +{ + // Create an image barrier object + VkImageMemoryBarrier image_memory_barrier{}; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.srcAccessMask = src_access_mask; + image_memory_barrier.dstAccessMask = dst_access_mask; + image_memory_barrier.oldLayout = old_layout; + image_memory_barrier.newLayout = new_layout; + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = image; + image_memory_barrier.subresourceRange = subresource_range; // Put barrier inside setup command buffer - vkCmdPipelineBarrier( - command_buffer, - src_mask, - dst_mask, - 0, - 0, nullptr, - 0, nullptr, - 1, &barrier); + vkCmdPipelineBarrier(command_buffer, src_stage_mask, dst_stage_mask, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); +} + +void image_layout_transition(VkCommandBuffer command_buffer, + VkImage image, + VkImageLayout old_layout, + VkImageLayout new_layout, + VkImageSubresourceRange const &subresource_range) +{ + VkPipelineStageFlags src_stage_mask = getPipelineStageFlags(old_layout); + VkPipelineStageFlags dst_stage_mask = getPipelineStageFlags(new_layout); + VkAccessFlags src_access_mask = getAccessFlags(old_layout); + VkAccessFlags dst_access_mask = getAccessFlags(new_layout); + + image_layout_transition(command_buffer, image, src_stage_mask, dst_stage_mask, src_access_mask, dst_access_mask, old_layout, new_layout, subresource_range); } // Fixed sub resource on first mip level and layer -void set_image_layout( - VkCommandBuffer command_buffer, - VkImage image, - VkImageAspectFlags aspect_mask, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkPipelineStageFlags src_mask, - VkPipelineStageFlags dst_mask) +void image_layout_transition(VkCommandBuffer command_buffer, + VkImage image, + VkImageLayout old_layout, + VkImageLayout new_layout) { VkImageSubresourceRange subresource_range = {}; - subresource_range.aspectMask = aspect_mask; + subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subresource_range.baseMipLevel = 0; subresource_range.levelCount = 1; + subresource_range.baseArrayLayer = 0; subresource_range.layerCount = 1; - set_image_layout(command_buffer, image, old_layout, new_layout, subresource_range, src_mask, dst_mask); + image_layout_transition(command_buffer, image, old_layout, new_layout, subresource_range); } -void insert_image_memory_barrier( - VkCommandBuffer command_buffer, - VkImage image, - VkAccessFlags src_access_mask, - VkAccessFlags dst_access_mask, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkPipelineStageFlags src_stage_mask, - VkPipelineStageFlags dst_stage_mask, - VkImageSubresourceRange subresource_range) +void image_layout_transition(VkCommandBuffer command_buffer, + std::vector> const &imagesAndRanges, + VkImageLayout old_layout, + VkImageLayout new_layout) { - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.srcAccessMask = src_access_mask; - barrier.dstAccessMask = dst_access_mask; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.image = image; - barrier.subresourceRange = subresource_range; - - vkCmdPipelineBarrier( - command_buffer, - src_stage_mask, - dst_stage_mask, - 0, - 0, nullptr, - 0, nullptr, - 1, &barrier); + VkPipelineStageFlags src_stage_mask = getPipelineStageFlags(old_layout); + VkPipelineStageFlags dst_stage_mask = getPipelineStageFlags(new_layout); + VkAccessFlags src_access_mask = getAccessFlags(old_layout); + VkAccessFlags dst_access_mask = getAccessFlags(new_layout); + + // Create image barrier objects + std::vector image_memory_barriers; + image_memory_barriers.reserve(imagesAndRanges.size()); + for (size_t i = 0; i < imagesAndRanges.size(); i++) + { + image_memory_barriers.emplace_back(VkImageMemoryBarrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + nullptr, + src_access_mask, + dst_access_mask, + old_layout, + new_layout, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + imagesAndRanges[i].first, + imagesAndRanges[i].second}); + } + + // Put barriers inside setup command buffer + vkCmdPipelineBarrier(command_buffer, + src_stage_mask, + dst_stage_mask, + 0, + 0, + nullptr, + 0, + nullptr, + static_cast(image_memory_barriers.size()), + image_memory_barriers.data()); } + namespace gbuffer { std::vector get_load_all_store_swapchain() diff --git a/framework/common/vk_common.h b/framework/common/vk_common.h index 005689aeaa..5809845578 100644 --- a/framework/common/vk_common.h +++ b/framework/common/vk_common.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2018-2021, Arm Limited and Contributors - * Copyright (c) 2019-2021, Sascha Willems +/* Copyright (c) 2018-2023, Arm Limited and Contributors + * Copyright (c) 2019-2023, Sascha Willems * * SPDX-License-Identifier: Apache-2.0 * @@ -123,9 +123,9 @@ struct ImageMemoryBarrier }; /** -* @brief Buffer memory barrier structure used to define -* memory access for a buffer during command recording. -*/ + * @brief Buffer memory barrier structure used to define + * memory access for a buffer during command recording. + */ struct BufferMemoryBarrier { VkPipelineStageFlags src_stage_mask{VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT}; @@ -138,42 +138,73 @@ struct BufferMemoryBarrier }; /** -* @brief Put an image memory barrier for setting an image layout on the sub resource into the given command buffer -*/ -void set_image_layout( - VkCommandBuffer command_buffer, - VkImage image, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkImageSubresourceRange subresource_range, - VkPipelineStageFlags src_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VkPipelineStageFlags dst_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - -/** -* @brief Uses a fixed sub resource layout with first mip level and layer -*/ -void set_image_layout( - VkCommandBuffer command_buffer, - VkImage image, - VkImageAspectFlags aspect_mask, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkPipelineStageFlags src_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VkPipelineStageFlags dst_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - -/** -* @brief Insert an image memory barrier into the command buffer -*/ -void insert_image_memory_barrier( - VkCommandBuffer command_buffer, - VkImage image, - VkAccessFlags src_access_mask, - VkAccessFlags dst_access_mask, - VkImageLayout old_layout, - VkImageLayout new_layout, - VkPipelineStageFlags src_stage_mask, - VkPipelineStageFlags dst_stage_mask, - VkImageSubresourceRange subresource_range); + * @brief Put an image memory barrier for a layout transition of an image, using explicitly give transition parameters. + * @param command_buffer The VkCommandBuffer to record the barrier. + * @param image The VkImage to transition. + * @param src_stage_mask The VkPipelineStageFlags to use as source. + * @param dst_stage_mask The VkPipelineStageFlags to use as destination. + * @param src_access_mask The VkAccessFlags to use as source. + * @param dst_access_mask The VkAccessFlags to use as destination. + * @param old_layout The VkImageLayout to transition from. + * @param new_layout The VkImageLayout to transition to. + * @param image_subresource_range The VkImageSubresourceRange to use with the transition. + */ +void image_layout_transition(VkCommandBuffer command_buffer, + VkImage image, + VkPipelineStageFlags src_stage_mask, + VkPipelineStageFlags dst_stage_mask, + VkAccessFlags src_access_mask, + VkAccessFlags dst_access_mask, + VkImageLayout old_layout, + VkImageLayout new_layout, + VkImageSubresourceRange const &image_subresource_range); + +/** + * @brief Put an image memory barrier for a layout transition of an image, on a given subresource range. + * + * The src_stage_mask, dst_stage_mask, src_access_mask, and dst_access_mask used are determined from old_layout and new_layout. + * + * @param command_buffer The VkCommandBuffer to record the barrier. + * @param image The VkImage to transition. + * @param old_layout The VkImageLayout to transition from. + * @param new_layout The VkImageLayout to transition to. + * @param image_subresource_range The VkImageSubresourceRange to use with the transition. + */ +void image_layout_transition(VkCommandBuffer command_buffer, + VkImage image, + VkImageLayout old_layout, + VkImageLayout new_layout, + VkImageSubresourceRange const &subresource_range); + +/** + * @brief Put an image memory barrier for a layout transition of an image, on a fixed subresource with first mip level and layer. + * + * The src_stage_mask, dst_stage_mask, src_access_mask, and dst_access_mask used are determined from old_layout and new_layout. + * + * @param command_buffer The VkCommandBuffer to record the barrier. + * @param image The VkImage to transition. + * @param old_layout The VkImageLayout to transition from. + * @param new_layout The VkImageLayout to transition to. + */ +void image_layout_transition(VkCommandBuffer command_buffer, + VkImage image, + VkImageLayout old_layout, + VkImageLayout new_layout); + +/** + * @brief Put an image memory barrier for a layout transition of a vector of images, with a given subresource range per image. + * + * The src_stage_mask, dst_stage_mask, src_access_mask, and dst_access_mask used are determined from old_layout and new_layout. + * + * @param command_buffer The VkCommandBuffer to record the barrier. + * @param imagesAndRanges The images to transition, with accompanying subresource ranges. + * @param old_layout The VkImageLayout to transition from. + * @param new_layout The VkImageLayout to transition to. + */ +void image_layout_transition(VkCommandBuffer command_buffer, + std::vector> const &imagesAndRanges, + VkImageLayout old_layout, + VkImageLayout new_layout); /** * @brief Load and store info for a render pass attachment. @@ -188,23 +219,23 @@ struct LoadStoreInfo namespace gbuffer { /** - * @return Load store info to load all and store only the swapchain - */ + * @return Load store info to load all and store only the swapchain + */ std::vector get_load_all_store_swapchain(); /** - * @return Load store info to clear all and store only the swapchain - */ + * @return Load store info to clear all and store only the swapchain + */ std::vector get_clear_all_store_swapchain(); /** - * @return Load store info to clear and store all images - */ + * @return Load store info to clear and store all images + */ std::vector get_clear_store_all(); /** - * @return Default clear values for the G-buffer - */ + * @return Default clear values for the G-buffer + */ std::vector get_clear_value(); } // namespace gbuffer diff --git a/framework/core/command_buffer.cpp b/framework/core/command_buffer.cpp index 6d41ff5b6c..563944cdb3 100644 --- a/framework/core/command_buffer.cpp +++ b/framework/core/command_buffer.cpp @@ -451,28 +451,15 @@ void CommandBuffer::image_memory_barrier(const core::ImageView &image_view, cons subresource_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; } - VkImageMemoryBarrier image_memory_barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}; - image_memory_barrier.oldLayout = memory_barrier.old_layout; - image_memory_barrier.newLayout = memory_barrier.new_layout; - image_memory_barrier.image = image_view.get_image().get_handle(); - image_memory_barrier.subresourceRange = subresource_range; - image_memory_barrier.srcAccessMask = memory_barrier.src_access_mask; - image_memory_barrier.dstAccessMask = memory_barrier.dst_access_mask; - image_memory_barrier.srcQueueFamilyIndex = memory_barrier.old_queue_family; - image_memory_barrier.dstQueueFamilyIndex = memory_barrier.new_queue_family; - - VkPipelineStageFlags src_stage_mask = memory_barrier.src_stage_mask; - VkPipelineStageFlags dst_stage_mask = memory_barrier.dst_stage_mask; - - vkCmdPipelineBarrier( - get_handle(), - src_stage_mask, - dst_stage_mask, - 0, - 0, nullptr, - 0, nullptr, - 1, - &image_memory_barrier); + vkb::image_layout_transition(get_handle(), + image_view.get_image().get_handle(), + memory_barrier.src_stage_mask, + memory_barrier.dst_stage_mask, + memory_barrier.src_access_mask, + memory_barrier.dst_access_mask, + memory_barrier.old_layout, + memory_barrier.new_layout, + subresource_range); } void CommandBuffer::buffer_memory_barrier(const core::Buffer &buffer, VkDeviceSize offset, VkDeviceSize size, const BufferMemoryBarrier &memory_barrier) diff --git a/framework/hpp_api_vulkan_sample.cpp b/framework/hpp_api_vulkan_sample.cpp index 3662a0ec74..fef59b3804 100644 --- a/framework/hpp_api_vulkan_sample.cpp +++ b/framework/hpp_api_vulkan_sample.cpp @@ -885,7 +885,7 @@ HPPTexture HPPApiVulkanSample::load_texture(const std::string &file, vkb::sg::Im // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy - vkb::common::set_image_layout( + vkb::common::image_layout_transition( command_buffer, texture.image->get_vk_image().get_handle(), vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, subresource_range); // Copy mip levels from staging buffer @@ -893,11 +893,11 @@ HPPTexture HPPApiVulkanSample::load_texture(const std::string &file, vkb::sg::Im stage_buffer.get_handle(), texture.image->get_vk_image().get_handle(), vk::ImageLayout::eTransferDstOptimal, bufferCopyRegions); // Change texture image layout to shader read after all mip levels have been copied - vkb::common::set_image_layout(command_buffer, - texture.image->get_vk_image().get_handle(), - vk::ImageLayout::eTransferDstOptimal, - vk::ImageLayout::eShaderReadOnlyOptimal, - subresource_range); + vkb::common::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + vk::ImageLayout::eTransferDstOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal, + subresource_range); get_device()->flush_command_buffer(command_buffer, queue.get_handle()); @@ -972,7 +972,7 @@ HPPTexture HPPApiVulkanSample::load_texture_array(const std::string &file, vkb:: // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy - vkb::common::set_image_layout( + vkb::common::image_layout_transition( command_buffer, texture.image->get_vk_image().get_handle(), vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, subresource_range); // Copy mip levels from staging buffer @@ -980,11 +980,11 @@ HPPTexture HPPApiVulkanSample::load_texture_array(const std::string &file, vkb:: stage_buffer.get_handle(), texture.image->get_vk_image().get_handle(), vk::ImageLayout::eTransferDstOptimal, buffer_copy_regions); // Change texture image layout to shader read after all mip levels have been copied - vkb::common::set_image_layout(command_buffer, - texture.image->get_vk_image().get_handle(), - vk::ImageLayout::eTransferDstOptimal, - vk::ImageLayout::eShaderReadOnlyOptimal, - subresource_range); + vkb::common::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + vk::ImageLayout::eTransferDstOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal, + subresource_range); get_device()->flush_command_buffer(command_buffer, queue.get_handle()); @@ -1056,7 +1056,7 @@ HPPTexture HPPApiVulkanSample::load_texture_cubemap(const std::string &file, vkb // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy - vkb::common::set_image_layout( + vkb::common::image_layout_transition( command_buffer, texture.image->get_vk_image().get_handle(), vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, subresource_range); // Copy mip levels from staging buffer @@ -1064,11 +1064,11 @@ HPPTexture HPPApiVulkanSample::load_texture_cubemap(const std::string &file, vkb stage_buffer.get_handle(), texture.image->get_vk_image().get_handle(), vk::ImageLayout::eTransferDstOptimal, buffer_copy_regions); // Change texture image layout to shader read after all mip levels have been copied - vkb::common::set_image_layout(command_buffer, - texture.image->get_vk_image().get_handle(), - vk::ImageLayout::eTransferDstOptimal, - vk::ImageLayout::eShaderReadOnlyOptimal, - subresource_range); + vkb::common::image_layout_transition(command_buffer, + texture.image->get_vk_image().get_handle(), + vk::ImageLayout::eTransferDstOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal, + subresource_range); get_device()->flush_command_buffer(command_buffer, queue.get_handle()); diff --git a/samples/api/hpp_texture_mipmap_generation/hpp_texture_mipmap_generation.cpp b/samples/api/hpp_texture_mipmap_generation/hpp_texture_mipmap_generation.cpp index 9feeffea1b..0720025992 100644 --- a/samples/api/hpp_texture_mipmap_generation/hpp_texture_mipmap_generation.cpp +++ b/samples/api/hpp_texture_mipmap_generation/hpp_texture_mipmap_generation.cpp @@ -20,6 +20,8 @@ */ #include "hpp_texture_mipmap_generation.h" + +#include #include HPPTextureMipMapGeneration::HPPTextureMipMapGeneration() @@ -248,30 +250,14 @@ void HPPTextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_ vk::CommandBuffer copy_command = device->create_command_buffer(vk::CommandBufferLevel::ePrimary, true); // Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout - vk::ImageMemoryBarrier image_memory_barrier({}, - vk::AccessFlagBits::eTransferWrite, - vk::ImageLayout::eUndefined, - vk::ImageLayout::eTransferDstOptimal, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - texture.image, - {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}); - copy_command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, image_memory_barrier); + vkb::common::image_layout_transition(copy_command, texture.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); // Copy the first mip of the chain, remaining mips will be generated vk::BufferImageCopy buffer_copy_region({}, {}, {}, {vk::ImageAspectFlagBits::eColor, 0, 0, 1}, {}, vk::Extent3D(texture.extent, 1)); copy_command.copyBufferToImage(staging_buffer, texture.image, vk::ImageLayout::eTransferDstOptimal, buffer_copy_region); // Transition first mip level to transfer source so we can blit(read) from it - image_memory_barrier = vk::ImageMemoryBarrier(vk::AccessFlagBits::eTransferWrite, - vk::AccessFlagBits::eTransferRead, - vk::ImageLayout::eTransferDstOptimal, - vk::ImageLayout::eTransferSrcOptimal, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - texture.image, - {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}); - copy_command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, image_memory_barrier); + vkb::common::image_layout_transition(copy_command, texture.image, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eTransferSrcOptimal); device->flush_command_buffer(copy_command, queue, true); @@ -294,41 +280,24 @@ void HPPTextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_ {{{}, {static_cast(texture.extent.width >> i), static_cast(texture.extent.height >> i), static_cast(1)}}}); // Prepare current mip level as image blit destination - image_memory_barrier = vk::ImageMemoryBarrier({}, - vk::AccessFlagBits::eTransferWrite, - vk::ImageLayout::eUndefined, - vk::ImageLayout::eTransferDstOptimal, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - texture.image, - {vk::ImageAspectFlagBits::eColor, i, 1, 0, 1}); - copy_command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, image_memory_barrier); + vk::ImageSubresourceRange image_subresource_range(vk::ImageAspectFlagBits::eColor, i, 1, 0, 1); + vkb::common::image_layout_transition( + copy_command, texture.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, image_subresource_range); // Blit from previous level blit_command.blitImage(texture.image, vk::ImageLayout::eTransferSrcOptimal, texture.image, vk::ImageLayout::eTransferDstOptimal, image_blit, vk::Filter::eLinear); // Prepare current mip level as image blit source for next level - image_memory_barrier = vk::ImageMemoryBarrier(vk::AccessFlagBits::eTransferWrite, - vk::AccessFlagBits::eTransferRead, - vk::ImageLayout::eTransferDstOptimal, - vk::ImageLayout::eTransferSrcOptimal, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - texture.image, - {vk::ImageAspectFlagBits::eColor, i, 1, 0, 1}); - copy_command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, image_memory_barrier); + vkb::common::image_layout_transition( + copy_command, texture.image, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eTransferSrcOptimal, image_subresource_range); } // After the loop, all mip layers are in TRANSFER_SRC layout, so transition all to SHADER_READ - image_memory_barrier = vk::ImageMemoryBarrier(vk::AccessFlagBits::eTransferRead, - vk::AccessFlagBits::eShaderRead, - vk::ImageLayout::eTransferSrcOptimal, - vk::ImageLayout::eShaderReadOnlyOptimal, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - texture.image, - {vk::ImageAspectFlagBits::eColor, 0, texture.mip_levels, 0, 1}); - copy_command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, image_memory_barrier); + vkb::common::image_layout_transition(copy_command, + texture.image, + vk::ImageLayout::eTransferSrcOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal, + {vk::ImageAspectFlagBits::eColor, 0, texture.mip_levels, 0, 1}); device->flush_command_buffer(blit_command, queue, true); // --------------------------------------------------------------- diff --git a/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp b/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp index 7e85e3f3d6..dd1acff5f2 100644 --- a/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp +++ b/samples/api/texture_mipmap_generation/texture_mipmap_generation.cpp @@ -142,16 +142,7 @@ void TextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_nam VkCommandBuffer copy_command = device->create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); // Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout - vkb::insert_image_memory_barrier( - copy_command, - texture.image, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); + vkb::image_layout_transition(copy_command, texture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Copy the first mip of the chain, remaining mips will be generated VkBufferImageCopy buffer_copy_region = {}; @@ -165,16 +156,7 @@ void TextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_nam vkCmdCopyBufferToImage(copy_command, staging_buffer, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_copy_region); // Transition first mip level to transfer source so we can blit(read) from it - vkb::insert_image_memory_barrier( - copy_command, - texture.image, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); + vkb::image_layout_transition(copy_command, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); device->flush_command_buffer(copy_command, queue, true); @@ -210,16 +192,11 @@ void TextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_nam image_blit.dstOffsets[1].z = 1; // Prepare current mip level as image blit destination - vkb::insert_image_memory_barrier( - blit_command, - texture.image, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - {VK_IMAGE_ASPECT_COLOR_BIT, i, 1, 0, 1}); + vkb::image_layout_transition(blit_command, + texture.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + {VK_IMAGE_ASPECT_COLOR_BIT, i, 1, 0, 1}); // Blit from previous level vkCmdBlitImage( @@ -233,29 +210,19 @@ void TextureMipMapGeneration::load_texture_generate_mipmaps(std::string file_nam VK_FILTER_LINEAR); // Prepare current mip level as image blit source for next level - vkb::insert_image_memory_barrier( - blit_command, - texture.image, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - {VK_IMAGE_ASPECT_COLOR_BIT, i, 1, 0, 1}); + vkb::image_layout_transition(blit_command, + texture.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + {VK_IMAGE_ASPECT_COLOR_BIT, i, 1, 0, 1}); } // After the loop, all mip layers are in TRANSFER_SRC layout, so transition all to SHADER_READ - vkb::insert_image_memory_barrier( - blit_command, - texture.image, - VK_ACCESS_TRANSFER_READ_BIT, - VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, texture.mip_levels, 0, 1}); + vkb::image_layout_transition(blit_command, + texture.image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, texture.mip_levels, 0, 1}); device->flush_command_buffer(blit_command, queue, true); // --------------------------------------------------------------- diff --git a/samples/extensions/descriptor_indexing/descriptor_indexing.cpp b/samples/extensions/descriptor_indexing/descriptor_indexing.cpp index 2afc8ded7b..3eae01de80 100644 --- a/samples/extensions/descriptor_indexing/descriptor_indexing.cpp +++ b/samples/extensions/descriptor_indexing/descriptor_indexing.cpp @@ -433,27 +433,14 @@ DescriptorIndexing::TestImage DescriptorIndexing::create_image(const float rgb[3 auto &cmd = get_device().request_command_buffer(); cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - VkImageMemoryBarrier barrier = vkb::initializers::image_memory_barrier(); - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - barrier.image = test_image.image; - vkCmdPipelineBarrier(cmd.get_handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &barrier); + vkb::image_layout_transition(cmd.get_handle(), test_image.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkBufferImageCopy copy_info{}; copy_info.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; copy_info.imageExtent = image_info.extent; vkCmdCopyBufferToImage(cmd.get_handle(), staging_buffer->get_handle(), test_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_info); - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier(cmd.get_handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &barrier); + vkb::image_layout_transition(cmd.get_handle(), test_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VK_CHECK(cmd.end()); diff --git a/samples/extensions/dynamic_rendering/dynamic_rendering.cpp b/samples/extensions/dynamic_rendering/dynamic_rendering.cpp index 59255c7efd..8f48127e8f 100644 --- a/samples/extensions/dynamic_rendering/dynamic_rendering.cpp +++ b/samples/extensions/dynamic_rendering/dynamic_rendering.cpp @@ -370,23 +370,17 @@ void DynamicRendering::build_command_buffers() if (enable_dynamic) { - vkb::insert_image_memory_barrier(draw_cmd_buffer, - swapchain_buffers[i].image, - 0, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, range); - - vkb::insert_image_memory_barrier(draw_cmd_buffer, - depth_stencil.image, - 0, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, depth_range); + vkb::image_layout_transition(draw_cmd_buffer, + swapchain_buffers[i].image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + range); + + vkb::image_layout_transition(draw_cmd_buffer, + depth_stencil.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + depth_range); VkRenderingAttachmentInfoKHR color_attachment_info = vkb::initializers::rendering_attachment_info(); color_attachment_info.imageView = swapchain_buffers[i].view; // color_attachment.image_view; @@ -417,15 +411,11 @@ void DynamicRendering::build_command_buffers() draw_scene(); vkCmdEndRenderingKHR(draw_cmd_buffer); - vkb::insert_image_memory_barrier(draw_cmd_buffer, - swapchain_buffers[i].image, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - 0, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - range); + vkb::image_layout_transition(draw_cmd_buffer, + swapchain_buffers[i].image, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + range); } else { diff --git a/samples/extensions/fragment_shading_rate/fragment_shading_rate.cpp b/samples/extensions/fragment_shading_rate/fragment_shading_rate.cpp index a16afe0ba0..a1ade7a3c6 100644 --- a/samples/extensions/fragment_shading_rate/fragment_shading_rate.cpp +++ b/samples/extensions/fragment_shading_rate/fragment_shading_rate.cpp @@ -186,20 +186,9 @@ void FragmentShadingRate::create_shading_rate_attachment() delete[] shading_rate_pattern_data; // Upload the buffer containing the shading rates to the image that'll be used as the shading rate attachment inside our renderpass - VkCommandBuffer copy_cmd = device->create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkImageSubresourceRange subresource_range = {}; - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_range.levelCount = 1; - subresource_range.layerCount = 1; - - VkImageMemoryBarrier image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.image = shading_rate_image.image; - image_memory_barrier.subresourceRange = subresource_range; - vkCmdPipelineBarrier(copy_cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + VkCommandBuffer copy_cmd = device->create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + vkb::image_layout_transition(copy_cmd, shading_rate_image.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkBufferImageCopy buffer_copy_region = {}; buffer_copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -210,13 +199,8 @@ void FragmentShadingRate::create_shading_rate_attachment() vkCmdCopyBufferToImage(copy_cmd, staging_buffer->get_handle(), shading_rate_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_copy_region); // Transfer image layout to fragment shading rate attachment layout required to access this in the renderpass - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = 0; - image_memory_barrier.image = shading_rate_image.image; - image_memory_barrier.subresourceRange = subresource_range; - vkCmdPipelineBarrier(copy_cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + vkb::image_layout_transition( + copy_cmd, shading_rate_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR); device->flush_command_buffer(copy_cmd, queue, true); diff --git a/samples/extensions/fragment_shading_rate_dynamic/fragment_shading_rate_dynamic.cpp b/samples/extensions/fragment_shading_rate_dynamic/fragment_shading_rate_dynamic.cpp index 3618439a35..153009a9e6 100644 --- a/samples/extensions/fragment_shading_rate_dynamic/fragment_shading_rate_dynamic.cpp +++ b/samples/extensions/fragment_shading_rate_dynamic/fragment_shading_rate_dynamic.cpp @@ -153,22 +153,9 @@ void FragmentShadingRateDynamic::create_shading_rate_attachment() VMA_MEMORY_USAGE_CPU_TO_GPU); staging_buffer->update(temp_buffer); - VkImageSubresourceRange subresource_range = {}; - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_range.levelCount = 1; - subresource_range.layerCount = 1; - auto cmd = device->create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkImageMemoryBarrier copy_barrier = vkb::initializers::image_memory_barrier(); - copy_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - copy_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - copy_barrier.image = shading_rate_image->get_handle(); - copy_barrier.subresourceRange = subresource_range; - copy_barrier.srcAccessMask = 0; - copy_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, ©_barrier); + vkb::image_layout_transition(cmd, shading_rate_image->get_handle(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkBufferImageCopy buffer_copy_region = {}; buffer_copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -177,15 +164,8 @@ void FragmentShadingRateDynamic::create_shading_rate_attachment() vkCmdCopyBufferToImage(cmd, staging_buffer->get_handle(), shading_rate_image->get_handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_copy_region); - VkImageMemoryBarrier memory_barrier = vkb::initializers::image_memory_barrier(); - memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - memory_barrier.newLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - memory_barrier.image = shading_rate_image->get_handle(); - memory_barrier.subresourceRange = subresource_range; - memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - memory_barrier.dstAccessMask = 0; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, - VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &memory_barrier); + vkb::image_layout_transition( + cmd, shading_rate_image->get_handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR); VK_CHECK(vkEndCommandBuffer(cmd)); @@ -880,41 +860,35 @@ void FragmentShadingRateDynamic::update_compute_pipeline() image_copy.extent = shading_rate_image->get_extent(); image_copy.srcOffset = {0, 0, 0}; + vkb::image_layout_transition( + command_buffer, shading_rate_image->get_handle(), VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VkImageSubresourceRange subresource_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkb::set_image_layout(command_buffer, shading_rate_image->get_handle(), - VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); - - auto image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - image_memory_barrier.subresourceRange = subresource_range; - image_memory_barrier.image = shading_rate_image_compute->get_handle(); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &image_memory_barrier); + vkb::image_layout_transition(command_buffer, + shading_rate_image_compute->get_handle(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + subresource_range); vkCmdCopyImage(command_buffer, shading_rate_image_compute->get_handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, shading_rate_image->get_handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); - auto shading_memory_barrier = vkb::initializers::image_memory_barrier(); - shading_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - shading_memory_barrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR; - shading_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - shading_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - shading_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - shading_memory_barrier.newLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; - shading_memory_barrier.subresourceRange = subresource_range; - shading_memory_barrier.image = shading_rate_image->get_handle(); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, 0, 0, VK_NULL_HANDLE, 0, - VK_NULL_HANDLE, 1, &shading_memory_barrier); - - vkb::set_image_layout(command_buffer, shading_rate_image_compute->get_handle(), - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, subresource_range); + vkb::image_layout_transition( + command_buffer, shading_rate_image->get_handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR); + + vkb::image_layout_transition(command_buffer, + shading_rate_image_compute->get_handle(), + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + {}, + {}, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_GENERAL, + subresource_range); VK_CHECK(vkEndCommandBuffer(compute_buffer.command_buffer)); diff --git a/samples/extensions/open_gl_interop/open_gl_interop.cpp b/samples/extensions/open_gl_interop/open_gl_interop.cpp index 53b7f96774..46fb00cbff 100644 --- a/samples/extensions/open_gl_interop/open_gl_interop.cpp +++ b/samples/extensions/open_gl_interop/open_gl_interop.cpp @@ -260,28 +260,9 @@ void OpenGLInterop::prepare_shared_resources() 0, 1}; vkCreateImageView(deviceHandle, &viewCreateInfo, nullptr, &sharedTexture.view); - with_command_buffer([&](VkCommandBuffer image_command_buffer) { - VkImageMemoryBarrier image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.image = sharedTexture.image; - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkImageSubresourceRange &subresource_range = image_memory_barrier.subresourceRange; - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_range.levelCount = 1; - subresource_range.layerCount = 1; - - vkCmdPipelineBarrier( - image_command_buffer, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &image_memory_barrier); - }, - sharedSemaphores.gl_ready); + with_command_buffer( + [&](VkCommandBuffer image_command_buffer) { vkb::image_layout_transition(image_command_buffer, sharedTexture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); }, + sharedSemaphores.gl_ready); } } @@ -700,24 +681,7 @@ void OpenGLInterop::build_command_buffers() VK_CHECK(vkBeginCommandBuffer(draw_cmd_buffers[i], &command_buffer_begin_info)); - { - VkImageMemoryBarrier image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.image = sharedTexture.image; - image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkImageSubresourceRange &subresource_range = image_memory_barrier.subresourceRange; - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_range.levelCount = 1; - subresource_range.layerCount = 1; - vkCmdPipelineBarrier( - draw_cmd_buffers[i], - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, - 0, nullptr, 0, nullptr, 1, &image_memory_barrier); - } + vkb::image_layout_transition(draw_cmd_buffers[i], sharedTexture.image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); vkCmdBeginRenderPass(draw_cmd_buffers[i], &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); @@ -744,31 +708,8 @@ void OpenGLInterop::build_command_buffers() vkCmdEndRenderPass(draw_cmd_buffers[i]); - { - VkImageMemoryBarrier image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.image = sharedTexture.image; - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkImageSubresourceRange &subresource_range = image_memory_barrier.subresourceRange; - subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource_range.levelCount = 1; - subresource_range.layerCount = 1; - - // Insert a memory dependency at the proper pipeline stages that will execute the image layout transition - // Source pipeline stage is host write/read execution (VK_PIPELINE_STAGE_HOST_BIT) - // Destination pipeline stage is copy command execution (VK_PIPELINE_STAGE_TRANSFER_BIT) - vkCmdPipelineBarrier( - draw_cmd_buffers[i], - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &image_memory_barrier); - } + vkb::image_layout_transition(draw_cmd_buffers[i], sharedTexture.image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + VK_CHECK(vkEndCommandBuffer(draw_cmd_buffers[i])); } } diff --git a/samples/extensions/ray_tracing_reflection/ray_tracing_reflection.cpp b/samples/extensions/ray_tracing_reflection/ray_tracing_reflection.cpp index 2c3b939c35..aa6b30c04d 100644 --- a/samples/extensions/ray_tracing_reflection/ray_tracing_reflection.cpp +++ b/samples/extensions/ray_tracing_reflection/ray_tracing_reflection.cpp @@ -187,10 +187,15 @@ void RaytracingReflection::create_storage_image() VK_CHECK(vkCreateImageView(get_device().get_handle(), &color_image_view, nullptr, &storage_image.view)); VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkb::set_image_layout(command_buffer, storage_image.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); + vkb::image_layout_transition(command_buffer, + storage_image.image, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + {}, + {}, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); get_device().flush_command_buffer(command_buffer, queue); } @@ -868,20 +873,20 @@ void RaytracingReflection::build_command_buffers() */ // Prepare current swap chain image as transfer destination - vkb::set_image_layout( - draw_cmd_buffers[i], - get_render_context().get_swapchain().get_images()[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + get_render_context().get_swapchain().get_images()[i], + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Prepare ray tracing output image as transfer source - vkb::set_image_layout( - draw_cmd_buffers[i], - storage_image.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + storage_image.image, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + {}, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range); VkImageCopy copy_region{}; copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; @@ -893,18 +898,21 @@ void RaytracingReflection::build_command_buffers() get_render_context().get_swapchain().get_images()[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); // Transition swap chain image back for presentation - vkb::set_image_layout(draw_cmd_buffers[i], - get_render_context().get_swapchain().get_images()[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + get_render_context().get_swapchain().get_images()[i], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); // Transition ray tracing output image back to general layout - vkb::set_image_layout(draw_cmd_buffers[i], - storage_image.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + storage_image.image, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + {}, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_GENERAL, + subresource_range); /* Start a new render pass to draw the UI overlay on top of the ray traced image diff --git a/samples/extensions/raytracing_basic/raytracing_basic.cpp b/samples/extensions/raytracing_basic/raytracing_basic.cpp index 53c45697f2..703d22f2b6 100644 --- a/samples/extensions/raytracing_basic/raytracing_basic.cpp +++ b/samples/extensions/raytracing_basic/raytracing_basic.cpp @@ -117,10 +117,15 @@ void RaytracingBasic::create_storage_image() VK_CHECK(vkCreateImageView(get_device().get_handle(), &color_image_view, nullptr, &storage_image.view)); VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkb::set_image_layout(command_buffer, storage_image.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); + vkb::image_layout_transition(command_buffer, + storage_image.image, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + {}, + {}, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); get_device().flush_command_buffer(command_buffer, queue); } @@ -741,20 +746,21 @@ void RaytracingBasic::build_command_buffers() */ // Prepare current swap chain image as transfer destination - vkb::set_image_layout( - draw_cmd_buffers[i], - get_render_context().get_swapchain().get_images()[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + get_render_context().get_swapchain().get_images()[i], + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Prepare ray tracing output image as transfer source - vkb::set_image_layout( - draw_cmd_buffers[i], - storage_image.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + storage_image.image, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + {}, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + subresource_range); VkImageCopy copy_region{}; copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; @@ -766,20 +772,21 @@ void RaytracingBasic::build_command_buffers() get_render_context().get_swapchain().get_images()[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); // Transition swap chain image back for presentation - vkb::set_image_layout( - draw_cmd_buffers[i], - get_render_context().get_swapchain().get_images()[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + get_render_context().get_swapchain().get_images()[i], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); // Transition ray tracing output image back to general layout - vkb::set_image_layout( - draw_cmd_buffers[i], - storage_image.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + storage_image.image, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + {}, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_GENERAL, + subresource_range); /* Start a new render pass to draw the UI overlay on top of the ray traced image diff --git a/samples/extensions/raytracing_extended/raytracing_extended.cpp b/samples/extensions/raytracing_extended/raytracing_extended.cpp index 207614e151..93956cd8ca 100644 --- a/samples/extensions/raytracing_extended/raytracing_extended.cpp +++ b/samples/extensions/raytracing_extended/raytracing_extended.cpp @@ -197,10 +197,15 @@ void RaytracingExtended::create_storage_image() VK_CHECK(vkCreateImageView(get_device().get_handle(), &color_image_view, nullptr, &storage_image.view)); VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - vkb::set_image_layout(command_buffer, storage_image.image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_GENERAL, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); + vkb::image_layout_transition(command_buffer, + storage_image.image, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + {}, + {}, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}); get_device().flush_command_buffer(command_buffer, queue); } @@ -1401,20 +1406,21 @@ void RaytracingExtended::draw() Copy ray tracing output to swap chain image */ // Prepare current swap chain image as transfer destination - vkb::set_image_layout( - draw_cmd_buffers[i], - get_render_context().get_swapchain().get_images()[i], - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + get_render_context().get_swapchain().get_images()[i], + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // Prepare ray tracing output image as transfer source - vkb::set_image_layout( - draw_cmd_buffers[i], - storage_image.image, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + storage_image.image, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + {}, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + subresource_range); VkImageCopy copy_region{}; copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; @@ -1426,20 +1432,21 @@ void RaytracingExtended::draw() get_render_context().get_swapchain().get_images()[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); // Transition swap chain image back for presentation - vkb::set_image_layout( - draw_cmd_buffers[i], - get_render_context().get_swapchain().get_images()[i], - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + get_render_context().get_swapchain().get_images()[i], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); // Transition ray tracing output image back to general layout - vkb::set_image_layout( - draw_cmd_buffers[i], - storage_image.image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - subresource_range); + vkb::image_layout_transition(draw_cmd_buffers[i], + storage_image.image, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + {}, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_GENERAL, + subresource_range); VK_CHECK(vkEndCommandBuffer(draw_cmd_buffers[i])); submit_info.commandBufferCount = 1; diff --git a/samples/performance/multi_draw_indirect/multi_draw_indirect.cpp b/samples/performance/multi_draw_indirect/multi_draw_indirect.cpp index 8f44ebdccc..f6e9ab2a1d 100644 --- a/samples/performance/multi_draw_indirect/multi_draw_indirect.cpp +++ b/samples/performance/multi_draw_indirect/multi_draw_indirect.cpp @@ -343,15 +343,8 @@ void MultiDrawIndirect::load_scene() subresource_range.baseMipLevel = 0; subresource_range.levelCount = texture.n_mip_maps; - VkImageMemoryBarrier image_barrier = vkb::initializers::image_memory_barrier(); - image_barrier.srcAccessMask = 0; - image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_barrier.image = texture.image->get_handle(); - image_barrier.subresourceRange = subresource_range; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - - vkCmdPipelineBarrier(texture_cmd.get_handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_barrier); + vkb::image_layout_transition( + texture_cmd.get_handle(), texture.image->get_handle(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); auto offsets = image->get_offsets(); VkBufferImageCopy region = {}; @@ -420,27 +413,17 @@ void MultiDrawIndirect::load_scene() } } - auto &cmd = device->get_command_pool().request_command_buffer(); - cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, VK_NULL_HANDLE); - std::vector image_barriers; - image_barriers.reserve(textures.size()); - for (auto &&texture : textures) + std::vector> imagesAndRanges; + imagesAndRanges.reserve(textures.size()); + for (auto const &texture : textures) { - VkImageSubresourceRange subresource_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - subresource_range.baseMipLevel = 0; - subresource_range.levelCount = texture.n_mip_maps; - - VkImageMemoryBarrier image_barrier = vkb::initializers::image_memory_barrier(); - image_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_barrier.image = texture.image->get_handle(); - image_barrier.subresourceRange = subresource_range; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - image_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - image_barriers.emplace_back(image_barrier); + imagesAndRanges.emplace_back( + std::make_pair(texture.image->get_handle(), VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, texture.n_mip_maps, 0, 1})); } - vkCmdPipelineBarrier(cmd.get_handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, static_cast(image_barriers.size()), image_barriers.data()); + + auto &cmd = device->get_command_pool().request_command_buffer(); + cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, VK_NULL_HANDLE); + vkb::image_layout_transition(cmd.get_handle(), imagesAndRanges, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); cmd.end(); auto &queue = device->get_queue_by_flags(VK_QUEUE_GRAPHICS_BIT, 0); queue.submit(cmd, device->request_fence()); diff --git a/samples/performance/texture_compression_basisu/texture_compression_basisu.cpp b/samples/performance/texture_compression_basisu/texture_compression_basisu.cpp index 9865587fba..863b18d915 100644 --- a/samples/performance/texture_compression_basisu/texture_compression_basisu.cpp +++ b/samples/performance/texture_compression_basisu/texture_compression_basisu.cpp @@ -233,23 +233,8 @@ void TextureCompressionBasisu::transcode_texture(const std::string &input_file, subresource_range.layerCount = 1; // Transition the texture image layout to transfer target, so we can safely copy our buffer data to it. - VkImageMemoryBarrier image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.image = texture.image; - image_memory_barrier.subresourceRange = subresource_range; - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - // Insert a memory dependency at the proper pipeline stages that will execute the image layout transition - vkCmdPipelineBarrier( - copy_command, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &image_memory_barrier); + vkb::image_layout_transition(copy_command, texture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); // Copy mip levels from staging buffer vkCmdCopyBufferToImage( @@ -261,20 +246,9 @@ void TextureCompressionBasisu::transcode_texture(const std::string &input_file, buffer_copy_regions.data()); // Once the data has been uploaded we transfer to the texture image to the shader read layout, so it can be sampled from - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // Insert a memory dependency at the proper pipeline stages that will execute the image layout transition - vkCmdPipelineBarrier( - copy_command, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &image_memory_barrier); + vkb::image_layout_transition( + copy_command, texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range); // Store current layout for later reuse texture.image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; diff --git a/samples/performance/texture_compression_comparison/texture_compression_comparison.cpp b/samples/performance/texture_compression_comparison/texture_compression_comparison.cpp index 83ff55cacb..d204cfc24d 100644 --- a/samples/performance/texture_compression_comparison/texture_compression_comparison.cpp +++ b/samples/performance/texture_compression_comparison/texture_compression_comparison.cpp @@ -327,27 +327,12 @@ std::unique_ptr TextureCompressionComparison::create_image(ktxTe VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); - VkImageMemoryBarrier initial_image_memory_barrier = vkb::initializers::image_memory_barrier(); - initial_image_memory_barrier.image = image; - initial_image_memory_barrier.subresourceRange = subresource_range; - initial_image_memory_barrier.srcAccessMask = 0; - initial_image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - initial_image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - initial_image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &initial_image_memory_barrier); + vkb::image_layout_transition(command_buffer, image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range); vkCmdCopyBufferToImage(command_buffer, staging_buffer->get_handle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, buffer_copies.size(), buffer_copies.data()); - VkImageMemoryBarrier image_memory_barrier = vkb::initializers::image_memory_barrier(); - image_memory_barrier.image = image; - image_memory_barrier.subresourceRange = subresource_range; - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + vkb::image_layout_transition(command_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &image_memory_barrier); device->flush_command_buffer(command_buffer, get_device().get_queue_by_flags(VK_QUEUE_GRAPHICS_BIT, 0).get_handle(), true); return image_out; diff --git a/samples/tooling/profiles/profiles.cpp b/samples/tooling/profiles/profiles.cpp index 3fc5f053fe..725fe70b38 100644 --- a/samples/tooling/profiles/profiles.cpp +++ b/samples/tooling/profiles/profiles.cpp @@ -22,6 +22,7 @@ #include "profiles.h" #include "common/error.h" +#include "common/vk_common.h" #include "core/command_pool.h" #include "core/queue.h" #include "fence_pool.h" @@ -236,27 +237,14 @@ void Profiles::generate_textures() auto &cmd = get_device().request_command_buffer(); cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - VkImageMemoryBarrier barrier = vkb::initializers::image_memory_barrier(); - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - barrier.image = textures[i].image; - vkCmdPipelineBarrier(cmd.get_handle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &barrier); + vkb::image_layout_transition(cmd.get_handle(), textures[i].image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkBufferImageCopy copy_info{}; copy_info.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; copy_info.imageExtent = image_info.extent; vkCmdCopyBufferToImage(cmd.get_handle(), staging_buffer->get_handle(), textures[i].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_info); - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier(cmd.get_handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &barrier); + vkb::image_layout_transition(cmd.get_handle(), textures[i].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VK_CHECK(cmd.end());