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