Flutter Impeller
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.
6 #include "fml/closure.h"
7 #include "fml/synchronization/waitable_event.h"
10 #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
11 
12 namespace impeller {
13 namespace testing {
14 
15 TEST(DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools) {
16  auto const context = MockVulkanContextBuilder().Build();
17 
18  auto const pool1 = context->GetDescriptorPoolRecycler()->Get();
19  auto const pool2 = context->GetDescriptorPoolRecycler()->Get();
20 
21  // The two descriptor pools should be different.
22  EXPECT_NE(pool1.get(), pool2.get());
23 
24  context->Shutdown();
25 }
26 
27 TEST(DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable) {
28  auto const context = MockVulkanContextBuilder().Build();
29 
30  {
31  // Fetch a pool (which will be created).
32  auto pool = DescriptorPoolVK(context);
33  pool.AllocateDescriptorSets({}, *context);
34  }
35 
36  // There is a chance that the first death rattle item below is destroyed in
37  // the same reclaim cycle as the pool allocation above. These items are placed
38  // into a std::vector and free'd, which may free in reverse order. That would
39  // imply that the death rattle and subsequent waitable event fires before the
40  // pool is reset. To work around this, we can either manually remove items
41  // from the vector or use two death rattles.
42  for (auto i = 0u; i < 2; i++) {
43  // Add something to the resource manager and have it notify us when it's
44  // destroyed. That should give us a non-flaky signal that the pool has been
45  // reclaimed as well.
46  auto waiter = fml::AutoResetWaitableEvent();
47  auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
48  {
50  context->GetResourceManager(), std::move(rattle));
51  }
52  waiter.Wait();
53  }
54 
55  auto const pool = context->GetDescriptorPoolRecycler()->Get();
56 
57  // Now check that we only ever created one pool.
58  auto const called = GetMockVulkanFunctions(context->GetDevice());
59  EXPECT_EQ(
60  std::count(called->begin(), called->end(), "vkCreateDescriptorPool"), 1u);
61 
62  context->Shutdown();
63 }
64 
65 TEST(DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded) {
66  auto const context = MockVulkanContextBuilder().Build();
67 
68  // Create 33 pools
69  {
70  std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
71  for (auto i = 0u; i < 33; i++) {
72  auto pool = std::make_unique<DescriptorPoolVK>(context);
73  pool->AllocateDescriptorSets({}, *context);
74  pools.push_back(std::move(pool));
75  }
76  }
77 
78  // See note above.
79  for (auto i = 0u; i < 2; i++) {
80  auto waiter = fml::AutoResetWaitableEvent();
81  auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
82  {
84  context->GetResourceManager(), std::move(rattle));
85  }
86  waiter.Wait();
87  }
88 
89  auto const called = GetMockVulkanFunctions(context->GetDevice());
90  EXPECT_EQ(
91  std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
92  33u);
93  EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetDescriptorPool"),
94  33u);
95 
96  // Now create 33 more descriptor pools and observe that only one more is
97  // allocated.
98  {
99  std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
100  for (auto i = 0u; i < 33; i++) {
101  auto pool = std::make_unique<DescriptorPoolVK>(context);
102  pool->AllocateDescriptorSets({}, *context);
103  pools.push_back(std::move(pool));
104  }
105  }
106 
107  for (auto i = 0u; i < 2; i++) {
108  auto waiter = fml::AutoResetWaitableEvent();
109  auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
110  {
112  context->GetResourceManager(), std::move(rattle));
113  }
114  waiter.Wait();
115  }
116 
117  auto const called_twice = GetMockVulkanFunctions(context->GetDevice());
118  // 32 of the descriptor pools were recycled, so only one more is created.
119  EXPECT_EQ(
120  std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
121  34u);
122 
123  context->Shutdown();
124 }
125 
126 } // namespace testing
127 } // namespace impeller
impeller::UniqueResourceVKT
A unique handle to a resource which will be reclaimed by the specified resource manager.
Definition: resource_manager_vk.h:143
impeller::testing::TEST
TEST(AiksCanvasTest, EmptyCullRect)
Definition: canvas_unittests.cc:18
impeller::DescriptorPoolVK
A per-frame descriptor pool. Descriptors from this pool don't need to be freed individually....
Definition: descriptor_pool_vk.h:27
resource_manager_vk.h
descriptor_pool_vk.h
impeller
Definition: aiks_blend_unittests.cc:18