Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit db49661

Browse files
author
Jonah Williams
authored
[Impeller] cache onscreen render targets. (#50751)
Currently we cache render pass objects to offscreen render targets only. Caching onscreen doesn't work as 1) the render targets are stored on the texture_vk object and 2) the texture_vk object is recreated for each frame (see https://github.com/flutter/engine/blob/main/impeller/renderer/backend/vulkan/surface_vk.cc#L14 ). To make sure the render pass is cached, move the storage to the texture source. part of flutter/flutter#141750
1 parent 69ebe43 commit db49661

File tree

6 files changed

+99
-6
lines changed

6 files changed

+99
-6
lines changed

impeller/renderer/backend/vulkan/test/mock_vulkan.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct MockImage {};
4242

4343
struct MockSemaphore {};
4444

45+
struct MockFramebuffer {};
46+
4547
static ISize currentImageSize = ISize{1, 1};
4648

4749
class MockDevice final {
@@ -686,6 +688,14 @@ VkResult vkAcquireNextImageKHR(VkDevice device,
686688
return VK_SUCCESS;
687689
}
688690

691+
VkResult vkCreateFramebuffer(VkDevice device,
692+
const VkFramebufferCreateInfo* pCreateInfo,
693+
const VkAllocationCallbacks* pAllocator,
694+
VkFramebuffer* pFramebuffer) {
695+
*pFramebuffer = reinterpret_cast<VkFramebuffer>(new MockFramebuffer());
696+
return VK_SUCCESS;
697+
}
698+
689699
PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance,
690700
const char* pName) {
691701
if (strcmp("vkEnumerateInstanceExtensionProperties", pName) == 0) {
@@ -814,6 +824,8 @@ PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance,
814824
return (PFN_vkVoidFunction)vkDestroySurfaceKHR;
815825
} else if (strcmp("vkAcquireNextImageKHR", pName) == 0) {
816826
return (PFN_vkVoidFunction)vkAcquireNextImageKHR;
827+
} else if (strcmp("vkCreateFramebuffer", pName) == 0) {
828+
return (PFN_vkVoidFunction)vkCreateFramebuffer;
817829
}
818830
return noop;
819831
}

impeller/renderer/backend/vulkan/test/swapchain_unittests.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "gtest/gtest.h"
77
#include "impeller/renderer/backend/vulkan/swapchain_vk.h"
88
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
9+
#include "impeller/renderer/backend/vulkan/texture_vk.h"
910
#include "vulkan/vulkan_enums.hpp"
1011

1112
namespace impeller {
@@ -52,5 +53,43 @@ TEST(SwapchainTest, RecreateSwapchainWhenSizeChanges) {
5253
EXPECT_EQ(image_b->GetSize(), expected_size);
5354
}
5455

56+
TEST(SwapchainTest, CachesRenderPassOnSwapchainImage) {
57+
auto const context = MockVulkanContextBuilder().Build();
58+
59+
auto surface = CreateSurface(*context);
60+
auto swapchain =
61+
SwapchainVK::Create(context, std::move(surface), ISize{1, 1});
62+
63+
EXPECT_TRUE(swapchain->IsValid());
64+
65+
// We should create 3 swapchain images with the current mock setup. However,
66+
// we will only ever return the first image, so the render pass and
67+
// framebuffer will be cached after one call to AcquireNextDrawable.
68+
auto drawable = swapchain->AcquireNextDrawable();
69+
RenderTarget render_target = drawable->GetTargetRenderPassDescriptor();
70+
71+
auto texture = render_target.GetRenderTargetTexture();
72+
auto& texture_vk = TextureVK::Cast(*texture);
73+
EXPECT_EQ(texture_vk.GetFramebuffer(), nullptr);
74+
EXPECT_EQ(texture_vk.GetRenderPass(), nullptr);
75+
76+
auto command_buffer = context->CreateCommandBuffer();
77+
auto render_pass = command_buffer->CreateRenderPass(render_target);
78+
79+
render_pass->EncodeCommands();
80+
81+
EXPECT_NE(texture_vk.GetFramebuffer(), nullptr);
82+
EXPECT_NE(texture_vk.GetRenderPass(), nullptr);
83+
84+
{
85+
auto drawable = swapchain->AcquireNextDrawable();
86+
auto texture = render_target.GetRenderTargetTexture();
87+
auto& texture_vk = TextureVK::Cast(*texture);
88+
89+
EXPECT_NE(texture_vk.GetFramebuffer(), nullptr);
90+
EXPECT_NE(texture_vk.GetRenderPass(), nullptr);
91+
}
92+
}
93+
5594
} // namespace testing
5695
} // namespace impeller

