Fix use-after-free of committed resource heaps

Heaps were destroyed immediately instead of deferring destruction
until after all work using the buffer was complete. This is only
a problem on D3D12. Vulkan allocations already have deferred
deletion, and Metal allocations are managed by the driver.

No-Try: true
Bug: chromium:1313172
Change-Id: I0ef43709949c9e86c40e766f7f2029b14c8a2e97
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85840
Reviewed-by: Brandon Jones <bajones@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
(cherry picked from commit e8d5678b704ac881d0325f73f71168e31333fe04)
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85866
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
index 8c888f5..41733c4 100644
--- a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
+++ b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
@@ -227,6 +227,7 @@
             }
         }
         mAllocationsToDelete.ClearUpTo(completedSerial);
+        mHeapsToDelete.ClearUpTo(completedSerial);
     }
 
     void ResourceAllocatorManager::DeallocateMemory(ResourceHeapAllocation& allocation) {
@@ -238,9 +239,12 @@
 
         // Directly allocated ResourceHeapAllocations are created with a heap object that must be
         // manually deleted upon deallocation. See ResourceAllocatorManager::CreateCommittedResource
-        // for more information.
+        // for more information. Acquire this heap as a unique_ptr and add it to the queue of heaps
+        // to delete. It cannot be deleted immediately because it may be in use by in-flight or
+        // pending commands.
         if (allocation.GetInfo().mMethod == AllocationMethod::kDirect) {
-            delete allocation.GetResourceHeap();
+            mHeapsToDelete.Enqueue(std::unique_ptr<ResourceHeapBase>(allocation.GetResourceHeap()),
+                                   mDevice->GetPendingCommandSerial());
         }
 
         // Invalidate the allocation immediately in case one accidentally
diff --git a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h
index 703d401..331c982 100644
--- a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h
+++ b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h
@@ -100,6 +100,7 @@
             mPooledHeapAllocators;
 
         SerialQueue<ExecutionSerial, ResourceHeapAllocation> mAllocationsToDelete;
+        SerialQueue<ExecutionSerial, std::unique_ptr<ResourceHeapBase>> mHeapsToDelete;
     };
 
 }  // namespace dawn::native::d3d12