Revert "[WGPUFuture] Implement CreateComputePipelineAsyncF"

This reverts commit 7545caf54c08af0d28bbd5b09315a6dd9cced539.

Reason for revert: Looks to be breaking Dawn->Chromium roll.
The second CL in this stack was unluckier and failed CQ, but
this one also has a lot of suspicious flakes in its build:
https://dawn-review.googlesource.com/c/dawn/+/174140?checksRunsSelected=android-dawn-arm64-rel&tab=checks

Original change's description:
> [WGPUFuture] Implement CreateComputePipelineAsyncF
>
> Implementing the future version by
> creating the CreateComputePipelineAsyncEvent which
> inherites EventManager::TrackEvent.
>
> Bug: dawn:2353, dawn:1987
> Change-Id: I4a75d4a996cfff20055349b3f6e75031c99a51cf
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/174140
> Kokoro: Kokoro <noreply+kokoro@google.com>
> Reviewed-by: Loko Kung <lokokung@google.com>

TBR=enga@chromium.org,shrekshao@google.com,noreply+kokoro@google.com,lokokung@google.com

Change-Id: Ibbbb6f7055f5e75f1d01f7be47b95a3ead7fcabd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: dawn:2353, dawn:1987
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/180561
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Kokoro: Kai Ninomiya <kainino@chromium.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
diff --git a/src/dawn/native/CreatePipelineAsyncTask.cpp b/src/dawn/native/CreatePipelineAsyncTask.cpp
index a466be2..d6ea436 100644
--- a/src/dawn/native/CreatePipelineAsyncTask.cpp
+++ b/src/dawn/native/CreatePipelineAsyncTask.cpp
@@ -32,8 +32,6 @@
 #include "dawn/native/AsyncTask.h"
 #include "dawn/native/ComputePipeline.h"
 #include "dawn/native/Device.h"
-#include "dawn/native/EventManager.h"
-#include "dawn/native/Instance.h"
 #include "dawn/native/RenderPipeline.h"
 #include "dawn/native/utils/WGPUHelpers.h"
 #include "dawn/platform/DawnPlatform.h"
