Reserve command blocks once in CommandIterator::AcquireCommandBlocks

This patch first computes the total size of all the incoming command
blocks before acquiring all the command blocks so that we only need
to call `mBlocks.reserve()` once in this function.

Bug: 363713615
Change-Id: I0f5bc56f021944d6ca1ade9b8497ba02f2402cf6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/204700
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/CommandAllocator.cpp b/src/dawn/native/CommandAllocator.cpp
index ab73e78..f18dbea 100644
--- a/src/dawn/native/CommandAllocator.cpp
+++ b/src/dawn/native/CommandAllocator.cpp
@@ -72,10 +72,16 @@
 void CommandIterator::AcquireCommandBlocks(std::vector<CommandAllocator> allocators) {
     DAWN_ASSERT(IsEmpty());
     mBlocks.clear();
+
+    size_t totalBlocksCount = 0;
+    for (CommandAllocator& allocator : allocators) {
+        totalBlocksCount += allocator.GetCommandBlocksCount();
+    }
+
+    mBlocks.reserve(totalBlocksCount);
     for (CommandAllocator& allocator : allocators) {
         CommandBlocks blocks = allocator.AcquireBlocks();
         if (!blocks.empty()) {
-            mBlocks.reserve(mBlocks.size() + blocks.size());
             for (BlockDef& block : blocks) {
                 mBlocks.push_back(std::move(block));
             }
@@ -174,6 +180,10 @@
     return mCurrentPtr == reinterpret_cast<const char*>(&mPlaceholderSpace[0]);
 }
 
+size_t CommandAllocator::GetCommandBlocksCount() const {
+    return mBlocks.size();
+}
+
 CommandBlocks&& CommandAllocator::AcquireBlocks() {
     DAWN_ASSERT(mCurrentPtr != nullptr && mEndPtr != nullptr);
     DAWN_ASSERT(IsPtrAligned(mCurrentPtr, alignof(uint32_t)));
diff --git a/src/dawn/native/CommandAllocator.h b/src/dawn/native/CommandAllocator.h
index ed5b4ae..def18ef 100644
--- a/src/dawn/native/CommandAllocator.h
+++ b/src/dawn/native/CommandAllocator.h
@@ -209,6 +209,8 @@
 
     const char* CopyAsNullTerminatedString(std::string_view in);
 
+    size_t GetCommandBlocksCount() const;
+
   private:
     // This is used for some internal computations and can be any power of two as long as code
     // using the CommandAllocator passes the static_asserts.