Move client-side OnCompletion callbacks to the server.
We need callbacks to be processed server-side so that callback
ordering can be made consistent.
Bug: dawn:516
Change-Id: Ie5590ca33fce6bda431f93ae9ff8e832468109c1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27481
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_wire/client/ClientDoers.cpp b/src/dawn_wire/client/ClientDoers.cpp
index 7fdabc0..c13f715 100644
--- a/src/dawn_wire/client/ClientDoers.cpp
+++ b/src/dawn_wire/client/ClientDoers.cpp
@@ -70,4 +70,16 @@
return true;
}
+ bool Client::DoFenceOnCompletionCallback(Fence* fence,
+ uint64_t requestSerial,
+ WGPUFenceCompletionStatus status) {
+ // The fence might have been deleted or recreated so this isn't an error.
+ if (fence == nullptr) {
+ return true;
+ }
+
+ fence->OnCompletionCallback(requestSerial, status);
+ return true;
+ }
+
}} // namespace dawn_wire::client
diff --git a/src/dawn_wire/client/Fence.cpp b/src/dawn_wire/client/Fence.cpp
index d9e1fa7..329998f 100644
--- a/src/dawn_wire/client/Fence.cpp
+++ b/src/dawn_wire/client/Fence.cpp
@@ -14,6 +14,7 @@
#include "dawn_wire/client/Fence.h"
+#include "dawn_wire/client/Client.h"
#include "dawn_wire/client/Device.h"
namespace dawn_wire { namespace client {
@@ -21,67 +22,61 @@
Fence::~Fence() {
// Callbacks need to be fired in all cases, as they can handle freeing resources
// so we call them with "Unknown" status.
- for (auto& request : mRequests.IterateAll()) {
- request.completionCallback(WGPUFenceCompletionStatus_Unknown, request.userdata);
+ for (auto& it : mOnCompletionRequests) {
+ if (it.second.callback) {
+ it.second.callback(WGPUFenceCompletionStatus_Unknown, it.second.userdata);
+ }
}
- mRequests.Clear();
+ mOnCompletionRequests.clear();
}
void Fence::Initialize(Queue* queue, const WGPUFenceDescriptor* descriptor) {
mQueue = queue;
- uint64_t initialValue = descriptor != nullptr ? descriptor->initialValue : 0u;
- mSignaledValue = initialValue;
- mCompletedValue = initialValue;
- }
-
- void Fence::CheckPassedFences() {
- for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
- request.completionCallback(WGPUFenceCompletionStatus_Success, request.userdata);
- }
- mRequests.ClearUpTo(mCompletedValue);
+ mCompletedValue = descriptor != nullptr ? descriptor->initialValue : 0u;
}
void Fence::OnCompletion(uint64_t value,
WGPUFenceOnCompletionCallback callback,
void* userdata) {
- if (value > mSignaledValue) {
- device->InjectError(WGPUErrorType_Validation,
- "Value greater than fence signaled value");
- callback(WGPUFenceCompletionStatus_Error, userdata);
- return;
- }
+ uint32_t serial = mOnCompletionRequestSerial++;
+ ASSERT(mOnCompletionRequests.find(serial) == mOnCompletionRequests.end());
- if (value <= mCompletedValue) {
- callback(WGPUFenceCompletionStatus_Success, userdata);
- return;
- }
+ FenceOnCompletionCmd cmd;
+ cmd.fenceId = this->id;
+ cmd.value = value;
+ cmd.requestSerial = serial;
- Fence::OnCompletionData request;
- request.completionCallback = callback;
- request.userdata = userdata;
- mRequests.Enqueue(std::move(request), value);
+ mOnCompletionRequests[serial] = {callback, userdata};
+
+ this->device->GetClient()->SerializeCommand(cmd);
}
void Fence::OnUpdateCompletedValueCallback(uint64_t value) {
mCompletedValue = value;
- CheckPassedFences();
+ }
+
+ bool Fence::OnCompletionCallback(uint64_t requestSerial, WGPUFenceCompletionStatus status) {
+ auto requestIt = mOnCompletionRequests.find(requestSerial);
+ if (requestIt == mOnCompletionRequests.end()) {
+ return false;
+ }
+
+ // Remove the request data so that the callback cannot be called again.
+ // ex.) inside the callback: if the fence is deleted, all callbacks reject.
+ OnCompletionData request = std::move(requestIt->second);
+ mOnCompletionRequests.erase(requestIt);
+
+ request.callback(status, request.userdata);
+ return true;
}
uint64_t Fence::GetCompletedValue() const {
return mCompletedValue;
}
- uint64_t Fence::GetSignaledValue() const {
- return mSignaledValue;
- }
-
Queue* Fence::GetQueue() const {
return mQueue;
}
- void Fence::SetSignaledValue(uint64_t value) {
- mSignaledValue = value;
- }
-
}} // namespace dawn_wire::client
diff --git a/src/dawn_wire/client/Fence.h b/src/dawn_wire/client/Fence.h
index 107b4e7..58d89c3 100644
--- a/src/dawn_wire/client/Fence.h
+++ b/src/dawn_wire/client/Fence.h
@@ -33,22 +33,20 @@
void CheckPassedFences();
void OnCompletion(uint64_t value, WGPUFenceOnCompletionCallback callback, void* userdata);
void OnUpdateCompletedValueCallback(uint64_t value);
+ bool OnCompletionCallback(uint64_t requestSerial, WGPUFenceCompletionStatus status);
uint64_t GetCompletedValue() const;
- uint64_t GetSignaledValue() const;
Queue* GetQueue() const;
- void SetSignaledValue(uint64_t value);
-
private:
struct OnCompletionData {
- WGPUFenceOnCompletionCallback completionCallback = nullptr;
+ WGPUFenceOnCompletionCallback callback = nullptr;
void* userdata = nullptr;
};
Queue* mQueue = nullptr;
- uint64_t mSignaledValue = 0;
uint64_t mCompletedValue = 0;
- SerialMap<OnCompletionData> mRequests;
+ uint64_t mOnCompletionRequestSerial = 0;
+ std::map<uint64_t, OnCompletionData> mOnCompletionRequests;
};
}} // namespace dawn_wire::client
diff --git a/src/dawn_wire/client/Queue.cpp b/src/dawn_wire/client/Queue.cpp
index ad11673..52de14c 100644
--- a/src/dawn_wire/client/Queue.cpp
+++ b/src/dawn_wire/client/Queue.cpp
@@ -33,29 +33,6 @@
return ToAPI(fence);
}
- void Queue::Signal(WGPUFence cFence, uint64_t signalValue) {
- Fence* fence = FromAPI(cFence);
- if (fence->GetQueue() != this) {
- device->InjectError(WGPUErrorType_Validation,
- "Fence must be signaled on the queue on which it was created.");
- return;
- }
- if (signalValue <= fence->GetSignaledValue()) {
- device->InjectError(WGPUErrorType_Validation,
- "Fence value less than or equal to signaled value");
- return;
- }
-
- fence->SetSignaledValue(signalValue);
-
- QueueSignalCmd cmd;
- cmd.self = ToAPI(this);
- cmd.fence = cFence;
- cmd.signalValue = signalValue;
-
- device->GetClient()->SerializeCommand(cmd);
- }
-
void Queue::WriteBuffer(WGPUBuffer cBuffer,
uint64_t bufferOffset,
const void* data,
diff --git a/src/dawn_wire/client/Queue.h b/src/dawn_wire/client/Queue.h
index 866bccd..9e50348 100644
--- a/src/dawn_wire/client/Queue.h
+++ b/src/dawn_wire/client/Queue.h
@@ -29,7 +29,6 @@
using ObjectBase::ObjectBase;
WGPUFence CreateFence(const WGPUFenceDescriptor* descriptor);
- void Signal(WGPUFence fence, uint64_t signalValue);
void WriteBuffer(WGPUBuffer cBuffer, uint64_t bufferOffset, const void* data, size_t size);
void WriteTexture(const WGPUTextureCopyView* destination,
const void* data,
diff --git a/src/dawn_wire/server/Server.h b/src/dawn_wire/server/Server.h
index 8049e80..2859714 100644
--- a/src/dawn_wire/server/Server.h
+++ b/src/dawn_wire/server/Server.h
@@ -48,6 +48,12 @@
uint64_t value;
};
+ struct FenceOnCompletionUserdata {
+ Server* server;
+ ObjectHandle fence;
+ uint64_t requestSerial;
+ };
+
class Server : public ServerBase {
public:
Server(WGPUDevice device,
@@ -77,6 +83,7 @@
static void ForwardPopErrorScope(WGPUErrorType type, const char* message, void* userdata);
static void ForwardBufferMapAsync(WGPUBufferMapAsyncStatus status, void* userdata);
static void ForwardFenceCompletedValue(WGPUFenceCompletionStatus status, void* userdata);
+ static void ForwardFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata);
// Error callbacks
void OnUncapturedError(WGPUErrorType type, const char* message);
@@ -87,6 +94,8 @@
void OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus status, MapUserdata* userdata);
void OnFenceCompletedValueUpdated(WGPUFenceCompletionStatus status,
FenceCompletionUserdata* userdata);
+ void OnFenceOnCompletion(WGPUFenceCompletionStatus status,
+ FenceOnCompletionUserdata* userdata);
#include "dawn_wire/server/ServerPrototypes_autogen.inc"
diff --git a/src/dawn_wire/server/ServerFence.cpp b/src/dawn_wire/server/ServerFence.cpp
index 1a4105c..cea561e 100644
--- a/src/dawn_wire/server/ServerFence.cpp
+++ b/src/dawn_wire/server/ServerFence.cpp
@@ -38,4 +38,42 @@
SerializeCommand(cmd);
}
+ bool Server::DoFenceOnCompletion(ObjectId fenceId, uint64_t value, uint64_t requestSerial) {
+ // The null object isn't valid as `self`
+ if (fenceId == 0) {
+ return false;
+ }
+
+ auto* fence = FenceObjects().Get(fenceId);
+ if (fence == nullptr) {
+ return false;
+ }
+
+ FenceOnCompletionUserdata* userdata = new FenceOnCompletionUserdata;
+ userdata->server = this;
+ userdata->fence = ObjectHandle{fenceId, fence->generation};
+ userdata->requestSerial = requestSerial;
+
+ mProcs.fenceOnCompletion(fence->handle, value, ForwardFenceOnCompletion, userdata);
+ return true;
+ }
+
+ // static
+ void Server::ForwardFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
+ auto* data = reinterpret_cast<FenceOnCompletionUserdata*>(userdata);
+ data->server->OnFenceOnCompletion(status, data);
+ }
+
+ void Server::OnFenceOnCompletion(WGPUFenceCompletionStatus status,
+ FenceOnCompletionUserdata* userdata) {
+ std::unique_ptr<FenceOnCompletionUserdata> data{userdata};
+
+ ReturnFenceOnCompletionCallbackCmd cmd;
+ cmd.fence = data->fence;
+ cmd.requestSerial = data->requestSerial;
+ cmd.status = status;
+
+ SerializeCommand(cmd);
+ }
+
}} // namespace dawn_wire::server
diff --git a/src/dawn_wire/server/ServerQueue.cpp b/src/dawn_wire/server/ServerQueue.cpp
index 0c5a6b8..b6d2903 100644
--- a/src/dawn_wire/server/ServerQueue.cpp
+++ b/src/dawn_wire/server/ServerQueue.cpp
@@ -21,7 +21,6 @@
if (cFence == nullptr) {
return false;
}
-
mProcs.queueSignal(cSelf, cFence, signalValue);
ObjectId fenceId = FenceObjectIdTable().Get(cFence);