Flutter Engine
The Flutter Engine
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"
11#include "vulkan/vulkan_enums.hpp"
12#include "vulkan/vulkan_handles.hpp"
13
14namespace impeller {
15namespace testing {
16
17vk::UniqueSurfaceKHR CreateSurface(const ContextVK& context) {
18#if FML_OS_DARWIN
19 impeller::vk::MetalSurfaceCreateInfoEXT createInfo = {};
20 auto [result, surface] =
21 context.GetInstance().createMetalSurfaceEXTUnique(createInfo);
22 FML_DCHECK(result == vk::Result::eSuccess);
23 return std::move(surface);
24#else
25 return {};
26#endif // FML_OS_DARWIN
27}
28
29TEST(SwapchainTest, CanCreateSwapchain) {
30 auto const context = MockVulkanContextBuilder().Build();
31
32 auto surface = CreateSurface(*context);
33 auto swapchain =
34 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1});
35
36 EXPECT_TRUE(swapchain->IsValid());
37}
38
39TEST(SwapchainTest, RecreateSwapchainWhenSizeChanges) {
40 auto const context = MockVulkanContextBuilder().Build();
41
42 auto surface = CreateSurface(*context);
44 auto swapchain =
45 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1},
46 /*enable_msaa=*/false);
47 auto image = swapchain->AcquireNextDrawable();
48 auto expected_size = ISize{1, 1};
49 EXPECT_EQ(image->GetSize(), expected_size);
50
52 swapchain->UpdateSurfaceSize(ISize{100, 100});
53
54 auto image_b = swapchain->AcquireNextDrawable();
55 expected_size = ISize{100, 100};
56 EXPECT_EQ(image_b->GetSize(), expected_size);
57}
58
59TEST(SwapchainTest, CachesRenderPassOnSwapchainImage) {
60 auto const context = MockVulkanContextBuilder().Build();
61
62 auto surface = CreateSurface(*context);
63 auto swapchain =
64 KHRSwapchainVK::Create(context, std::move(surface), ISize{1, 1});
65
66 EXPECT_TRUE(swapchain->IsValid());
67
68 // The mock swapchain will always create 3 images, verify each one starts
69 // out with the same MSAA and depth+stencil texture, and no cached
70 // framebuffer.
71 std::vector<std::shared_ptr<Texture>> msaa_textures;
72 std::vector<std::shared_ptr<Texture>> depth_stencil_textures;
73 for (auto i = 0u; i < 3u; i++) {
74 auto drawable = swapchain->AcquireNextDrawable();
75 RenderTarget render_target = drawable->GetTargetRenderPassDescriptor();
76
77 auto texture = render_target.GetRenderTargetTexture();
78 auto& texture_vk = TextureVK::Cast(*texture);
79 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
80 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
81
82 auto command_buffer = context->CreateCommandBuffer();
83 auto render_pass = command_buffer->CreateRenderPass(render_target);
84 render_pass->EncodeCommands();
85
86 auto& depth = render_target.GetDepthAttachment();
87 depth_stencil_textures.push_back(depth.has_value() ? depth->texture
88 : nullptr);
89 msaa_textures.push_back(
90 render_target.GetColorAttachments().find(0u)->second.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->GetTargetRenderPassDescriptor();
106
107 auto texture = render_target.GetRenderTargetTexture();
108 auto& texture_vk = TextureVK::Cast(*texture);
109
110 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
111 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
112 framebuffers.push_back(texture_vk.GetCachedFramebuffer());
113 render_passes.push_back(texture_vk.GetCachedRenderPass());
114 }
115
116 // Iterate through once more to verify render passes and framebuffers are
117 // unchanged.
118 for (auto i = 0u; i < 3u; i++) {
119 auto drawable = swapchain->AcquireNextDrawable();
120 RenderTarget render_target = drawable->GetTargetRenderPassDescriptor();
121
122 auto texture = render_target.GetRenderTargetTexture();
123 auto& texture_vk = TextureVK::Cast(*texture);
124
125 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), framebuffers[i]);
126 EXPECT_EQ(texture_vk.GetCachedRenderPass(), render_passes[i]);
127 }
128}
129
130} // namespace testing
131} // namespace impeller
static TextureVK & Cast(Texture &base)
Definition: backend_cast.h:13
vk::Instance GetInstance() const
Definition: context_vk.cc:509
std::shared_ptr< Texture > GetRenderTargetTexture() const
const std::map< size_t, ColorAttachment > & GetColorAttachments() 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)
Definition: swapchain_vk.cc:18
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
Definition: mock_vulkan.cc:912
VkSwapchainKHR swapchain
Definition: main.cc:64
VkSurfaceKHR surface
Definition: main.cc:49
GAsyncResult * result
#define FML_DCHECK(condition)
Definition: logging.h:103
FlTexture * texture
sk_sp< const SkImage > image
Definition: SkRecords.h:269
TEST(AiksCanvasTest, EmptyCullRect)
vk::UniqueSurfaceKHR CreateSurface(const ContextVK &context)
void SetSwapchainImageSize(ISize size)
Override the image size returned by all swapchain images.
Definition: mock_vulkan.cc:932
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678