dawn::wire::client: Merge object allocators, add variadic Make.
This commit changes all the [Object]Allocators from the Client into a PerType<ObjectStore> member that contains a bunch of ObjectStore acting on ObjectBase. Adds a new (template) member functions to the client, Make/Get/Free that act on any object type, and update all the uses of previous [Object]Allocator to use these new methods. Also removes generated code that was generated per object type in favor of using the type-generic ObjectAllocator. Bug: dawn:1451 Change-Id: I6463b2fc4a827e3000c2a666abf08aa1a71c3b3b Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/93141 Reviewed-by: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
e57c296035
commit
0ebe86d1ca
|
@ -58,7 +58,7 @@ namespace dawn::wire::client {
|
||||||
|
|
||||||
//* For object creation, store the object ID the client will use for the result.
|
//* For object creation, store the object ID the client will use for the result.
|
||||||
{% if method.return_type.category == "object" %}
|
{% if method.return_type.category == "object" %}
|
||||||
auto* returnObject = self->GetClient()->{{method.return_type.name.CamelCase()}}Allocator().New(self->GetClient());
|
auto* returnObject = self->GetClient()->Make<{{method.return_type.name.CamelCase()}}>();
|
||||||
cmd.result = returnObject->GetWireHandle();
|
cmd.result = returnObject->GetWireHandle();
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ namespace dawn::wire::client {
|
||||||
|
|
||||||
Client* client = obj->GetClient();
|
Client* client = obj->GetClient();
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
client->{{type.name.CamelCase()}}Allocator().Free(obj);
|
client->Free(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client{{as_MethodSuffix(type.name, Name("reference"))}}({{cType}} cObj) {
|
void Client{{as_MethodSuffix(type.name, Name("reference"))}}({{cType}} cObj) {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "dawn/wire/ChunkedCommandHandler.h"
|
#include "dawn/wire/ChunkedCommandHandler.h"
|
||||||
#include "dawn/wire/WireCmd_autogen.h"
|
#include "dawn/wire/WireCmd_autogen.h"
|
||||||
#include "dawn/wire/client/ApiObjects.h"
|
#include "dawn/wire/client/ApiObjects.h"
|
||||||
#include "dawn/wire/client/ObjectAllocator.h"
|
|
||||||
|
|
||||||
namespace dawn::wire::client {
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
|
@ -27,25 +26,6 @@ namespace dawn::wire::client {
|
||||||
ClientBase() = default;
|
ClientBase() = default;
|
||||||
~ClientBase() override = default;
|
~ClientBase() override = default;
|
||||||
|
|
||||||
{% for type in by_category["object"] %}
|
|
||||||
const ObjectAllocator<{{type.name.CamelCase()}}>& {{type.name.CamelCase()}}Allocator() const {
|
|
||||||
return m{{type.name.CamelCase()}}Allocator;
|
|
||||||
}
|
|
||||||
ObjectAllocator<{{type.name.CamelCase()}}>& {{type.name.CamelCase()}}Allocator() {
|
|
||||||
return m{{type.name.CamelCase()}}Allocator;
|
|
||||||
}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
void FreeObject(ObjectType objectType, ObjectBase* obj) {
|
|
||||||
switch (objectType) {
|
|
||||||
{% for type in by_category["object"] %}
|
|
||||||
case ObjectType::{{type.name.CamelCase()}}:
|
|
||||||
m{{type.name.CamelCase()}}Allocator.Free(static_cast<{{type.name.CamelCase()}}*>(obj));
|
|
||||||
break;
|
|
||||||
{% endfor %}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Implementation of the ObjectIdProvider interface
|
// Implementation of the ObjectIdProvider interface
|
||||||
{% for type in by_category["object"] %}
|
{% for type in by_category["object"] %}
|
||||||
|
@ -63,10 +43,6 @@ namespace dawn::wire::client {
|
||||||
return WireResult::Success;
|
return WireResult::Success;
|
||||||
}
|
}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% for type in by_category["object"] %}
|
|
||||||
ObjectAllocator<{{type.name.CamelCase()}}> m{{type.name.CamelCase()}}Allocator;
|
|
||||||
{% endfor %}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::wire::client
|
} // namespace dawn::wire::client
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace dawn::wire::client {
|
||||||
{% for command in cmd_records["return command"] %}
|
{% for command in cmd_records["return command"] %}
|
||||||
bool Client::Handle{{command.name.CamelCase()}}(DeserializeBuffer* deserializeBuffer) {
|
bool Client::Handle{{command.name.CamelCase()}}(DeserializeBuffer* deserializeBuffer) {
|
||||||
Return{{command.name.CamelCase()}}Cmd cmd;
|
Return{{command.name.CamelCase()}}Cmd cmd;
|
||||||
WireResult deserializeResult = cmd.Deserialize(deserializeBuffer, &mAllocator);
|
WireResult deserializeResult = cmd.Deserialize(deserializeBuffer, &mWireCommandAllocator);
|
||||||
|
|
||||||
if (deserializeResult == WireResult::FatalError) {
|
if (deserializeResult == WireResult::FatalError) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -32,7 +32,7 @@ namespace dawn::wire::client {
|
||||||
{% set name = as_varName(member.name) %}
|
{% set name = as_varName(member.name) %}
|
||||||
|
|
||||||
{% if member.type.dict_name == "ObjectHandle" %}
|
{% if member.type.dict_name == "ObjectHandle" %}
|
||||||
{{Type}}* {{name}} = {{Type}}Allocator().GetObject(cmd.{{name}}.id);
|
{{Type}}* {{name}} = Get<{{Type}}>(cmd.{{name}}.id);
|
||||||
if ({{name}} != nullptr && {{name}}->GetWireGeneration() != cmd.{{name}}.generation) {
|
if ({{name}} != nullptr && {{name}}->GetWireGeneration() != cmd.{{name}}.generation) {
|
||||||
{{name}} = nullptr;
|
{{name}} = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ namespace dawn::wire::client {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
mAllocator.Reset();
|
mWireCommandAllocator.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deserializeBuffer.AvailableSize() != 0) {
|
if (deserializeBuffer.AvailableSize() != 0) {
|
||||||
|
|
|
@ -90,9 +90,10 @@ dawn_component("wire") {
|
||||||
"client/Instance.h",
|
"client/Instance.h",
|
||||||
"client/LimitsAndFeatures.cpp",
|
"client/LimitsAndFeatures.cpp",
|
||||||
"client/LimitsAndFeatures.h",
|
"client/LimitsAndFeatures.h",
|
||||||
"client/ObjectAllocator.h",
|
|
||||||
"client/ObjectBase.cpp",
|
"client/ObjectBase.cpp",
|
||||||
"client/ObjectBase.h",
|
"client/ObjectBase.h",
|
||||||
|
"client/ObjectStore.cpp",
|
||||||
|
"client/ObjectStore.h",
|
||||||
"client/QuerySet.cpp",
|
"client/QuerySet.cpp",
|
||||||
"client/QuerySet.h",
|
"client/QuerySet.h",
|
||||||
"client/Queue.cpp",
|
"client/Queue.cpp",
|
||||||
|
|
|
@ -63,7 +63,8 @@ target_sources(dawn_wire PRIVATE
|
||||||
"client/Instance.h"
|
"client/Instance.h"
|
||||||
"client/LimitsAndFeatures.cpp"
|
"client/LimitsAndFeatures.cpp"
|
||||||
"client/LimitsAndFeatures.h"
|
"client/LimitsAndFeatures.h"
|
||||||
"client/ObjectAllocator.h"
|
"client/ObjectStore.cpp"
|
||||||
|
"client/ObjectStore.h"
|
||||||
"client/ObjectBase.cpp"
|
"client/ObjectBase.cpp"
|
||||||
"client/ObjectBase.h"
|
"client/ObjectBase.h"
|
||||||
"client/QuerySet.cpp"
|
"client/QuerySet.cpp"
|
||||||
|
|
|
@ -71,7 +71,7 @@ void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device* device = client->DeviceAllocator().New(client);
|
Device* device = client->Make<Device>();
|
||||||
uint64_t serial = mRequestDeviceRequests.Add({callback, device->GetWireId(), userdata});
|
uint64_t serial = mRequestDeviceRequests.Add({callback, device->GetWireId(), userdata});
|
||||||
|
|
||||||
AdapterRequestDeviceCmd cmd;
|
AdapterRequestDeviceCmd cmd;
|
||||||
|
@ -110,12 +110,12 @@ bool Adapter::OnRequestDeviceCallback(uint64_t requestSerial,
|
||||||
}
|
}
|
||||||
|
|
||||||
Client* client = GetClient();
|
Client* client = GetClient();
|
||||||
Device* device = client->DeviceAllocator().GetObject(request.deviceObjectId);
|
Device* device = client->Get<Device>(request.deviceObjectId);
|
||||||
|
|
||||||
// If the return status is a failure we should give a null device to the callback and
|
// If the return status is a failure we should give a null device to the callback and
|
||||||
// free the allocation.
|
// free the allocation.
|
||||||
if (status != WGPURequestDeviceStatus_Success) {
|
if (status != WGPURequestDeviceStatus_Success) {
|
||||||
client->DeviceAllocator().Free(device);
|
client->Free(device);
|
||||||
request.callback(status, nullptr, message, request.userdata);
|
request.callback(status, nullptr, message, request.userdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
||||||
// Create the buffer and send the creation command.
|
// Create the buffer and send the creation command.
|
||||||
// This must happen after any potential device->CreateErrorBuffer()
|
// This must happen after any potential device->CreateErrorBuffer()
|
||||||
// as server expects allocating ids to be monotonically increasing
|
// as server expects allocating ids to be monotonically increasing
|
||||||
Buffer* buffer = wireClient->BufferAllocator().New(wireClient);
|
Buffer* buffer = wireClient->Make<Buffer>();
|
||||||
buffer->mDevice = device;
|
buffer->mDevice = device;
|
||||||
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
||||||
buffer->mSize = descriptor->size;
|
buffer->mSize = descriptor->size;
|
||||||
|
@ -127,7 +127,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
||||||
WGPUBuffer Buffer::CreateError(Device* device, const WGPUBufferDescriptor* descriptor) {
|
WGPUBuffer Buffer::CreateError(Device* device, const WGPUBufferDescriptor* descriptor) {
|
||||||
Client* client = device->GetClient();
|
Client* client = device->GetClient();
|
||||||
|
|
||||||
Buffer* buffer = client->BufferAllocator().New(client);
|
Buffer* buffer = client->Make<Buffer>();
|
||||||
buffer->mDevice = device;
|
buffer->mDevice = device;
|
||||||
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
||||||
buffer->mSize = descriptor->size;
|
buffer->mSize = descriptor->size;
|
||||||
|
|
|
@ -61,7 +61,7 @@ void Client::DestroyAllObjects() {
|
||||||
cmd.objectType = ObjectType::Device;
|
cmd.objectType = ObjectType::Device;
|
||||||
cmd.objectId = object->GetWireId();
|
cmd.objectId = object->GetWireId();
|
||||||
SerializeCommand(cmd);
|
SerializeCommand(cmd);
|
||||||
FreeObject(ObjectType::Device, object);
|
mObjectStores[ObjectType::Device].Free(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& objectList : mObjects) {
|
for (auto& objectList : mObjects) {
|
||||||
|
@ -76,13 +76,13 @@ void Client::DestroyAllObjects() {
|
||||||
cmd.objectType = objectType;
|
cmd.objectType = objectType;
|
||||||
cmd.objectId = object->GetWireId();
|
cmd.objectId = object->GetWireId();
|
||||||
SerializeCommand(cmd);
|
SerializeCommand(cmd);
|
||||||
FreeObject(objectType, object);
|
mObjectStores[objectType].Free(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedTexture Client::ReserveTexture(WGPUDevice device) {
|
ReservedTexture Client::ReserveTexture(WGPUDevice device) {
|
||||||
Texture* texture = TextureAllocator().New(this);
|
Texture* texture = Make<Texture>();
|
||||||
|
|
||||||
ReservedTexture result;
|
ReservedTexture result;
|
||||||
result.texture = ToAPI(texture);
|
result.texture = ToAPI(texture);
|
||||||
|
@ -94,7 +94,7 @@ ReservedTexture Client::ReserveTexture(WGPUDevice device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
|
ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
|
||||||
SwapChain* swapChain = SwapChainAllocator().New(this);
|
SwapChain* swapChain = Make<SwapChain>();
|
||||||
|
|
||||||
ReservedSwapChain result;
|
ReservedSwapChain result;
|
||||||
result.swapchain = ToAPI(swapChain);
|
result.swapchain = ToAPI(swapChain);
|
||||||
|
@ -106,7 +106,7 @@ ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedDevice Client::ReserveDevice() {
|
ReservedDevice Client::ReserveDevice() {
|
||||||
Device* device = DeviceAllocator().New(this);
|
Device* device = Make<Device>();
|
||||||
|
|
||||||
ReservedDevice result;
|
ReservedDevice result;
|
||||||
result.device = ToAPI(device);
|
result.device = ToAPI(device);
|
||||||
|
@ -116,7 +116,7 @@ ReservedDevice Client::ReserveDevice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedInstance Client::ReserveInstance() {
|
ReservedInstance Client::ReserveInstance() {
|
||||||
Instance* instance = InstanceAllocator().New(this);
|
Instance* instance = Make<Instance>();
|
||||||
|
|
||||||
ReservedInstance result;
|
ReservedInstance result;
|
||||||
result.instance = ToAPI(instance);
|
result.instance = ToAPI(instance);
|
||||||
|
@ -126,19 +126,19 @@ ReservedInstance Client::ReserveInstance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ReclaimTextureReservation(const ReservedTexture& reservation) {
|
void Client::ReclaimTextureReservation(const ReservedTexture& reservation) {
|
||||||
TextureAllocator().Free(FromAPI(reservation.texture));
|
Free(FromAPI(reservation.texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ReclaimSwapChainReservation(const ReservedSwapChain& reservation) {
|
void Client::ReclaimSwapChainReservation(const ReservedSwapChain& reservation) {
|
||||||
SwapChainAllocator().Free(FromAPI(reservation.swapchain));
|
Free(FromAPI(reservation.swapchain));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ReclaimDeviceReservation(const ReservedDevice& reservation) {
|
void Client::ReclaimDeviceReservation(const ReservedDevice& reservation) {
|
||||||
DeviceAllocator().Free(FromAPI(reservation.device));
|
Free(FromAPI(reservation.device));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::ReclaimInstanceReservation(const ReservedInstance& reservation) {
|
void Client::ReclaimInstanceReservation(const ReservedInstance& reservation) {
|
||||||
InstanceAllocator().Free(FromAPI(reservation.instance));
|
Free(FromAPI(reservation.instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Disconnect() {
|
void Client::Disconnect() {
|
||||||
|
@ -165,4 +165,8 @@ bool Client::IsDisconnected() const {
|
||||||
return mDisconnected;
|
return mDisconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::Free(ObjectBase* obj, ObjectType type) {
|
||||||
|
mObjectStores[type].Free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::wire::client
|
} // namespace dawn::wire::client
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define SRC_DAWN_WIRE_CLIENT_CLIENT_H_
|
#define SRC_DAWN_WIRE_CLIENT_CLIENT_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "dawn/common/LinkedList.h"
|
#include "dawn/common/LinkedList.h"
|
||||||
#include "dawn/common/NonCopyable.h"
|
#include "dawn/common/NonCopyable.h"
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
#include "dawn/wire/WireCmd_autogen.h"
|
#include "dawn/wire/WireCmd_autogen.h"
|
||||||
#include "dawn/wire/WireDeserializeAllocator.h"
|
#include "dawn/wire/WireDeserializeAllocator.h"
|
||||||
#include "dawn/wire/client/ClientBase_autogen.h"
|
#include "dawn/wire/client/ClientBase_autogen.h"
|
||||||
|
#include "dawn/wire/client/ObjectStore.h"
|
||||||
|
|
||||||
namespace dawn::wire::client {
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
|
@ -37,6 +39,32 @@ class Client : public ClientBase {
|
||||||
Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService);
|
Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService);
|
||||||
~Client() override;
|
~Client() override;
|
||||||
|
|
||||||
|
// Make<T>(arg1, arg2, arg3) creates a new T, calling a constructor of the form:
|
||||||
|
//
|
||||||
|
// T::T(ObjectBaseParams, arg1, arg2, arg3)
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
T* Make(Args&&... args) {
|
||||||
|
constexpr ObjectType type = ObjectTypeToTypeEnum<T>::value;
|
||||||
|
|
||||||
|
ObjectBaseParams params = {this, mObjectStores[type].ReserveHandle()};
|
||||||
|
T* object = new T(params, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
mObjects[type].Append(object);
|
||||||
|
mObjectStores[type].Insert(std::unique_ptr<T>(object));
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Free(T* obj) {
|
||||||
|
Free(obj, ObjectTypeToTypeEnum<T>::value);
|
||||||
|
}
|
||||||
|
void Free(ObjectBase* obj, ObjectType type);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* Get(ObjectId id) {
|
||||||
|
return static_cast<T*>(mObjectStores[ObjectTypeToTypeEnum<T>::value].Get(id));
|
||||||
|
}
|
||||||
|
|
||||||
// ChunkedCommandHandler implementation
|
// ChunkedCommandHandler implementation
|
||||||
const volatile char* HandleCommandsImpl(const volatile char* commands, size_t size) override;
|
const volatile char* HandleCommandsImpl(const volatile char* commands, size_t size) override;
|
||||||
|
|
||||||
|
@ -67,21 +95,16 @@ class Client : public ClientBase {
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
bool IsDisconnected() const;
|
bool IsDisconnected() const;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void TrackObject(T* object) {
|
|
||||||
mObjects[ObjectTypeToTypeEnum<T>::value].Append(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DestroyAllObjects();
|
void DestroyAllObjects();
|
||||||
|
|
||||||
#include "dawn/wire/client/ClientPrototypes_autogen.inc"
|
#include "dawn/wire/client/ClientPrototypes_autogen.inc"
|
||||||
|
|
||||||
ChunkedCommandSerializer mSerializer;
|
ChunkedCommandSerializer mSerializer;
|
||||||
WireDeserializeAllocator mAllocator;
|
WireDeserializeAllocator mWireCommandAllocator;
|
||||||
|
PerObjectType<ObjectStore> mObjectStores;
|
||||||
MemoryTransferService* mMemoryTransferService = nullptr;
|
MemoryTransferService* mMemoryTransferService = nullptr;
|
||||||
std::unique_ptr<MemoryTransferService> mOwnedMemoryTransferService = nullptr;
|
std::unique_ptr<MemoryTransferService> mOwnedMemoryTransferService = nullptr;
|
||||||
|
|
||||||
PerObjectType<LinkedList<ObjectBase>> mObjects;
|
PerObjectType<LinkedList<ObjectBase>> mObjects;
|
||||||
bool mDisconnected = false;
|
bool mDisconnected = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "dawn/common/Log.h"
|
#include "dawn/common/Log.h"
|
||||||
#include "dawn/wire/client/ApiObjects_autogen.h"
|
#include "dawn/wire/client/ApiObjects_autogen.h"
|
||||||
#include "dawn/wire/client/Client.h"
|
#include "dawn/wire/client/Client.h"
|
||||||
#include "dawn/wire/client/ObjectAllocator.h"
|
|
||||||
|
|
||||||
namespace dawn::wire::client {
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
|
@ -221,7 +220,7 @@ WGPUQueue Device::GetQueue() {
|
||||||
if (mQueue == nullptr) {
|
if (mQueue == nullptr) {
|
||||||
// Get the primary queue for this device.
|
// Get the primary queue for this device.
|
||||||
Client* client = GetClient();
|
Client* client = GetClient();
|
||||||
mQueue = client->QueueAllocator().New(client);
|
mQueue = client->Make<Queue>();
|
||||||
|
|
||||||
DeviceGetQueueCmd cmd;
|
DeviceGetQueueCmd cmd;
|
||||||
cmd.self = ToAPI(this);
|
cmd.self = ToAPI(this);
|
||||||
|
@ -243,7 +242,7 @@ void Device::CreateComputePipelineAsync(WGPUComputePipelineDescriptor const* des
|
||||||
"GPU device disconnected", userdata);
|
"GPU device disconnected", userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipeline* pipeline = client->ComputePipelineAllocator().New(client);
|
ComputePipeline* pipeline = client->Make<ComputePipeline>();
|
||||||
|
|
||||||
CreatePipelineAsyncRequest request = {};
|
CreatePipelineAsyncRequest request = {};
|
||||||
request.createComputePipelineAsyncCallback = callback;
|
request.createComputePipelineAsyncCallback = callback;
|
||||||
|
@ -270,20 +269,17 @@ bool Device::OnCreateComputePipelineAsyncCallback(uint64_t requestSerial,
|
||||||
}
|
}
|
||||||
|
|
||||||
Client* client = GetClient();
|
Client* client = GetClient();
|
||||||
auto* pipelineAllocation =
|
ComputePipeline* pipeline = client->Get<ComputePipeline>(request.pipelineObjectID);
|
||||||
client->ComputePipelineAllocator().GetObject(request.pipelineObjectID);
|
|
||||||
|
|
||||||
// If the return status is a failure we should give a null pipeline to the callback and
|
// If the return status is a failure we should give a null pipeline to the callback and
|
||||||
// free the allocation.
|
// free the allocation.
|
||||||
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
||||||
client->ComputePipelineAllocator().Free(pipelineAllocation);
|
client->Free(pipeline);
|
||||||
request.createComputePipelineAsyncCallback(status, nullptr, message, request.userdata);
|
request.createComputePipelineAsyncCallback(status, nullptr, message, request.userdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPUComputePipeline pipeline = reinterpret_cast<WGPUComputePipeline>(pipelineAllocation);
|
request.createComputePipelineAsyncCallback(status, ToAPI(pipeline), message, request.userdata);
|
||||||
request.createComputePipelineAsyncCallback(status, pipeline, message, request.userdata);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +292,7 @@ void Device::CreateRenderPipelineAsync(WGPURenderPipelineDescriptor const* descr
|
||||||
"GPU device disconnected", userdata);
|
"GPU device disconnected", userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipeline* pipeline = client->RenderPipelineAllocator().New(client);
|
RenderPipeline* pipeline = client->Make<RenderPipeline>();
|
||||||
|
|
||||||
CreatePipelineAsyncRequest request = {};
|
CreatePipelineAsyncRequest request = {};
|
||||||
request.createRenderPipelineAsyncCallback = callback;
|
request.createRenderPipelineAsyncCallback = callback;
|
||||||
|
@ -323,20 +319,17 @@ bool Device::OnCreateRenderPipelineAsyncCallback(uint64_t requestSerial,
|
||||||
}
|
}
|
||||||
|
|
||||||
Client* client = GetClient();
|
Client* client = GetClient();
|
||||||
auto* pipelineAllocation =
|
RenderPipeline* pipeline = client->Get<RenderPipeline>(request.pipelineObjectID);
|
||||||
client->RenderPipelineAllocator().GetObject(request.pipelineObjectID);
|
|
||||||
|
|
||||||
// If the return status is a failure we should give a null pipeline to the callback and
|
// If the return status is a failure we should give a null pipeline to the callback and
|
||||||
// free the allocation.
|
// free the allocation.
|
||||||
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
||||||
client->RenderPipelineAllocator().Free(pipelineAllocation);
|
client->Free(pipeline);
|
||||||
request.createRenderPipelineAsyncCallback(status, nullptr, message, request.userdata);
|
request.createRenderPipelineAsyncCallback(status, nullptr, message, request.userdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPURenderPipeline pipeline = reinterpret_cast<WGPURenderPipeline>(pipelineAllocation);
|
request.createRenderPipelineAsyncCallback(status, ToAPI(pipeline), message, request.userdata);
|
||||||
request.createRenderPipelineAsyncCallback(status, pipeline, message, request.userdata);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ void Instance::RequestAdapter(const WGPURequestAdapterOptions* options,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Adapter* adapter = client->AdapterAllocator().New(client);
|
Adapter* adapter = client->Make<Adapter>();
|
||||||
uint64_t serial = mRequestAdapterRequests.Add({callback, adapter->GetWireId(), userdata});
|
uint64_t serial = mRequestAdapterRequests.Add({callback, adapter->GetWireId(), userdata});
|
||||||
|
|
||||||
InstanceRequestAdapterCmd cmd;
|
InstanceRequestAdapterCmd cmd;
|
||||||
|
@ -82,12 +82,12 @@ bool Instance::OnRequestAdapterCallback(uint64_t requestSerial,
|
||||||
}
|
}
|
||||||
|
|
||||||
Client* client = GetClient();
|
Client* client = GetClient();
|
||||||
Adapter* adapter = client->AdapterAllocator().GetObject(request.adapterObjectId);
|
Adapter* adapter = client->Get<Adapter>(request.adapterObjectId);
|
||||||
|
|
||||||
// If the return status is a failure we should give a null adapter to the callback and
|
// If the return status is a failure we should give a null adapter to the callback and
|
||||||
// free the allocation.
|
// free the allocation.
|
||||||
if (status != WGPURequestAdapterStatus_Success) {
|
if (status != WGPURequestAdapterStatus_Success) {
|
||||||
client->AdapterAllocator().Free(adapter);
|
client->Free(adapter);
|
||||||
request.callback(status, nullptr, message, request.userdata);
|
request.callback(status, nullptr, message, request.userdata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
// Copyright 2019 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 SRC_DAWN_WIRE_CLIENT_OBJECTALLOCATOR_H_
|
|
||||||
#define SRC_DAWN_WIRE_CLIENT_OBJECTALLOCATOR_H_
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "dawn/common/Assert.h"
|
|
||||||
#include "dawn/common/Compiler.h"
|
|
||||||
#include "dawn/wire/WireCmd_autogen.h"
|
|
||||||
#include "dawn/wire/client/ObjectBase.h"
|
|
||||||
|
|
||||||
namespace dawn::wire::client {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class ObjectAllocator {
|
|
||||||
public:
|
|
||||||
ObjectAllocator() {
|
|
||||||
// ID 0 is nullptr
|
|
||||||
mObjects.emplace_back(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Client>
|
|
||||||
T* New(Client* client) {
|
|
||||||
ObjectHandle handle = GetFreeHandle();
|
|
||||||
ObjectBaseParams params = {client, handle};
|
|
||||||
auto object = std::make_unique<T>(params);
|
|
||||||
client->TrackObject(object.get());
|
|
||||||
|
|
||||||
if (handle.id >= mObjects.size()) {
|
|
||||||
ASSERT(handle.id == mObjects.size());
|
|
||||||
mObjects.emplace_back(std::move(object));
|
|
||||||
} else {
|
|
||||||
// The generation should never overflow. We don't recycle ObjectIds that would
|
|
||||||
// overflow their next generation.
|
|
||||||
ASSERT(handle.generation != 0);
|
|
||||||
ASSERT(mObjects[handle.id] == nullptr);
|
|
||||||
mObjects[handle.id] = std::move(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mObjects[handle.id].get();
|
|
||||||
}
|
|
||||||
void Free(T* obj) {
|
|
||||||
ASSERT(obj->IsInList());
|
|
||||||
// The wire reuses ID for objects to keep them in a packed array starting from 0.
|
|
||||||
// To avoid issues with asynchronous server->client communication referring to an ID that's
|
|
||||||
// already reused, each handle also has a generation that's increment by one on each reuse.
|
|
||||||
// Avoid overflows by only reusing the ID if the increment of the generation won't overflow.
|
|
||||||
ObjectHandle currentHandle = obj->GetWireHandle();
|
|
||||||
if (DAWN_LIKELY(currentHandle.generation != std::numeric_limits<ObjectGeneration>::max())) {
|
|
||||||
mFreeHandles.push_back({currentHandle.id, currentHandle.generation + 1});
|
|
||||||
}
|
|
||||||
mObjects[currentHandle.id] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* GetObject(uint32_t id) {
|
|
||||||
if (id >= mObjects.size()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return mObjects[id].get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ObjectHandle GetFreeHandle() {
|
|
||||||
if (mFreeHandles.empty()) {
|
|
||||||
return {mCurrentId++, 0};
|
|
||||||
}
|
|
||||||
ObjectHandle handle = mFreeHandles.back();
|
|
||||||
mFreeHandles.pop_back();
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0 is an ID reserved to represent nullptr
|
|
||||||
uint32_t mCurrentId = 1;
|
|
||||||
std::vector<ObjectHandle> mFreeHandles;
|
|
||||||
std::vector<std::unique_ptr<T>> mObjects;
|
|
||||||
};
|
|
||||||
} // namespace dawn::wire::client
|
|
||||||
|
|
||||||
#endif // SRC_DAWN_WIRE_CLIENT_OBJECTALLOCATOR_H_
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2022 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/ObjectStore.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
|
ObjectStore::ObjectStore() {
|
||||||
|
// ID 0 is nullptr
|
||||||
|
mObjects.emplace_back(nullptr);
|
||||||
|
mCurrentId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectHandle ObjectStore::ReserveHandle() {
|
||||||
|
if (mFreeHandles.empty()) {
|
||||||
|
return {mCurrentId++, 0};
|
||||||
|
}
|
||||||
|
ObjectHandle handle = mFreeHandles.back();
|
||||||
|
mFreeHandles.pop_back();
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectStore::Insert(std::unique_ptr<ObjectBase> obj) {
|
||||||
|
ObjectId id = obj->GetWireId();
|
||||||
|
|
||||||
|
if (id >= mObjects.size()) {
|
||||||
|
ASSERT(id == mObjects.size());
|
||||||
|
mObjects.emplace_back(std::move(obj));
|
||||||
|
} else {
|
||||||
|
// The generation should never overflow. We don't recycle ObjectIds that would
|
||||||
|
// overflow their next generation.
|
||||||
|
ASSERT(obj->GetWireGeneration() != 0);
|
||||||
|
ASSERT(mObjects[id] == nullptr);
|
||||||
|
mObjects[id] = std::move(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectStore::Free(ObjectBase* obj) {
|
||||||
|
ASSERT(obj->IsInList());
|
||||||
|
// The wire reuses ID for objects to keep them in a packed array starting from 0.
|
||||||
|
// To avoid issues with asynchronous server->client communication referring to an ID that's
|
||||||
|
// already reused, each handle also has a generation that's increment by one on each reuse.
|
||||||
|
// Avoid overflows by only reusing the ID if the increment of the generation won't overflow.
|
||||||
|
const ObjectHandle& currentHandle = obj->GetWireHandle();
|
||||||
|
if (DAWN_LIKELY(currentHandle.generation != std::numeric_limits<ObjectGeneration>::max())) {
|
||||||
|
mFreeHandles.push_back({currentHandle.id, currentHandle.generation + 1});
|
||||||
|
}
|
||||||
|
mObjects[currentHandle.id] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectBase* ObjectStore::Get(ObjectId id) const {
|
||||||
|
if (id >= mObjects.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return mObjects[id].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire::client
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright 2019 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 SRC_DAWN_WIRE_CLIENT_OBJECTSTORE_H_
|
||||||
|
#define SRC_DAWN_WIRE_CLIENT_OBJECTSTORE_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "dawn/wire/client/ObjectBase.h"
|
||||||
|
|
||||||
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
// A helper class used in Client, ObjectStore owns the association of some ObjectBase and
|
||||||
|
// ObjectHandles. The lifetime of the ObjectBase is then owned by the ObjectStore, destruction
|
||||||
|
// happening when Free is called.
|
||||||
|
//
|
||||||
|
// Since the wire has one "ID" namespace per type of object, each ObjectStore should contain a
|
||||||
|
// single type of objects. However no templates are used because Client wraps ObjectStore and is
|
||||||
|
// type-generic, so ObjectStore is type-erased to only work on ObjectBase.
|
||||||
|
class ObjectStore {
|
||||||
|
public:
|
||||||
|
ObjectStore();
|
||||||
|
|
||||||
|
ObjectHandle ReserveHandle();
|
||||||
|
void Insert(std::unique_ptr<ObjectBase> obj);
|
||||||
|
void Free(ObjectBase* obj);
|
||||||
|
ObjectBase* Get(ObjectId id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t mCurrentId;
|
||||||
|
std::vector<ObjectHandle> mFreeHandles;
|
||||||
|
std::vector<std::unique_ptr<ObjectBase>> mObjects;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn::wire::client
|
||||||
|
|
||||||
|
#endif // SRC_DAWN_WIRE_CLIENT_OBJECTSTORE_H_
|
|
@ -22,7 +22,7 @@ namespace dawn::wire::client {
|
||||||
// static
|
// static
|
||||||
WGPUQuerySet QuerySet::Create(Device* device, const WGPUQuerySetDescriptor* descriptor) {
|
WGPUQuerySet QuerySet::Create(Device* device, const WGPUQuerySetDescriptor* descriptor) {
|
||||||
Client* wireClient = device->GetClient();
|
Client* wireClient = device->GetClient();
|
||||||
QuerySet* querySet = wireClient->QuerySetAllocator().New(wireClient);
|
QuerySet* querySet = wireClient->Make<QuerySet>();
|
||||||
|
|
||||||
// Copy over descriptor data for reflection.
|
// Copy over descriptor data for reflection.
|
||||||
querySet->mType = descriptor->type;
|
querySet->mType = descriptor->type;
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace dawn::wire::client {
|
||||||
// static
|
// static
|
||||||
WGPUTexture Texture::Create(Device* device, const WGPUTextureDescriptor* descriptor) {
|
WGPUTexture Texture::Create(Device* device, const WGPUTextureDescriptor* descriptor) {
|
||||||
Client* wireClient = device->GetClient();
|
Client* wireClient = device->GetClient();
|
||||||
Texture* texture = wireClient->TextureAllocator().New(wireClient);
|
Texture* texture = wireClient->Make<Texture>();
|
||||||
|
|
||||||
// Copy over descriptor data for reflection.
|
// Copy over descriptor data for reflection.
|
||||||
texture->mSize = descriptor->size;
|
texture->mSize = descriptor->size;
|
||||||
|
|
Loading…
Reference in New Issue