[graphite] wire up graphite dawn backend with nanobench

Bug: skia:13804
Change-Id: I4996775f0553d46f8adac3f545db3249a73c0d4a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/597023
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Auto-Submit: Peng Huang <penghuang@chromium.org>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index e6fe2ab..ea914d2 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1953,6 +1953,10 @@
       sources += [ "tools/graphite/ContextFactory.cpp" ]
       sources += [ "tools/graphite/GraphiteTestContext.h" ]
       sources += [ "tools/graphite/GraphiteTestContext.cpp" ]
+      if (skia_use_dawn) {
+        sources += [ "tools/graphite/dawn/DawnTestContext.cpp" ]
+        sources += [ "tools/graphite/dawn/GraphiteDawnTestContext.h" ]
+      }
       if (skia_use_metal) {
         sources += [ "tools/graphite/mtl/GraphiteMtlTestContext.h" ]
         sources += [ "tools/graphite/mtl/MtlTestContext.mm" ]
diff --git a/tools/flags/CommonFlagsConfig.cpp b/tools/flags/CommonFlagsConfig.cpp
index 82a2ac1..92e5424 100644
--- a/tools/flags/CommonFlagsConfig.cpp
+++ b/tools/flags/CommonFlagsConfig.cpp
@@ -135,6 +135,9 @@
 #ifdef SK_DIRECT3D
     { "grd3d",                 "graphite", "api=direct3d" },
 #endif
+#ifdef SK_DAWN
+    { "grdawn",                "graphite", "api=dawn" },
+#endif
 #ifdef SK_METAL
     { "grmtl",                 "graphite", "api=metal" },
 #endif
@@ -466,15 +469,9 @@
         if (optionValue == nullptr) {
             return false;
         }
-#ifdef SK_VULKAN
-        if (optionValue->equals("vulkan")) {
-            *outContextType = sk_gpu_test::GrContextFactory::kVulkan_ContextType;
-            return true;
-        }
-#endif
-#ifdef SK_METAL
-        if (optionValue->equals("metal")) {
-            *outContextType = sk_gpu_test::GrContextFactory::kMetal_ContextType;
+#ifdef SK_DAWN
+        if (optionValue->equals("dawn")) {
+            *outContextType = sk_gpu_test::GrContextFactory::kDawn_ContextType;
             return true;
         }
 #endif
@@ -484,6 +481,19 @@
             return true;
         }
 #endif
+#ifdef SK_METAL
+        if (optionValue->equals("metal")) {
+            *outContextType = sk_gpu_test::GrContextFactory::kMetal_ContextType;
+            return true;
+        }
+#endif
+#ifdef SK_VULKAN
+        if (optionValue->equals("vulkan")) {
+            *outContextType = sk_gpu_test::GrContextFactory::kVulkan_ContextType;
+            return true;
+        }
+#endif
+
         return false;
     }
 #endif
diff --git a/tools/graphite/ContextFactory.cpp b/tools/graphite/ContextFactory.cpp
index c0d49f5..3c04241 100644
--- a/tools/graphite/ContextFactory.cpp
+++ b/tools/graphite/ContextFactory.cpp
@@ -9,6 +9,9 @@
 
 #include "include/gpu/graphite/Context.h"
 
+#ifdef SK_DAWN
+#include "tools/graphite/dawn/GraphiteDawnTestContext.h"
+#endif
 #ifdef SK_METAL
 #include "tools/graphite/mtl/GraphiteMtlTestContext.h"
 #endif
