From 088bef549e4e731304f2c48681141f1485b5cb84 Mon Sep 17 00:00:00 2001 From: renderexpert Date: Sat, 11 May 2024 10:31:48 +0100 Subject: [PATCH] Fix Vulkan validation in vkQueueSubmit() Signed-off-by: renderexpert --- drape/vulkan/vulkan_base_context.cpp | 107 ++++++++++------ drape/vulkan/vulkan_texture.cpp | 179 +++++++++++++++++---------- drape/vulkan/vulkan_texture.hpp | 7 ++ 3 files changed, 189 insertions(+), 104 deletions(-) diff --git a/drape/vulkan/vulkan_base_context.cpp b/drape/vulkan/vulkan_base_context.cpp index 6c1506bfdc..c914ac3f22 100644 --- a/drape/vulkan/vulkan_base_context.cpp +++ b/drape/vulkan/vulkan_base_context.cpp @@ -16,26 +16,6 @@ namespace { uint32_t constexpr kDefaultStagingBufferSizeInBytes = 3 * 1024 * 1024; -VkImageMemoryBarrier PostRenderBarrier(VkImage image) -{ - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.pNext = nullptr; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageMemoryBarrier.image = image; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - return imageMemoryBarrier; -} - uint16_t PackAttachmentsOperations(VulkanBaseContext::AttachmentsOperations const & operations) { uint16_t result = 0; @@ -307,11 +287,12 @@ void VulkanBaseContext::SetFramebuffer(ref_ptr framebuffer) { ref_ptr fb = m_currentFramebuffer; ref_ptr tex = fb->GetTexture()->GetHardwareTexture(); - VkImageMemoryBarrier imageBarrier = PostRenderBarrier(tex->GetImage()); - vkCmdPipelineBarrier(m_renderingCommandBuffers[m_inflightFrameIndex], - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, - nullptr, 0, nullptr, 1, &imageBarrier); + + // Allow to use framebuffer in the fragment shader in the next pass. + tex->MakeImageLayoutTransition(m_renderingCommandBuffers[m_inflightFrameIndex], + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } } @@ -453,6 +434,51 @@ void VulkanBaseContext::ApplyFramebuffer(std::string const & framebufferLabel) } } + // Make transitions for the current color and depth-stencil attachments. + if (m_currentFramebuffer != nullptr) + { + ref_ptr framebuffer = m_currentFramebuffer; + ref_ptr tex = framebuffer->GetTexture()->GetHardwareTexture(); + tex->MakeImageLayoutTransition(m_renderingCommandBuffers[m_inflightFrameIndex], + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + if (auto ds = framebuffer->GetDepthStencilRef()) + { + ref_ptr dsTex = ds->GetTexture()->GetHardwareTexture(); + dsTex->MakeImageLayoutTransition(m_renderingCommandBuffers[m_inflightFrameIndex], + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + } + } + else + { + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.pNext = nullptr; + imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imageMemoryBarrier.image = m_swapchainImages[m_imageIndex]; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + vkCmdPipelineBarrier(m_renderingCommandBuffers[m_inflightFrameIndex], + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, + nullptr, 0, nullptr, 1, &imageMemoryBarrier); + + m_depthTexture->MakeImageLayoutTransition(m_renderingCommandBuffers[m_inflightFrameIndex], + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + } + m_pipelineKey.m_renderPass = fbData.m_renderPass; VkClearValue clearValues[2]; @@ -1051,7 +1077,7 @@ VkRenderPass VulkanBaseContext::CreateRenderPass(uint32_t attachmentsCount, Atta std::array dependencies = {}; - // Write-after-write for depth/stencil attachment. + // Write-after-write for depth/stencil attachment (begin render pass). dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; dependencies[0].dstSubpass = 0; dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; @@ -1060,7 +1086,7 @@ VkRenderPass VulkanBaseContext::CreateRenderPass(uint32_t attachmentsCount, Atta dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; dependencies[0].dependencyFlags = 0; - // Write-after-write for color attachment. + // Write-after-write for color attachment (begin render pass). dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; dependencies[1].dstSubpass = 0; dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -1069,23 +1095,26 @@ VkRenderPass VulkanBaseContext::CreateRenderPass(uint32_t attachmentsCount, Atta dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies[1].dependencyFlags = 0; - // Write-after-read for color attachment. - dependencies[2].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[2].dstSubpass = 0; - dependencies[2].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[2].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[2].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[2].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + // Read-after-write and write-after-write for color attachment (end render pass). + dependencies[2].srcSubpass = 0; + dependencies[2].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[2].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[2].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[2].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[2].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies[2].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - // Read-after-write for color attachment. + // Write-after-write for depth attachment (end render pass). + // Write-after-write happens because of layout transition to the final layout. dependencies[3].srcSubpass = 0; dependencies[3].dstSubpass = VK_SUBPASS_EXTERNAL; - dependencies[3].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[3].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; dependencies[3].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[3].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[3].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[3].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + dependencies[3].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dependencies[3].dstAccessMask = 0; + dependencies[3].dependencyFlags = 0; VkRenderPassCreateInfo renderPassInfo = {}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; diff --git a/drape/vulkan/vulkan_texture.cpp b/drape/vulkan/vulkan_texture.cpp index 8a2a58c750..2d91949f59 100644 --- a/drape/vulkan/vulkan_texture.cpp +++ b/drape/vulkan/vulkan_texture.cpp @@ -20,47 +20,6 @@ namespace vulkan { namespace { -VkImageMemoryBarrier PreTransferBarrier(VkImageLayout initialLayout, VkImage image) -{ - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.pNext = nullptr; - imageMemoryBarrier.srcAccessMask = (initialLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) ? - VK_ACCESS_SHADER_READ_BIT : 0; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.oldLayout = initialLayout; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageMemoryBarrier.image = image; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - return imageMemoryBarrier; -} - -VkImageMemoryBarrier PostTransferBarrier(VkImage image) -{ - VkImageMemoryBarrier imageMemoryBarrier = {}; - imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageMemoryBarrier.pNext = nullptr; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageMemoryBarrier.image = image; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - return imageMemoryBarrier; -} - VkBufferImageCopy BufferCopyRegion(uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t stagingOffset) { @@ -121,16 +80,17 @@ void VulkanTexture::Create(ref_ptr context, Params const & // Create image. if (params.m_format == TextureFormat::DepthStencil || params.m_format == TextureFormat::Depth) { - VkImageAspectFlags const aspect = + m_aspectFlags = params.m_format == TextureFormat::DepthStencil ? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) : VK_IMAGE_ASPECT_DEPTH_BIT; m_textureObject = m_objectManager->CreateImage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - format, tiling, aspect, params.m_width, params.m_height); + format, tiling, m_aspectFlags, params.m_width, params.m_height); } else { + m_aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; m_textureObject = m_objectManager->CreateImage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - format, tiling, VK_IMAGE_ASPECT_COLOR_BIT, + format, tiling, m_aspectFlags, params.m_width, params.m_height); } } @@ -194,22 +154,19 @@ void VulkanTexture::UploadData(ref_ptr context, uint32_t x, offset = staging.m_offset; } - auto imageMemoryBarrier = PreTransferBarrier(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - m_textureObject.m_image); - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &imageMemoryBarrier); + // Here we use VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, because we also read textures + // in vertex shaders. + MakeImageLayoutTransition(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); auto bufferCopyRegion = BufferCopyRegion(x, y, width, height, offset); vkCmdCopyBufferToImage(commandBuffer, sb, m_textureObject.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); - // Here we use VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, because we also read textures - // in vertex shaders. - imageMemoryBarrier = PostTransferBarrier(m_textureObject.m_image); - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &imageMemoryBarrier); + MakeImageLayoutTransition(commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } void VulkanTexture::Bind(ref_ptr context) const @@ -221,22 +178,20 @@ void VulkanTexture::Bind(ref_ptr context) const // Fill texture on the first bind. if (m_creationStagingBuffer != nullptr) { - auto imageMemoryBarrier = PreTransferBarrier(VK_IMAGE_LAYOUT_UNDEFINED, m_textureObject.m_image); - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &imageMemoryBarrier); + // Here we use VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, because we also read textures + // in vertex shaders. + MakeImageLayoutTransition(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); auto staging = m_creationStagingBuffer->GetReservationById(m_reservationId); auto bufferCopyRegion = BufferCopyRegion(0, 0, GetWidth(), GetHeight(), staging.m_offset); vkCmdCopyBufferToImage(commandBuffer, staging.m_stagingBuffer, m_textureObject.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion); - // Here we use VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, because we also read textures - // in vertex shaders. - imageMemoryBarrier = PostTransferBarrier(m_textureObject.m_image); - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, - &imageMemoryBarrier); + MakeImageLayoutTransition(commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); m_creationStagingBuffer.reset(); } @@ -257,5 +212,99 @@ SamplerKey VulkanTexture::GetSamplerKey() const { return SamplerKey(m_params.m_filter, m_params.m_wrapSMode, m_params.m_wrapTMode); } + +void VulkanTexture::MakeImageLayoutTransition(VkCommandBuffer commandBuffer, + VkImageLayout newLayout, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask) const +{ + VkAccessFlags srcAccessMask = 0; + VkAccessFlags dstAccessMask = 0; + + VkPipelineStageFlags const noAccessMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags srcRemainingMask = srcStageMask & ~noAccessMask; + VkPipelineStageFlags dstRemainingMask = dstStageMask & ~noAccessMask; + + auto const srcTestAndRemoveBit = [&](VkPipelineStageFlagBits stageBit, + VkAccessFlags accessBits) { + if (srcStageMask & stageBit) + { + srcAccessMask |= accessBits; + srcRemainingMask &= ~stageBit; + } + }; + + srcTestAndRemoveBit(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + + srcTestAndRemoveBit(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + + srcTestAndRemoveBit(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + srcTestAndRemoveBit(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT); + + srcTestAndRemoveBit(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + srcTestAndRemoveBit(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + + CHECK(srcRemainingMask == 0, ("Not implemented transition for src pipeline stage")); + + auto const dstTestAndRemoveBit = [&](VkPipelineStageFlagBits stageBit, + VkAccessFlags accessBits) { + if (dstStageMask & stageBit) + { + dstAccessMask |= accessBits; + dstRemainingMask &= ~stageBit; + } + }; + + dstTestAndRemoveBit(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + + dstTestAndRemoveBit(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + + dstTestAndRemoveBit(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + dstTestAndRemoveBit(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT); + + dstTestAndRemoveBit(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + CHECK(dstRemainingMask == 0, ("Not implemented transition for dest pipeline stage")); + + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.pNext = nullptr; + imageMemoryBarrier.srcAccessMask = srcAccessMask; + imageMemoryBarrier.dstAccessMask = dstAccessMask; + imageMemoryBarrier.oldLayout = m_currentLayout; + imageMemoryBarrier.newLayout = newLayout; + imageMemoryBarrier.image = GetImage(); + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.subresourceRange.aspectMask = m_aspectFlags; + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, + nullptr, 0, nullptr, 1, &imageMemoryBarrier); + + m_currentLayout = newLayout; +} } // namespace vulkan } // namespace dp diff --git a/drape/vulkan/vulkan_texture.hpp b/drape/vulkan/vulkan_texture.hpp index 90a9f61c3f..edc0cbda6e 100644 --- a/drape/vulkan/vulkan_texture.hpp +++ b/drape/vulkan/vulkan_texture.hpp @@ -39,9 +39,16 @@ public: VkImage GetImage() const { return m_textureObject.m_image; } SamplerKey GetSamplerKey() const; + void MakeImageLayoutTransition(VkCommandBuffer commandBuffer, + VkImageLayout newLayout, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask) const; + private: ref_ptr m_objectManager; VulkanObject m_textureObject; + mutable VkImageLayout m_currentLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageAspectFlags m_aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; mutable drape_ptr m_creationStagingBuffer; uint32_t m_reservationId = 0; bool m_isMutable = false;