@@ -42,129 +40,64 @@
 
 namespace dawn::native {
 
-CreateComputePipelineAsyncEvent::CreateComputePipelineAsyncEvent(
-    DeviceBase* device,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo,
-    Ref<ComputePipelineBase> pipeline,
-    Ref<SystemEvent> systemEvent)
-    : TrackedEvent(callbackInfo.mode, std::move(systemEvent)),
-      mCallback(callbackInfo.callback),
-      mUserdata(callbackInfo.userdata),
-      mPipeline(std::move(pipeline)),
-      mScopedUseShaderPrograms(mPipeline->UseShaderPrograms()) {}
-
-CreateComputePipelineAsyncEvent::CreateComputePipelineAsyncEvent(
-    DeviceBase* device,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo,
-    Ref<ComputePipelineBase> pipeline)
-    : TrackedEvent(callbackInfo.mode, TrackedEvent::Completed{}),
-      mCallback(callbackInfo.callback),
-      mUserdata(callbackInfo.userdata),
-      mPipeline(std::move(pipeline)) {}
-
-CreateComputePipelineAsyncEvent::CreateComputePipelineAsyncEvent(
-    DeviceBase* device,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo,
-    std::unique_ptr<ErrorData> error,
-    const char* label)
-    : TrackedEvent(callbackInfo.mode, TrackedEvent::Completed{}),
-      mCallback(callbackInfo.callback),
-      mUserdata(callbackInfo.userdata),
-      mPipeline(ComputePipelineBase::MakeError(device, label)),
-      mError(std::move(error)) {}
-
-CreateComputePipelineAsyncEvent::~CreateComputePipelineAsyncEvent() {
-    EnsureComplete(EventCompletionType::Shutdown);
+CreateComputePipelineAsyncTask::CreateComputePipelineAsyncTask(
+    Ref<ComputePipelineBase> nonInitializedComputePipeline,
+    WGPUCreateComputePipelineAsyncCallback callback,
+    void* userdata)
+    : mComputePipeline(std::move(nonInitializedComputePipeline)),
+      mCallback(callback),
+      mUserdata(userdata),
+      mScopedUseShaderPrograms(mComputePipeline->UseShaderPrograms()) {
+    DAWN_ASSERT(mComputePipeline != nullptr);
 }
 
-void CreateComputePipelineAsyncEvent::Initialize() {
-    const char* eventLabel = utils::GetLabelForTrace(mPipeline->GetLabel().c_str());
-    DeviceBase* device = mPipeline->GetDevice();
+CreateComputePipelineAsyncTask::~CreateComputePipelineAsyncTask() = default;
+
+void CreateComputePipelineAsyncTask::Run() {
+    const char* eventLabel = utils::GetLabelForTrace(mComputePipeline->GetLabel().c_str());
+
+    DeviceBase* device = mComputePipeline->GetDevice();
     TRACE_EVENT_FLOW_END1(device->GetPlatform(), General,
-                          "CreateComputePipelineAsyncEvent::InitializeAsync", this, "label",
-                          eventLabel);
-    TRACE_EVENT1(device->GetPlatform(), General, "CreateComputePipelineAsyncEvent::Initialize",
-                 "label", eventLabel);
+                          "CreateComputePipelineAsyncTask::RunAsync", this, "label", eventLabel);
+    TRACE_EVENT1(device->GetPlatform(), General, "CreateComputePipelineAsyncTask::Run", "label",
+                 eventLabel);
 
     MaybeError maybeError;
     {
         SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(device->GetPlatform(), "CreateComputePipelineUS");
-        maybeError = mPipeline->Initialize(std::move(mScopedUseShaderPrograms));
+        maybeError = mComputePipeline->Initialize(std::move(mScopedUseShaderPrograms));
     }
     DAWN_HISTOGRAM_BOOLEAN(device->GetPlatform(), "CreateComputePipelineSuccess",
                            maybeError.IsSuccess());
     if (maybeError.IsError()) {
-        mError = maybeError.AcquireError();
+        device->AddComputePipelineAsyncCallbackTask(
+            maybeError.AcquireError(), mComputePipeline->GetLabel().c_str(), mCallback, mUserdata);
+    } else {
+        device->AddComputePipelineAsyncCallbackTask(mComputePipeline, mCallback, mUserdata);
     }
-
-    // TODO(dawn:2451): API re-entrant callbacks in spontaneous mode that use the device could
-    // deadlock itself.
-    device->GetInstance()->GetEventManager()->SetFutureReady(mFutureID);
 }
 
-void CreateComputePipelineAsyncEvent::InitializeAsync() {
-    DeviceBase* device = mPipeline->GetDevice();
-    const char* eventLabel = utils::GetLabelForTrace(mPipeline->GetLabel().c_str());
+void CreateComputePipelineAsyncTask::RunAsync(
+    std::unique_ptr<CreateComputePipelineAsyncTask> task) {
+    DeviceBase* device = task->mComputePipeline->GetDevice();
+
+    const char* eventLabel = utils::GetLabelForTrace(task->mComputePipeline->GetLabel().c_str());
+
     TRACE_EVENT_FLOW_BEGIN1(device->GetPlatform(), General,
-                            "CreateComputePipelineAsyncEvent::InitializeAsync", this, "label",
+                            "CreateComputePipelineAsyncTask::RunAsync", task.get(), "label",
                             eventLabel);
 
-    auto asyncTask = [event = Ref<CreateComputePipelineAsyncEvent>(this)] { event->Initialize(); };
+    // Using "taskPtr = std::move(task)" causes compilation error while it should be supported
+    // since C++14:
+    // https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-160
+    auto asyncTask = [taskPtr = task.release()] {
+        std::unique_ptr<CreateComputePipelineAsyncTask> innnerTaskPtr(taskPtr);
+        innnerTaskPtr->Run();
+    };
+
     device->GetAsyncTaskManager()->PostTask(std::move(asyncTask));
 }
 
-void CreateComputePipelineAsyncEvent::Complete(EventCompletionType completionType) {
-    if (completionType == EventCompletionType::Shutdown) {
-        if (mCallback) {
-            mCallback(ToAPI(wgpu::CreatePipelineAsyncStatus::InstanceDropped), nullptr,
-                      "Instance dropped", mUserdata);
-        }
-        return;
-    }
-
-    DeviceBase* device = mPipeline->GetDevice();
-    // TODO(dawn:2353): Device losts later than this check could potentially lead to racing
-    // condition.
-    if (device->IsLost()) {
-        // Invalid async creation should "succeed" if the device is already lost.
-        if (!mPipeline->IsError()) {
-            mPipeline = ComputePipelineBase::MakeError(device, mPipeline->GetLabel().c_str());
-        }
-        if (mCallback) {
-            mCallback(ToAPI(wgpu::CreatePipelineAsyncStatus::Success),
-                      ToAPI(ReturnToAPI(std::move(mPipeline))), "", mUserdata);
-        }
-        return;
-    }
-
-    if (mError != nullptr) {
-        wgpu::CreatePipelineAsyncStatus status;
-        switch (mError->GetType()) {
-            case InternalErrorType::Validation:
-                status = wgpu::CreatePipelineAsyncStatus::ValidationError;
-                break;
-            default:
-                status = wgpu::CreatePipelineAsyncStatus::InternalError;
-                break;
-        }
-        if (mCallback) {
-            mCallback(ToAPI(status), nullptr, mError->GetFormattedMessage().c_str(), mUserdata);
-        }
-        return;
-    }
-
-    {
-        auto deviceLock(device->GetScopedLock());
-        if (device->GetState() == DeviceBase::State::Alive) {
-            mPipeline = device->AddOrGetCachedComputePipeline(std::move(mPipeline));
-        }
-    }
-    if (mCallback) {
-        mCallback(ToAPI(wgpu::CreatePipelineAsyncStatus::Success),
-                  ToAPI(ReturnToAPI(std::move(mPipeline))), "", mUserdata);
-    }
-}
-
 CreateRenderPipelineAsyncTask::CreateRenderPipelineAsyncTask(
     Ref<RenderPipelineBase> nonInitializedRenderPipeline,
     WGPUCreateRenderPipelineAsyncCallback callback,
diff --git a/src/dawn/native/CreatePipelineAsyncTask.h b/src/dawn/native/CreatePipelineAsyncTask.h
index d192564..1163aca 100644
--- a/src/dawn/native/CreatePipelineAsyncTask.h
+++ b/src/dawn/native/CreatePipelineAsyncTask.h
@@ -34,7 +34,6 @@
 #include "dawn/common/Ref.h"
 #include "dawn/native/CallbackTaskManager.h"
 #include "dawn/native/Error.h"
-#include "dawn/native/EventManager.h"
 #include "dawn/native/Pipeline.h"
 #include "dawn/webgpu.h"
 #include "partition_alloc/pointers/raw_ptr.h"
@@ -46,47 +45,28 @@
 class PipelineLayoutBase;
 class RenderPipelineBase;
 class ShaderModuleBase;
+struct FlatComputePipelineDescriptor;
 
-// CreateComputePipelineAsyncEvent represents the async event managed by event manager,
-// and the async task run on a separate task to initialize the pipeline.
-class CreateComputePipelineAsyncEvent final : public EventManager::TrackedEvent {
+// CreateComputePipelineAsyncTask defines all the inputs and outputs of
+// CreateComputePipelineAsync() tasks, which are the same among all the backends.
+class CreateComputePipelineAsyncTask {
   public:
-    // Create an event backed by the given system event (for async pipeline creation goes through
-    // the backend).
-    CreateComputePipelineAsyncEvent(DeviceBase* device,
-                                    const CreateComputePipelineAsyncCallbackInfo& callbackInfo,
-                                    Ref<ComputePipelineBase> pipeline,
-                                    Ref<SystemEvent> systemEvent);
-    // Create an event that's ready at creation (for cached results)
-    CreateComputePipelineAsyncEvent(DeviceBase* device,
-                                    const CreateComputePipelineAsyncCallbackInfo& callbackInfo,
-                                    Ref<ComputePipelineBase> pipeline);
-    // Create an event that's ready at creation (for errors)
-    CreateComputePipelineAsyncEvent(DeviceBase* device,
-                                    const CreateComputePipelineAsyncCallbackInfo& callbackInfo,
-                                    std::unique_ptr<ErrorData> error,
-                                    const char* label);
+    CreateComputePipelineAsyncTask(Ref<ComputePipelineBase> nonInitializedComputePipeline,
+                                   WGPUCreateComputePipelineAsyncCallback callback,
+                                   void* userdata);
+    ~CreateComputePipelineAsyncTask();
 
-    ~CreateComputePipelineAsyncEvent() override;
+    void Run();
 
-    // Entrance call to start an AsyncTask initializing the pipeline.
-    void InitializeAsync();
-    // Body of pipeline initialization wrapped in an AsyncTask run by AsyncTaskManager.
-    void Initialize();
-
-    void Complete(EventCompletionType completionType) override;
+    static void RunAsync(std::unique_ptr<CreateComputePipelineAsyncTask> task);
 
   private:
+    Ref<ComputePipelineBase> mComputePipeline;
     WGPUCreateComputePipelineAsyncCallback mCallback;
     // TODO(https://crbug.com/2364): The pointer is dangling in
     // webgpu_cts_with_validation_tests. We should investigate, and decide if
     // this should be fixed, or turned into a DisableDanglingPtrDetection.
     raw_ptr<void, DanglingUntriaged> mUserdata;
-    // For some errors (e.g. device lost) we still need to resolve and return a pipeline with
-    // Pipeline::MakeError. So we need to hold the pipeline and the error separately.
-    Ref<ComputePipelineBase> mPipeline;
-    std::unique_ptr<ErrorData> mError;
-
     // Used to keep ShaderModuleBase::mTintProgram alive until pipeline initialization is done.
     PipelineBase::ScopedUseShaderPrograms mScopedUseShaderPrograms;
 };
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 4904abe..af8f738 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -1234,46 +1234,37 @@
     TRACE_EVENT1(GetPlatform(), General, "DeviceBase::APICreateComputePipelineAsync", "label",
                  utils::GetLabelForTrace(descriptor->label));
 
-    CreateComputePipelineAsyncCallbackInfo callbackInfo = {};
-    callbackInfo.mode = wgpu::CallbackMode::AllowProcessEvents;
-    callbackInfo.callback = callback;
-    callbackInfo.userdata = userdata;
-    APICreateComputePipelineAsyncF(descriptor, callbackInfo);
+    auto resultOrError = CreateUninitializedComputePipeline(descriptor);
+    // Enqueue the callback directly when an error has been found in the front-end
+    // validation.
+    if (resultOrError.IsError()) {
+        AddComputePipelineAsyncCallbackTask(resultOrError.AcquireError(), descriptor->label,
+                                            callback, userdata);
+        return;
+    }
+
+    Ref<ComputePipelineBase> uninitializedComputePipeline = resultOrError.AcquireSuccess();
+
+    // Call the callback directly when we can get a cached compute pipeline object.
+    Ref<ComputePipelineBase> cachedComputePipeline =
+        GetCachedComputePipeline(uninitializedComputePipeline.Get());
+    if (cachedComputePipeline.Get() != nullptr) {
+        mCallbackTaskManager->AddCallbackTask(
+            std::bind(callback, WGPUCreatePipelineAsyncStatus_Success,
+                      ToAPI(ReturnToAPI(std::move(cachedComputePipeline))), "", userdata));
+    } else {
+        // Otherwise we will create the pipeline object in InitializeComputePipelineAsyncImpl(),
+        // where the pipeline object may be initialized asynchronously and the result will be
+        // saved to mCreatePipelineAsyncTracker.
+        InitializeComputePipelineAsyncImpl(std::move(uninitializedComputePipeline), callback,
+                                           userdata);
+    }
 }
 Future DeviceBase::APICreateComputePipelineAsyncF(
     const ComputePipelineDescriptor* descriptor,
     const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    EventManager* manager = GetInstance()->GetEventManager();
-    auto GetFuture = [&](Ref<EventManager::TrackedEvent>&& event) {
-        FutureID futureID = manager->TrackEvent(std::move(event));
-        return Future{futureID};
-    };
-
-    if (IsLost()) {
-        // Device lost error: create an async event that completes when created.
-        return GetFuture(AcquireRef(new CreateComputePipelineAsyncEvent(
-            this, callbackInfo, DAWN_DEVICE_LOST_ERROR("Device lost"), descriptor->label)));
-    }
-
-    auto resultOrError = CreateUninitializedComputePipeline(descriptor);
-    if (resultOrError.IsError()) {
-        // Validation error: create an async event that completes when created.
-        return GetFuture(AcquireRef(new CreateComputePipelineAsyncEvent(
-            this, callbackInfo, resultOrError.AcquireError(), descriptor->label)));
-    }
-
-    Ref<ComputePipelineBase> uninitializedComputePipeline = resultOrError.AcquireSuccess();
-    Ref<ComputePipelineBase> cachedComputePipeline =
-        GetCachedComputePipeline(uninitializedComputePipeline.Get());
-    if (cachedComputePipeline.Get() != nullptr) {
-        // Cached pipeline: create an async event that completes when created.
-        return GetFuture(AcquireRef(new CreateComputePipelineAsyncEvent(
-            this, callbackInfo, std::move(cachedComputePipeline))));
-    }
-
-    // New pipeline: create an async event that is really async.
-    return GetFuture(
-        InitializeComputePipelineAsyncImpl(std::move(uninitializedComputePipeline), callbackInfo));
+    // TODO(dawn:1987) Implement this.
+    DAWN_CHECK(false);
 }
 PipelineLayoutBase* DeviceBase::APICreatePipelineLayout(
     const PipelineLayoutDescriptor* descriptor) {
@@ -1927,11 +1918,11 @@
     return CreateUninitializedComputePipelineImpl(Unpack(&appliedDescriptor));
 }
 
-// This base version is creating the pipeline synchronously,
-// and is overwritten on the backends that actually support asynchronous pipeline creation.
-Ref<EventManager::TrackedEvent> DeviceBase::InitializeComputePipelineAsyncImpl(
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
+// This function is overwritten with the async version on the backends that supports
+// initializing compute pipelines asynchronously.
+void DeviceBase::InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                                    WGPUCreateComputePipelineAsyncCallback callback,
+                                                    void* userdata) {
     MaybeError maybeError;
     {
         SCOPED_DAWN_HISTOGRAM_TIMER_MICROS(GetPlatform(), "CreateComputePipelineUS");
@@ -1940,11 +1931,11 @@
     DAWN_HISTOGRAM_BOOLEAN(GetPlatform(), "CreateComputePipelineSuccess", maybeError.IsSuccess());
 
     if (maybeError.IsError()) {
-        return AcquireRef(new CreateComputePipelineAsyncEvent(
-            this, callbackInfo, maybeError.AcquireError(), computePipeline->GetLabel().c_str()));
+        AddComputePipelineAsyncCallbackTask(
+            maybeError.AcquireError(), computePipeline->GetLabel().c_str(), callback, userdata);
+    } else {
+        AddComputePipelineAsyncCallbackTask(std::move(computePipeline), callback, userdata);
     }
-    return AcquireRef(
-        new CreateComputePipelineAsyncEvent(this, callbackInfo, std::move(computePipeline)));
 }
 
 // This function is overwritten with the async version on the backends
@@ -2246,6 +2237,55 @@
     return mWorkerTaskPool.get();
 }
 
+void DeviceBase::AddComputePipelineAsyncCallbackTask(
+    std::unique_ptr<ErrorData> error,
+    const char* label,
+    WGPUCreateComputePipelineAsyncCallback callback,
+    void* userdata) {
+    if (GetState() != State::Alive) {
+        // If the device is no longer alive, errors should not be reported anymore.
+        // Call the callback with an error pipeline.
+        return mCallbackTaskManager->AddCallbackTask(
+            [callback, pipeline = ComputePipelineBase::MakeError(this, label), userdata]() mutable {
+                callback(WGPUCreatePipelineAsyncStatus_Success,
+                         ToAPI(ReturnToAPI(std::move(pipeline))), "", userdata);
+            });
+    }
+
+    WGPUCreatePipelineAsyncStatus status = CreatePipelineAsyncStatusFromErrorType(error->GetType());
+    mCallbackTaskManager->AddCallbackTask(
+        [callback, message = error->GetFormattedMessage(), status, userdata]() {
+            callback(status, nullptr, message.c_str(), userdata);
+        });
+}
+
+void DeviceBase::AddComputePipelineAsyncCallbackTask(
+    Ref<ComputePipelineBase> pipeline,
+    WGPUCreateComputePipelineAsyncCallback callback,
+    void* userdata) {
+    mCallbackTaskManager->AddCallbackTask(
+        [callback, pipeline = std::move(pipeline), userdata]() mutable {
+            // TODO(dawn:529): call AddOrGetCachedComputePipeline() asynchronously in
+            // CreateComputePipelineAsyncTaskImpl::Run() when the front-end pipeline cache is
+            // thread-safe.
+            DAWN_ASSERT(pipeline != nullptr);
+            {
+                // This is called inside a callback, and no lock will be held by default so we
+                // have to lock now to protect the cache. Note: we don't lock inside
+                // AddOrGetCachedComputePipeline() to avoid deadlock because many places calling
+                // that method might already have the lock held. For example,
+                // APICreateComputePipeline()
+                DeviceBase* device = pipeline->GetDevice();
+                auto deviceLock(device->GetScopedLock());
+                if (device->GetState() == State::Alive) {
+                    pipeline = device->AddOrGetCachedComputePipeline(std::move(pipeline));
+                }
+            }
+            callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(ReturnToAPI(std::move(pipeline))),
+                     "", userdata);
+        });
+}
+
 void DeviceBase::AddRenderPipelineAsyncCallbackTask(std::unique_ptr<ErrorData> error,
                                                     const char* label,
                                                     WGPUCreateRenderPipelineAsyncCallback callback,
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index d6e9386..69128c6 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -167,7 +167,7 @@
 
     MaybeError ValidateObject(const ApiObjectBase* object) const;
 
-    virtual InstanceBase* GetInstance() const;
+    InstanceBase* GetInstance() const;
     AdapterBase* GetAdapter() const;
     PhysicalDeviceBase* GetPhysicalDevice() const;
     virtual dawn::platform::Platform* GetPlatform() const;
@@ -436,7 +436,9 @@
     dawn::platform::WorkerTaskPool* GetWorkerTaskPool() const;
 
     // Enqueue a successfully-create async pipeline creation callback.
-    // TODO(dawn:2353): Remove.
+    void AddComputePipelineAsyncCallbackTask(Ref<ComputePipelineBase> pipeline,
+                                             WGPUCreateComputePipelineAsyncCallback callback,
+                                             void* userdata);
     void AddRenderPipelineAsyncCallbackTask(Ref<RenderPipelineBase> pipeline,
                                             WGPUCreateRenderPipelineAsyncCallback callback,
                                             void* userdata);
@@ -444,7 +446,10 @@
     // If the device is lost, then further errors should not be reported to
     // the application. Instead of an error, a successful callback is enqueued, using
     // an error pipeline created with `label`.
-    // TODO(dawn:2353): Remove.
+    void AddComputePipelineAsyncCallbackTask(std::unique_ptr<ErrorData> error,
+                                             const char* label,
+                                             WGPUCreateComputePipelineAsyncCallback callback,
+                                             void* userdata);
     void AddRenderPipelineAsyncCallbackTask(std::unique_ptr<ErrorData> error,
                                             const char* label,
                                             WGPUCreateRenderPipelineAsyncCallback callback,
@@ -473,9 +478,6 @@
     // DAWN_ASSERT(device.IsLockedByCurrentThread())
     bool IsLockedByCurrentThreadIfNeeded() const;
 
-    Ref<ComputePipelineBase> AddOrGetCachedComputePipeline(
-        Ref<ComputePipelineBase> computePipeline);
-
   protected:
     // Constructor used only for mocking and testing.
     DeviceBase();
@@ -542,11 +544,13 @@
         ComputePipelineBase* uninitializedComputePipeline);
     Ref<RenderPipelineBase> GetCachedRenderPipeline(
         RenderPipelineBase* uninitializedRenderPipeline);
+    Ref<ComputePipelineBase> AddOrGetCachedComputePipeline(
+        Ref<ComputePipelineBase> computePipeline);
     Ref<RenderPipelineBase> AddOrGetCachedRenderPipeline(Ref<RenderPipelineBase> renderPipeline);
     virtual Ref<PipelineCacheBase> GetOrCreatePipelineCacheImpl(const CacheKey& key);
-    virtual Ref<EventManager::TrackedEvent> InitializeComputePipelineAsyncImpl(
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo);
+    virtual void InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                                    WGPUCreateComputePipelineAsyncCallback callback,
+                                                    void* userdata);
     virtual void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                                    WGPUCreateRenderPipelineAsyncCallback callback,
                                                    void* userdata);
diff --git a/src/dawn/native/EventManager.cpp b/src/dawn/native/EventManager.cpp
index 9438603..7037557 100644
--- a/src/dawn/native/EventManager.cpp
+++ b/src/dawn/native/EventManager.cpp
@@ -345,7 +345,6 @@
 
 FutureID EventManager::TrackEvent(Ref<TrackedEvent>&& event) {
     FutureID futureID = mNextFutureID++;
-    event->mFutureID = futureID;
     return mEvents.Use([&](auto events) {
         if (!events->has_value()) {
             return futureID;
diff --git a/src/dawn/native/EventManager.h b/src/dawn/native/EventManager.h
index 9a859b8..024dc37 100644
--- a/src/dawn/native/EventManager.h
+++ b/src/dawn/native/EventManager.h
@@ -152,7 +152,6 @@
     virtual void Complete(EventCompletionType) = 0;
 
     wgpu::CallbackMode mCallbackMode;
-    FutureID mFutureID = kNullFutureID;
 
 #if DAWN_ENABLE_ASSERTS
     std::atomic<bool> mCurrentlyBeingWaited = false;
diff --git a/src/dawn/native/d3d11/ComputePipelineD3D11.cpp b/src/dawn/native/d3d11/ComputePipelineD3D11.cpp
index 3a36168..01b2df8 100644
--- a/src/dawn/native/d3d11/ComputePipelineD3D11.cpp
+++ b/src/dawn/native/d3d11/ComputePipelineD3D11.cpp
@@ -92,14 +92,13 @@
     d3dDeviceContext->CSSetShader(mComputeShader.Get(), nullptr, 0);
 }
 
-Ref<CreateComputePipelineAsyncEvent> ComputePipeline::InitializeAsync(
-    Device* device,
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    Ref<CreateComputePipelineAsyncEvent> event = AcquireRef(new CreateComputePipelineAsyncEvent(
-        device, callbackInfo, std::move(computePipeline), AcquireRef(new SystemEvent())));
-    event->InitializeAsync();
-    return event;
+void ComputePipeline::InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                      WGPUCreateComputePipelineAsyncCallback callback,
+                                      void* userdata) {
+    std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
+        std::make_unique<CreateComputePipelineAsyncTask>(std::move(computePipeline), callback,
+                                                         userdata);
+    CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
 }
 
 bool ComputePipeline::UsesNumWorkgroups() const {
diff --git a/src/dawn/native/d3d11/ComputePipelineD3D11.h b/src/dawn/native/d3d11/ComputePipelineD3D11.h
index a100832..304fe41 100644
--- a/src/dawn/native/d3d11/ComputePipelineD3D11.h
+++ b/src/dawn/native/d3d11/ComputePipelineD3D11.h
@@ -29,7 +29,6 @@
 #define SRC_DAWN_NATIVE_D3D11_COMPUTEPIPELINEGL_H_
 
 #include "dawn/native/ComputePipeline.h"
-#include "dawn/native/CreatePipelineAsyncTask.h"
 
 #include "dawn/native/d3d/d3d_platform.h"
 
@@ -43,10 +42,9 @@
     static Ref<ComputePipeline> CreateUninitialized(
         Device* device,
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor);
-    static Ref<CreateComputePipelineAsyncEvent> InitializeAsync(
-        Device* device,
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo);
+    static void InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                WGPUCreateComputePipelineAsyncCallback callback,
+                                void* userdata);
 
     void ApplyNow(const ScopedSwapStateCommandRecordingContext* commandContext);
 
diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp
index a7d559c..e42ad64 100644
--- a/src/dawn/native/d3d11/DeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/DeviceD3D11.cpp
@@ -230,10 +230,10 @@
     return TextureView::Create(texture, descriptor);
 }
 
-Ref<EventManager::TrackedEvent> Device::InitializeComputePipelineAsyncImpl(
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    return ComputePipeline::InitializeAsync(this, std::move(computePipeline), callbackInfo);
+void Device::InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                                WGPUCreateComputePipelineAsyncCallback callback,
+                                                void* userdata) {
+    ComputePipeline::InitializeAsync(std::move(computePipeline), callback, userdata);
 }
 
 void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
diff --git a/src/dawn/native/d3d11/DeviceD3D11.h b/src/dawn/native/d3d11/DeviceD3D11.h
index 6aa203a..7d34cb1 100644
--- a/src/dawn/native/d3d11/DeviceD3D11.h
+++ b/src/dawn/native/d3d11/DeviceD3D11.h
@@ -137,9 +137,9 @@
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor) override;
     Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
         const UnpackedPtr<RenderPipelineDescriptor>& descriptor) override;
-    Ref<EventManager::TrackedEvent> InitializeComputePipelineAsyncImpl(
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo) override;
+    void InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                            WGPUCreateComputePipelineAsyncCallback callback,
+                                            void* userdata) override;
     void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                            WGPUCreateRenderPipelineAsyncCallback callback,
                                            void* userdata) override;
