Flutter Engine
 
Loading...
Searching...
No Matches
descriptor_pool_vk_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.
9
10namespace impeller {
11namespace testing {
12
13TEST(DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools) {
14 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
15
16 vk::UniqueDescriptorPool pool1 = context->GetDescriptorPoolRecycler()->Get();
17 vk::UniqueDescriptorPool pool2 = context->GetDescriptorPoolRecycler()->Get();
18
19 // The two descriptor pools should be different.
20 EXPECT_NE(pool1.get(), pool2.get());
21
22 context->Shutdown();
23}
24
25TEST(DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable) {
26 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
27
28 {
29 // Fetch a pool (which will be created).
30 DescriptorPoolVK pool = DescriptorPoolVK(context);
31 pool.AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
32 }
33
34 std::shared_ptr<DescriptorPoolVK> pool =
35 context->GetDescriptorPoolRecycler()->GetDescriptorPool();
36
37 // Now check that we only ever created one pool.
38 std::shared_ptr<std::vector<std::string>> called =
39 GetMockVulkanFunctions(context->GetDevice());
40 EXPECT_EQ(
41 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"), 1u);
42
43 context->Shutdown();
44}
45
46TEST(DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded) {
47 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
48
49 // Create 33 pools
50 {
51 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
52 for (size_t i = 0u; i < 33; i++) {
53 std::unique_ptr<DescriptorPoolVK> pool =
54 std::make_unique<DescriptorPoolVK>(context);
55 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
56 pools.push_back(std::move(pool));
57 }
58 }
59
60 std::shared_ptr<std::vector<std::string>> called =
61 GetMockVulkanFunctions(context->GetDevice());
62 EXPECT_EQ(
63 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
64 33u);
65
66 // Now create 33 more descriptor pools and observe that only one more is
67 // allocated.
68 {
69 std::vector<std::shared_ptr<DescriptorPoolVK>> pools;
70 for (size_t i = 0u; i < 33; i++) {
71 std::shared_ptr<DescriptorPoolVK> pool =
72 context->GetDescriptorPoolRecycler()->GetDescriptorPool();
73 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
74 pools.push_back(std::move(pool));
75 }
76 }
77
78 std::shared_ptr<std::vector<std::string>> called_twice =
79 GetMockVulkanFunctions(context->GetDevice());
80 // 32 of the descriptor pools were recycled, so only one more is created.
81 EXPECT_EQ(
82 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
83 34u);
84
85 context->Shutdown();
86}
87
88TEST(DescriptorPoolRecyclerVKTest, MultipleCommandBuffersShareDescriptorPool) {
89 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
90
91 std::shared_ptr<CommandBuffer> cmd_buffer_1 = context->CreateCommandBuffer();
92 std::shared_ptr<CommandBuffer> cmd_buffer_2 = context->CreateCommandBuffer();
93
94 CommandBufferVK& vk_1 = CommandBufferVK::Cast(*cmd_buffer_1);
95 CommandBufferVK& vk_2 = CommandBufferVK::Cast(*cmd_buffer_2);
96
97 EXPECT_EQ(&vk_1.GetDescriptorPool(), &vk_2.GetDescriptorPool());
98
99 // Resetting resources creates a new pool.
100 context->DisposeThreadLocalCachedResources();
101
102 std::shared_ptr<CommandBuffer> cmd_buffer_3 = context->CreateCommandBuffer();
103 CommandBufferVK& vk_3 = CommandBufferVK::Cast(*cmd_buffer_3);
104
105 EXPECT_NE(&vk_1.GetDescriptorPool(), &vk_3.GetDescriptorPool());
106
107 context->Shutdown();
108}
109
110TEST(DescriptorPoolRecyclerVKTest, DescriptorsAreRecycled) {
111 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
112
113 {
114 DescriptorPoolVK pool = DescriptorPoolVK(context);
115 pool.AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
116 }
117
118 // Should reuse the same descriptor set allocated above.
119 std::shared_ptr<DescriptorPoolVK> pool =
120 context->GetDescriptorPoolRecycler()->GetDescriptorPool();
121 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
122
123 std::shared_ptr<std::vector<std::string>> called =
124 GetMockVulkanFunctions(context->GetDevice());
125 EXPECT_EQ(
126 std::count(called->begin(), called->end(), "vkAllocateDescriptorSets"),
127 1);
128
129 // Should allocate a new descriptor set.
130 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
131 EXPECT_EQ(
132 std::count(called->begin(), called->end(), "vkAllocateDescriptorSets"),
133 2);
134}
135
136} // namespace testing
137} // namespace impeller
static CommandBufferVK & Cast(CommandBuffer &base)
DescriptorPoolVK & GetDescriptorPool() const
A per-frame descriptor pool. Descriptors from this pool don't need to be freed individually....
fml::StatusOr< vk::DescriptorSet > AllocateDescriptorSets(const vk::DescriptorSetLayout &layout, PipelineKey pipeline_key, const ContextVK &context_vk)
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
TEST(FrameTimingsRecorderTest, RecordVsync)
std::shared_ptr< std::vector< std::string > > GetMockVulkanFunctions(VkDevice device)