Fix Vulkan leak if vkMapMemory fails

This introduces a macro DAWN_TRY_WITH_CLEANUP which allows
some code to be run before the early return.

Bug: chromium:1177332
Change-Id: I529c9ca6f2b0cf6ffd4bf85719a4e2a1c2552d1b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/42003
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
diff --git a/src/dawn_native/Error.h b/src/dawn_native/Error.h
index 4715c83..f7bc4a3 100644
--- a/src/dawn_native/Error.h
+++ b/src/dawn_native/Error.h
@@ -97,16 +97,20 @@
     // When Errors aren't handled explicitly, calls to functions returning errors should be
     // wrapped in an DAWN_TRY. It will return the error if any, otherwise keep executing
     // the current function.
-#define DAWN_TRY(EXPR)                                                                       \
-    {                                                                                        \
-        auto DAWN_LOCAL_VAR = EXPR;                                                          \
-        if (DAWN_UNLIKELY(DAWN_LOCAL_VAR.IsError())) {                                       \
-            std::unique_ptr<::dawn_native::ErrorData> error = DAWN_LOCAL_VAR.AcquireError(); \
-            error->AppendBacktrace(__FILE__, __func__, __LINE__);                            \
-            return {std::move(error)};                                                       \
-        }                                                                                    \
-    }                                                                                        \
-    for (;;)                                                                                 \
+#define DAWN_TRY(EXPR) DAWN_TRY_WITH_CLEANUP(EXPR, {})
+
+#define DAWN_TRY_WITH_CLEANUP(EXPR, BODY)                                   \
+    {                                                                       \
+        auto DAWN_LOCAL_VAR = EXPR;                                         \
+        if (DAWN_UNLIKELY(DAWN_LOCAL_VAR.IsError())) {                      \
+            {BODY} /* comment to force the formatter to insert a newline */ \
+            std::unique_ptr<::dawn_native::ErrorData>                       \
+                error = DAWN_LOCAL_VAR.AcquireError();                      \
+            error->AppendBacktrace(__FILE__, __func__, __LINE__);           \
+            return {std::move(error)};                                      \
+        }                                                                   \
+    }                                                                       \
+    for (;;)                                                                \
     break
 
     // DAWN_TRY_ASSIGN is the same as DAWN_TRY for ResultOrError and assigns the success value, if
diff --git a/src/dawn_native/vulkan/ResourceMemoryAllocatorVk.cpp b/src/dawn_native/vulkan/ResourceMemoryAllocatorVk.cpp
index f143c68..13ea9be 100644
--- a/src/dawn_native/vulkan/ResourceMemoryAllocatorVk.cpp
+++ b/src/dawn_native/vulkan/ResourceMemoryAllocatorVk.cpp
@@ -150,11 +150,14 @@
 
         void* mappedPointer = nullptr;
         if (mappable) {
-            DAWN_TRY(
+            DAWN_TRY_WITH_CLEANUP(
                 CheckVkSuccess(mDevice->fn.MapMemory(mDevice->GetVkDevice(),
                                                      ToBackend(resourceHeap.get())->GetMemory(), 0,
                                                      size, 0, &mappedPointer),
-                               "vkMapMemory"));
+                               "vkMapMemory"),
+                {
+                    mAllocatorsPerType[memoryType]->DeallocateResourceHeap(std::move(resourceHeap));
+                });
         }
 
         AllocationInfo info;