diff --git a/src/dawn/native/d3d12/ComputePipelineD3D12.cpp b/src/dawn/native/d3d12/ComputePipelineD3D12.cpp
index 0bdc208..a8a51e2 100644
--- a/src/dawn/native/d3d12/ComputePipelineD3D12.cpp
+++ b/src/dawn/native/d3d12/ComputePipelineD3D12.cpp
@@ -151,14 +151,13 @@
     SetDebugName(ToBackend(GetDevice()), GetPipelineState(), "Dawn_ComputePipeline", GetLabel());
 }
 
-Ref<CreateComputePipelineAsyncEvent> ComputePipeline::InitializeAsync(
-    Device* device,
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    Ref<CreateComputePipelineAsyncEvent> event = AcquireRef(new CreateComputePipelineAsyncEvent(
-        device, callbackInfo, std::move(computePipeline), AcquireRef(new SystemEvent())));
-    event->InitializeAsync();
-    return event;
+void ComputePipeline::InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                      WGPUCreateComputePipelineAsyncCallback callback,
+                                      void* userdata) {
+    std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
+        std::make_unique<CreateComputePipelineAsyncTask>(std::move(computePipeline), callback,
+                                                         userdata);
+    CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
 }
 
 bool ComputePipeline::UsesNumWorkgroups() const {
diff --git a/src/dawn/native/d3d12/ComputePipelineD3D12.h b/src/dawn/native/d3d12/ComputePipelineD3D12.h
index ac6db1d..c15cca7 100644
--- a/src/dawn/native/d3d12/ComputePipelineD3D12.h
+++ b/src/dawn/native/d3d12/ComputePipelineD3D12.h
@@ -29,7 +29,6 @@
 #define SRC_DAWN_NATIVE_D3D12_COMPUTEPIPELINED3D12_H_
 
 #include "dawn/native/ComputePipeline.h"
-#include "dawn/native/CreatePipelineAsyncTask.h"
 
 #include "dawn/native/d3d12/d3d12_platform.h"
 
@@ -42,10 +41,9 @@
     static Ref<ComputePipeline> CreateUninitialized(
         Device* device,
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor);
-    static Ref<CreateComputePipelineAsyncEvent> InitializeAsync(
-        Device* device,
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo);
+    static void InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                WGPUCreateComputePipelineAsyncCallback callback,
+                                void* userdata);
     ComputePipeline() = delete;
 
     ID3D12PipelineState* GetPipelineState() const;
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index 27ef397..977b13b 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -412,10 +412,10 @@
     const TextureViewDescriptor* descriptor) {
     return TextureView::Create(texture, descriptor);
 }
