[native][d3d11] Add Storage::Map/Unmap functions that return a span

Cleans up a bunch of boilerplate, and ensures we return a span with a
valid size.

Bug: chromium:549088024
Change-Id: I5d8d9548ba6ccbb13dcf135402bd61928e6aa8c4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/337195
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/dawn/native/d3d11/BufferD3D11.cpp b/src/dawn/native/d3d11/BufferD3D11.cpp
index 0057a34..6247cf3 100644
--- a/src/dawn/native/d3d11/BufferD3D11.cpp
+++ b/src/dawn/native/d3d11/BufferD3D11.cpp
@@ -34,6 +34,7 @@
 
 #include "dawn/platform/DawnPlatform.h"
 #include "src/dawn/common/Constants.h"
+#include "src/dawn/common/Defer.h"
 #include "src/dawn/common/Math.h"
 #include "src/dawn/native/ChainUtils.h"
 #include "src/dawn/native/CommandBuffer.h"
@@ -888,6 +889,23 @@
     bool IsGPUWritable() const { return mD3d11Usage == D3D11_USAGE_DEFAULT; }
     size_t GetSize() const { return mSize; }
 
+    ResultOrError<Span<std::byte>> Map(const ScopedCommandRecordingContext* commandContext,
+                                       D3D11_MAP d3dMapTypeUsed) {
+        D3D11_MAPPED_SUBRESOURCE mappedSubresource;
+        DAWN_TRY(
+            CheckHRESULT(commandContext->Map(GetD3D11Buffer(), /*Subresource=*/0, d3dMapTypeUsed,
+                                             /*MapFlags=*/0, &mappedSubresource),
+                         "ID3D11DeviceContext::Map"));
+        Span<std::byte> data =
+            // SAFETY: The mapped pointer is the size of the whole buffer
+            DAWN_UNSAFE_BUFFERS({static_cast<std::byte*>(mappedSubresource.pData), GetSize()});
+        return data;
+    }
+
+    void Unmap(const ScopedCommandRecordingContext* commandContext) {
+        commandContext->Unmap(GetD3D11Buffer(), /*Subresource=*/0);
+    }
+
   private:
     ComPtr<ID3D11Buffer> mD3d11Buffer;
     uint64_t mRevision = 0;
@@ -1171,48 +1189,23 @@
 
     // TODO(42241146): This is a slow path. It's usually used by uncommon use cases:
     // - GPU writes a CPU writable buffer.
-    auto MapAndCopy = [](const ScopedCommandRecordingContext* commandContext, Storage* dst,
-                         Span<const std::byte> srcData) -> MaybeError {
-        D3D11_MAPPED_SUBRESOURCE mappedDstResource;
-        DAWN_TRY(CheckHRESULT(
-            commandContext->Map(dst->GetD3D11Buffer(), /*Subresource=*/0, D3D11_MAP_WRITE_DISCARD,
-                                /*MapFlags=*/0, &mappedDstResource),
-            "ID3D11DeviceContext::Map dst"));
-        DAWN_ASSERT(dst->GetSize() >= srcData.size());
-        Span<std::byte> dstData =
-            // SAFETY: The mapped destination pointer contains at least srcData.size() bytes
-            DAWN_UNSAFE_BUFFERS({static_cast<std::byte*>(mappedDstResource.pData), srcData.size()});
-        dstData.CopyFrom(srcData);
-        commandContext->Unmap(dst->GetD3D11Buffer(), /*Subresource=*/0);
-        return {};
-    };
-
     DAWN_ASSERT(dstStorage->IsCPUWritable());
     Storage* stagingStorage;
-    // GetOrCreateStorage returns a buffer of GetAllocatedSize() bytes
     DAWN_TRY_ASSIGN(stagingStorage, GetOrCreateStorage(StorageType::Staging));
     DAWN_TRY(SyncStorage(commandContext, stagingStorage));
-    D3D11_MAPPED_SUBRESOURCE mappedSrcResource;
-    DAWN_TRY(CheckHRESULT(commandContext->Map(stagingStorage->GetD3D11Buffer(),
-                                              /*Subresource=*/0, D3D11_MAP_READ,
-                                              /*MapFlags=*/0, &mappedSrcResource),
-                          "ID3D11DeviceContext::Map src"));
-    DAWN_ASSERT(stagingStorage->GetSize() == GetAllocatedSize());
-    Span<const std::byte> srcData =
-        // SAFETY: The mapped source pointer contains GetAllocatedSize() bytes.
-        DAWN_UNSAFE_BUFFERS({static_cast<const std::byte*>(mappedSrcResource.pData),
-                             checked_cast<size_t>(GetAllocatedSize())});
-    auto result = MapAndCopy(commandContext, dstStorage, srcData);
 
-    commandContext->Unmap(stagingStorage->GetD3D11Buffer(),
-                          /*Subresource=*/0);
+    Span<std::byte> srcData;
+    DAWN_TRY_ASSIGN(srcData, stagingStorage->Map(commandContext, D3D11_MAP_READ));
+    // Make sure to unmap even if mapping dstStorage fails below
+    Defer unmapSrcData;
+    unmapSrcData.Append([&] { stagingStorage->Unmap(commandContext); });
 
-    if (result.IsError()) {
-        return result;
-    }
+    Span<std::byte> dstData;
+    DAWN_TRY_ASSIGN(dstData, dstStorage->Map(commandContext, D3D11_MAP_WRITE_DISCARD));
+    dstData.CopyFrom(srcData);
+    dstStorage->Unmap(commandContext);
 
     dstStorage->SetRevision(mLastUpdatedStorage->GetRevision());
-
     return {};
 }
 
@@ -1275,16 +1268,7 @@
     // Sync previously modified content before mapping.
     DAWN_TRY(SyncStorage(commandContext, mMappableStorage));
 
-    D3D11_MAPPED_SUBRESOURCE mappedResource;
-    DAWN_TRY(CheckHRESULT(commandContext->Map(mMappableStorage->GetD3D11Buffer(),
-                                              /*Subresource=*/0, mD3DMapTypeUsed,
-                                              /*MapFlags=*/0, &mappedResource),
-                          "ID3D11DeviceContext::Map"));
-    DAWN_ASSERT(mMappableStorage->GetSize() <= GetAllocatedSize());
-    // SAFETY: The pointer returned is for the actual memory of the resource and contains at least
-    // GetAllocatedSize() bytes.
-    mMappedData = DAWN_UNSAFE_BUFFERS(
-        {static_cast<std::byte*>(mappedResource.pData), checked_cast<size_t>(GetAllocatedSize())});
+    DAWN_TRY_ASSIGN(mMappedData, mMappableStorage->Map(commandContext, mD3DMapTypeUsed));
 
     return {};
 }
@@ -1292,8 +1276,7 @@
 void GPUUsableBuffer::UnmapInternal(const ScopedCommandRecordingContext* commandContext) {
     DAWN_ASSERT(!mMappedData.empty());
     DAWN_ASSERT(mMappableStorage);
-    commandContext->Unmap(mMappableStorage->GetD3D11Buffer(),
-                          /*Subresource=*/0);
+    mMappableStorage->Unmap(commandContext);
     mMappedData = {};
     // Only increment revision if the buffer was mapped for writing.
     if (mD3DMapTypeUsed != D3D11_MAP_READ) {