Metal: Support creating render pipeline asynchronously

This patch implements the asynchronous path of creating render
pipeline on Metal backend.

BUG=dawn:529
TEST=dawn_end2end_tests

Change-Id: I3f40949f35f6cbc340bebf481bd4e204b12d86c2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64880
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 19b900b..1432aa9 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -117,6 +117,10 @@
                                             size_t blueprintHash,
                                             WGPUCreateComputePipelineAsyncCallback callback,
                                             void* userdata) override;
+        void CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor,
+                                           size_t blueprintHash,
+                                           WGPUCreateRenderPipelineAsyncCallback callback,
+                                           void* userdata) override;
 
         void InitTogglesFromDriver();
         void ShutDownImpl() override;
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 7d199f7..d900575e 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -291,6 +291,12 @@
                                                 void* userdata) {
         ComputePipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
     }
+    void Device::CreateRenderPipelineAsyncImpl(const RenderPipelineDescriptor* descriptor,
+                                               size_t blueprintHash,
+                                               WGPUCreateRenderPipelineAsyncCallback callback,
+                                               void* userdata) {
+        RenderPipeline::CreateAsync(this, descriptor, blueprintHash, callback, userdata);
+    }
 
     ResultOrError<ExecutionSerial> Device::CheckAndUpdateCompletedSerials() {
         uint64_t frontendCompletedSerial{GetCompletedCommandSerial()};
diff --git a/src/dawn_native/metal/RenderPipelineMTL.h b/src/dawn_native/metal/RenderPipelineMTL.h
index 1d81072..6f9f9c8 100644
--- a/src/dawn_native/metal/RenderPipelineMTL.h
+++ b/src/dawn_native/metal/RenderPipelineMTL.h
@@ -30,6 +30,11 @@
         static ResultOrError<Ref<RenderPipeline>> Create(
             Device* device,
             const RenderPipelineDescriptor* descriptor);
+        static void CreateAsync(Device* device,
+                                const RenderPipelineDescriptor* descriptor,
+                                size_t blueprintHash,
+                                WGPUCreateRenderPipelineAsyncCallback callback,
+                                void* userdata);
 
         MTLPrimitiveType GetMTLPrimitiveTopology() const;
         MTLWinding GetMTLFrontFace() const;
diff --git a/src/dawn_native/metal/RenderPipelineMTL.mm b/src/dawn_native/metal/RenderPipelineMTL.mm
index 818536a..e8d7667 100644
--- a/src/dawn_native/metal/RenderPipelineMTL.mm
+++ b/src/dawn_native/metal/RenderPipelineMTL.mm
@@ -14,6 +14,7 @@
 
 #include "dawn_native/metal/RenderPipelineMTL.h"
 
+#include "dawn_native/CreatePipelineAsyncTask.h"
 #include "dawn_native/VertexFormat.h"
 #include "dawn_native/metal/DeviceMTL.h"
 #include "dawn_native/metal/PipelineLayoutMTL.h"
@@ -501,4 +502,16 @@
         return mtlVertexDescriptor;
     }
 
+    void RenderPipeline::CreateAsync(Device* device,
+                                     const RenderPipelineDescriptor* descriptor,
+                                     size_t blueprintHash,
+                                     WGPUCreateRenderPipelineAsyncCallback callback,
+                                     void* userdata) {
+        Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
+        std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask =
+            std::make_unique<CreateRenderPipelineAsyncTask>(pipeline, blueprintHash, callback,
+                                                            userdata);
+        CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask));
+    }
+
 }}  // namespace dawn_native::metal