diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index 23d73817cc9090bb1258b6a2ec6a4bda21c67f60..657570b68a7ca81f4878a671c0ba381726c52689 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -75,8 +75,6 @@ namespace vkcv { const ImageHandle &handle) { auto &image = (*this) [handle]; - recordImageLayoutTransition(handle, 0, 0, vk::ImageLayout::eGeneral, cmdBuffer); - vk::ImageAspectFlags aspectFlags; if (isDepthFormat(image.m_format)) { aspectFlags = vk::ImageAspectFlagBits::eDepth; @@ -105,8 +103,8 @@ namespace vkcv { { vk::Offset3D(0, 0, 0), vk::Offset3D(dstWidth, dstHeight, dstDepth) } ); - //recordImageLayoutTransition(handle, 1, srcMip, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer); - //recordImageLayoutTransition(handle, 1, dstMip, vk::ImageLayout::eTransferDstOptimal, cmdBuffer); + recordImageLayoutTransition(handle, 1, srcMip, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer); + recordImageLayoutTransition(handle, 1, dstMip, vk::ImageLayout::eTransferDstOptimal, cmdBuffer); cmdBuffer.blitImage(image.m_handle, image.m_layers[0].m_layouts[srcMip], image.m_handle, image.m_layers[0].m_layouts[dstMip], region, vk::Filter::eLinear); @@ -121,9 +119,6 @@ namespace vkcv { recordImageMemoryBarrier(handle, cmdBuffer); } - - //recordImageLayoutTransition(handle, 1, image.m_viewPerMip.size() - 1, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer); - //recordImageLayoutTransition(handle, 0, 0, vk::ImageLayout::eGeneral, cmdBuffer); } const ImageEntry &ImageManager::operator[](const ImageHandle &handle) const { @@ -410,10 +405,11 @@ namespace vkcv { return views [mipLevel]; } - static vk::ImageMemoryBarrier createImageLayoutTransitionBarrier(const ImageEntry &image, - uint32_t mipLevelCount, - uint32_t mipLevelOffset, - vk::ImageLayout newLayout) { + static Vector<vk::ImageMemoryBarrier> createImageLayoutTransitionBarriers(const ImageEntry &image, + uint32_t mipLevelCount, + uint32_t mipLevelOffset, + vk::ImageLayout newLayout, + bool keepOldLayout) { vk::ImageAspectFlags aspectFlags; if (isDepthFormat(image.m_format)) { aspectFlags = vk::ImageAspectFlagBits::eDepth; @@ -434,59 +430,98 @@ namespace vkcv { if (mipLevelCount <= 0) { return {}; } + + Vector<vk::ImageMemoryBarrier> barriers; + vk::ImageLayout layout = vk::ImageLayout::eUndefined; + uint32_t levels = 0; + + for (uint32_t i = 1; i <= mipLevelCount; i++) { + if ((levels > 0) && (layout != image.m_layers[0].m_layouts[mipLevelOffset + mipLevelCount - i])) { + const vk::ImageSubresourceRange imageSubresourceRange( + aspectFlags, + mipLevelOffset + mipLevelCount - (i - 1), + levels, + 0, + static_cast<uint32_t>(image.m_layers.size()) + ); + + // TODO: precise AccessFlagBits, will require a lot of context + barriers.emplace_back( + vk::AccessFlagBits::eMemoryWrite, + vk::AccessFlagBits::eMemoryRead, + layout, + keepOldLayout? layout : newLayout, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + image.m_handle, + imageSubresourceRange + ); + + levels = 0; + } + + layout = image.m_layers[0].m_layouts[mipLevelOffset + mipLevelCount - i]; + levels++; + } - vk::ImageSubresourceRange imageSubresourceRange( - aspectFlags, - mipLevelOffset, - mipLevelCount, - 0, - static_cast<uint32_t>(image.m_layers.size()) - ); - - // TODO: precise AccessFlagBits, will require a lot of context - vk::ImageMemoryBarrier barrier ( - vk::AccessFlagBits::eMemoryWrite, - vk::AccessFlagBits::eMemoryRead, - image.m_layers[imageSubresourceRange.baseArrayLayer].m_layouts[imageSubresourceRange.baseMipLevel], - newLayout, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - image.m_handle, - imageSubresourceRange - ); + if (levels > 0) { + const vk::ImageSubresourceRange imageSubresourceRange( + aspectFlags, + mipLevelOffset, + levels, + 0, + static_cast<uint32_t>(image.m_layers.size()) + ); + + // TODO: precise AccessFlagBits, will require a lot of context + barriers.emplace_back( + vk::AccessFlagBits::eMemoryWrite, + vk::AccessFlagBits::eMemoryRead, + layout, + keepOldLayout? layout : newLayout, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + image.m_handle, + imageSubresourceRange + ); + } - return barrier; + return barriers; } void ImageManager::switchImageLayoutImmediate(const ImageHandle &handle, vk::ImageLayout newLayout) { auto &image = (*this) [handle]; - const auto transitionBarrier = createImageLayoutTransitionBarrier(image, 0, 0, newLayout); + const auto transitionBarriers = createImageLayoutTransitionBarriers(image, 0, 0, newLayout, false); auto &core = getCore(); auto stream = core.createCommandStream(QueueType::Graphics); core.recordCommandsToStream( stream, - [transitionBarrier](const vk::CommandBuffer &commandBuffer) { + [transitionBarriers](const vk::CommandBuffer &commandBuffer) { // TODO: precise PipelineStageFlagBits, will require a lot of context - commandBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eTopOfPipe, - vk::PipelineStageFlagBits::eBottomOfPipe, - {}, - nullptr, - nullptr, - transitionBarrier - ); + for (const auto& barrier : transitionBarriers) { + commandBuffer.pipelineBarrier( + vk::PipelineStageFlagBits::eTopOfPipe, + vk::PipelineStageFlagBits::eBottomOfPipe, + {}, + nullptr, + nullptr, + barrier + ); + } }, nullptr ); core.submitCommandStream(stream, false); - for (uint32_t i = transitionBarrier.subresourceRange.baseArrayLayer; i < transitionBarrier.subresourceRange.layerCount; i++) { - for (uint32_t j = transitionBarrier.subresourceRange.baseMipLevel; j < transitionBarrier.subresourceRange.levelCount; j++) { - image.m_layers[i].m_layouts[j] = newLayout; + for (const auto& barrier : transitionBarriers) { + for (uint32_t i = 0; i < barrier.subresourceRange.layerCount; i++) { + for (uint32_t j = 0; j < barrier.subresourceRange.levelCount; j++) { + image.m_layers[barrier.subresourceRange.baseArrayLayer + i].m_layouts[barrier.subresourceRange.baseMipLevel + j] = newLayout; + } } } } @@ -496,27 +531,29 @@ namespace vkcv { vk::ImageLayout newLayout, vk::CommandBuffer cmdBuffer) { auto &image = (*this) [handle]; - const auto transitionBarrier = createImageLayoutTransitionBarrier( + + const auto transitionBarriers = createImageLayoutTransitionBarriers( image, mipLevelCount, mipLevelOffset, - newLayout + newLayout, + false ); - if (transitionBarrier.subresourceRange.levelCount > 0) { + for (const auto& barrier : transitionBarriers) { cmdBuffer.pipelineBarrier( vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, nullptr, - transitionBarrier + barrier ); - } - - for (uint32_t i = transitionBarrier.subresourceRange.baseArrayLayer; i < transitionBarrier.subresourceRange.layerCount; i++) { - for (uint32_t j = transitionBarrier.subresourceRange.baseMipLevel; j < transitionBarrier.subresourceRange.levelCount; j++) { - image.m_layers[i].m_layouts[j] = newLayout; + + for (uint32_t i = 0; i < barrier.subresourceRange.layerCount; i++) { + for (uint32_t j = 0; j < barrier.subresourceRange.levelCount; j++) { + image.m_layers[barrier.subresourceRange.baseArrayLayer + i].m_layouts[barrier.subresourceRange.baseMipLevel + j] = newLayout; + } } } } @@ -525,51 +562,24 @@ namespace vkcv { vk::CommandBuffer cmdBuffer) { auto &image = (*this) [handle]; - const uint32_t mipLevelCount = image.m_viewPerMip.size(); - bool mipLevelConsistency = true; - - for (uint32_t i = 1; i < mipLevelCount; i++) { - if (image.m_layers[0].m_layouts[i] != image.m_layers[0].m_layouts[0]) { - mipLevelConsistency = false; - } - } + const auto transitionBarriers = createImageLayoutTransitionBarriers( + image, + 0, + 0, + vk::ImageLayout::eUndefined, + true + ); - if (mipLevelConsistency) { - const auto transitionBarrier = createImageLayoutTransitionBarrier( - image, - 0, - 0, - image.m_layers[0].m_layouts[0] - ); - + for (const auto& barrier : transitionBarriers) { cmdBuffer.pipelineBarrier( vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, nullptr, nullptr, - transitionBarrier + barrier ); - } else { - for (uint32_t i = 0; i < mipLevelCount; i++) { - const auto transitionBarrier = createImageLayoutTransitionBarrier( - image, - 1, - i, - image.m_layers[0].m_layouts[i] - ); - - cmdBuffer.pipelineBarrier( - vk::PipelineStageFlagBits::eAllCommands, - vk::PipelineStageFlagBits::eAllCommands, - {}, - nullptr, - nullptr, - transitionBarrier - ); - } } - } constexpr uint32_t getBytesPerPixel(vk::Format format) {