Flutter Engine
The 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.
6#include "fml/closure.h"
11
12namespace impeller {
13namespace testing {
14
15TEST(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
27TEST(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
65TEST(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
AutoreleasePool pool
#define TEST(S, s, D, expected)
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition closure.h:32
A per-frame descriptor pool. Descriptors from this pool don't need to be freed individually....
A unique handle to a resource which will be reclaimed by the specified resource manager.
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
std::shared_ptr< std::vector< std::string > > GetMockVulkanFunctions(VkDevice device)