From 69480728d879f9f1a544b5faaeebb44b53cb9dc7 Mon Sep 17 00:00:00 2001 From: Sergey Kosarevsky Date: Mon, 25 Sep 2023 20:57:32 -0700 Subject: [PATCH] igl | vulkan | Take care of texture dependencies Summary: Make sure texture dependencies are transitioned to correct image layouts. Reviewed By: pixelperfect3 Differential Revision: D49522647 fbshipit-source-id: 7fea148b30d19c9eabc92029fc5050f8646ef46c --- src/igl/vulkan/CommandBuffer.cpp | 41 ++++++++++++++++++++----- src/igl/vulkan/RenderCommandEncoder.cpp | 29 ++++++++++++++++- src/igl/vulkan/RenderCommandEncoder.h | 4 +++ 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/igl/vulkan/CommandBuffer.cpp b/src/igl/vulkan/CommandBuffer.cpp index 7dd3065ce8..054b2d9d9e 100644 --- a/src/igl/vulkan/CommandBuffer.cpp +++ b/src/igl/vulkan/CommandBuffer.cpp @@ -31,8 +31,7 @@ std::unique_ptr CommandBuffer::createComputeCommandEncod namespace { -void transitionToColorAttachment(VkCommandBuffer buffer, - const std::shared_ptr& colorTex) { +void transitionToColorAttachment(VkCommandBuffer buffer, ITexture* colorTex) { // We really shouldn't get a null here, but just in case. if (!IGL_VERIFY(colorTex)) { return; @@ -60,6 +59,28 @@ void transitionToColorAttachment(VkCommandBuffer buffer, VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}); } +void transitionToShaderReadOnly(VkCommandBuffer cmdBuf, ITexture* texture) { + // We really shouldn't get a null here, but just in case. + if (!IGL_VERIFY(texture)) { + return; + } + + const vulkan::Texture& tex = static_cast(*texture); + const vulkan::VulkanImage& img = tex.getVulkanTexture().getVulkanImage(); + // this must match the final layout of the render pass + img.imageLayout_ = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + if (img.usageFlags_ & VK_IMAGE_USAGE_SAMPLED_BIT) { + // transition sampled images to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + img.transitionLayout( + cmdBuf, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // wait for all subsequent fragment shaders + VkImageSubresourceRange{ + VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}); + } +} + } // namespace std::unique_ptr CommandBuffer::createRenderCommandEncoder( @@ -70,19 +91,23 @@ std::unique_ptr CommandBuffer::createRenderCommandEncoder IGL_PROFILER_FUNCTION(); IGL_ASSERT(framebuffer); - (void)dependencies; // will be implemented later - framebuffer_ = framebuffer; + for (ITexture* IGL_NULLABLE tex : dependencies.textures) { + if (tex) { + transitionToShaderReadOnly(wrapper_.cmdBuf_, tex); + } + } + // prepare all the color attachments const auto& indices = framebuffer->getColorAttachmentIndices(); for (auto i : indices) { const auto colorTex = framebuffer->getColorAttachment(i); - transitionToColorAttachment(wrapper_.cmdBuf_, colorTex); + transitionToColorAttachment(wrapper_.cmdBuf_, colorTex.get()); // handle MSAA const auto colorResolveTex = framebuffer->getResolveColorAttachment(i); if (colorResolveTex) { - transitionToColorAttachment(wrapper_.cmdBuf_, colorResolveTex); + transitionToColorAttachment(wrapper_.cmdBuf_, colorResolveTex.get()); } } @@ -102,8 +127,8 @@ std::unique_ptr CommandBuffer::createRenderCommandEncoder VkImageSubresourceRange{flags, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}); } - auto encoder = - RenderCommandEncoder::create(shared_from_this(), ctx_, renderPass, framebuffer, outResult); + auto encoder = RenderCommandEncoder::create( + shared_from_this(), ctx_, renderPass, framebuffer, dependencies, outResult); if (ctx_.enhancedShaderDebuggingStore_) { encoder->binder().bindStorageBuffer( diff --git a/src/igl/vulkan/RenderCommandEncoder.cpp b/src/igl/vulkan/RenderCommandEncoder.cpp index 32e84d1400..f2ca761090 100644 --- a/src/igl/vulkan/RenderCommandEncoder.cpp +++ b/src/igl/vulkan/RenderCommandEncoder.cpp @@ -126,9 +126,11 @@ RenderCommandEncoder::RenderCommandEncoder(const std::shared_ptr& void RenderCommandEncoder::initialize(const RenderPassDesc& renderPass, const std::shared_ptr& framebuffer, + const Dependencies& dependencies, Result* outResult) { IGL_PROFILER_FUNCTION(); framebuffer_ = framebuffer; + dependencies_ = dependencies; Result::setOk(outResult); @@ -288,13 +290,14 @@ std::unique_ptr RenderCommandEncoder::create( VulkanContext& ctx, const RenderPassDesc& renderPass, const std::shared_ptr& framebuffer, + const Dependencies& dependencies, Result* outResult) { IGL_PROFILER_FUNCTION(); Result ret; std::unique_ptr encoder(new RenderCommandEncoder(commandBuffer, ctx)); - encoder->initialize(renderPass, framebuffer, &ret); + encoder->initialize(renderPass, framebuffer, dependencies, &ret); Result::setResult(outResult, ret); return ret.isOk() ? std::move(encoder) : nullptr; @@ -328,11 +331,35 @@ void RenderCommandEncoder::endEncoding() { VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}); } }; + auto transitionToColorAttachment = [](VkCommandBuffer cmdBuf, ITexture* texture) { + if (!texture) { + return; + } + const vulkan::Texture& tex = static_cast(*texture); + const vulkan::VulkanImage& img = tex.getVulkanTexture().getVulkanImage(); + img.imageLayout_ = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + if (img.usageFlags_ & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + img.transitionLayout( + cmdBuf, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VkImageSubresourceRange{ + VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}); + } + }; isEncoding_ = false; ctx_.vf_.vkCmdEndRenderPass(cmdBuffer_); + for (ITexture* IGL_NULLABLE tex : dependencies_.textures) { + if (tex) { + transitionToColorAttachment(cmdBuffer_, tex); + } + } + dependencies_ = {}; + // set image layouts after the render pass const FramebufferDesc& desc = static_cast((*framebuffer_)).getDesc(); diff --git a/src/igl/vulkan/RenderCommandEncoder.h b/src/igl/vulkan/RenderCommandEncoder.h index e814e1f33d..8ad1c2393a 100644 --- a/src/igl/vulkan/RenderCommandEncoder.h +++ b/src/igl/vulkan/RenderCommandEncoder.h @@ -27,6 +27,7 @@ class RenderCommandEncoder : public IRenderCommandEncoder { VulkanContext& ctx, const RenderPassDesc& renderPass, const std::shared_ptr& framebuffer, + const Dependencies& dependencies, Result* outResult); ~RenderCommandEncoder() override { @@ -124,7 +125,10 @@ class RenderCommandEncoder : public IRenderCommandEncoder { void initialize(const RenderPassDesc& renderPass, const std::shared_ptr& framebuffer, + const Dependencies& dependencies, Result* outResult); + + Dependencies dependencies_ = {}; }; } // namespace vulkan