[dawn][emscripten] Implements onSubmittedWorkDone future entry point.
Bug: 372077545
Change-Id: I7748fc294a4d8d2e659902307742d89c7f3e4533
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/209895
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/third_party/emdawnwebgpu/library_webgpu.js b/third_party/emdawnwebgpu/library_webgpu.js
index 3e81bab..b4d9f3d 100644
--- a/third_party/emdawnwebgpu/library_webgpu.js
+++ b/third_party/emdawnwebgpu/library_webgpu.js
@@ -137,8 +137,8 @@
importJsDevice__deps: ['emwgpuCreateDevice', 'emwgpuCreateQueue'],
importJsDevice: (device, parentPtr = 0) => {
var queuePtr = _emwgpuCreateQueue(parentPtr);
- WebGPU.Internals.jsObjectInsert(queuePtr, device.queue);
var devicePtr = _emwgpuCreateDevice(parentPtr, queuePtr);
+ WebGPU.Internals.jsObjectInsert(queuePtr, device.queue);
WebGPU.Internals.jsObjectInsert(devicePtr, device);
return devicePtr;
},
@@ -1491,7 +1491,7 @@
return ptr;
},
- emwgpuDeviceCreateComputePipelineAsync__i53abi:false,
+ emwgpuDeviceCreateComputePipelineAsync__i53abi: false,
emwgpuDeviceCreateComputePipelineAsync__deps: ['emwgpuCreateComputePipeline', 'emwgpuOnCreateComputePipelineCompleted'],
emwgpuDeviceCreateComputePipelineAsync: (devicePtr, futureIdL, futureIdH, descriptor) => {
var desc = WebGPU.makeComputePipelineDesc(descriptor);
@@ -1601,7 +1601,7 @@
return ptr;
},
- emwgpuDeviceCreateRenderPipelineAsync__i53abi:false,
+ emwgpuDeviceCreateRenderPipelineAsync__i53abi: false,
emwgpuDeviceCreateRenderPipelineAsync__deps: ['emwgpuCreateRenderPipeline', 'emwgpuOnCreateRenderPipelineCompleted'],
emwgpuDeviceCreateRenderPipelineAsync: (devicePtr, futureIdL, futureIdH, descriptor) => {
var desc = WebGPU.makeRenderPipelineDesc(descriptor);
@@ -1956,22 +1956,19 @@
// Methods of Queue
// --------------------------------------------------------------------------
- wgpuQueueOnSubmittedWorkDone__deps: ['$callUserCallback'],
- wgpuQueueOnSubmittedWorkDone: (queuePtr, callback, userdata) => {
+ emwgpuQueueOnSubmittedWorkDone__i53abi: false,
+ emwgpuQueueOnSubmittedWorkDone__deps: ['emwgpuOnWorkDoneCompleted'],
+ emwgpuQueueOnSubmittedWorkDone: (queuePtr, futureIdL, futureIdH) => {
var queue = WebGPU.getJsObject(queuePtr);
{{{ runtimeKeepalivePush() }}}
- queue.onSubmittedWorkDone().then(() => {
+ WebGPU.Internals.futureInsert(futureIdL, futureIdH, queue.onSubmittedWorkDone().then(() => {
{{{ runtimeKeepalivePop() }}}
- callUserCallback(() => {
- {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.QueueWorkDoneStatus.Success }}}, userdata);
- });
+ _emwgpuOnWorkDoneCompleted(futureIdL, futureIdH, {{{ gpu.QueueWorkDoneStatus.Success }}});
}, () => {
{{{ runtimeKeepalivePop() }}}
- callUserCallback(() => {
- {{{ makeDynCall('vip', 'callback') }}}({{{ gpu.QueueWorkDoneStatus.Error }}}, userdata);
- });
- });
+ _emwgpuOnWorkDoneCompleted(futureIdL, futureIdH, {{{ gpu.QueueWorkDoneStatus.Error }}});
+ }));
},
wgpuQueueSetLabel: (queuePtr, labelPtr) => {
diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp
index 2e72892..f2ba66b 100644
--- a/third_party/emdawnwebgpu/webgpu.cpp
+++ b/third_party/emdawnwebgpu/webgpu.cpp
@@ -78,6 +78,7 @@
void emwgpuInstanceRequestAdapter(WGPUInstance instance,
FutureID futureId,
const WGPURequestAdapterOptions* options);
+void emwgpuQueueOnSubmittedWorkDone(WGPUQueue queue, FutureID futureId);
} // extern "C"
// ----------------------------------------------------------------------------
@@ -286,7 +287,6 @@
X(ComputePipeline) \
X(PipelineLayout) \
X(QuerySet) \
- X(Queue) \
X(RenderBundle) \
X(RenderBundleEncoder) \
X(RenderPassEncoder) \
@@ -313,6 +313,7 @@
MapAsync,
RequestAdapter,
RequestDevice,
+ WorkDone,
};
class EventManager;
@@ -641,6 +642,11 @@
WGPUBufferMapState mMapState;
};
+struct WGPUQueueImpl final : public EventSource, public RefCounted {
+ public:
+ WGPUQueueImpl(const EventSource* source);
+};
+
// Device is specially implemented in order to handle refcounting the Queue.
struct WGPUDeviceImpl final : public EventSource,
public RefCountedWithExternalCount {
@@ -943,6 +949,38 @@
std::optional<std::string> mMessage = std::nullopt;
};
+class WorkDoneEvent final : public TrackedEvent {
+ public:
+ static constexpr EventType kType = EventType::WorkDone;
+
+ WorkDoneEvent(InstanceID instance,
+ const WGPUQueueWorkDoneCallbackInfo2& callbackInfo)
+ : TrackedEvent(instance, callbackInfo.mode),
+ mCallback(callbackInfo.callback),
+ mUserdata1(callbackInfo.userdata1),
+ mUserdata2(callbackInfo.userdata2) {}
+
+ EventType GetType() override { return kType; }
+
+ void ReadyHook(WGPUQueueWorkDoneStatus status) { mStatus = status; }
+
+ void Complete(FutureID, EventCompletionType type) override {
+ if (type == EventCompletionType::Shutdown) {
+ mStatus = WGPUQueueWorkDoneStatus_InstanceDropped;
+ }
+ if (mCallback) {
+ mCallback(mStatus, mUserdata1, mUserdata2);
+ }
+ }
+
+ private:
+ WGPUQueueWorkDoneCallback2 mCallback = nullptr;
+ void* mUserdata1 = nullptr;
+ void* mUserdata2 = nullptr;
+
+ WGPUQueueWorkDoneStatus mStatus;
+};
+
// ----------------------------------------------------------------------------
// WGPU struct implementations.
// ----------------------------------------------------------------------------
@@ -1128,6 +1166,12 @@
}
// ----------------------------------------------------------------------------
+// WGPUQueueImpl implementations.
+// ----------------------------------------------------------------------------
+
+WGPUQueueImpl::WGPUQueueImpl(const EventSource* source) : EventSource(source) {}
+
+// ----------------------------------------------------------------------------
// Definitions for C++ emwgpu functions (callable from library_webgpu.js)
// ----------------------------------------------------------------------------
extern "C" {
@@ -1153,6 +1197,10 @@
return new WGPUDeviceImpl(source, queue);
}
+WGPUQueue emwgpuCreateQueue(const EventSource* source) {
+ return new WGPUQueueImpl(source);
+}
+
// Future event callbacks.
void emwgpuOnCreateComputePipelineCompleted(
FutureID futureId,
@@ -1204,6 +1252,10 @@
nullptr, message);
}
}
+void emwgpuOnWorkDoneCompleted(FutureID futureId,
+ WGPUQueueWorkDoneStatus status) {
+ GetEventManager().SetFutureReady<WorkDoneEvent>(futureId, status);
+}
// Uncaptured error handler is similar to the Future event callbacks, but it
// doesn't go through the EventManager and just calls the callback on the Device
@@ -1299,7 +1351,7 @@
// For RequestDevice, we always create a Device and Queue up front. The
// Device is also immediately associated with the DeviceLostEvent.
- WGPUQueue queue = new WGPUQueueImpl();
+ WGPUQueue queue = new WGPUQueueImpl(adapter);
WGPUDevice device = new WGPUDeviceImpl(adapter, descriptor, queue);
auto [deviceLostFutureId, _] = GetEventManager().TrackEvent(
@@ -1510,6 +1562,19 @@
// Methods of Queue
// ----------------------------------------------------------------------------
+WGPUFuture wgpuQueueOnSubmittedWorkDone2(
+ WGPUQueue queue,
+ WGPUQueueWorkDoneCallbackInfo2 callbackInfo) {
+ auto [futureId, tracked] = GetEventManager().TrackEvent(
+ std::make_unique<WorkDoneEvent>(queue->GetInstanceId(), callbackInfo));
+ if (!tracked) {
+ return WGPUFuture{kNullFutureId};
+ }
+
+ emwgpuQueueOnSubmittedWorkDone(queue, futureId);
+ return WGPUFuture{futureId};
+}
+
// ----------------------------------------------------------------------------
// Methods of RenderBundle
// ----------------------------------------------------------------------------