-Ref<EventManager::TrackedEvent> Device::InitializeComputePipelineAsyncImpl(
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    return ComputePipeline::InitializeAsync(this, std::move(computePipeline), callbackInfo);
+void Device::InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                                WGPUCreateComputePipelineAsyncCallback callback,
+                                                void* userdata) {
+    ComputePipeline::InitializeAsync(std::move(computePipeline), callback, userdata);
 }
 void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                                WGPUCreateRenderPipelineAsyncCallback callback,
diff --git a/src/dawn/native/d3d12/DeviceD3D12.h b/src/dawn/native/d3d12/DeviceD3D12.h
index 9ec1674..c8040cc 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.h
+++ b/src/dawn/native/d3d12/DeviceD3D12.h
@@ -217,9 +217,9 @@
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor) override;
     Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
         const UnpackedPtr<RenderPipelineDescriptor>& descriptor) override;
-    Ref<EventManager::TrackedEvent> InitializeComputePipelineAsyncImpl(
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo) override;
+    void InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                            WGPUCreateComputePipelineAsyncCallback callback,
+                                            void* userdata) override;
     void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                            WGPUCreateRenderPipelineAsyncCallback callback,
                                            void* userdata) override;
diff --git a/src/dawn/native/metal/ComputePipelineMTL.h b/src/dawn/native/metal/ComputePipelineMTL.h
index e6a1518..d0e1e33 100644
--- a/src/dawn/native/metal/ComputePipelineMTL.h
+++ b/src/dawn/native/metal/ComputePipelineMTL.h
@@ -31,7 +31,6 @@
 #include <vector>
 
 #include "dawn/native/ComputePipeline.h"
