Flutter Engine
 
Loading...
Searching...
No Matches
swapchain_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/testing/testing.h" // IWYU pragma: keep
6#include "gtest/gtest.h"
12
13namespace impeller {
14namespace testing {
15
16vk::UniqueSurfaceKHR CreateSurface(const ContextVK& context) {
17#if FML_OS_DARWIN
18 impeller::vk::MetalSurfaceCreateInfoEXT createInfo = {};
19 auto [result, surface] =
20 context.GetInstance().createMetalSurfaceEXTUnique(createInfo);
21 FML_DCHECK(result == vk::Result::eSuccess);
22 return std::move(surface);
23#else
24 return {};
25#endif // FML_OS_DARWIN
26}
27
28TEST(SwapchainTest, CanCreateSwapchain) {
29 auto const context = MockVulkanContextBuilder().Build();
30
31 auto surface = CreateSurface(*context);
32 auto swapchain =
33 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1});
34
35 EXPECT_TRUE(swapchain->IsValid());
36}
37
38TEST(SwapchainTest, RecreateSwapchainWhenSizeChanges) {
39 auto const context = MockVulkanContextBuilder().Build();
40
41 auto surface = CreateSurface(*context);
43 auto swapchain =
44 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1},
45 /*enable_msaa=*/false);
46 auto image = swapchain->AcquireNextDrawable();
47 auto expected_size = ISize{1, 1};
48 EXPECT_EQ(image->GetSize(), expected_size);
49
51 swapchain->UpdateSurfaceSize(ISize{100, 100});
52
53 auto image_b = swapchain->AcquireNextDrawable();
54 expected_size = ISize{100, 100};
55 EXPECT_EQ(image_b->GetSize(), expected_size);
56}
57
58TEST(SwapchainTest, CachesRenderPassOnSwapchainImage) {
59 auto const context = MockVulkanContextBuilder().Build();
60
61 auto surface = CreateSurface(*context);
62 auto swapchain =
63 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1});
64
65 EXPECT_TRUE(swapchain->IsValid());
66
67 // The mock swapchain will always create 3 images, verify each one starts
68 // out with the same MSAA and depth+stencil texture, and no cached
69 // framebuffer.
70 std::vector<std::shared_ptr<Texture>> msaa_textures;
71 std::vector<std::shared_ptr<Texture>> depth_stencil_textures;
72 for (auto i = 0u; i < 3u; i++) {
73 auto drawable = swapchain->AcquireNextDrawable();
74 RenderTarget render_target = drawable->GetRenderTarget();
75
76 auto texture = render_target.GetRenderTargetTexture();
77 auto& texture_vk = TextureVK::Cast(*texture);
78 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
79 nullptr);
80 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
81 nullptr);
82
83 auto command_buffer = context->CreateCommandBuffer();
84 auto render_pass = command_buffer->CreateRenderPass(render_target);
85 render_pass->EncodeCommands();
86
87 auto& depth = render_target.GetDepthAttachment();
88 depth_stencil_textures.push_back(depth.has_value() ? depth->texture
89 : nullptr);
90 msaa_textures.push_back(render_target.GetColorAttachment(0).texture);
91 }
92
93 for (auto i = 1; i < 3; i++) {
94 EXPECT_EQ(msaa_textures[i - 1], msaa_textures[i]);
95 EXPECT_EQ(depth_stencil_textures[i - 1], depth_stencil_textures[i]);
96 }
97
98 // After each images has been acquired once and the render pass presented,
99 // each should have a cached framebuffer and render pass.
100
101 std::vector<SharedHandleVK<vk::Framebuffer>> framebuffers;
102 std::vector<SharedHandleVK<vk::RenderPass>> render_passes;
103 for (auto i = 0u; i < 3u; i++) {
104 auto drawable = swapchain->AcquireNextDrawable();
105 RenderTarget render_target = drawable->GetRenderTarget();
106
107 auto texture = render_target.GetRenderTargetTexture();
108 auto& texture_vk = TextureVK::Cast(*texture);
109
110 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
111 nullptr);
112 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
113 nullptr);
114 framebuffers.push_back(
115 texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer);
116 render_passes.push_back(
117 texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass);
118 }
119
120 // Iterate through once more to verify render passes and framebuffers are
121 // unchanged.
122 for (auto i = 0u; i < 3u; i++) {
123 auto drawable = swapchain->AcquireNextDrawable();
124 RenderTarget render_target = drawable->GetRenderTarget();
125
126 auto texture = render_target.GetRenderTargetTexture();
127 auto& texture_vk = TextureVK::Cast(*texture);
128
129 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
130 framebuffers[i]);
131 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
132 render_passes[i]);
133 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount1).framebuffer,
134 framebuffers[i]);
135 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount1).render_pass,
136 render_passes[i]);
137 }
138}
139
140} // namespace testing
141} // namespace impeller
static TextureVK & Cast(Texture &base)
vk::Instance GetInstance() const
ColorAttachment GetColorAttachment(size_t index) const
Get the color attachment at [index].
std::shared_ptr< Texture > GetRenderTargetTexture() const
const std::optional< DepthAttachment > & GetDepthAttachment() const
static std::shared_ptr< SwapchainVK > Create(const std::shared_ptr< Context > &context, vk::UniqueSurfaceKHR surface, const ISize &size, bool enable_msaa=true)
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
FlutterVulkanImage * image
VkSwapchainKHR swapchain
Definition main.cc:80
VkSurfaceKHR surface
Definition main.cc:65
#define FML_DCHECK(condition)
Definition logging.h:122
FlTexture * texture
TEST(FrameTimingsRecorderTest, RecordVsync)
vk::UniqueSurfaceKHR CreateSurface(const ContextVK &context)
void SetSwapchainImageSize(ISize size)
Override the image size returned by all swapchain images.
std::shared_ptr< Texture > texture
Definition formats.h:657