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:
parent
91904cdfde
commit
9fa68833b2
|
@ -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",
|
||||||
|
|
|
@ -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",
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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_
|
Loading…
Reference in New Issue