Destroy ResourceAllocationManager in d3d12::Device::DestroyImpl

Since the ZeroBuffer (4MB) is released in DestroyImpl, it sticks
around in the resource allocation manager, along with a large amount
of unneeded tracking data structures.

To further reduce memory consumption after developers Destroy, we now
delete the ResourceAllocationManager in DestroyImpl and ensure any
remaining objects go through the same shutdown path as normal usage.

Placed resources must be released before any heaps they reside in.

Bug: chromium:1377789
Change-Id: I7a0f6ad2fdcc60bfe5a51586c8a620f4862c38a5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/111601
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/PooledResourceMemoryAllocator.cpp b/src/dawn/native/PooledResourceMemoryAllocator.cpp
index 96b10c6..0310dde 100644
--- a/src/dawn/native/PooledResourceMemoryAllocator.cpp
+++ b/src/dawn/native/PooledResourceMemoryAllocator.cpp
@@ -23,7 +23,9 @@
 PooledResourceMemoryAllocator::PooledResourceMemoryAllocator(ResourceHeapAllocator* heapAllocator)
     : mHeapAllocator(heapAllocator) {}
 
-PooledResourceMemoryAllocator::~PooledResourceMemoryAllocator() = default;
+PooledResourceMemoryAllocator::~PooledResourceMemoryAllocator() {
+    ASSERT(mPool.empty());
+}
 
 void PooledResourceMemoryAllocator::DestroyPool() {
     for (auto& resourceHeap : mPool) {
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index 56ce607..f01915d 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -847,10 +847,9 @@
         ::CloseHandle(mFenceEvent);
     }
 
-    // Release recycled resource heaps.
-    if (mResourceAllocatorManager != nullptr) {
-        mResourceAllocatorManager->DestroyPool();
-    }
+    // Release recycled resource heaps and all other objects waiting for deletion in the resource
+    // allocation manager.
+    mResourceAllocatorManager.reset();
 
     // We need to handle clearing up com object refs that were enqeued after TickImpl
     mUsedComObjectRefs.ClearUpTo(std::numeric_limits<ExecutionSerial>::max());
diff --git a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
index 201cd9c..1a760e2 100644
--- a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
+++ b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.cpp
@@ -330,6 +330,16 @@
     }
 }
 
+ResourceAllocatorManager::~ResourceAllocatorManager() {
+    // Ensure any remaining objects go through the same shutdown path as normal usage.
+    // Placed resources must be released before any heaps they reside in.
+    Tick(std::numeric_limits<ExecutionSerial>::max());
+    DestroyPool();
+
+    ASSERT(mAllocationsToDelete.Empty());
+    ASSERT(mHeapsToDelete.Empty());
+}
+
 ResultOrError<ResourceHeapAllocation> ResourceAllocatorManager::AllocateMemory(
     D3D12_HEAP_TYPE heapType,
     const D3D12_RESOURCE_DESC& resourceDescriptor,
diff --git a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h
index 8f3ffb8..1904abe 100644
--- a/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h
+++ b/src/dawn/native/d3d12/ResourceAllocatorManagerD3D12.h
@@ -59,6 +59,7 @@
 class ResourceAllocatorManager {
   public:
     explicit ResourceAllocatorManager(Device* device);
+    ~ResourceAllocatorManager();
 
     ResultOrError<ResourceHeapAllocation> AllocateMemory(
         D3D12_HEAP_TYPE heapType,
@@ -71,8 +72,6 @@
 
     void Tick(ExecutionSerial lastCompletedSerial);
 
-    void DestroyPool();
-
   private:
     void FreeMemory(ResourceHeapAllocation& allocation);
 
@@ -97,6 +96,8 @@
 
     uint64_t GetResourcePadding(const D3D12_RESOURCE_DESC& resourceDescriptor) const;
 
+    void DestroyPool();
+
     Device* mDevice;
     uint32_t mResourceHeapTier;