xref: /aosp_15_r20/external/skia/src/gpu/graphite/dawn/DawnAsyncWait.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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_DawnAsyncWait_DEFINED
9 #define skgpu_graphite_DawnAsyncWait_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 
13 #include "webgpu/webgpu_cpp.h"  // NO_G3_REWRITE
14 
15 #include <atomic>
16 #include <functional>
17 
18 namespace skgpu::graphite {
19 
20 class DawnSharedContext;
21 
22 class DawnAsyncWait {
23 public:
24     DawnAsyncWait(const DawnSharedContext*);
25 
26     // Returns true if the wait has been signaled and false otherwise. If the Context allows
27     // yielding, then this function yields execution to the event loop where Dawn's asynchronous
28     // tasks get scheduled and returns as soon as the loop yields the execution back to the caller.
29     // Otherwise, it just checks.
30     bool yieldAndCheck() const;
31 
32     // Returns true if it is legal to call busyWait().
33     bool mayBusyWait() const;
34 
35     // Busy-waits until this wait has been signaled. May only be called if the Context allows
36     // yielding.
37     // TODO(armansito): This could benefit from a timeout in the case the wait never gets signaled.
38     void busyWait() const;
39 
40     // Marks this wait as resolved. Once called, all calls to `yieldAndCheck` and `busyWait` will
41     // return true immediately.
signal()42     void signal() { fSignaled = true; }
43 
44     // Resets this object into its unsignaled state.
reset()45     void reset() { fSignaled = false; }
46 
47 private:
48     const DawnSharedContext* fSharedContext;
49     std::atomic_bool fSignaled;
50 };
51 
52 template <typename T> class DawnAsyncResult {
53 public:
DawnAsyncResult(const DawnSharedContext * sharedContext)54     DawnAsyncResult(const DawnSharedContext* sharedContext) : fSync(sharedContext) {}
55 
~DawnAsyncResult()56     ~DawnAsyncResult() {
57         if (fSync.mayBusyWait()) {
58             fSync.busyWait();
59         }
60         SkASSERT(fSync.yieldAndCheck());
61     }
62 
set(const T & result)63     void set(const T& result) {
64         fResult = result;
65         fSync.signal();
66     }
67 
getIfReady()68     const T* getIfReady() const { return fSync.yieldAndCheck() ? &fResult : nullptr; }
69 
waitAndGet()70     const T& waitAndGet() const {
71         // If fSync is already signaled, the wait will return immediately.
72         fSync.busyWait();
73         return fResult;
74     }
75 
76 private:
77     DawnAsyncWait fSync;
78     T fResult;
79 };
80 
81 } // namespace skgpu::graphite
82 
83 #endif // skgpu_graphite_DawnAsyncWait_DEFINED
84