-#include "dawn/native/CreatePipelineAsyncTask.h"
 
 #include "dawn/common/NSRef.h"
 
@@ -46,10 +45,9 @@
     static Ref<ComputePipeline> CreateUninitialized(
         Device* device,
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor);
-    static Ref<CreateComputePipelineAsyncEvent> InitializeAsync(
-        Device* device,
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo);
+    static void InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                WGPUCreateComputePipelineAsyncCallback callback,
+                                void* userdata);
 
     ComputePipeline(DeviceBase* device, const UnpackedPtr<ComputePipelineDescriptor>& descriptor);
     ~ComputePipeline() override;
diff --git a/src/dawn/native/metal/ComputePipelineMTL.mm b/src/dawn/native/metal/ComputePipelineMTL.mm
index 8666d32..346594b 100644
--- a/src/dawn/native/metal/ComputePipelineMTL.mm
+++ b/src/dawn/native/metal/ComputePipelineMTL.mm
@@ -123,29 +123,21 @@
     return mRequiresStorageBufferLength;
 }
 
-Ref<CreateComputePipelineAsyncEvent> ComputePipeline::InitializeAsync(
-    Device* device,
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
+void ComputePipeline::InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                      WGPUCreateComputePipelineAsyncCallback callback,
+                                      void* userdata) {
+    PhysicalDeviceBase* physicalDevice = computePipeline->GetDevice()->GetPhysicalDevice();
+    std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
+        std::make_unique<CreateComputePipelineAsyncTask>(std::move(computePipeline), callback,
+                                                         userdata);
     // Workaround a crash where the validation layers on AMD crash with partition alloc.
     // See crbug.com/dawn/1200.
-    PhysicalDeviceBase* physicalDevice = computePipeline->GetDevice()->GetPhysicalDevice();
     if (IsMetalValidationEnabled(physicalDevice) &&
         gpu_info::IsAMD(physicalDevice->GetVendorId())) {
-        MaybeError maybeError = computePipeline->Initialize();
-        if (maybeError.IsError()) {
-            return AcquireRef(
-                new CreateComputePipelineAsyncEvent(device, callbackInfo, maybeError.AcquireError(),
-                                                    computePipeline->GetLabel().c_str()));
-        }
-        return AcquireRef(
-            new CreateComputePipelineAsyncEvent(device, callbackInfo, std::move(computePipeline)));
+        asyncTask->Run();
+        return;
     }
-
-    Ref<CreateComputePipelineAsyncEvent> event = AcquireRef(new CreateComputePipelineAsyncEvent(
-        device, callbackInfo, std::move(computePipeline), AcquireRef(new SystemEvent())));
-    event->InitializeAsync();
-    return event;
+    CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
 }
 
 }  // namespace dawn::native::metal