@@ -45,6 +48,11 @@
     std::unique_ptr<GraphiteTestContext> testCtx;
 
     switch (type) {
+        case GrContextFactory::kDawn_ContextType: {
+#ifdef SK_DAWN
+            testCtx = graphite::DawnTestContext::Make();
+#endif
+        } break;
         case GrContextFactory::kMetal_ContextType: {
 #ifdef SK_METAL
             testCtx = graphite::MtlTestContext::Make();
diff --git a/tools/graphite/dawn/DawnTestContext.cpp b/tools/graphite/dawn/DawnTestContext.cpp
new file mode 100644
index 0000000..e40b6df
--- /dev/null
+++ b/tools/graphite/dawn/DawnTestContext.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tools/graphite/dawn/GraphiteDawnTestContext.h"
+
+#include "include/gpu/graphite/Context.h"
+#include "include/gpu/graphite/ContextOptions.h"
+#include "include/gpu/graphite/dawn/DawnTypes.h"
+#include "include/private/SkOnce.h"
+
+#include "dawn/dawn_proc.h"
+
+#define LOG_ADAPTER 0
+
+namespace skiatest::graphite {
+
+std::unique_ptr<GraphiteTestContext> DawnTestContext::Make() {
+    static std::unique_ptr<dawn::native::Instance> gInstance;
+    static dawn::native::Adapter gAdapter;
+    static SkOnce gOnce;
+
+    gOnce([]{
+        gInstance = std::make_unique<dawn::native::Instance>();
+
+        gInstance->DiscoverDefaultAdapters();
+        DawnProcTable backendProcs = dawn::native::GetProcs();
+        dawnProcSetProcs(&backendProcs);
+
+        std::vector<dawn::native::Adapter> adapters = gInstance->GetAdapters();
+        SkASSERT(!adapters.empty());
+        // Sort adapters by adapterType(DiscreteGPU, IntegratedGPU, CPU) and
+        // backendType(WebGPU, D3D11, D3D12, Metal, Vulkan, OpenGL, OpenGLES).
+        std::sort(
+            adapters.begin(), adapters.end(),
+            [](dawn::native::Adapter a, dawn::native::Adapter b) {
+                wgpu::AdapterProperties propA;
+                wgpu::AdapterProperties propB;
+                a.GetProperties(&propA);
+                b.GetProperties(&propB);
+                return std::tuple(propA.adapterType, propA.backendType) <
+                       std::tuple(propB.adapterType, propB.backendType);
+            });
+
+        gAdapter = adapters.front();
+
+#if LOG_ADAPTER
+        wgpu::AdapterProperties properties;
+        gAdapter.GetProperties(&properties);
+        SkDebugf("GPU: %s\nDriver: %s\n", properties.name, properties.driverDescription);
+#endif
+    });
+
+    std::array<wgpu::FeatureName, 2> features = {
+        wgpu::FeatureName::DepthClipControl,
+        wgpu::FeatureName::Depth32FloatStencil8,
+    };
+    wgpu::DeviceDescriptor desc;
+    desc.requiredFeaturesCount = features.size();
+    desc.requiredFeatures      = features.data();
+
+#if !defined(SK_DEBUG)
+        wgpu::DawnTogglesDeviceDescriptor togglesDeviceDesc;
+        std::array<const char*, 1> toggles = {
+            "skip_validation",
+        };
+        togglesDeviceDesc.forceEnabledTogglesCount = toggles.size();
+        togglesDeviceDesc.forceEnabledToggles      = toggles.data();
+        desc.nextInChain                           = &togglesDeviceDesc;
+#endif
+    auto device = wgpu::Device::Acquire(gAdapter.CreateDevice(&desc));
+    SkASSERT(device);
+    device.SetUncapturedErrorCallback(
+            [](WGPUErrorType type, const char* message, void*) {
+                SK_ABORT("Device error: %s\n", message);
+            },
+            0);
+
+    skgpu::graphite::DawnBackendContext backendContext;
+    backendContext.fDevice = device;
+    backendContext.fQueue  = device.GetQueue();
+    return std::unique_ptr<GraphiteTestContext>(new DawnTestContext(backendContext));
+}
+
+std::unique_ptr<skgpu::graphite::Context> DawnTestContext::makeContext() {
+    return skgpu::graphite::Context::MakeDawn(fBackendContext,
+                                              skgpu::graphite::ContextOptions{});
+}
+
+}  // namespace skiatest::graphite
+
diff --git a/tools/graphite/dawn/GraphiteDawnTestContext.h b/tools/graphite/dawn/GraphiteDawnTestContext.h
new file mode 100644
index 0000000..768bf9c
--- /dev/null
+++ b/tools/graphite/dawn/GraphiteDawnTestContext.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skiatest_graphite_DawnTestContext_DEFINED
+#define skiatest_graphite_DawnTestContext_DEFINED
+
+#include "tools/graphite/GraphiteTestContext.h"
+
+#include "include/gpu/graphite/dawn/DawnBackendContext.h"
+
+#include "webgpu/webgpu_cpp.h"
+#include "dawn/native/DawnNative.h"
+
+namespace skiatest::graphite {
+
+class DawnTestContext : public GraphiteTestContext {
+public:
+    ~DawnTestContext() override {}
+
+    static std::unique_ptr<GraphiteTestContext> Make();
+
+    skgpu::BackendApi backend() override { return skgpu::BackendApi::kDawn; }
+
+    std::unique_ptr<skgpu::graphite::Context> makeContext() override;
+
+    const skgpu::graphite::DawnBackendContext& getBackendContext() const {
+        return fBackendContext;
+    }
+
+protected:
+    DawnTestContext(const skgpu::graphite::DawnBackendContext& backendContext)
+            : fBackendContext(backendContext) {}
+
+    skgpu::graphite::DawnBackendContext     fBackendContext;
+};
+
+}  // namespace skiatest::graphite
+
+#endif // skiatest_graphite_DawnTestContext_DEFINED