[Impeller] fix descriptor pool recycler test flake. (#48479)

This test worked by 1) releasing an item to be destructed on a background thead 2) adding a second item to this queue with a waitable event.

The idea being you could wait for the event and that would tell you when 1) was complete. Unfortunately these items are released by being placed into a std::vector, which destroyed in _reverse_ order. Somtimes when the test state was queried the work was done and sometimes it wasn't

To fix this, add a second waitable event that guarantees that both the first event and the original event have finished - because we do not add these event until the first is destructed and we do not add items to the destroy list while it is in progress.
diff --git a/impeller/renderer/backend/vulkan/descriptor_pool_vk_unittests.cc b/impeller/renderer/backend/vulkan/descriptor_pool_vk_unittests.cc
index 99756e1..c7f3cc3 100644
--- a/impeller/renderer/backend/vulkan/descriptor_pool_vk_unittests.cc
+++ b/impeller/renderer/backend/vulkan/descriptor_pool_vk_unittests.cc
@@ -69,16 +69,24 @@
     pool.AllocateDescriptorSets(1024, 1024, {});
   }
 
-  // Add something to the resource manager and have it notify us when it's
-  // destroyed. That should give us a non-flaky signal that the pool has been
-  // reclaimed as well.
-  auto waiter = fml::AutoResetWaitableEvent();
-  auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
-  {
-    UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
-                                            std::move(rattle));
+  // There is a chance that the first death rattle item below is destroyed in
+  // the same reclaim cycle as the pool allocation above. These items are placed
+  // into a std::vector and free'd, which may free in reverse order. That would
+  // imply that the death rattle and subsequent waitable event fires before the
+  // pool is reset. To work around this, we can either manually remove items
+  // from the vector or use two death rattles.
+  for (auto i = 0u; i < 2; i++) {
+    // Add something to the resource manager and have it notify us when it's
+    // destroyed. That should give us a non-flaky signal that the pool has been
+    // reclaimed as well.
+    auto waiter = fml::AutoResetWaitableEvent();
+    auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
+    {
+      UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
+                                              std::move(rattle));
+    }
+    waiter.Wait();
   }
-  waiter.Wait();
 
   auto const [pool, _] = context->GetDescriptorPoolRecycler()->Get(1024);
 
@@ -90,5 +98,66 @@
   context->Shutdown();
 }
 
+TEST(DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded) {
+  auto const context = MockVulkanContextBuilder().Build();
+
+  // Create 33 pools
+  {
+    std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
+    for (auto i = 0u; i < 33; i++) {
+      auto pool = std::make_unique<DescriptorPoolVK>(context);
+      pool->AllocateDescriptorSets(1024, 1024, {});
+      pools.push_back(std::move(pool));
+    }
+  }
+
+  // See note above.
+  for (auto i = 0u; i < 2; i++) {
+    auto waiter = fml::AutoResetWaitableEvent();
+    auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
+    {
+      UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
+                                              std::move(rattle));
+    }
+    waiter.Wait();
+  }
+
+  auto const called = GetMockVulkanFunctions(context->GetDevice());
+  EXPECT_EQ(
+      std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
+      33u);
+  EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetDescriptorPool"),
+            33u);
+
+  // Now create 33 more descriptor pools and observe that only one more is
+  // allocated.
+  {
+    std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
+    for (auto i = 0u; i < 33; i++) {
+      auto pool = std::make_unique<DescriptorPoolVK>(context);
+      pool->AllocateDescriptorSets(1024, 1024, {});
+      pools.push_back(std::move(pool));
+    }
+  }
+
+  for (auto i = 0u; i < 2; i++) {
+    auto waiter = fml::AutoResetWaitableEvent();
+    auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
+    {
+      UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
+                                              std::move(rattle));
+    }
+    waiter.Wait();
+  }
+
+  auto const called_twice = GetMockVulkanFunctions(context->GetDevice());
+  // 32 of the descriptor pools were recycled, so only one more is created.
+  EXPECT_EQ(
+      std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
+      34u);
+
+  context->Shutdown();
+}
+
 }  // namespace testing
 }  // namespace impeller