d3d11: Cache ScopedUseBuffer for internal uniform buffer

Avoid repeated ScopedUseBuffer creation/release's overhead by caching it
in ScopedCommandRecordingContext during the first uniform buffer flush.

Bug: 503235007
Change-Id: I792146e15e9d3c745c2ecd8acb001f29c82dd96e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/303135
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
index 92ce522..d7b51a7 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
@@ -56,7 +56,9 @@
 }
 
 ScopedCommandRecordingContext::ScopedCommandRecordingContext(ScopedCommandRecordingContext&& other)
-    : mGuard(std::move(other.mGuard)), mLockD3D11Scope(other.mLockD3D11Scope) {
+    : mGuard(std::move(other.mGuard)),
+      mLockD3D11Scope(other.mLockD3D11Scope),
+      mUniformBufferInUse(std::move(other.mUniformBufferInUse)) {
     other.mLockD3D11Scope = false;
 }
 
@@ -73,6 +75,7 @@
         // Move the guard and lock state
         mGuard = std::move(other.mGuard);
         mLockD3D11Scope = other.mLockD3D11Scope;
+        mUniformBufferInUse = std::move(other.mUniformBufferInUse);
         other.mLockD3D11Scope = false;
     }
     return *this;
@@ -184,7 +187,9 @@
 
 MaybeError ScopedCommandRecordingContext::FlushUniformBuffer() const {
     if (Get()->mUniformBufferDirty) {
-        auto scopedUseUniformBuffer = Get()->mUniformBuffer->UseInternal();
+        if (!mUniformBufferInUse) {
+            mUniformBufferInUse = Get()->mUniformBuffer->UseInternal();
+        }
         DAWN_TRY(Get()->mUniformBuffer->Write(this, 0, Get()->mUniformBufferData.data(),
                                               Get()->mUniformBufferData.size() * sizeof(uint32_t)));
         Get()->mUniformBufferDirty = false;
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
index 4db7249..f3007a0 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
@@ -28,6 +28,7 @@
 #ifndef SRC_DAWN_NATIVE_D3D11_COMMANDRECORDINGCONTEXT_D3D11_H_
 #define SRC_DAWN_NATIVE_D3D11_COMMANDRECORDINGCONTEXT_D3D11_H_
 
+#include <optional>
 #include <utility>
 
 #include "absl/container/flat_hash_set.h"
@@ -37,6 +38,7 @@
 #include "dawn/common/NonCopyable.h"
 #include "dawn/common/Ref.h"
 #include "dawn/common/StackAllocated.h"
+#include "dawn/native/Buffer.h"
 #include "dawn/native/Error.h"
 #include "dawn/native/d3d/KeyedMutex.h"
 #include "dawn/native/d3d/d3d_platform.h"
@@ -201,6 +203,9 @@
     STACK_ALLOCATED_IGNORE("TODO: avoid heap allocated class containing StackAllocated members")
     CommandRecordingContext::Guard mGuard;
     bool mLockD3D11Scope = false;
+    // The scoped use of the uniform buffer to keep it in the InUse state for the lifetime of the
+    // scoped command context. This is lazily initialized.
+    mutable std::optional<BufferBase::ScopedUseBuffer> mUniformBufferInUse;
 };
 
 // For using ID3D11DeviceContext directly. It swaps and resets ID3DDeviceContextState of