• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef skgpu_graphite_DawnBackendContext_DEFINED
9 #define skgpu_graphite_DawnBackendContext_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 #include "webgpu/webgpu_cpp.h"  // NO_G3_REWRITE
13 
14 #include <memory>
15 
16 namespace skgpu::graphite {
17 
18 class Context;
19 struct ContextOptions;
20 
21 /**
22  * WebGPU needs to allow the main thread loop to run to detect GPU progress. Dawn native has a
23  * function wgpu::Instance::ProcessEvents, not (currently) present in WebGPU, that can be used to
24  * detect GPU progress.
25  *
26  * When compiling using Emscripten/WASM the -s ASYNCIFY option can be used to yield. E.g.:
27  *
28  * EM_ASYNC_JS(void, asyncSleep, (), {
29  *                 await new Promise((resolve, _) = > {
30  *                     setTimeout(resolve, 0);
31  *                 })
32  *             });
33  *
34  * WebGPUTickFunction(wgpu::Device&) { asyncSleep(); }
35  *
36  * If no DawnTickFunction is provided then the graphite::Context will be "non-yielding". This
37  * implies the following restrictions on the Context:
38  *
39  * 1) SyncToCpu::kYes is disallowed as a parameter to Context::submit.
40  * 2) The client must guarantee that GPU work has completed before destroying Context as Context
41  *    cannot await the work completion in its destructor. Context reports whether it is awaiting
42  *    GPU work completion via Context::hasUnfinishedGpuWork().
43  *
44  * Using a non-yielding Context makes it possible to build and run Graphite/Dawn on WebGPU without
45  * -s ASYNCIFY.
46  */
47 using DawnTickFunction = void(const wgpu::Instance& device);
48 
49 #if !defined(__EMSCRIPTEN__)
DawnNativeProcessEventsFunction(const wgpu::Instance & instance)50 SK_API inline void DawnNativeProcessEventsFunction(const wgpu::Instance& instance) {
51     instance.ProcessEvents();
52 }
53 #endif
54 
55 // The DawnBackendContext contains all of the base Dawn objects needed by the graphite Dawn
56 // backend. The client will create this object and pass it into the Context::MakeDawn factory call
57 // when setting up Skia.
58 struct SK_API DawnBackendContext {
59     wgpu::Instance fInstance;
60     wgpu::Device fDevice;
61     wgpu::Queue fQueue;
62     // See comment on DawnTickFunction.
63     DawnTickFunction* fTick =
64 #if defined(__EMSCRIPTEN__)
65             nullptr;
66 #else
67             DawnNativeProcessEventsFunction;
68 #endif
69 };
70 
71 namespace ContextFactory {
72 SK_API std::unique_ptr<Context> MakeDawn(const DawnBackendContext&, const ContextOptions&);
73 } // namespace ContextFactory
74 
75 } // namespace skgpu::graphite
76 
77 #endif // skgpu_graphite_DawnBackendContext_DEFINED
78