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 #include "src/gpu/ganesh/dawn/GrDawnAsyncWait.h" 9 10 #include "include/core/SkTypes.h" 11 12 #ifdef __EMSCRIPTEN__ 13 #include <emscripten.h> 14 #endif // __EMSCRIPTEN__ 15 16 namespace { 17 18 #ifdef __EMSCRIPTEN__ 19 20 // When we use Dawn/WebGPU in a WebAssembly environment, we do not have access to 21 // `wgpu::Device::Tick()`, which is only available to dawn_native. Here we emulate the same 22 // behavior by scheduling and awaiting on a single async task, which will yield to the browser's 23 // underlying event loop. 24 // 25 // This requires that Emscripten is configured with `-s ASYNCIFY` to work as expected. 26 EM_ASYNC_JS(void, asyncSleep, (), { 27 await new Promise((resolve, _) => { 28 setTimeout(resolve, 0); 29 }) 30 }); 31 32 #endif // __EMSCRIPTEN__ 33 34 } // namespace 35 GrDawnAsyncWait(const wgpu::Device & device)36GrDawnAsyncWait::GrDawnAsyncWait(const wgpu::Device& device) : fDevice(device), fSignaled(false) {} 37 yieldAndCheck() const38bool GrDawnAsyncWait::yieldAndCheck() const { 39 if (fSignaled.load()) { 40 return true; 41 } 42 #ifdef __EMSCRIPTEN__ 43 asyncSleep(); 44 #else 45 fDevice.Tick(); 46 #endif // __EMSCRIPTEN__ 47 return fSignaled.load(); 48 } 49 busyWait() const50void GrDawnAsyncWait::busyWait() const { 51 while (!this->yieldAndCheck()) {} 52 } 53