Skip to content

Commit 65133d0

Browse files
committed
Update
[ghstack-poisoned]
2 parents 405fde9 + 92925e0 commit 65133d0

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

backends/webgpu/runtime/WebGPUCompat.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212

1313
#include <cstdint>
1414

15+
#if defined(__EMSCRIPTEN__)
16+
#include <emscripten/emscripten.h>
17+
#else
18+
#include <chrono>
19+
#include <thread>
20+
#endif
21+
1522
namespace executorch::backends::webgpu {
1623

1724
// Caller's instance must enable TimedWaitAny; returns the WaitAny status.
@@ -21,4 +28,15 @@ inline WGPUWaitStatus webgpu_wait(WGPUInstance instance, WGPUFuture future) {
2128
return wgpuInstanceWaitAny(instance, 1, &info, UINT64_MAX);
2229
}
2330

31+
// Blocking event-loop pump for the output-map readback (browser: JS yield).
32+
inline void webgpu_poll(WGPUInstance instance) {
33+
#if defined(__EMSCRIPTEN__)
34+
(void)instance;
35+
emscripten_sleep(0);
36+
#else
37+
wgpuInstanceProcessEvents(instance);
38+
std::this_thread::sleep_for(std::chrono::microseconds(50));
39+
#endif
40+
}
41+
2442
} // namespace executorch::backends::webgpu

backends/webgpu/runtime/WebGPUGraph.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ void WebGPUGraph::execute() {
580580
namespace {
581581

582582
struct MapCallbackData {
583+
bool done = false;
583584
WGPUMapAsyncStatus status = WGPUMapAsyncStatus_Error;
584585
};
585586

@@ -590,6 +591,7 @@ void buffer_map_callback(
590591
void* /*userdata2*/) {
591592
auto* data = static_cast<MapCallbackData*>(userdata1);
592593
data->status = status;
594+
data->done = true;
593595
}
594596

595597
} // namespace
@@ -598,29 +600,35 @@ void WebGPUGraph::copy_outputs(std::vector<std::pair<void*, size_t>>& outputs) {
598600
const size_t count = std::min(outputs.size(), output_staging_buffers_.size());
599601

600602
std::vector<MapCallbackData> cb_data(count);
601-
std::vector<WGPUFuture> map_futures(count, WGPUFuture{});
602603

603604
for (size_t i = 0; i < count; i++) {
604605
if (outputs[i].second == 0) {
606+
cb_data[i].done = true;
605607
cb_data[i].status = WGPUMapAsyncStatus_Success;
606608
continue;
607609
}
608610
WGPUBufferMapCallbackInfo cb_info = {};
609-
cb_info.mode = WGPUCallbackMode_WaitAnyOnly;
611+
cb_info.mode = WGPUCallbackMode_AllowSpontaneous;
610612
cb_info.callback = buffer_map_callback;
611613
cb_info.userdata1 = &cb_data[i];
612-
map_futures[i] = wgpuBufferMapAsync(
614+
wgpuBufferMapAsync(
613615
output_staging_buffers_[i],
614616
WGPUMapMode_Read,
615617
0,
616618
outputs[i].second,
617619
cb_info);
618620
}
619621

620-
for (size_t i = 0; i < count; i++) {
621-
if (outputs[i].second != 0 &&
622-
webgpu_wait(instance_, map_futures[i]) != WGPUWaitStatus_Success) {
623-
throw std::runtime_error("WebGPU: WaitAny failed for output map");
622+
// WaitAny returns pre-queue on CI Dawn+SwiftShader here; pump until mapped.
623+
bool all_mapped = false;
624+
while (!all_mapped) {
625+
webgpu_poll(instance_);
626+
all_mapped = true;
627+
for (size_t i = 0; i < count; i++) {
628+
if (outputs[i].second != 0 && !cb_data[i].done) {
629+
all_mapped = false;
630+
break;
631+
}
624632
}
625633
}
626634

0 commit comments

Comments
 (0)