Metal: Optimize Render Pass Command Buffer Execution

Don't set redundant state.

Change-Id: Ie08c290386bc73fec6bc893d9b94846aaf8d55b1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/135302
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Gregg Tavares <gman@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/metal/CommandBufferMTL.mm b/src/dawn/native/metal/CommandBufferMTL.mm
index eba8012..c0994a5 100644
--- a/src/dawn/native/metal/CommandBufferMTL.mm
+++ b/src/dawn/native/metal/CommandBufferMTL.mm
@@ -589,8 +589,12 @@
         : mLengthTracker(lengthTracker) {}
 
     void OnSetVertexBuffer(VertexBufferSlot slot, Buffer* buffer, uint64_t offset) {
+        id<MTLBuffer> mtlBuffer = buffer->GetMTLBuffer();
+        if (mVertexBuffers[slot] == mtlBuffer && mVertexBufferOffsets[slot] == offset) {
+            return;
+        }
         buffer->TrackUsage();
-        mVertexBuffers[slot] = buffer->GetMTLBuffer();
+        mVertexBuffers[slot] = mtlBuffer;
         mVertexBufferOffsets[slot] = offset;
 
         DAWN_ASSERT(buffer->GetSize() < std::numeric_limits<uint32_t>::max());
@@ -1517,6 +1521,9 @@
             case Command::SetRenderPipeline: {
                 SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
                 RenderPipeline* newPipeline = ToBackend(cmd->pipeline).Get();
+                if (newPipeline == lastPipeline) {
+                    break;
+                }
 
                 vertexBuffers.OnSetPipeline(lastPipeline, newPipeline);
                 bindGroups.OnSetPipeline(newPipeline);