diff --git a/src/dawn/native/metal/DeviceMTL.h b/src/dawn/native/metal/DeviceMTL.h
index e292bd5..fa40bbb 100644
--- a/src/dawn/native/metal/DeviceMTL.h
+++ b/src/dawn/native/metal/DeviceMTL.h
@@ -123,9 +123,9 @@
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor) override;
     Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
         const UnpackedPtr<RenderPipelineDescriptor>& descriptor) override;
-    Ref<EventManager::TrackedEvent> InitializeComputePipelineAsyncImpl(
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo) override;
+    void InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                            WGPUCreateComputePipelineAsyncCallback callback,
+                                            void* userdata) override;
     void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                            WGPUCreateRenderPipelineAsyncCallback callback,
                                            void* userdata) override;
diff --git a/src/dawn/native/metal/DeviceMTL.mm b/src/dawn/native/metal/DeviceMTL.mm
index 25c89a1..2ac4c5f 100644
--- a/src/dawn/native/metal/DeviceMTL.mm
+++ b/src/dawn/native/metal/DeviceMTL.mm
@@ -239,10 +239,10 @@
     const TextureViewDescriptor* descriptor) {
     return TextureView::Create(texture, descriptor);
 }
-Ref<EventManager::TrackedEvent> Device::InitializeComputePipelineAsyncImpl(
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    return ComputePipeline::InitializeAsync(this, std::move(computePipeline), callbackInfo);
+void Device::InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                                WGPUCreateComputePipelineAsyncCallback callback,
+                                                void* userdata) {
+    ComputePipeline::InitializeAsync(std::move(computePipeline), callback, userdata);
 }
 void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                                WGPUCreateRenderPipelineAsyncCallback callback,
diff --git a/src/dawn/native/vulkan/ComputePipelineVk.cpp b/src/dawn/native/vulkan/ComputePipelineVk.cpp
index 21fddec..225ea5f 100644
--- a/src/dawn/native/vulkan/ComputePipelineVk.cpp
+++ b/src/dawn/native/vulkan/ComputePipelineVk.cpp
@@ -161,14 +161,13 @@
     return mHandle;
 }
 
-Ref<CreateComputePipelineAsyncEvent> ComputePipeline::InitializeAsync(
-    Device* device,
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    Ref<CreateComputePipelineAsyncEvent> event = AcquireRef(new CreateComputePipelineAsyncEvent(
-        device, callbackInfo, std::move(computePipeline), AcquireRef(new SystemEvent())));
-    event->InitializeAsync();
-    return event;
+void ComputePipeline::InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                      WGPUCreateComputePipelineAsyncCallback callback,
+                                      void* userdata) {
+    std::unique_ptr<CreateComputePipelineAsyncTask> asyncTask =
+        std::make_unique<CreateComputePipelineAsyncTask>(std::move(computePipeline), callback,
+                                                         userdata);
+    CreateComputePipelineAsyncTask::RunAsync(std::move(asyncTask));
 }
 
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/native/vulkan/ComputePipelineVk.h b/src/dawn/native/vulkan/ComputePipelineVk.h
index cbda763..87a8ddd 100644
--- a/src/dawn/native/vulkan/ComputePipelineVk.h
+++ b/src/dawn/native/vulkan/ComputePipelineVk.h
@@ -31,7 +31,6 @@
 #include "dawn/native/ComputePipeline.h"
 
 #include "dawn/common/vulkan_platform.h"
-#include "dawn/native/CreatePipelineAsyncTask.h"
 #include "dawn/native/Error.h"
 
 namespace dawn::native::vulkan {
@@ -43,10 +42,9 @@
     static Ref<ComputePipeline> CreateUninitialized(
         Device* device,
         const UnpackedPtr<ComputePipelineDescriptor>& descriptor);
-    static Ref<CreateComputePipelineAsyncEvent> InitializeAsync(
-        Device* device,
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo);
+    static void InitializeAsync(Ref<ComputePipelineBase> computePipeline,
+                                WGPUCreateComputePipelineAsyncCallback callback,
+                                void* userdata);
 
     VkPipeline GetHandle() const;
 
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp
index f1a0e7f..9d3218b 100644
--- a/src/dawn/native/vulkan/DeviceVk.cpp
+++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -210,10 +210,10 @@
 Ref<PipelineCacheBase> Device::GetOrCreatePipelineCacheImpl(const CacheKey& key) {
     return PipelineCache::Create(this, key);
 }
-Ref<EventManager::TrackedEvent> Device::InitializeComputePipelineAsyncImpl(
-    Ref<ComputePipelineBase> computePipeline,
-    const CreateComputePipelineAsyncCallbackInfo& callbackInfo) {
-    return ComputePipeline::InitializeAsync(this, std::move(computePipeline), callbackInfo);
+void Device::InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                                WGPUCreateComputePipelineAsyncCallback callback,
+                                                void* userdata) {
+    ComputePipeline::InitializeAsync(std::move(computePipeline), callback, userdata);
 }
 void Device::InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                                WGPUCreateRenderPipelineAsyncCallback callback,
diff --git a/src/dawn/native/vulkan/DeviceVk.h b/src/dawn/native/vulkan/DeviceVk.h
index 235333c..82856ec 100644
--- a/src/dawn/native/vulkan/DeviceVk.h
+++ b/src/dawn/native/vulkan/DeviceVk.h
@@ -157,9 +157,9 @@
     Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
         const UnpackedPtr<RenderPipelineDescriptor>& descriptor) override;
     Ref<PipelineCacheBase> GetOrCreatePipelineCacheImpl(const CacheKey& key) override;
-    Ref<EventManager::TrackedEvent> InitializeComputePipelineAsyncImpl(
-        Ref<ComputePipelineBase> computePipeline,
-        const CreateComputePipelineAsyncCallbackInfo& callbackInfo) override;
+    void InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
+                                            WGPUCreateComputePipelineAsyncCallback callback,
+                                            void* userdata) override;
     void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
                                            WGPUCreateRenderPipelineAsyncCallback callback,
                                            void* userdata) override;