impeller/renderer/backend/vulkan/texture_source_vk.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,22 @@ fml::Status TextureSourceVK::SetLayout(const BarrierVK& barrier) const {
5858
return {};
5959
}
6060

61+
void TextureSourceVK::SetFramebuffer(
62+
const SharedHandleVK<vk::Framebuffer>& framebuffer) {
63+
framebuffer_ = framebuffer;
64+
}
65+
66+
void TextureSourceVK::SetRenderPass(
67+
const SharedHandleVK<vk::RenderPass>& render_pass) {
68+
render_pass_ = render_pass;
69+
}
70+
71+
SharedHandleVK<vk::Framebuffer> TextureSourceVK::GetFramebuffer() const {
72+
return framebuffer_;
73+
}
74+
75+
SharedHandleVK<vk::RenderPass> TextureSourceVK::GetRenderPass() const {
76+
return render_pass_;
77+
}
78+
6179
} // namespace impeller

impeller/renderer/backend/vulkan/texture_source_vk.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,38 @@ class TextureSourceVK {
6565
/// Whether or not this is a swapchain image.
6666
virtual bool IsSwapchainImage() const = 0;
6767

68+
/// Store the last framebuffer object used with this texture.
69+
///
70+
/// This field is only set if this texture is used as the resolve texture
71+
/// of a render pass. By construction, this framebuffer should be compatible
72+
/// with any future render passes.
73+
void SetFramebuffer(const SharedHandleVK<vk::Framebuffer>& framebuffer);
74+
75+
/// Store the last render pass object used with this texture.
76+
///
77+
/// This field is only set if this texture is used as the resolve texture
78+
/// of a render pass. By construction, this framebuffer should be compatible
79+
/// with any future render passes.
80+
void SetRenderPass(const SharedHandleVK<vk::RenderPass>& render_pass);
81+
82+
/// Retrieve the last framebuffer object used with this texture.
83+
///
84+
/// May be nullptr if no previous framebuffer existed.
85+
SharedHandleVK<vk::Framebuffer> GetFramebuffer() const;
86+
87+
/// Retrieve the last render pass object used with this texture.
88+
///
89+
/// May be nullptr if no previous render pass existed.
90+
SharedHandleVK<vk::RenderPass> GetRenderPass() const;
91+
6892
protected:
6993
const TextureDescriptor desc_;
7094

7195
explicit TextureSourceVK(TextureDescriptor desc);
7296

7397
private:
98+
SharedHandleVK<vk::Framebuffer> framebuffer_ = nullptr;
99+
SharedHandleVK<vk::RenderPass> render_pass_ = nullptr;
74100
mutable RWMutex layout_mutex_;
75101
mutable vk::ImageLayout layout_ IPLR_GUARDED_BY(layout_mutex_) =
76102
vk::ImageLayout::eUndefined;

impeller/renderer/backend/vulkan/texture_vk.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,20 +175,20 @@ vk::ImageView TextureVK::GetRenderTargetView() const {
175175

176176
void TextureVK::SetFramebuffer(
177177
const SharedHandleVK<vk::Framebuffer>& framebuffer) {
178-
framebuffer_ = framebuffer;
178+
source_->SetFramebuffer(framebuffer);
179179
}
180180

181181
void TextureVK::SetRenderPass(
182182
const SharedHandleVK<vk::RenderPass>& render_pass) {
183-
render_pass_ = render_pass;
183+
source_->SetRenderPass(render_pass);
184184
}
185185

186186
SharedHandleVK<vk::Framebuffer> TextureVK::GetFramebuffer() const {
187-
return framebuffer_;
187+
return source_->GetFramebuffer();
188188
}
189189

190190
SharedHandleVK<vk::RenderPass> TextureVK::GetRenderPass() const {
191-
return render_pass_;
191+
return source_->GetRenderPass();
192192
}
193193

194194
} // namespace impeller

impeller/renderer/backend/vulkan/texture_vk.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@ class TextureVK final : public Texture, public BackendCast<TextureVK, Texture> {
7373
private:
7474
std::weak_ptr<Context> context_;
7575
std::shared_ptr<TextureSourceVK> source_;
76-
SharedHandleVK<vk::Framebuffer> framebuffer_ = nullptr;
77-
SharedHandleVK<vk::RenderPass> render_pass_ = nullptr;
7876

7977
// |Texture|
8078
void SetLabel(std::string_view label) override;

0 commit comments

Comments
 (0)