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