5 #include "flutter/testing/testing.h"
6 #include "fml/synchronization/waitable_event.h"
10 #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
15 TEST(CommandPoolRecyclerVKTest, GetsACommandPoolPerThread) {
16 auto const context = MockVulkanContextBuilder().Build();
24 std::shared_ptr<CommandPoolVK> pool1;
25 std::shared_ptr<CommandPoolVK> pool2;
29 [&]() { pool1 =
context->GetCommandPoolRecycler()->Get(); });
32 [&]() { pool2 =
context->GetCommandPoolRecycler()->Get(); });
38 EXPECT_NE(pool1, pool2);
44 TEST(CommandPoolRecyclerVKTest, GetsTheSameCommandPoolOnSameThread) {
45 auto const context = MockVulkanContextBuilder().Build();
47 auto const pool1 =
context->GetCommandPoolRecycler()->Get();
48 auto const pool2 =
context->GetCommandPoolRecycler()->Get();
51 EXPECT_EQ(pool1.get(), pool2.get());
61 class DeathRattle final {
63 explicit DeathRattle(std::function<
void()> callback)
64 : callback_(
std::move(callback)) {}
66 DeathRattle(DeathRattle&&) =
default;
67 DeathRattle& operator=(DeathRattle&&) =
default;
69 ~DeathRattle() { callback_(); }
72 std::function<void()> callback_;
76 void WaitForReclaim(
const std::shared_ptr<ContextVK>&
context) {
86 for (
int i = 0; i < 2; i++) {
87 auto waiter = fml::AutoResetWaitableEvent();
88 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
90 UniqueResourceVKT<DeathRattle> resource(
context->GetResourceManager(),
100 std::shared_ptr<std::vector<std::string>> ReclaimAndGetMockVulkanFunctions(
101 const std::shared_ptr<ContextVK>&
context) {
103 return GetMockVulkanFunctions(
context->GetDevice());
108 TEST(CommandPoolRecyclerVKTest, ReclaimMakesCommandPoolAvailable) {
109 auto const context = MockVulkanContextBuilder().Build();
113 auto const recycler =
context->GetCommandPoolRecycler();
114 auto const pool = recycler->Get();
123 std::thread thread([&]() {
124 auto const pool =
context->GetCommandPoolRecycler()->Get();
125 EXPECT_NE(pool.get(),
nullptr);
131 auto const called = ReclaimAndGetMockVulkanFunctions(
context);
132 EXPECT_EQ(std::count(called->begin(), called->end(),
"vkCreateCommandPool"),
138 TEST(CommandPoolRecyclerVKTest, CommandBuffersAreRecycled) {
139 auto const context = MockVulkanContextBuilder().Build();
143 auto const recycler =
context->GetCommandPoolRecycler();
144 auto pool = recycler->Get();
146 auto buffer = pool->CreateCommandBuffer();
147 pool->CollectCommandBuffer(std::move(buffer));
158 auto const recycler =
context->GetCommandPoolRecycler();
159 auto pool = recycler->Get();
161 auto buffer = pool->CreateCommandBuffer();
162 pool->CollectCommandBuffer(std::move(buffer));
169 auto const called = ReclaimAndGetMockVulkanFunctions(
context);
170 EXPECT_EQ(std::count(called->begin(), called->end(),
"vkCreateCommandPool"),
173 std::count(called->begin(), called->end(),
"vkAllocateCommandBuffers"),
179 TEST(CommandPoolRecyclerVKTest, ExtraCommandBufferAllocationsTriggerTrim) {
180 auto const context = MockVulkanContextBuilder().Build();
184 auto const recycler =
context->GetCommandPoolRecycler();
185 auto pool = recycler->Get();
188 for (
auto i = 0; i < 64; i++) {
189 auto buffer = pool->CreateCommandBuffer();
190 pool->CollectCommandBuffer(std::move(buffer));
198 auto called = ReclaimAndGetMockVulkanFunctions(
context);
199 EXPECT_EQ(std::count(called->begin(), called->end(),
"vkResetCommandPool"),
205 auto const recycler =
context->GetCommandPoolRecycler();
206 auto pool = recycler->Get();
215 called = ReclaimAndGetMockVulkanFunctions(
context);
216 EXPECT_EQ(std::count(called->begin(), called->end(),
217 "vkResetCommandPoolReleaseResources"),
223 TEST(CommandPoolRecyclerVKTest, RecyclerGlobalPoolMapSize) {
224 auto context = MockVulkanContextBuilder().Build();
225 auto const recycler =
context->GetCommandPoolRecycler();
231 auto pool = recycler->Get();
245 const vk::Device&
GetDevice()
const override {
return device_; }
247 return physical_device_;
252 vk::PhysicalDevice physical_device_;
255 TEST(CommandPoolVKTest, DestroysCleanlyIfDeviceIsDestroyed) {
256 auto const context = MockVulkanContextBuilder().Build();
259 vk::CommandPoolCreateInfo info;
260 info.setQueueFamilyIndex(
context->GetGraphicsQueue()->GetIndex().family);
261 info.setFlags(vk::CommandPoolCreateFlagBits::eTransient);
263 auto device =
context->GetDevice();
264 auto [result, pool] = device.createCommandPoolUnique(info);
265 ASSERT_EQ(result, vk::Result::eSuccess);
267 auto device_holder = std::make_shared<MockDeviceHolder>(device);
268 std::weak_ptr<DeviceHolderVK> weak_device_holder = device_holder;
270 auto command_pool = std::make_unique<CommandPoolVK>(
271 std::move(pool), std::vector<vk::UniqueCommandBuffer>{},
context,
275 device_holder.reset();
279 command_pool.reset();
281 auto const called = ReclaimAndGetMockVulkanFunctions(
context);
282 EXPECT_EQ(std::count(called->begin(), called->end(),
"vkDestroyCommandPool"),
static int GetGlobalPoolCount(const ContextVK &context)
Holds a strong reference to the underlying logical Vulkan device. This comes in handy when the contex...
const vk::PhysicalDevice & GetPhysicalDevice() const override
MockDeviceHolder(vk::Device device)
const vk::Device & GetDevice() const override
TEST(AllocationSizeTest, CanCreateTypedAllocations)
std::shared_ptr< ContextGLES > context