[wgpu-headers] Introduce 2nd userdata to onSubmittedWorkDone callback.
- We need to differentiate between 1 userdata and 2 userdata because
they use different callback mechanisms that won't work with one
another.
- Note that usages will be updated in a follow up after
mapAsync has been updated as well since there's some inter-dependency
between these two calls.
Bug: 42241461
Change-Id: I961bcb96620bee3b6fe5654769e80a6058ce011f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/188225
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 4b71a1a..02bf724 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -2786,6 +2786,15 @@
]
},
{
+ "name": "on submitted work done 2",
+ "_comment": "TODO(crbug.com/dawn/2021): This is dawn/emscripten-only until we rename it to replace the old API. See bug for details.",
+ "tags": ["dawn", "emscripten"],
+ "returns": "future",
+ "args": [
+ {"name": "callback info", "type": "queue work done callback info 2"}
+ ]
+ },
+ {
"name": "write buffer",
"args": [
{"name": "buffer", "type": "buffer"},
@@ -2849,6 +2858,12 @@
{"name": "userdata", "type": "void *"}
]
},
+ "queue work done callback 2": {
+ "category": "callback function",
+ "args": [
+ {"name": "status", "type": "queue work done status"}
+ ]
+ },
"queue work done callback info": {
"category": "structure",
"extensible": "in",
@@ -2858,6 +2873,12 @@
{"name": "userdata", "type": "void *"}
]
},
+ "queue work done callback info 2": {
+ "category": "callback info",
+ "members": [
+ {"name": "callback", "type": "queue work done callback 2"}
+ ]
+ },
"queue work done status": {
"category": "enum",
"emscripten_no_enum_table": true,
diff --git a/src/dawn/dawn_wire.json b/src/dawn/dawn_wire.json
index 212d7ba..85fbcf0 100644
--- a/src/dawn/dawn_wire.json
+++ b/src/dawn/dawn_wire.json
@@ -81,7 +81,8 @@
"queue on submitted work done": [
{ "name": "queue id", "type": "ObjectId", "id_type": "queue" },
{ "name": "event manager handle", "type": "ObjectHandle" },
- { "name": "future", "type": "future" }
+ { "name": "future", "type": "future" },
+ { "name": "userdata count", "type": "uint8_t", "_comment": "TODO(crbug.com/dawn/2509): Remove this once Chromium overrides the correct functions in the proc table."}
],
"queue write buffer": [
{"name": "queue id", "type": "ObjectId", "id_type": "queue" },
@@ -246,6 +247,7 @@
"QuerySetGetCount",
"QueueOnSubmittedWorkDone",
"QueueOnSubmittedWorkDoneF",
+ "QueueOnSubmittedWorkDone2",
"QueueWriteBuffer",
"QueueWriteTexture",
"SurfaceGetCapabilities",
diff --git a/src/dawn/native/Queue.cpp b/src/dawn/native/Queue.cpp
index 8109c1f..9c5e924 100644
--- a/src/dawn/native/Queue.cpp
+++ b/src/dawn/native/Queue.cpp
@@ -200,43 +200,6 @@
MaybeError WaitForIdleForDestruction() override { DAWN_UNREACHABLE(); }
};
-struct WorkDoneEvent final : public EventManager::TrackedEvent {
- std::optional<wgpu::QueueWorkDoneStatus> mEarlyStatus;
- WGPUQueueWorkDoneCallback mCallback;
- raw_ptr<void> mUserdata;
-
- // Create an event backed by the given queue execution serial.
- WorkDoneEvent(const QueueWorkDoneCallbackInfo& callbackInfo,
- QueueBase* queue,
- ExecutionSerial serial)
- : TrackedEvent(callbackInfo.mode, queue, serial),
- mCallback(callbackInfo.callback),
- mUserdata(callbackInfo.userdata) {}
-
- // Create an event that's ready at creation (for errors, etc.)
- WorkDoneEvent(const QueueWorkDoneCallbackInfo& callbackInfo,
- QueueBase* queue,
- wgpu::QueueWorkDoneStatus earlyStatus)
- : TrackedEvent(callbackInfo.mode, queue, kBeginningOfGPUTime),
- mEarlyStatus(earlyStatus),
- mCallback(callbackInfo.callback),
- mUserdata(callbackInfo.userdata) {}
-
- ~WorkDoneEvent() override { EnsureComplete(EventCompletionType::Shutdown); }
-
- void Complete(EventCompletionType completionType) override {
- // WorkDoneEvent has no error cases other than the mEarlyStatus ones.
- wgpu::QueueWorkDoneStatus status = wgpu::QueueWorkDoneStatus::Success;
- if (completionType == EventCompletionType::Shutdown) {
- status = wgpu::QueueWorkDoneStatus::InstanceDropped;
- } else if (mEarlyStatus) {
- status = mEarlyStatus.value();
- }
-
- mCallback(ToAPI(status), mUserdata.ExtractAsDangling());
- }
-};
-
} // namespace
// TrackTaskCallback
@@ -316,6 +279,58 @@
}
Future QueueBase::APIOnSubmittedWorkDoneF(const QueueWorkDoneCallbackInfo& callbackInfo) {
+ return APIOnSubmittedWorkDone2(
+ {ToAPI(callbackInfo.nextInChain), ToAPI(callbackInfo.mode),
+ [](WGPUQueueWorkDoneStatus status, void* callback, void* userdata) {
+ auto cb = reinterpret_cast<WGPUQueueWorkDoneCallback>(callback);
+ cb(status, userdata);
+ },
+ reinterpret_cast<void*>(callbackInfo.callback), callbackInfo.userdata});
+}
+
+Future QueueBase::APIOnSubmittedWorkDone2(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo) {
+ struct WorkDoneEvent final : public EventManager::TrackedEvent {
+ std::optional<WGPUQueueWorkDoneStatus> mEarlyStatus;
+ WGPUQueueWorkDoneCallback2 mCallback;
+ raw_ptr<void> mUserdata1;
+ raw_ptr<void> mUserdata2;
+
+ // Create an event backed by the given queue execution serial.
+ WorkDoneEvent(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo,
+ QueueBase* queue,
+ ExecutionSerial serial)
+ : TrackedEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode), queue, serial),
+ mCallback(callbackInfo.callback),
+ mUserdata1(callbackInfo.userdata1),
+ mUserdata2(callbackInfo.userdata2) {}
+
+ // Create an event that's ready at creation (for errors, etc.)
+ WorkDoneEvent(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo,
+ QueueBase* queue,
+ wgpu::QueueWorkDoneStatus earlyStatus)
+ : TrackedEvent(static_cast<wgpu::CallbackMode>(callbackInfo.mode),
+ queue,
+ kBeginningOfGPUTime),
+ mEarlyStatus(ToAPI(earlyStatus)),
+ mCallback(callbackInfo.callback),
+ mUserdata1(callbackInfo.userdata1),
+ mUserdata2(callbackInfo.userdata2) {}
+
+ ~WorkDoneEvent() override { EnsureComplete(EventCompletionType::Shutdown); }
+
+ void Complete(EventCompletionType completionType) override {
+ // WorkDoneEvent has no error cases other than the mEarlyStatus ones.
+ WGPUQueueWorkDoneStatus status = WGPUQueueWorkDoneStatus_Success;
+ if (completionType == EventCompletionType::Shutdown) {
+ status = WGPUQueueWorkDoneStatus_InstanceDropped;
+ } else if (mEarlyStatus) {
+ status = mEarlyStatus.value();
+ }
+
+ mCallback(status, mUserdata1.ExtractAsDangling(), mUserdata2.ExtractAsDangling());
+ }
+ };
+
// TODO(crbug.com/dawn/2052): Once we always return a future, change this to log to the instance
// (note, not raise a validation error to the device) and return the null future.
DAWN_ASSERT(callbackInfo.nextInChain == nullptr);
diff --git a/src/dawn/native/Queue.h b/src/dawn/native/Queue.h
index a8d40b6..9f6c3ef 100644
--- a/src/dawn/native/Queue.h
+++ b/src/dawn/native/Queue.h
@@ -75,6 +75,7 @@
void APISubmit(uint32_t commandCount, CommandBufferBase* const* commands);
void APIOnSubmittedWorkDone(WGPUQueueWorkDoneCallback callback, void* userdata);
Future APIOnSubmittedWorkDoneF(const QueueWorkDoneCallbackInfo& callbackInfo);
+ Future APIOnSubmittedWorkDone2(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo);
void APIWriteBuffer(BufferBase* buffer, uint64_t bufferOffset, const void* data, size_t size);
void APIWriteTexture(const ImageCopyTexture* destination,
const void* data,
diff --git a/src/dawn/wire/client/Queue.cpp b/src/dawn/wire/client/Queue.cpp
index cfdf86b..2680e16 100644
--- a/src/dawn/wire/client/Queue.cpp
+++ b/src/dawn/wire/client/Queue.cpp
@@ -41,10 +41,11 @@
public:
static constexpr EventType kType = EventType::WorkDone;
- explicit WorkDoneEvent(const WGPUQueueWorkDoneCallbackInfo& callbackInfo)
+ explicit WorkDoneEvent(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo)
: TrackedEvent(callbackInfo.mode),
mCallback(callbackInfo.callback),
- mUserdata(callbackInfo.userdata) {}
+ mUserdata1(callbackInfo.userdata1),
+ mUserdata2(callbackInfo.userdata2) {}
EventType GetType() override { return kType; }
@@ -61,13 +62,16 @@
if (mStatus == WGPUQueueWorkDoneStatus_DeviceLost) {
mStatus = WGPUQueueWorkDoneStatus_Success;
}
+ void* userdata1 = mUserdata1.ExtractAsDangling();
+ void* userdata2 = mUserdata2.ExtractAsDangling();
if (mCallback) {
- mCallback(mStatus, mUserdata.ExtractAsDangling());
+ mCallback(mStatus, userdata1, userdata2);
}
}
- WGPUQueueWorkDoneCallback mCallback;
- raw_ptr<void> mUserdata;
+ WGPUQueueWorkDoneCallback2 mCallback;
+ raw_ptr<void> mUserdata1;
+ raw_ptr<void> mUserdata2;
WGPUQueueWorkDoneStatus mStatus = WGPUQueueWorkDoneStatus_Success;
};
@@ -87,11 +91,7 @@
}
void Queue::OnSubmittedWorkDone(WGPUQueueWorkDoneCallback callback, void* userdata) {
- WGPUQueueWorkDoneCallbackInfo callbackInfo = {};
- callbackInfo.mode = WGPUCallbackMode_AllowSpontaneous;
- callbackInfo.callback = callback;
- callbackInfo.userdata = userdata;
- OnSubmittedWorkDoneF(callbackInfo);
+ OnSubmittedWorkDoneF({nullptr, WGPUCallbackMode_AllowSpontaneous, callback, userdata});
}
WGPUFuture Queue::OnSubmittedWorkDoneF(const WGPUQueueWorkDoneCallbackInfo& callbackInfo) {
@@ -101,6 +101,36 @@
Client* client = GetClient();
auto [futureIDInternal, tracked] =
+ GetEventManager().TrackEvent(std::make_unique<WorkDoneEvent>(WGPUQueueWorkDoneCallbackInfo2{
+ callbackInfo.nextInChain, callbackInfo.mode,
+ [](WGPUQueueWorkDoneStatus status, void* callback, void* userdata) {
+ auto cb = reinterpret_cast<WGPUQueueWorkDoneCallback>(callback);
+ cb(status, userdata);
+ },
+ reinterpret_cast<void*>(callbackInfo.callback != nullptr ? callbackInfo.callback
+ : nullptr),
+ callbackInfo.userdata}));
+ if (!tracked) {
+ return {futureIDInternal};
+ }
+
+ QueueOnSubmittedWorkDoneCmd cmd;
+ cmd.queueId = GetWireId();
+ cmd.eventManagerHandle = GetEventManagerHandle();
+ cmd.future = {futureIDInternal};
+ cmd.userdataCount = 1;
+
+ client->SerializeCommand(cmd);
+ return {futureIDInternal};
+}
+
+WGPUFuture Queue::OnSubmittedWorkDone2(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo) {
+ // TODO(crbug.com/dawn/2052): Once we always return a future, change this to log to the instance
+ // (note, not raise a validation error to the device) and return the null future.
+ DAWN_ASSERT(callbackInfo.nextInChain == nullptr);
+
+ Client* client = GetClient();
+ auto [futureIDInternal, tracked] =
GetEventManager().TrackEvent(std::make_unique<WorkDoneEvent>(callbackInfo));
if (!tracked) {
return {futureIDInternal};
@@ -110,6 +140,7 @@
cmd.queueId = GetWireId();
cmd.eventManagerHandle = GetEventManagerHandle();
cmd.future = {futureIDInternal};
+ cmd.userdataCount = 2;
client->SerializeCommand(cmd);
return {futureIDInternal};
diff --git a/src/dawn/wire/client/Queue.h b/src/dawn/wire/client/Queue.h
index 6708c03..0566f08 100644
--- a/src/dawn/wire/client/Queue.h
+++ b/src/dawn/wire/client/Queue.h
@@ -45,6 +45,7 @@
// Dawn API
void OnSubmittedWorkDone(WGPUQueueWorkDoneCallback callback, void* userdata);
WGPUFuture OnSubmittedWorkDoneF(const WGPUQueueWorkDoneCallbackInfo& callbackInfo);
+ WGPUFuture OnSubmittedWorkDone2(const WGPUQueueWorkDoneCallbackInfo2& callbackInfo);
void WriteBuffer(WGPUBuffer cBuffer, uint64_t bufferOffset, const void* data, size_t size);
void WriteTexture(const WGPUImageCopyTexture* destination,
const void* data,
diff --git a/src/dawn/wire/server/ServerQueue.cpp b/src/dawn/wire/server/ServerQueue.cpp
index 807861b..338a3b5 100644
--- a/src/dawn/wire/server/ServerQueue.cpp
+++ b/src/dawn/wire/server/ServerQueue.cpp
@@ -43,14 +43,22 @@
WireResult Server::DoQueueOnSubmittedWorkDone(Known<WGPUQueue> queue,
ObjectHandle eventManager,
- WGPUFuture future) {
+ WGPUFuture future,
+ uint8_t userdataCount) {
auto userdata = MakeUserdata<QueueWorkDoneUserdata>();
userdata->queue = queue.AsHandle();
userdata->eventManager = eventManager;
userdata->future = future;
- mProcs.queueOnSubmittedWorkDone(queue->handle, ForwardToServer<&Server::OnQueueWorkDone>,
- userdata.release());
+ if (userdataCount == 1) {
+ mProcs.queueOnSubmittedWorkDone(queue->handle, ForwardToServer<&Server::OnQueueWorkDone>,
+ userdata.release());
+ } else {
+ mProcs.queueOnSubmittedWorkDone2(
+ queue->handle,
+ {nullptr, WGPUCallbackMode_AllowProcessEvents,
+ ForwardToServer2<&Server::OnQueueWorkDone>, userdata.release(), nullptr});
+ }
return WireResult::Success;
}