dawn_wire/client: Encapsulate all queue/fence-related logic

This CL only moves code, renames client::Fence members, and introduces
client::Queue. Additional fence methods are added for the interaction
with the queue. There are no functional changes.

With this ApiProcs.cpp is almost passthrough and will be removed in a
follow-up CL.

Bug: dawn:445
Change-Id: I65544ef76b54614452cf7c74a948a96cb35a4cfe
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24061
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2020-06-30 17:53:08 +00:00 committed by Commit Bot service account
parent 91904cdfde
commit 9fa68833b2
11 changed files with 208 additions and 90 deletions

View File

@ -119,7 +119,8 @@
"client_special_objects": [ "client_special_objects": [
"Buffer", "Buffer",
"Device", "Device",
"Fence" "Fence",
"Queue"
], ],
"server_custom_pre_handler_commands": [ "server_custom_pre_handler_commands": [
"BufferDestroy", "BufferDestroy",

View File

@ -20,9 +20,7 @@ import("${dawn_root}/scripts/dawn_component.gni")
# Public dawn_wire headers so they can be publically visible for # Public dawn_wire headers so they can be publically visible for
# dependencies of dawn_wire # dependencies of dawn_wire
source_set("dawn_wire_headers") { source_set("dawn_wire_headers") {
public_deps = [ public_deps = [ "${dawn_root}/src/dawn:dawn_headers" ]
"${dawn_root}/src/dawn:dawn_headers",
]
all_dependent_configs = [ "${dawn_root}/src/common:dawn_public_include_dirs" ] all_dependent_configs = [ "${dawn_root}/src/common:dawn_public_include_dirs" ]
sources = [ sources = [
"${dawn_root}/src/include/dawn_wire/Wire.h", "${dawn_root}/src/include/dawn_wire/Wire.h",
@ -78,6 +76,8 @@ dawn_component("dawn_wire") {
"client/Fence.cpp", "client/Fence.cpp",
"client/Fence.h", "client/Fence.h",
"client/ObjectAllocator.h", "client/ObjectAllocator.h",
"client/Queue.cpp",
"client/Queue.h",
"server/ObjectStorage.h", "server/ObjectStorage.h",
"server/Server.cpp", "server/Server.cpp",
"server/Server.h", "server/Server.h",
@ -89,7 +89,5 @@ dawn_component("dawn_wire") {
] ]
# Make headers publicly visible # Make headers publicly visible
public_deps = [ public_deps = [ ":dawn_wire_headers" ]
":dawn_wire_headers",
]
} }

View File

@ -42,6 +42,8 @@ target_sources(dawn_wire PRIVATE
"client/Fence.cpp" "client/Fence.cpp"
"client/Fence.h" "client/Fence.h"
"client/ObjectAllocator.h" "client/ObjectAllocator.h"
"client/Queue.cpp"
"client/Queue.h"
"server/ObjectStorage.h" "server/ObjectStorage.h"
"server/Server.cpp" "server/Server.cpp"
"server/Server.h" "server/Server.h"

View File

@ -20,6 +20,7 @@
#include "dawn_wire/client/Buffer.h" #include "dawn_wire/client/Buffer.h"
#include "dawn_wire/client/Device.h" #include "dawn_wire/client/Device.h"
#include "dawn_wire/client/Fence.h" #include "dawn_wire/client/Fence.h"
#include "dawn_wire/client/Queue.h"
#include "dawn_wire/client/ApiObjects_autogen.h" #include "dawn_wire/client/ApiObjects_autogen.h"

View File

@ -86,8 +86,8 @@ namespace dawn_wire { namespace client {
} }
uint64_t ClientHandwrittenFenceGetCompletedValue(WGPUFence cSelf) { uint64_t ClientHandwrittenFenceGetCompletedValue(WGPUFence cSelf) {
auto fence = reinterpret_cast<Fence*>(cSelf); Fence* fence = reinterpret_cast<Fence*>(cSelf);
return fence->completedValue; return fence->GetCompletedValue();
} }
void ClientHandwrittenFenceOnCompletion(WGPUFence cFence, void ClientHandwrittenFenceOnCompletion(WGPUFence cFence,
@ -95,72 +95,18 @@ namespace dawn_wire { namespace client {
WGPUFenceOnCompletionCallback callback, WGPUFenceOnCompletionCallback callback,
void* userdata) { void* userdata) {
Fence* fence = reinterpret_cast<Fence*>(cFence); Fence* fence = reinterpret_cast<Fence*>(cFence);
if (value > fence->signaledValue) { fence->OnCompletion(value, callback, userdata);
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(fence->device),
WGPUErrorType_Validation,
"Value greater than fence signaled value");
callback(WGPUFenceCompletionStatus_Error, userdata);
return;
}
if (value <= fence->completedValue) {
callback(WGPUFenceCompletionStatus_Success, userdata);
return;
}
Fence::OnCompletionData request;
request.completionCallback = callback;
request.userdata = userdata;
fence->requests.Enqueue(std::move(request), value);
} }
WGPUFence ClientHandwrittenQueueCreateFence(WGPUQueue cSelf, WGPUFence ClientHandwrittenQueueCreateFence(WGPUQueue cSelf,
WGPUFenceDescriptor const* descriptor) { WGPUFenceDescriptor const* descriptor) {
Queue* queue = reinterpret_cast<Queue*>(cSelf); Queue* queue = reinterpret_cast<Queue*>(cSelf);
Device* device = queue->device; return queue->CreateFence(descriptor);
QueueCreateFenceCmd cmd;
cmd.self = cSelf;
auto* allocation = device->GetClient()->FenceAllocator().New(device);
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
cmd.descriptor = descriptor;
device->GetClient()->SerializeCommand(cmd);
WGPUFence cFence = reinterpret_cast<WGPUFence>(allocation->object.get());
Fence* fence = reinterpret_cast<Fence*>(cFence);
fence->queue = queue;
uint64_t initialValue = descriptor != nullptr ? descriptor->initialValue : 0u;
fence->signaledValue = initialValue;
fence->completedValue = initialValue;
return cFence;
} }
void ClientHandwrittenQueueSignal(WGPUQueue cQueue, WGPUFence cFence, uint64_t signalValue) { void ClientHandwrittenQueueSignal(WGPUQueue cQueue, WGPUFence cFence, uint64_t signalValue) {
Fence* fence = reinterpret_cast<Fence*>(cFence);
Queue* queue = reinterpret_cast<Queue*>(cQueue); Queue* queue = reinterpret_cast<Queue*>(cQueue);
if (fence->queue != queue) { queue->Signal(cFence, signalValue);
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(fence->device),
WGPUErrorType_Validation,
"Fence must be signaled on the queue on which it was created.");
return;
}
if (signalValue <= fence->signaledValue) {
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(fence->device),
WGPUErrorType_Validation,
"Fence value less than or equal to signaled value");
return;
}
fence->signaledValue = signalValue;
QueueSignalCmd cmd;
cmd.self = cQueue;
cmd.fence = cFence;
cmd.signalValue = signalValue;
queue->device->GetClient()->SerializeCommand(cmd);
} }
void ClientHandwrittenQueueWriteBuffer(WGPUQueue cQueue, void ClientHandwrittenQueueWriteBuffer(WGPUQueue cQueue,
@ -169,16 +115,7 @@ namespace dawn_wire { namespace client {
const void* data, const void* data,
size_t size) { size_t size) {
Queue* queue = reinterpret_cast<Queue*>(cQueue); Queue* queue = reinterpret_cast<Queue*>(cQueue);
Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer); queue->WriteBuffer(cBuffer, bufferOffset, data, size);
QueueWriteBufferInternalCmd cmd;
cmd.queueId = queue->id;
cmd.bufferId = buffer->id;
cmd.bufferOffset = bufferOffset;
cmd.data = static_cast<const uint8_t*>(data);
cmd.size = size;
queue->device->GetClient()->SerializeCommand(cmd);
} }
void ClientDeviceReference(WGPUDevice) { void ClientDeviceReference(WGPUDevice) {

View File

@ -77,8 +77,7 @@ namespace dawn_wire { namespace client {
return true; return true;
} }
fence->completedValue = value; fence->OnUpdateCompletedValueCallback(value);
fence->CheckPassedFences();
return true; return true;
} }

View File

@ -24,7 +24,7 @@
namespace dawn_wire { namespace client { namespace dawn_wire { namespace client {
class Client; class Client;
struct Queue; class Queue;
class Device : public ObjectBase { class Device : public ObjectBase {
public: public:

View File

@ -14,22 +14,74 @@
#include "dawn_wire/client/Fence.h" #include "dawn_wire/client/Fence.h"
#include "dawn_wire/client/ApiProcs_autogen.h"
namespace dawn_wire { namespace client { namespace dawn_wire { namespace client {
Fence::~Fence() { Fence::~Fence() {
// Callbacks need to be fired in all cases, as they can handle freeing resources // Callbacks need to be fired in all cases, as they can handle freeing resources
// so we call them with "Unknown" status. // so we call them with "Unknown" status.
for (auto& request : requests.IterateAll()) { for (auto& request : mRequests.IterateAll()) {
request.completionCallback(WGPUFenceCompletionStatus_Unknown, request.userdata); request.completionCallback(WGPUFenceCompletionStatus_Unknown, request.userdata);
} }
requests.Clear(); mRequests.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() { void Fence::CheckPassedFences() {
for (auto& request : requests.IterateUpTo(completedValue)) { for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
request.completionCallback(WGPUFenceCompletionStatus_Success, request.userdata); request.completionCallback(WGPUFenceCompletionStatus_Success, request.userdata);
} }
requests.ClearUpTo(completedValue); mRequests.ClearUpTo(mCompletedValue);
}
void Fence::OnCompletion(uint64_t value,
WGPUFenceOnCompletionCallback callback,
void* userdata) {
if (value > mSignaledValue) {
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(device), WGPUErrorType_Validation,
"Value greater than fence signaled value");
callback(WGPUFenceCompletionStatus_Error, userdata);
return;
}
if (value <= mCompletedValue) {
callback(WGPUFenceCompletionStatus_Success, userdata);
return;
}
Fence::OnCompletionData request;
request.completionCallback = callback;
request.userdata = userdata;
mRequests.Enqueue(std::move(request), value);
}
void Fence::OnUpdateCompletedValueCallback(uint64_t value) {
mCompletedValue = value;
CheckPassedFences();
}
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 }} // namespace dawn_wire::client

View File

@ -22,21 +22,33 @@
namespace dawn_wire { namespace client { namespace dawn_wire { namespace client {
struct Queue; class Queue;
struct Fence : ObjectBase { class Fence : public ObjectBase {
public:
using ObjectBase::ObjectBase; using ObjectBase::ObjectBase;
~Fence(); ~Fence();
void CheckPassedFences(); void Initialize(Queue* queue, const WGPUFenceDescriptor* descriptor);
void CheckPassedFences();
void OnCompletion(uint64_t value, WGPUFenceOnCompletionCallback callback, void* userdata);
void OnUpdateCompletedValueCallback(uint64_t value);
uint64_t GetCompletedValue() const;
uint64_t GetSignaledValue() const;
Queue* GetQueue() const;
void SetSignaledValue(uint64_t value);
private:
struct OnCompletionData { struct OnCompletionData {
WGPUFenceOnCompletionCallback completionCallback = nullptr; WGPUFenceOnCompletionCallback completionCallback = nullptr;
void* userdata = nullptr; void* userdata = nullptr;
}; };
Queue* queue = nullptr; Queue* mQueue = nullptr;
uint64_t signaledValue = 0; uint64_t mSignaledValue = 0;
uint64_t completedValue = 0; uint64_t mCompletedValue = 0;
SerialMap<OnCompletionData> requests; SerialMap<OnCompletionData> mRequests;
}; };
}} // namespace dawn_wire::client }} // namespace dawn_wire::client

View File

@ -0,0 +1,78 @@
// Copyright 2020 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn_wire/client/Queue.h"
#include "dawn_wire/client/ApiProcs_autogen.h"
#include "dawn_wire/client/Client.h"
#include "dawn_wire/client/Device.h"
namespace dawn_wire { namespace client {
WGPUFence Queue::CreateFence(WGPUFenceDescriptor const* descriptor) {
auto* allocation = device->GetClient()->FenceAllocator().New(device);
QueueCreateFenceCmd cmd;
cmd.self = reinterpret_cast<WGPUQueue>(this);
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
cmd.descriptor = descriptor;
device->GetClient()->SerializeCommand(cmd);
Fence* fence = allocation->object.get();
fence->Initialize(this, descriptor);
return reinterpret_cast<WGPUFence>(fence);
}
void Queue::Signal(WGPUFence cFence, uint64_t signalValue) {
Fence* fence = reinterpret_cast<Fence*>(cFence);
if (fence->GetQueue() != this) {
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(fence->device),
WGPUErrorType_Validation,
"Fence must be signaled on the queue on which it was created.");
return;
}
if (signalValue <= fence->GetSignaledValue()) {
ClientDeviceInjectError(reinterpret_cast<WGPUDevice>(fence->device),
WGPUErrorType_Validation,
"Fence value less than or equal to signaled value");
return;
}
fence->SetSignaledValue(signalValue);
QueueSignalCmd cmd;
cmd.self = reinterpret_cast<WGPUQueue>(this);
cmd.fence = cFence;
cmd.signalValue = signalValue;
device->GetClient()->SerializeCommand(cmd);
}
void Queue::WriteBuffer(WGPUBuffer cBuffer,
uint64_t bufferOffset,
const void* data,
size_t size) {
Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer);
QueueWriteBufferInternalCmd cmd;
cmd.queueId = id;
cmd.bufferId = buffer->id;
cmd.bufferOffset = bufferOffset;
cmd.data = static_cast<const uint8_t*>(data);
cmd.size = size;
device->GetClient()->SerializeCommand(cmd);
}
}} // namespace dawn_wire::client

View File

@ -0,0 +1,38 @@
// Copyright 2020 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNWIRE_CLIENT_QUEUE_H_
#define DAWNWIRE_CLIENT_QUEUE_H_
#include <dawn/webgpu.h>
#include "dawn_wire/WireClient.h"
#include "dawn_wire/client/ObjectBase.h"
#include <map>
namespace dawn_wire { namespace client {
class Queue : public ObjectBase {
public:
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);
};
}} // namespace dawn_wire::client
#endif // DAWNWIRE_CLIENT_QUEUE_H_