Use UpdateSubresource for full size buffer writes

The perf is much better than using a new staging buffer each time.

Bug: chromium:1480926

Change-Id: Ibf562c10eb4ea0f5e96003ef1ca91a1323df72a5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/150702
Reviewed-by: Peng Huang <penghuang@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/d3d11/BufferD3D11.cpp b/src/dawn/native/d3d11/BufferD3D11.cpp
index dfefc41..a58b322 100644
--- a/src/dawn/native/d3d11/BufferD3D11.cpp
+++ b/src/dawn/native/d3d11/BufferD3D11.cpp
@@ -531,9 +531,26 @@
 
     DAWN_ASSERT(mD3d11ConstantBuffer);
 
+    // For a full size write, UpdateSubresource() can be used to update mD3d11ConstantBuffer.
+    if (size == GetSize() && offset == 0) {
+        if (size == mAllocatedSize) {
+            d3d11DeviceContext1->UpdateSubresource(mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0,
+                                                   nullptr, data,
+                                                   /*SrcRowPitch=*/size,
+                                                   /*SrcDepthPitch*/ 0);
+        } else {
+            std::vector<uint8_t> allocatedData(mAllocatedSize, 0);
+            std::memcpy(allocatedData.data(), data, size);
+            d3d11DeviceContext1->UpdateSubresource(mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0,
+                                                   nullptr, allocatedData.data(),
+                                                   /*SrcRowPitch=*/mAllocatedSize,
+                                                   /*SrcDepthPitch*/ 0);
+        }
+        return {};
+    }
+
     // If the mD3d11NonConstantBuffer is null, we have to create a staging buffer for transfer the
-    // data to mD3d11ConstantBuffer, since UpdateSubresource() has many restrictions. For example,
-    // the size of the data has to be a multiple of 16, etc
+    // data to mD3d11ConstantBuffer.
     BufferDescriptor descriptor;
     descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
     descriptor.size = Align(size, D3D11BufferSizeAlignment(descriptor.usage));