diff --git a/src/dawn/tests/end2end/CreatePipelineAsyncTests.cpp b/src/dawn/tests/end2end/CreatePipelineAsyncTests.cpp
index 4b94d71..2eb37c5 100644
--- a/src/dawn/tests/end2end/CreatePipelineAsyncTests.cpp
+++ b/src/dawn/tests/end2end/CreatePipelineAsyncTests.cpp
@@ -27,7 +27,6 @@
 
 #include <string>
 
-#include "dawn/native/DawnNative.h"
 #include "dawn/tests/DawnTest.h"
 #include "dawn/utils/ComboRenderPipelineDescriptor.h"
 #include "dawn/utils/WGPUHelpers.h"
@@ -171,33 +170,6 @@
     ValidateCreateComputePipelineAsync();
 }
 
-// Verify that callback can be nullptr.
-TEST_P(CreatePipelineAsyncTest, CreateComputePipelineAsyncNullCallback) {
-    DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-    // TODO(crbug.com/dawn/2471): QueueGL hangs
-    DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
-
-    wgpu::ComputePipelineDescriptor csDesc;
-    csDesc.compute.module = utils::CreateShaderModule(device, R"(
-        struct SSBO {
-            value : u32
-        }
-        @group(0) @binding(0) var<storage, read_write> ssbo : SSBO;
-
-        @compute @workgroup_size(1) fn main() {
-            ssbo.value = 1u;
-        })");
-
-    wgpu::CreateComputePipelineAsyncCallbackInfo callbackInfo;
-    callbackInfo.mode = wgpu::CallbackMode::AllowProcessEvents;
-    callbackInfo.callback = nullptr;
-    device.CreateComputePipelineAsync(&csDesc, callbackInfo);
-
-    while (dawn::native::InstanceProcessEvents(instance.Get())) {
-        WaitABit();
-    }
-}
-
 // This is a regression test for a bug on the member "entryPoint" of FlatComputePipelineDescriptor.
 TEST_P(CreatePipelineAsyncTest, ReleaseEntryPointAfterCreatComputePipelineAsync) {
     wgpu::ComputePipelineDescriptor csDesc;
diff --git a/src/dawn/tests/end2end/DeviceLifetimeTests.cpp b/src/dawn/tests/end2end/DeviceLifetimeTests.cpp
index 170c42b..02ce3a6 100644
--- a/src/dawn/tests/end2end/DeviceLifetimeTests.cpp
+++ b/src/dawn/tests/end2end/DeviceLifetimeTests.cpp
@@ -358,10 +358,6 @@
         nullptr);
 
     device = nullptr;
-    // Need to call ProcessEvents, otherwise it will be an instance drop.
-    // TODO(dawn:2353): Update to use WGPUCreateComputePipelineAsyncCallbackInfo version of
-    // CreateComputePipelineAsync and then we don't need to call ProcessEvents explicitly.
-    instance.ProcessEvents();
 }
 
 // Test that the device can be dropped inside a createPipelineAsync callback
@@ -492,10 +488,6 @@
     wgpu::ComputePipeline p = device.CreateComputePipeline(&desc);
 
     device = nullptr;
-    // Need to call ProcessEvents, otherwise it will be an instance drop.
-    // TODO(dawn:2353): Update to use WGPUCreateComputePipelineAsyncCallbackInfo version of
-    // CreateComputePipelineAsync and then we don't need to call ProcessEvents explicitly
-    instance.ProcessEvents();
 }
 
 // Test that the device can be dropped inside a createPipelineAsync callback which will race
diff --git a/src/dawn/tests/end2end/DeviceLostTests.cpp b/src/dawn/tests/end2end/DeviceLostTests.cpp
index 03cf778..5c8ebad 100644
--- a/src/dawn/tests/end2end/DeviceLostTests.cpp
+++ b/src/dawn/tests/end2end/DeviceLostTests.cpp
@@ -472,11 +472,6 @@
 
     device.CreateComputePipelineAsync(&descriptor, callback, nullptr);
     LoseDeviceForTesting();
-    // Need to call ProcessEvents, otherwise it will be an instance drop as LoseDeviceForTesting
-    // is the last statement of the test body.
-    // TODO(dawn:2353): Update to use WGPUCreateComputePipelineAsyncCallbackInfo version of
-    // CreateComputePipelineAsync and then we don't need to call ProcessEvents explicitly
-    GetInstance().ProcessEvents();
 }
 
 // This is a regression test for crbug.com/1212385 where Dawn didn't clean up all
diff --git a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
index cb1dbe9..46a6ea9 100644
--- a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
+++ b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
@@ -323,7 +323,7 @@
         .Times(1);
 
     device.CreateComputePipelineAsync(ToCppAPI(&desc), cb.Callback(), cb.MakeUserdata(this));
-    ProcessEvents();
+    device.Tick();
 
     // Device lost should only happen because of destruction.
     EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
@@ -374,7 +374,7 @@
         .Times(1);
 
     device.CreateComputePipelineAsync(ToCppAPI(&desc), cb.Callback(), cb.MakeUserdata(this));
-    ProcessEvents();
+    device.Tick();
 
     // Device lost should only happen because of destruction.
     EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
diff --git a/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp b/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp
index 44314f4..ea26b2c 100644
--- a/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp
+++ b/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp
@@ -53,7 +53,6 @@
         }
     )";
 
-// TODO(dawn:2353): Update names of the test and file.
 class CreatePipelineAsyncTaskTests : public DawnMockTest {};
 
 // A regression test for a null pointer issue in CreateRenderPipelineAsyncTask::Run().
@@ -110,6 +109,60 @@
     EXPECT_CALL(*renderPipelineMock.Get(), DestroyImpl).Times(1);
 }
 
+// A regression test for a null pointer issue in CreateComputePipelineAsyncTask::Run().
+// See crbug.com/dawn/1310 for more details.
+TEST_F(CreatePipelineAsyncTaskTests, InitializationValidationErrorInCreateComputePipelineAsync) {
+    wgpu::ComputePipelineDescriptor desc = {};
+    desc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
+    Ref<ComputePipelineMock> computePipelineMock =
+        ComputePipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
+
+    ON_CALL(*computePipelineMock.Get(), InitializeImpl)
+        .WillByDefault(testing::Return(testing::ByMove(
+            DAWN_MAKE_ERROR(InternalErrorType::Validation, "Initialization Error"))));
+
+    CreateComputePipelineAsyncTask asyncTask(
+        computePipelineMock,
+        [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline returnPipeline,
+           const char* message, void* userdata) {
+            EXPECT_EQ(WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_ValidationError,
+                      status);
+        },
+        nullptr);
+
+    asyncTask.Run();
+    device.Tick();
+
+    EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
+}
+
+// Test that Internal error are converted to the InternalError status in async pipeline creation
+// callbacks.
+TEST_F(CreatePipelineAsyncTaskTests, InitializationInternalErrorInCreateComputePipelineAsync) {
+    wgpu::ComputePipelineDescriptor desc = {};
+    desc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
+    Ref<ComputePipelineMock> computePipelineMock =
+        ComputePipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
+
+    ON_CALL(*computePipelineMock.Get(), InitializeImpl)
+        .WillByDefault(testing::Return(testing::ByMove(
+            DAWN_MAKE_ERROR(dawn::native::InternalErrorType::Internal, "Initialization Error"))));
+
+    dawn::native::CreateComputePipelineAsyncTask asyncTask(
+        computePipelineMock,
+        [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline returnPipeline,
+           const char* message, void* userdata) {
+            EXPECT_EQ(WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_InternalError,
+                      status);
+        },
+        nullptr);
+
+    asyncTask.Run();
+    device.Tick();
+
+    EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
+}
+
 // Test that a long async task's execution won't extend to after the device is dropped.
 // Device dropping should wait for that task to finish.
 TEST_F(CreatePipelineAsyncTaskTests, LongAsyncTaskFinishesBeforeDeviceIsDropped) {
@@ -142,65 +195,5 @@
     EXPECT_TRUE(done);
 }
 
