From 25afb3739b1755b29ec329b183e0108a633bfb0d Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sun, 18 Feb 2024 13:11:40 -0800 Subject: [PATCH 1/2] [Impeller] cache onscreen render targets. --- .../backend/vulkan/texture_source_vk.cc | 18 +++++++++++++ .../backend/vulkan/texture_source_vk.h | 26 +++++++++++++++++++ .../renderer/backend/vulkan/texture_vk.cc | 8 +++--- impeller/renderer/backend/vulkan/texture_vk.h | 2 -- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/impeller/renderer/backend/vulkan/texture_source_vk.cc b/impeller/renderer/backend/vulkan/texture_source_vk.cc index 4a39bce151bd8..f200bc5778aaf 100644 --- a/impeller/renderer/backend/vulkan/texture_source_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_source_vk.cc @@ -58,4 +58,22 @@ fml::Status TextureSourceVK::SetLayout(const BarrierVK& barrier) const { return {}; } +void TextureSourceVK::SetFramebuffer( + const SharedHandleVK& framebuffer) { + framebuffer_ = framebuffer; +} + +void TextureSourceVK::SetRenderPass( + const SharedHandleVK& render_pass) { + render_pass_ = render_pass; +} + +SharedHandleVK TextureSourceVK::GetFramebuffer() const { + return framebuffer_; +} + +SharedHandleVK TextureSourceVK::GetRenderPass() const { + return render_pass_; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/texture_source_vk.h b/impeller/renderer/backend/vulkan/texture_source_vk.h index 4f76a8067cf4f..502a9a180dfcf 100644 --- a/impeller/renderer/backend/vulkan/texture_source_vk.h +++ b/impeller/renderer/backend/vulkan/texture_source_vk.h @@ -65,12 +65,38 @@ class TextureSourceVK { /// Whether or not this is a swapchain image. virtual bool IsSwapchainImage() const = 0; + /// Store the last framebuffer object used with this texture. + /// + /// This field is only set if this texture is used as the resolve texture + /// of a render pass. By construction, this framebuffer should be compatible + /// with any future render passes. + void SetFramebuffer(const SharedHandleVK& framebuffer); + + /// Store the last render pass object used with this texture. + /// + /// This field is only set if this texture is used as the resolve texture + /// of a render pass. By construction, this framebuffer should be compatible + /// with any future render passes. + void SetRenderPass(const SharedHandleVK& render_pass); + + /// Retrieve the last framebuffer object used with this texture. + /// + /// May be nullptr if no previous framebuffer existed. + SharedHandleVK GetFramebuffer() const; + + /// Retrieve the last render pass object used with this texture. + /// + /// May be nullptr if no previous render pass existed. + SharedHandleVK GetRenderPass() const; + protected: const TextureDescriptor desc_; explicit TextureSourceVK(TextureDescriptor desc); private: + SharedHandleVK framebuffer_ = nullptr; + SharedHandleVK render_pass_ = nullptr; mutable RWMutex layout_mutex_; mutable vk::ImageLayout layout_ IPLR_GUARDED_BY(layout_mutex_) = vk::ImageLayout::eUndefined; diff --git a/impeller/renderer/backend/vulkan/texture_vk.cc b/impeller/renderer/backend/vulkan/texture_vk.cc index b105d31b96e85..cd3d93ff7fb0d 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_vk.cc @@ -175,20 +175,20 @@ vk::ImageView TextureVK::GetRenderTargetView() const { void TextureVK::SetFramebuffer( const SharedHandleVK& framebuffer) { - framebuffer_ = framebuffer; + source_->SetFramebuffer(framebuffer); } void TextureVK::SetRenderPass( const SharedHandleVK& render_pass) { - render_pass_ = render_pass; + source_->SetRenderPass(render_pass); } SharedHandleVK TextureVK::GetFramebuffer() const { - return framebuffer_; + return source_->GetFramebuffer(); } SharedHandleVK TextureVK::GetRenderPass() const { - return render_pass_; + return source_->GetRenderPass(); } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/texture_vk.h b/impeller/renderer/backend/vulkan/texture_vk.h index 5826e3df78174..7a8be812eab31 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.h +++ b/impeller/renderer/backend/vulkan/texture_vk.h @@ -73,8 +73,6 @@ class TextureVK final : public Texture, public BackendCast { private: std::weak_ptr context_; std::shared_ptr source_; - SharedHandleVK framebuffer_ = nullptr; - SharedHandleVK render_pass_ = nullptr; // |Texture| void SetLabel(std::string_view label) override; From e12969c03586653ef636d79d3905e85301261738 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 20 Feb 2024 14:36:42 -0800 Subject: [PATCH 2/2] add test for swapchain cache. --- .../backend/vulkan/test/mock_vulkan.cc | 12 ++++++ .../vulkan/test/swapchain_unittests.cc | 39 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/impeller/renderer/backend/vulkan/test/mock_vulkan.cc b/impeller/renderer/backend/vulkan/test/mock_vulkan.cc index a44bdda6b2d08..739c16e5bcaad 100644 --- a/impeller/renderer/backend/vulkan/test/mock_vulkan.cc +++ b/impeller/renderer/backend/vulkan/test/mock_vulkan.cc @@ -42,6 +42,8 @@ struct MockImage {}; struct MockSemaphore {}; +struct MockFramebuffer {}; + static ISize currentImageSize = ISize{1, 1}; class MockDevice final { @@ -684,6 +686,14 @@ VkResult vkAcquireNextImageKHR(VkDevice device, return VK_SUCCESS; } +VkResult vkCreateFramebuffer(VkDevice device, + const VkFramebufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkFramebuffer* pFramebuffer) { + *pFramebuffer = reinterpret_cast(new MockFramebuffer()); + return VK_SUCCESS; +} + PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance, const char* pName) { if (strcmp("vkEnumerateInstanceExtensionProperties", pName) == 0) { @@ -812,6 +822,8 @@ PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance, return (PFN_vkVoidFunction)vkDestroySurfaceKHR; } else if (strcmp("vkAcquireNextImageKHR", pName) == 0) { return (PFN_vkVoidFunction)vkAcquireNextImageKHR; + } else if (strcmp("vkCreateFramebuffer", pName) == 0) { + return (PFN_vkVoidFunction)vkCreateFramebuffer; } return noop; } diff --git a/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc b/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc index a78d3187b58df..f0af23ed75b46 100644 --- a/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc +++ b/impeller/renderer/backend/vulkan/test/swapchain_unittests.cc @@ -6,6 +6,7 @@ #include "gtest/gtest.h" #include "impeller/renderer/backend/vulkan/swapchain_vk.h" #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h" +#include "impeller/renderer/backend/vulkan/texture_vk.h" #include "vulkan/vulkan_enums.hpp" namespace impeller { @@ -52,5 +53,43 @@ TEST(SwapchainTest, RecreateSwapchainWhenSizeChanges) { EXPECT_EQ(image_b->GetSize(), expected_size); } +TEST(SwapchainTest, CachesRenderPassOnSwapchainImage) { + auto const context = MockVulkanContextBuilder().Build(); + + auto surface = CreateSurface(*context); + auto swapchain = + SwapchainVK::Create(context, std::move(surface), ISize{1, 1}); + + EXPECT_TRUE(swapchain->IsValid()); + + // We should create 3 swapchain images with the current mock setup. However, + // we will only ever return the first image, so the render pass and + // framebuffer will be cached after one call to AcquireNextDrawable. + auto drawable = swapchain->AcquireNextDrawable(); + RenderTarget render_target = drawable->GetTargetRenderPassDescriptor(); + + auto texture = render_target.GetRenderTargetTexture(); + auto& texture_vk = TextureVK::Cast(*texture); + EXPECT_EQ(texture_vk.GetFramebuffer(), nullptr); + EXPECT_EQ(texture_vk.GetRenderPass(), nullptr); + + auto command_buffer = context->CreateCommandBuffer(); + auto render_pass = command_buffer->CreateRenderPass(render_target); + + render_pass->EncodeCommands(); + + EXPECT_NE(texture_vk.GetFramebuffer(), nullptr); + EXPECT_NE(texture_vk.GetRenderPass(), nullptr); + + { + auto drawable = swapchain->AcquireNextDrawable(); + auto texture = render_target.GetRenderTargetTexture(); + auto& texture_vk = TextureVK::Cast(*texture); + + EXPECT_NE(texture_vk.GetFramebuffer(), nullptr); + EXPECT_NE(texture_vk.GetRenderPass(), nullptr); + } +} + } // namespace testing } // namespace impeller