diff --git a/dawn_wire.json b/dawn_wire.json index f3c1c8c408..54d8c94b61 100644 --- a/dawn_wire.json +++ b/dawn_wire.json @@ -119,7 +119,8 @@ "client_special_objects": [ "Buffer", "Device", - "Fence" + "Fence", + "Queue" ], "server_custom_pre_handler_commands": [ "BufferDestroy", diff --git a/src/dawn_wire/BUILD.gn b/src/dawn_wire/BUILD.gn index 5d1b2d7f2d..aa8b0c0ec2 100644 --- a/src/dawn_wire/BUILD.gn +++ b/src/dawn_wire/BUILD.gn @@ -20,9 +20,7 @@ import("${dawn_root}/scripts/dawn_component.gni") # Public dawn_wire headers so they can be publically visible for # dependencies of dawn_wire source_set("dawn_wire_headers") { - public_deps = [ - "${dawn_root}/src/dawn:dawn_headers", - ] + public_deps = [ "${dawn_root}/src/dawn:dawn_headers" ] all_dependent_configs = [ "${dawn_root}/src/common:dawn_public_include_dirs" ] sources = [ "${dawn_root}/src/include/dawn_wire/Wire.h", @@ -78,6 +76,8 @@ dawn_component("dawn_wire") { "client/Fence.cpp", "client/Fence.h", "client/ObjectAllocator.h", + "client/Queue.cpp", + "client/Queue.h", "server/ObjectStorage.h", "server/Server.cpp", "server/Server.h", @@ -89,7 +89,5 @@ dawn_component("dawn_wire") { ] # Make headers publicly visible - public_deps = [ - ":dawn_wire_headers", - ] + public_deps = [ ":dawn_wire_headers" ] } diff --git a/src/dawn_wire/CMakeLists.txt b/src/dawn_wire/CMakeLists.txt index 8ec7bff9ab..579d46acf1 100644 --- a/src/dawn_wire/CMakeLists.txt +++ b/src/dawn_wire/CMakeLists.txt @@ -42,6 +42,8 @@ target_sources(dawn_wire PRIVATE "client/Fence.cpp" "client/Fence.h" "client/ObjectAllocator.h" + "client/Queue.cpp" + "client/Queue.h" "server/ObjectStorage.h" "server/Server.cpp" "server/Server.h" diff --git a/src/dawn_wire/client/ApiObjects.h b/src/dawn_wire/client/ApiObjects.h index b74eefe615..f842d53f46 100644 --- a/src/dawn_wire/client/ApiObjects.h +++ b/src/dawn_wire/client/ApiObjects.h @@ -20,6 +20,7 @@ #include "dawn_wire/client/Buffer.h" #include "dawn_wire/client/Device.h" #include "dawn_wire/client/Fence.h" +#include "dawn_wire/client/Queue.h" #include "dawn_wire/client/ApiObjects_autogen.h" diff --git a/src/dawn_wire/client/ApiProcs.cpp b/src/dawn_wire/client/ApiProcs.cpp index 047528479c..db4365b384 100644 --- a/src/dawn_wire/client/ApiProcs.cpp +++ b/src/dawn_wire/client/ApiProcs.cpp @@ -86,8 +86,8 @@ namespace dawn_wire { namespace client { } uint64_t ClientHandwrittenFenceGetCompletedValue(WGPUFence cSelf) { - auto fence = reinterpret_cast(cSelf); - return fence->completedValue; + Fence* fence = reinterpret_cast(cSelf); + return fence->GetCompletedValue(); } void ClientHandwrittenFenceOnCompletion(WGPUFence cFence, @@ -95,72 +95,18 @@ namespace dawn_wire { namespace client { WGPUFenceOnCompletionCallback callback, void* userdata) { Fence* fence = reinterpret_cast(cFence); - if (value > fence->signaledValue) { - ClientDeviceInjectError(reinterpret_cast(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); + fence->OnCompletion(value, callback, userdata); } WGPUFence ClientHandwrittenQueueCreateFence(WGPUQueue cSelf, WGPUFenceDescriptor const* descriptor) { Queue* queue = reinterpret_cast(cSelf); - Device* device = queue->device; - - 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(allocation->object.get()); - - Fence* fence = reinterpret_cast(cFence); - fence->queue = queue; - - uint64_t initialValue = descriptor != nullptr ? descriptor->initialValue : 0u; - fence->signaledValue = initialValue; - fence->completedValue = initialValue; - return cFence; + return queue->CreateFence(descriptor); } void ClientHandwrittenQueueSignal(WGPUQueue cQueue, WGPUFence cFence, uint64_t signalValue) { - Fence* fence = reinterpret_cast(cFence); Queue* queue = reinterpret_cast(cQueue); - if (fence->queue != queue) { - ClientDeviceInjectError(reinterpret_cast(fence->device), - WGPUErrorType_Validation, - "Fence must be signaled on the queue on which it was created."); - return; - } - if (signalValue <= fence->signaledValue) { - ClientDeviceInjectError(reinterpret_cast(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); + queue->Signal(cFence, signalValue); } void ClientHandwrittenQueueWriteBuffer(WGPUQueue cQueue, @@ -169,16 +115,7 @@ namespace dawn_wire { namespace client { const void* data, size_t size) { Queue* queue = reinterpret_cast(cQueue); - Buffer* buffer = reinterpret_cast(cBuffer); - - QueueWriteBufferInternalCmd cmd; - cmd.queueId = queue->id; - cmd.bufferId = buffer->id; - cmd.bufferOffset = bufferOffset; - cmd.data = static_cast(data); - cmd.size = size; - - queue->device->GetClient()->SerializeCommand(cmd); + queue->WriteBuffer(cBuffer, bufferOffset, data, size); } void ClientDeviceReference(WGPUDevice) { diff --git a/src/dawn_wire/client/ClientDoers.cpp b/src/dawn_wire/client/ClientDoers.cpp index ffc5198e18..55818ba7be 100644 --- a/src/dawn_wire/client/ClientDoers.cpp +++ b/src/dawn_wire/client/ClientDoers.cpp @@ -77,8 +77,7 @@ namespace dawn_wire { namespace client { return true; } - fence->completedValue = value; - fence->CheckPassedFences(); + fence->OnUpdateCompletedValueCallback(value); return true; } diff --git a/src/dawn_wire/client/Device.h b/src/dawn_wire/client/Device.h index f32259a76f..42dff18267 100644 --- a/src/dawn_wire/client/Device.h +++ b/src/dawn_wire/client/Device.h @@ -24,7 +24,7 @@ namespace dawn_wire { namespace client { class Client; - struct Queue; + class Queue; class Device : public ObjectBase { public: diff --git a/src/dawn_wire/client/Fence.cpp b/src/dawn_wire/client/Fence.cpp index 607483e520..aa0407cc77 100644 --- a/src/dawn_wire/client/Fence.cpp +++ b/src/dawn_wire/client/Fence.cpp @@ -14,22 +14,74 @@ #include "dawn_wire/client/Fence.h" +#include "dawn_wire/client/ApiProcs_autogen.h" + namespace dawn_wire { namespace client { 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 : requests.IterateAll()) { + for (auto& request : mRequests.IterateAll()) { 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() { - for (auto& request : requests.IterateUpTo(completedValue)) { + for (auto& request : mRequests.IterateUpTo(mCompletedValue)) { 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(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 diff --git a/src/dawn_wire/client/Fence.h b/src/dawn_wire/client/Fence.h index 4acde6d683..107b4e7f44 100644 --- a/src/dawn_wire/client/Fence.h +++ b/src/dawn_wire/client/Fence.h @@ -22,21 +22,33 @@ namespace dawn_wire { namespace client { - struct Queue; - struct Fence : ObjectBase { + class Queue; + class Fence : public ObjectBase { + public: using ObjectBase::ObjectBase; ~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 { WGPUFenceOnCompletionCallback completionCallback = nullptr; void* userdata = nullptr; }; - Queue* queue = nullptr; - uint64_t signaledValue = 0; - uint64_t completedValue = 0; - SerialMap requests; + Queue* mQueue = nullptr; + uint64_t mSignaledValue = 0; + uint64_t mCompletedValue = 0; + SerialMap mRequests; }; }} // namespace dawn_wire::client diff --git a/src/dawn_wire/client/Queue.cpp b/src/dawn_wire/client/Queue.cpp new file mode 100644 index 0000000000..fa338f326c --- /dev/null +++ b/src/dawn_wire/client/Queue.cpp @@ -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(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(fence); + } + + void Queue::Signal(WGPUFence cFence, uint64_t signalValue) { + Fence* fence = reinterpret_cast(cFence); + if (fence->GetQueue() != this) { + ClientDeviceInjectError(reinterpret_cast(fence->device), + WGPUErrorType_Validation, + "Fence must be signaled on the queue on which it was created."); + return; + } + if (signalValue <= fence->GetSignaledValue()) { + ClientDeviceInjectError(reinterpret_cast(fence->device), + WGPUErrorType_Validation, + "Fence value less than or equal to signaled value"); + return; + } + + fence->SetSignaledValue(signalValue); + + QueueSignalCmd cmd; + cmd.self = reinterpret_cast(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(cBuffer); + + QueueWriteBufferInternalCmd cmd; + cmd.queueId = id; + cmd.bufferId = buffer->id; + cmd.bufferOffset = bufferOffset; + cmd.data = static_cast(data); + cmd.size = size; + + device->GetClient()->SerializeCommand(cmd); + } + +}} // namespace dawn_wire::client diff --git a/src/dawn_wire/client/Queue.h b/src/dawn_wire/client/Queue.h new file mode 100644 index 0000000000..9e51618742 --- /dev/null +++ b/src/dawn_wire/client/Queue.h @@ -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 + +#include "dawn_wire/WireClient.h" +#include "dawn_wire/client/ObjectBase.h" + +#include + +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_