-// Verify CreateComputePipelineAsync and the internal CreateComputePipelineAsyncEvent behavior
-// on creating compute pipeline with validation error.
-TEST_F(CreatePipelineAsyncTaskTests, InitializationValidationErrorInCreateComputePipelineAsync) {
-    wgpu::ComputePipelineDescriptor desc = {};
-    desc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
-    Ref<ComputePipelineMock> computePipelineMock =
-        ComputePipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
-
-    ON_CALL(*computePipelineMock.Get(), InitializeImpl)
-        .WillByDefault(testing::Return(testing::ByMove(
-            DAWN_MAKE_ERROR(InternalErrorType::Validation, "Initialization Error"))));
-    ON_CALL(*mDeviceMock.get(), CreateUninitializedComputePipelineImpl)
-        .WillByDefault(testing::Return(testing::ByMove(computePipelineMock)));
-
-    wgpu::CreateComputePipelineAsyncCallbackInfo callbackInfo = {};
-    callbackInfo.mode = wgpu::CallbackMode::AllowProcessEvents;
-    callbackInfo.callback =
-        [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline returnPipeline,
-           const char* message, void* userdata) {
-            EXPECT_EQ(WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_ValidationError,
-                      status);
-        };
-    callbackInfo.userdata = nullptr;
-
-    device.CreateComputePipelineAsync(&desc, callbackInfo);
-    ProcessEvents();
-
-    EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
-}
-
-// Verify CreateComputePipelineAsync and the internal CreateComputePipelineAsyncEvent behavior
-// on creating compute pipeline with internal error.
-TEST_F(CreatePipelineAsyncTaskTests, InitializationInternalErrorInCreateComputePipelineAsync) {
-    wgpu::ComputePipelineDescriptor desc = {};
-    desc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
-    Ref<ComputePipelineMock> computePipelineMock =
-        ComputePipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
-
-    ON_CALL(*computePipelineMock.Get(), InitializeImpl)
-        .WillByDefault(testing::Return(testing::ByMove(
-            DAWN_MAKE_ERROR(dawn::native::InternalErrorType::Internal, "Initialization Error"))));
-    ON_CALL(*mDeviceMock.get(), CreateUninitializedComputePipelineImpl)
-        .WillByDefault(testing::Return(testing::ByMove(computePipelineMock)));
-
-    wgpu::CreateComputePipelineAsyncCallbackInfo callbackInfo = {};
-    callbackInfo.mode = wgpu::CallbackMode::AllowProcessEvents;
-    callbackInfo.callback =
-        [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline returnPipeline,
-           const char* message, void* userdata) {
-            EXPECT_EQ(WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_InternalError,
-                      status);
-        };
-    callbackInfo.userdata = nullptr;
-
-    device.CreateComputePipelineAsync(&desc, callbackInfo);
-    ProcessEvents();
-
-    EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
-}
-
 }  // anonymous namespace
 }  // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp b/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
index 52da171..1abf234 100644
--- a/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
+++ b/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
@@ -46,8 +46,4 @@
     dawnProcSetProcs(nullptr);
 }
 
-void DawnMockTest::ProcessEvents() {
-    mDeviceMock->GetInstance()->ProcessEvents();
-}
-
 }  // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/DawnMockTest.h b/src/dawn/tests/unittests/native/mocks/DawnMockTest.h
index cfea51f..47eb1c2 100644
--- a/src/dawn/tests/unittests/native/mocks/DawnMockTest.h
+++ b/src/dawn/tests/unittests/native/mocks/DawnMockTest.h
@@ -38,8 +38,6 @@
     DawnMockTest();
     ~DawnMockTest() override;
 
-    void ProcessEvents();
-
   protected:
     // TODO(https://crbug.com/dawn/2346): Investigate `DanglingUntriaged` pointers in dawn/test.
     raw_ptr<::testing::NiceMock<DeviceMock>, DanglingUntriaged> mDeviceMock;
diff --git a/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp b/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp
index 896169d..07d4c4f 100644
--- a/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp
@@ -133,10 +133,6 @@
     return mInstance->GetPlatform();
 }
 
-dawn::native::InstanceBase* DeviceMock::GetInstance() const {
-    return mInstance.Get();
-}
-
 QueueMock* DeviceMock::GetQueueMock() {
     return reinterpret_cast<QueueMock*>(GetQueue());
 }
diff --git a/src/dawn/tests/unittests/native/mocks/DeviceMock.h b/src/dawn/tests/unittests/native/mocks/DeviceMock.h
index 64b405b..d49e9a8 100644
--- a/src/dawn/tests/unittests/native/mocks/DeviceMock.h
+++ b/src/dawn/tests/unittests/native/mocks/DeviceMock.h
@@ -55,8 +55,6 @@
     ~DeviceMock() override;
     dawn::platform::Platform* GetPlatform() const override;
 
-    dawn::native::InstanceBase* GetInstance() const override;
-
     // Mock specific functionality.
     QueueMock* GetQueueMock();
 
diff --git a/webgpu-cts/expectations.txt b/webgpu-cts/expectations.txt
index 613dd1c..001b038 100644
--- a/webgpu-cts/expectations.txt
+++ b/webgpu-cts/expectations.txt
@@ -814,13 +814,6 @@
 crbug.com/dawn/1898 [ android-u ] webgpu:api,operation,vertex_state,index_format:primitive_restart:indexFormat="uint32";primitiveTopology="triangle-list" [ Failure ]
 
 ################################################################################
-# Frequent Timeouts on Android Arm (Pixel 6)
-################################################################################
-crbug.com/dawn/2353 [ android-pixel-6 ] webgpu:shader,execution,expression,call,builtin,step:f16:inputSource="const";vectorize="_undef_" [ Failure ]
-crbug.com/dawn/2353 [ android-pixel-6 ] webgpu:shader,execution,expression,call,builtin,step:f32:inputSource="const";vectorize="_undef_" [ Failure ]
-crbug.com/dawn/2353 [ android-pixel-6 ] webgpu:shader,execution,expression,unary,af_arithmetic:negation:inputSource="const";vectorize="_undef_" [ Failure ]
-
-################################################################################
 # Atomics tests fail with workgroupSize=2 on Android Arm (Pixel 6)
 ################################################################################
 crbug.com/tint/1974 [ android-t ] webgpu:shader,execution,expression,call,builtin,atomics,atomicAdd:add_workgroup:workgroupSize=2;dispatchSize=16;scalarType="i32" [ Failure ]