vulkan: Free "in flight" fences/commands in ShutdownImpl

There might still be fences and commands marked as in-flight in
ShutdownImpl if the device was lost. Delete them anyway because since
the device was lost, it means that all objects are no longer in the
"pending" state (from the Vulkan spec point of view)

Bug: chromium:1244454
Change-Id: I905a9a8e5174591bf93e3cdac3cdcb349d75a581
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63102
Commit-Queue: Austin Eng <enga@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index efab8a1..9a2cf96 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -935,7 +935,11 @@
         }
         mRecordingContext.signalSemaphores.clear();
 
+        // Some commands might still be marked as in-flight if we shut down because of a device
+        // loss. Recycle them as unused so that we free them below.
+        RecycleCompletedCommands();
         ASSERT(mCommandsInFlight.Empty());
+
         for (const CommandPoolAndBuffer& commands : mUnusedCommands) {
             // The VkCommandBuffer memory should be wholly owned by the pool and freed when it is
             // destroyed, but that's not the case in some drivers and the leak memory.
@@ -946,6 +950,13 @@
         }
         mUnusedCommands.clear();
 
+        // Some fences might still be marked as in-flight if we shut down because of a device loss.
+        // Delete them since at this point all commands are complete.
+        while (!mFencesInFlight.empty()) {
+            fn.DestroyFence(mVkDevice, *mFencesInFlight.front().first, nullptr);
+            mFencesInFlight.pop();
+        }
+
         for (VkFence fence : mUnusedFences) {
             fn.DestroyFence(mVkDevice, fence, nullptr);
         }