dawn_wsi: Pass the Metal queue to the SwapChainImpl

If the swapchain creates its own queue, there can be races to determine
whether the submit of the present happens first. The didn't show up
in our samples but was an issue in real apps. Passing the queue to the
swapchain makes it simple to keep operations well ordered.

BUG=dawn:225

Change-Id: I9cc8e6e8140ad4a816373cffc9bda74ee826a41b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11640
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 0174e4a..4eff03f 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -46,6 +46,7 @@
         void TickImpl() override;
 
         id<MTLDevice> GetMTLDevice();
+        id<MTLCommandQueue> GetMTLQueue();
 
         id<MTLCommandBuffer> GetPendingCommandBuffer();
         Serial GetPendingCommandSerial() const override;
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 046ed13..a62aad8 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -171,6 +171,10 @@
         return mMtlDevice;
     }
 
+    id<MTLCommandQueue> Device::GetMTLQueue() {
+        return mCommandQueue;
+    }
+
     id<MTLCommandBuffer> Device::GetPendingCommandBuffer() {
         TRACE_EVENT0(GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
                      "DeviceMTL::GetPendingCommandBuffer");
diff --git a/src/dawn_native/metal/SwapChainMTL.mm b/src/dawn_native/metal/SwapChainMTL.mm
index 0677ca0..c955212 100644
--- a/src/dawn_native/metal/SwapChainMTL.mm
+++ b/src/dawn_native/metal/SwapChainMTL.mm
@@ -26,6 +26,7 @@
         const auto& im = GetImplementation();
         DawnWSIContextMetal wsiContext = {};
         wsiContext.device = ToBackend(GetDevice())->GetMTLDevice();
+        wsiContext.queue = ToBackend(GetDevice())->GetMTLQueue();
         im.Init(im.userData, &wsiContext);
     }
 
diff --git a/src/include/dawn/dawn_wsi.h b/src/include/dawn/dawn_wsi.h
index 832af4b..ff83f72 100644
--- a/src/include/dawn/dawn_wsi.h
+++ b/src/include/dawn/dawn_wsi.h
@@ -69,6 +69,7 @@
 
 typedef struct {
     id<MTLDevice> device = nil;
+    id<MTLCommandQueue> queue = nil;
 } DawnWSIContextMetal;
 #endif
 
diff --git a/src/utils/MetalBinding.mm b/src/utils/MetalBinding.mm
index 4f9b5be..0dbdb4d 100644
--- a/src/utils/MetalBinding.mm
+++ b/src/utils/MetalBinding.mm
@@ -39,7 +39,7 @@
 
         void Init(DawnWSIContextMetal* ctx) {
             mMtlDevice = ctx->device;
-            mCommandQueue = [mMtlDevice newCommandQueue];
+            mCommandQueue = ctx->queue;
         }
 
         DawnSwapChainError Configure(DawnTextureFormat format,