| /* | |
| * 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 skgpu_graphite_DawnAsyncWait_DEFINED | |
| #define skgpu_graphite_DawnAsyncWait_DEFINED | |
| #include "include/core/SkTypes.h" | |
| #include "webgpu/webgpu_cpp.h" // NO_G3_REWRITE | |
| #include <atomic> | |
| #include <functional> | |
| namespace skgpu::graphite { | |
| class DawnSharedContext; | |
| class DawnAsyncWait { | |
| public: | |
| DawnAsyncWait(const DawnSharedContext*); | |
| // Returns true if the wait has been signaled and false otherwise. If the Context allows | |
| // yielding, then this function yields execution to the event loop where Dawn's asynchronous | |
| // tasks get scheduled and returns as soon as the loop yields the execution back to the caller. | |
| // Otherwise, it just checks. | |
| bool yieldAndCheck() const; | |
| // Returns true if it is legal to call busyWait(). | |
| bool mayBusyWait() const; | |
| // Busy-waits until this wait has been signaled. May only be called if the Context allows | |
| // yielding. | |
| // TODO(armansito): This could benefit from a timeout in the case the wait never gets signaled. | |
| void busyWait() const; | |
| // Marks this wait as resolved. Once called, all calls to `yieldAndCheck` and `busyWait` will | |
| // return true immediately. | |
| void signal() { fSignaled = true; } | |
| // Resets this object into its unsignaled state. | |
| void reset() { fSignaled = false; } | |
| private: | |
| const DawnSharedContext* fSharedContext; | |
| std::atomic_bool fSignaled; | |
| }; | |
| template <typename T> class DawnAsyncResult { | |
| public: | |
| DawnAsyncResult(const DawnSharedContext* sharedContext) : fSync(sharedContext) {} | |
| ~DawnAsyncResult() { | |
| if (fSync.mayBusyWait()) { | |
| fSync.busyWait(); | |
| } | |
| SkASSERT(fSync.yieldAndCheck()); | |
| } | |
| void set(const T& result) { | |
| fResult = result; | |
| fSync.signal(); | |
| } | |
| const T* getIfReady() const { return fSync.yieldAndCheck() ? &fResult : nullptr; } | |
| const T& waitAndGet() const { | |
| // If fSync is already signaled, the wait will return immediately. | |
| fSync.busyWait(); | |
| return fResult; | |
| } | |
| private: | |
| DawnAsyncWait fSync; | |
| T fResult; | |
| }; | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_DawnAsyncWait_DEFINED |