dawn::wire::client: Track the object generation on the objects
Previously the ObjectAllocator was tracking the generation on the side of the object. This was done to avoid the need to check that the objects aren't null before accessing the generation in ClientHandlers. This is only a very minor optimization for return commands so it is removed in favor of simplifying the code. The code is simplified in a bunch of place by getting the ObjectHandle for an object directly (since it knows the generation now) instead of walking the object graph returned by the allocator. The ObjectBase class is also changed to store an ObjectHandle interrnally that's only accessible via getters. Encapsulating the other memebers will be done in follow-up CLs. Also adds the generation to the ObjectBaseParams since all ObjectBases now require it. Bug: dawn:1451 Change-Id: Ic6c850fc989f715f7c80952ff447b7c29378cd27 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/93146 Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
87af04b769
commit
0f97df8c53
|
@ -58,8 +58,8 @@ 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* allocation = self->client->{{method.return_type.name.CamelCase()}}Allocator().New(self->client);
|
auto* returnObject = self->client->{{method.return_type.name.CamelCase()}}Allocator().New(self->client);
|
||||||
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
|
cmd.result = returnObject->GetWireHandle();
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for arg in method.arguments %}
|
{% for arg in method.arguments %}
|
||||||
|
@ -72,7 +72,7 @@ namespace dawn::wire::client {
|
||||||
self->client->SerializeCommand(cmd);
|
self->client->SerializeCommand(cmd);
|
||||||
|
|
||||||
{% if method.return_type.category == "object" %}
|
{% if method.return_type.category == "object" %}
|
||||||
return reinterpret_cast<{{as_cType(method.return_type.name)}}>(allocation->object.get());
|
return ToAPI(returnObject);
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
return self->{{method.name.CamelCase()}}(
|
return self->{{method.name.CamelCase()}}(
|
||||||
|
@ -94,7 +94,7 @@ namespace dawn::wire::client {
|
||||||
|
|
||||||
DestroyObjectCmd cmd;
|
DestroyObjectCmd cmd;
|
||||||
cmd.objectType = ObjectType::{{type.name.CamelCase()}};
|
cmd.objectType = ObjectType::{{type.name.CamelCase()}};
|
||||||
cmd.objectId = obj->id;
|
cmd.objectId = obj->GetWireId();
|
||||||
|
|
||||||
obj->client->SerializeCommand(cmd);
|
obj->client->SerializeCommand(cmd);
|
||||||
obj->client->{{type.name.CamelCase()}}Allocator().Free(obj);
|
obj->client->{{type.name.CamelCase()}}Allocator().Free(obj);
|
||||||
|
|
|
@ -54,12 +54,12 @@ namespace dawn::wire::client {
|
||||||
if (object == nullptr) {
|
if (object == nullptr) {
|
||||||
return WireResult::FatalError;
|
return WireResult::FatalError;
|
||||||
}
|
}
|
||||||
*out = reinterpret_cast<{{as_wireType(type)}}>(object)->id;
|
*out = reinterpret_cast<{{as_wireType(type)}}>(object)->GetWireId();
|
||||||
return WireResult::Success;
|
return WireResult::Success;
|
||||||
}
|
}
|
||||||
WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const final {
|
WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const final {
|
||||||
ASSERT(out != nullptr);
|
ASSERT(out != nullptr);
|
||||||
*out = (object == nullptr ? 0 : reinterpret_cast<{{as_wireType(type)}}>(object)->id);
|
*out = (object == nullptr ? 0 : reinterpret_cast<{{as_wireType(type)}}>(object)->GetWireId());
|
||||||
return WireResult::Success;
|
return WireResult::Success;
|
||||||
}
|
}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -33,8 +33,7 @@ namespace dawn::wire::client {
|
||||||
|
|
||||||
{% if member.type.dict_name == "ObjectHandle" %}
|
{% if member.type.dict_name == "ObjectHandle" %}
|
||||||
{{Type}}* {{name}} = {{Type}}Allocator().GetObject(cmd.{{name}}.id);
|
{{Type}}* {{name}} = {{Type}}Allocator().GetObject(cmd.{{name}}.id);
|
||||||
uint32_t {{name}}Generation = {{Type}}Allocator().GetGeneration(cmd.{{name}}.id);
|
if ({{name}} != nullptr && {{name}}->GetWireGeneration() != cmd.{{name}}.generation) {
|
||||||
if ({{name}}Generation != cmd.{{name}}.generation) {
|
|
||||||
{{name}} = nullptr;
|
{{name}} = nullptr;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -28,7 +28,6 @@ ObjectHandle& ObjectHandle::operator=(const volatile ObjectHandle& rhs) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ObjectHandle::ObjectHandle(const ObjectHandle& rhs) = default;
|
ObjectHandle::ObjectHandle(const ObjectHandle& rhs) = default;
|
||||||
ObjectHandle& ObjectHandle::operator=(const ObjectHandle& rhs) = default;
|
ObjectHandle& ObjectHandle::operator=(const ObjectHandle& rhs) = default;
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,13 @@ void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* allocation = client->DeviceAllocator().New(client);
|
Device* device = client->DeviceAllocator().New(client);
|
||||||
uint64_t serial = mRequestDeviceRequests.Add({callback, allocation->object->id, userdata});
|
uint64_t serial = mRequestDeviceRequests.Add({callback, device->GetWireId(), userdata});
|
||||||
|
|
||||||
AdapterRequestDeviceCmd cmd;
|
AdapterRequestDeviceCmd cmd;
|
||||||
cmd.adapterId = this->id;
|
cmd.adapterId = GetWireId();
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
cmd.deviceObjectHandle = ObjectHandle(allocation->object->id, allocation->generation);
|
cmd.deviceObjectHandle = device->GetWireHandle();
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
|
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
|
|
|
@ -40,7 +40,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
||||||
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;
|
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;
|
||||||
|
|
||||||
DeviceCreateBufferCmd cmd;
|
DeviceCreateBufferCmd cmd;
|
||||||
cmd.deviceId = device->id;
|
cmd.deviceId = device->GetWireId();
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
cmd.readHandleCreateInfoLength = 0;
|
cmd.readHandleCreateInfoLength = 0;
|
||||||
cmd.readHandleCreateInfo = nullptr;
|
cmd.readHandleCreateInfo = nullptr;
|
||||||
|
@ -74,8 +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
|
||||||
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(wireClient);
|
Buffer* buffer = wireClient->BufferAllocator().New(wireClient);
|
||||||
Buffer* buffer = bufferObjectAndSerial->object.get();
|
|
||||||
buffer->mDevice = device;
|
buffer->mDevice = device;
|
||||||
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
||||||
buffer->mSize = descriptor->size;
|
buffer->mSize = descriptor->size;
|
||||||
|
@ -98,7 +97,7 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
||||||
buffer->mMappedData = writeHandle->GetData();
|
buffer->mMappedData = writeHandle->GetData();
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
|
cmd.result = buffer->GetWireHandle();
|
||||||
|
|
||||||
wireClient->SerializeCommand(
|
wireClient->SerializeCommand(
|
||||||
cmd, cmd.readHandleCreateInfoLength + cmd.writeHandleCreateInfoLength,
|
cmd, cmd.readHandleCreateInfoLength + cmd.writeHandleCreateInfoLength,
|
||||||
|
@ -126,18 +125,18 @@ WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor
|
||||||
|
|
||||||
// static
|
// static
|
||||||
WGPUBuffer Buffer::CreateError(Device* device, const WGPUBufferDescriptor* descriptor) {
|
WGPUBuffer Buffer::CreateError(Device* device, const WGPUBufferDescriptor* descriptor) {
|
||||||
auto* allocation = device->client->BufferAllocator().New(device->client);
|
Buffer* buffer = device->client->BufferAllocator().New(device->client);
|
||||||
allocation->object->mDevice = device;
|
buffer->mDevice = device;
|
||||||
allocation->object->mDeviceIsAlive = device->GetAliveWeakPtr();
|
buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
|
||||||
allocation->object->mSize = descriptor->size;
|
buffer->mSize = descriptor->size;
|
||||||
allocation->object->mUsage = static_cast<WGPUBufferUsage>(descriptor->usage);
|
buffer->mUsage = static_cast<WGPUBufferUsage>(descriptor->usage);
|
||||||
|
|
||||||
DeviceCreateErrorBufferCmd cmd;
|
DeviceCreateErrorBufferCmd cmd;
|
||||||
cmd.self = ToAPI(device);
|
cmd.self = ToAPI(device);
|
||||||
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
|
cmd.result = buffer->GetWireHandle();
|
||||||
device->client->SerializeCommand(cmd);
|
device->client->SerializeCommand(cmd);
|
||||||
|
|
||||||
return ToAPI(allocation->object.get());
|
return ToAPI(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer() {
|
Buffer::~Buffer() {
|
||||||
|
@ -188,7 +187,7 @@ void Buffer::MapAsync(WGPUMapModeFlags mode,
|
||||||
|
|
||||||
// Serialize the command to send to the server.
|
// Serialize the command to send to the server.
|
||||||
BufferMapAsyncCmd cmd;
|
BufferMapAsyncCmd cmd;
|
||||||
cmd.bufferId = this->id;
|
cmd.bufferId = GetWireId();
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
cmd.mode = mode;
|
cmd.mode = mode;
|
||||||
cmd.offset = offset;
|
cmd.offset = offset;
|
||||||
|
@ -301,7 +300,7 @@ void Buffer::Unmap() {
|
||||||
mWriteHandle->SizeOfSerializeDataUpdate(mMapOffset, mMapSize);
|
mWriteHandle->SizeOfSerializeDataUpdate(mMapOffset, mMapSize);
|
||||||
|
|
||||||
BufferUpdateMappedDataCmd cmd;
|
BufferUpdateMappedDataCmd cmd;
|
||||||
cmd.bufferId = id;
|
cmd.bufferId = GetWireId();
|
||||||
cmd.writeDataUpdateInfoLength = writeDataUpdateInfoLength;
|
cmd.writeDataUpdateInfoLength = writeDataUpdateInfoLength;
|
||||||
cmd.writeDataUpdateInfo = nullptr;
|
cmd.writeDataUpdateInfo = nullptr;
|
||||||
cmd.offset = mMapOffset;
|
cmd.offset = mMapOffset;
|
||||||
|
|
|
@ -59,7 +59,7 @@ void Client::DestroyAllObjects() {
|
||||||
|
|
||||||
DestroyObjectCmd cmd;
|
DestroyObjectCmd cmd;
|
||||||
cmd.objectType = ObjectType::Device;
|
cmd.objectType = ObjectType::Device;
|
||||||
cmd.objectId = object->id;
|
cmd.objectId = object->GetWireId();
|
||||||
SerializeCommand(cmd);
|
SerializeCommand(cmd);
|
||||||
FreeObject(ObjectType::Device, object);
|
FreeObject(ObjectType::Device, object);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ void Client::DestroyAllObjects() {
|
||||||
|
|
||||||
DestroyObjectCmd cmd;
|
DestroyObjectCmd cmd;
|
||||||
cmd.objectType = objectType;
|
cmd.objectType = objectType;
|
||||||
cmd.objectId = object->id;
|
cmd.objectId = object->GetWireId();
|
||||||
SerializeCommand(cmd);
|
SerializeCommand(cmd);
|
||||||
FreeObject(objectType, object);
|
FreeObject(objectType, object);
|
||||||
}
|
}
|
||||||
|
@ -82,46 +82,46 @@ void Client::DestroyAllObjects() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedTexture Client::ReserveTexture(WGPUDevice device) {
|
ReservedTexture Client::ReserveTexture(WGPUDevice device) {
|
||||||
auto* allocation = TextureAllocator().New(this);
|
Texture* texture = TextureAllocator().New(this);
|
||||||
|
|
||||||
ReservedTexture result;
|
ReservedTexture result;
|
||||||
result.texture = ToAPI(allocation->object.get());
|
result.texture = ToAPI(texture);
|
||||||
result.id = allocation->object->id;
|
result.id = texture->GetWireId();
|
||||||
result.generation = allocation->generation;
|
result.generation = texture->GetWireGeneration();
|
||||||
result.deviceId = FromAPI(device)->id;
|
result.deviceId = FromAPI(device)->GetWireId();
|
||||||
result.deviceGeneration = DeviceAllocator().GetGeneration(FromAPI(device)->id);
|
result.deviceGeneration = FromAPI(device)->GetWireGeneration();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
|
ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
|
||||||
auto* allocation = SwapChainAllocator().New(this);
|
SwapChain* swapChain = SwapChainAllocator().New(this);
|
||||||
|
|
||||||
ReservedSwapChain result;
|
ReservedSwapChain result;
|
||||||
result.swapchain = ToAPI(allocation->object.get());
|
result.swapchain = ToAPI(swapChain);
|
||||||
result.id = allocation->object->id;
|
result.id = swapChain->GetWireId();
|
||||||
result.generation = allocation->generation;
|
result.generation = swapChain->GetWireGeneration();
|
||||||
result.deviceId = FromAPI(device)->id;
|
result.deviceId = FromAPI(device)->GetWireId();
|
||||||
result.deviceGeneration = DeviceAllocator().GetGeneration(FromAPI(device)->id);
|
result.deviceGeneration = FromAPI(device)->GetWireGeneration();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedDevice Client::ReserveDevice() {
|
ReservedDevice Client::ReserveDevice() {
|
||||||
auto* allocation = DeviceAllocator().New(this);
|
Device* device = DeviceAllocator().New(this);
|
||||||
|
|
||||||
ReservedDevice result;
|
ReservedDevice result;
|
||||||
result.device = ToAPI(allocation->object.get());
|
result.device = ToAPI(device);
|
||||||
result.id = allocation->object->id;
|
result.id = device->GetWireId();
|
||||||
result.generation = allocation->generation;
|
result.generation = device->GetWireGeneration();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedInstance Client::ReserveInstance() {
|
ReservedInstance Client::ReserveInstance() {
|
||||||
auto* allocation = InstanceAllocator().New(this);
|
Instance* instance = InstanceAllocator().New(this);
|
||||||
|
|
||||||
ReservedInstance result;
|
ReservedInstance result;
|
||||||
result.instance = ToAPI(allocation->object.get());
|
result.instance = ToAPI(instance);
|
||||||
result.id = allocation->object->id;
|
result.id = instance->GetWireId();
|
||||||
result.generation = allocation->generation;
|
result.generation = instance->GetWireGeneration();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ bool Device::PopErrorScope(WGPUErrorCallback callback, void* userdata) {
|
||||||
|
|
||||||
uint64_t serial = mErrorScopes.Add({callback, userdata});
|
uint64_t serial = mErrorScopes.Add({callback, userdata});
|
||||||
DevicePopErrorScopeCmd cmd;
|
DevicePopErrorScopeCmd cmd;
|
||||||
cmd.deviceId = this->id;
|
cmd.deviceId = GetWireId();
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
return true;
|
return true;
|
||||||
|
@ -219,12 +219,11 @@ WGPUQueue Device::GetQueue() {
|
||||||
// on construction.
|
// on construction.
|
||||||
if (mQueue == nullptr) {
|
if (mQueue == nullptr) {
|
||||||
// Get the primary queue for this device.
|
// Get the primary queue for this device.
|
||||||
auto* allocation = client->QueueAllocator().New(client);
|
mQueue = client->QueueAllocator().New(client);
|
||||||
mQueue = allocation->object.get();
|
|
||||||
|
|
||||||
DeviceGetQueueCmd cmd;
|
DeviceGetQueueCmd cmd;
|
||||||
cmd.self = ToAPI(this);
|
cmd.self = ToAPI(this);
|
||||||
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
|
cmd.result = mQueue->GetWireHandle();
|
||||||
|
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
}
|
}
|
||||||
|
@ -241,20 +240,20 @@ void Device::CreateComputePipelineAsync(WGPUComputePipelineDescriptor const* des
|
||||||
"GPU device disconnected", userdata);
|
"GPU device disconnected", userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* allocation = client->ComputePipelineAllocator().New(client);
|
ComputePipeline* pipeline = client->ComputePipelineAllocator().New(client);
|
||||||
|
|
||||||
CreatePipelineAsyncRequest request = {};
|
CreatePipelineAsyncRequest request = {};
|
||||||
request.createComputePipelineAsyncCallback = callback;
|
request.createComputePipelineAsyncCallback = callback;
|
||||||
request.userdata = userdata;
|
request.userdata = userdata;
|
||||||
request.pipelineObjectID = allocation->object->id;
|
request.pipelineObjectID = pipeline->GetWireId();
|
||||||
|
|
||||||
uint64_t serial = mCreatePipelineAsyncRequests.Add(std::move(request));
|
uint64_t serial = mCreatePipelineAsyncRequests.Add(std::move(request));
|
||||||
|
|
||||||
DeviceCreateComputePipelineAsyncCmd cmd;
|
DeviceCreateComputePipelineAsyncCmd cmd;
|
||||||
cmd.deviceId = this->id;
|
cmd.deviceId = GetWireId();
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
cmd.pipelineObjectHandle = ObjectHandle{allocation->object->id, allocation->generation};
|
cmd.pipelineObjectHandle = pipeline->GetWireHandle();
|
||||||
|
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
}
|
}
|
||||||
|
@ -292,20 +291,20 @@ void Device::CreateRenderPipelineAsync(WGPURenderPipelineDescriptor const* descr
|
||||||
"GPU device disconnected", userdata);
|
"GPU device disconnected", userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* allocation = client->RenderPipelineAllocator().New(client);
|
RenderPipeline* pipeline = client->RenderPipelineAllocator().New(client);
|
||||||
|
|
||||||
CreatePipelineAsyncRequest request = {};
|
CreatePipelineAsyncRequest request = {};
|
||||||
request.createRenderPipelineAsyncCallback = callback;
|
request.createRenderPipelineAsyncCallback = callback;
|
||||||
request.userdata = userdata;
|
request.userdata = userdata;
|
||||||
request.pipelineObjectID = allocation->object->id;
|
request.pipelineObjectID = pipeline->GetWireId();
|
||||||
|
|
||||||
uint64_t serial = mCreatePipelineAsyncRequests.Add(std::move(request));
|
uint64_t serial = mCreatePipelineAsyncRequests.Add(std::move(request));
|
||||||
|
|
||||||
DeviceCreateRenderPipelineAsyncCmd cmd;
|
DeviceCreateRenderPipelineAsyncCmd cmd;
|
||||||
cmd.deviceId = this->id;
|
cmd.deviceId = GetWireId();
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
cmd.pipelineObjectHandle = ObjectHandle(allocation->object->id, allocation->generation);
|
cmd.pipelineObjectHandle = pipeline->GetWireHandle();
|
||||||
|
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,13 +40,13 @@ void Instance::RequestAdapter(const WGPURequestAdapterOptions* options,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* allocation = client->AdapterAllocator().New(client);
|
Adapter* adapter = client->AdapterAllocator().New(client);
|
||||||
uint64_t serial = mRequestAdapterRequests.Add({callback, allocation->object->id, userdata});
|
uint64_t serial = mRequestAdapterRequests.Add({callback, adapter->GetWireId(), userdata});
|
||||||
|
|
||||||
InstanceRequestAdapterCmd cmd;
|
InstanceRequestAdapterCmd cmd;
|
||||||
cmd.instanceId = this->id;
|
cmd.instanceId = GetWireId();
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
cmd.adapterObjectHandle = ObjectHandle(allocation->object->id, allocation->generation);
|
cmd.adapterObjectHandle = adapter->GetWireHandle();
|
||||||
cmd.options = options;
|
cmd.options = options;
|
||||||
|
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
|
|
|
@ -23,86 +23,72 @@
|
||||||
#include "dawn/common/Assert.h"
|
#include "dawn/common/Assert.h"
|
||||||
#include "dawn/common/Compiler.h"
|
#include "dawn/common/Compiler.h"
|
||||||
#include "dawn/wire/WireCmd_autogen.h"
|
#include "dawn/wire/WireCmd_autogen.h"
|
||||||
|
#include "dawn/wire/client/ObjectBase.h"
|
||||||
|
|
||||||
namespace dawn::wire::client {
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ObjectAllocator {
|
class ObjectAllocator {
|
||||||
public:
|
public:
|
||||||
struct ObjectAndSerial {
|
|
||||||
ObjectAndSerial(std::unique_ptr<T> object, uint32_t generation)
|
|
||||||
: object(std::move(object)), generation(generation) {}
|
|
||||||
std::unique_ptr<T> object;
|
|
||||||
uint32_t generation;
|
|
||||||
};
|
|
||||||
|
|
||||||
ObjectAllocator() {
|
ObjectAllocator() {
|
||||||
// ID 0 is nullptr
|
// ID 0 is nullptr
|
||||||
mObjects.emplace_back(nullptr, 0);
|
mObjects.emplace_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Client>
|
template <typename Client>
|
||||||
ObjectAndSerial* New(Client* client) {
|
T* New(Client* client) {
|
||||||
uint32_t id = GetNewId();
|
ObjectHandle handle = GetFreeHandle();
|
||||||
ObjectBaseParams params = {client, id};
|
ObjectBaseParams params = {client, handle};
|
||||||
auto object = std::make_unique<T>(params);
|
auto object = std::make_unique<T>(params);
|
||||||
client->TrackObject(object.get());
|
client->TrackObject(object.get());
|
||||||
|
|
||||||
if (id >= mObjects.size()) {
|
if (handle.id >= mObjects.size()) {
|
||||||
ASSERT(id == mObjects.size());
|
ASSERT(handle.id == mObjects.size());
|
||||||
mObjects.emplace_back(std::move(object), 0);
|
mObjects.emplace_back(std::move(object));
|
||||||
} else {
|
} else {
|
||||||
ASSERT(mObjects[id].object == nullptr);
|
|
||||||
|
|
||||||
mObjects[id].generation++;
|
|
||||||
// The generation should never overflow. We don't recycle ObjectIds that would
|
// The generation should never overflow. We don't recycle ObjectIds that would
|
||||||
// overflow their next generation.
|
// overflow their next generation.
|
||||||
ASSERT(mObjects[id].generation != 0);
|
ASSERT(handle.generation != 0);
|
||||||
|
ASSERT(mObjects[handle.id] == nullptr);
|
||||||
mObjects[id].object = std::move(object);
|
mObjects[handle.id] = std::move(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mObjects[id];
|
return mObjects[handle.id].get();
|
||||||
}
|
}
|
||||||
void Free(T* obj) {
|
void Free(T* obj) {
|
||||||
ASSERT(obj->IsInList());
|
ASSERT(obj->IsInList());
|
||||||
if (DAWN_LIKELY(mObjects[obj->id].generation != std::numeric_limits<uint32_t>::max())) {
|
// The wire reuses ID for objects to keep them in a packed array starting from 0.
|
||||||
// Only recycle this ObjectId if the generation won't overflow on the next
|
// To avoid issues with asynchronous server->client communication referring to an ID that's
|
||||||
// allocation.
|
// already reused, each handle also has a generation that's increment by one on each reuse.
|
||||||
FreeId(obj->id);
|
// 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[obj->id].object = nullptr;
|
mObjects[currentHandle.id] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* GetObject(uint32_t id) {
|
T* GetObject(uint32_t id) {
|
||||||
if (id >= mObjects.size()) {
|
if (id >= mObjects.size()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return mObjects[id].object.get();
|
return mObjects[id].get();
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t GetGeneration(uint32_t id) {
|
|
||||||
if (id >= mObjects.size()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return mObjects[id].generation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t GetNewId() {
|
ObjectHandle GetFreeHandle() {
|
||||||
if (mFreeIds.empty()) {
|
if (mFreeHandles.empty()) {
|
||||||
return mCurrentId++;
|
return {mCurrentId++, 0};
|
||||||
}
|
}
|
||||||
uint32_t id = mFreeIds.back();
|
ObjectHandle handle = mFreeHandles.back();
|
||||||
mFreeIds.pop_back();
|
mFreeHandles.pop_back();
|
||||||
return id;
|
return handle;
|
||||||
}
|
}
|
||||||
void FreeId(uint32_t id) { mFreeIds.push_back(id); }
|
|
||||||
|
|
||||||
// 0 is an ID reserved to represent nullptr
|
// 0 is an ID reserved to represent nullptr
|
||||||
uint32_t mCurrentId = 1;
|
uint32_t mCurrentId = 1;
|
||||||
std::vector<uint32_t> mFreeIds;
|
std::vector<ObjectHandle> mFreeHandles;
|
||||||
std::vector<ObjectAndSerial> mObjects;
|
std::vector<std::unique_ptr<T>> mObjects;
|
||||||
};
|
};
|
||||||
} // namespace dawn::wire::client
|
} // namespace dawn::wire::client
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,22 @@
|
||||||
namespace dawn::wire::client {
|
namespace dawn::wire::client {
|
||||||
|
|
||||||
ObjectBase::ObjectBase(const ObjectBaseParams& params)
|
ObjectBase::ObjectBase(const ObjectBaseParams& params)
|
||||||
: client(params.client), refcount(1), id(params.id) {}
|
: client(params.client), refcount(1), mHandle(params.handle) {}
|
||||||
|
|
||||||
ObjectBase::~ObjectBase() {
|
ObjectBase::~ObjectBase() {
|
||||||
RemoveFromList();
|
RemoveFromList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ObjectHandle& ObjectBase::GetWireHandle() const {
|
||||||
|
return mHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectId ObjectBase::GetWireId() const {
|
||||||
|
return mHandle.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectGeneration ObjectBase::GetWireGeneration() const {
|
||||||
|
return mHandle.generation;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::wire::client
|
} // namespace dawn::wire::client
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "dawn/webgpu.h"
|
#include "dawn/webgpu.h"
|
||||||
|
|
||||||
#include "dawn/common/LinkedList.h"
|
#include "dawn/common/LinkedList.h"
|
||||||
#include "dawn/wire/ObjectType_autogen.h"
|
|
||||||
#include "dawn/wire/ObjectHandle.h"
|
#include "dawn/wire/ObjectHandle.h"
|
||||||
|
|
||||||
namespace dawn::wire::client {
|
namespace dawn::wire::client {
|
||||||
|
@ -27,7 +26,7 @@ class Client;
|
||||||
|
|
||||||
struct ObjectBaseParams {
|
struct ObjectBaseParams {
|
||||||
Client* client;
|
Client* client;
|
||||||
ObjectId id;
|
ObjectHandle handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
// All objects on the client side have:
|
// All objects on the client side have:
|
||||||
|
@ -35,15 +34,23 @@ struct ObjectBaseParams {
|
||||||
// - The external reference count, starting at 1.
|
// - The external reference count, starting at 1.
|
||||||
// - An ID that is used to refer to this object when talking with the server side
|
// - An ID that is used to refer to this object when talking with the server side
|
||||||
// - A next/prev pointer. They are part of a linked list of objects of the same type.
|
// - A next/prev pointer. They are part of a linked list of objects of the same type.
|
||||||
struct ObjectBase : public LinkNode<ObjectBase> {
|
class ObjectBase : public LinkNode<ObjectBase> {
|
||||||
|
public:
|
||||||
explicit ObjectBase(const ObjectBaseParams& params);
|
explicit ObjectBase(const ObjectBaseParams& params);
|
||||||
~ObjectBase();
|
~ObjectBase();
|
||||||
|
|
||||||
virtual void CancelCallbacksForDisconnect() {}
|
virtual void CancelCallbacksForDisconnect() {}
|
||||||
|
|
||||||
|
const ObjectHandle& GetWireHandle() const;
|
||||||
|
ObjectId GetWireId() const;
|
||||||
|
ObjectGeneration GetWireGeneration() const;
|
||||||
|
|
||||||
|
// TODO(dawn:1451): Make these members private.
|
||||||
Client* const client;
|
Client* const client;
|
||||||
uint32_t refcount;
|
uint32_t refcount;
|
||||||
const ObjectId id;
|
|
||||||
|
private:
|
||||||
|
const ObjectHandle mHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::wire::client
|
} // namespace dawn::wire::client
|
||||||
|
|
|
@ -22,19 +22,18 @@ 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->client;
|
Client* wireClient = device->client;
|
||||||
auto* objectAndSerial = wireClient->QuerySetAllocator().New(wireClient);
|
QuerySet* querySet = wireClient->QuerySetAllocator().New(wireClient);
|
||||||
|
|
||||||
// Copy over descriptor data for reflection.
|
// Copy over descriptor data for reflection.
|
||||||
QuerySet* querySet = objectAndSerial->object.get();
|
|
||||||
querySet->mType = descriptor->type;
|
querySet->mType = descriptor->type;
|
||||||
querySet->mCount = descriptor->count;
|
querySet->mCount = descriptor->count;
|
||||||
|
|
||||||
// Send the Device::CreateQuerySet command without modifications.
|
// Send the Device::CreateQuerySet command without modifications.
|
||||||
DeviceCreateQuerySetCmd cmd;
|
DeviceCreateQuerySetCmd cmd;
|
||||||
cmd.self = ToAPI(device);
|
cmd.self = ToAPI(device);
|
||||||
cmd.selfId = device->id;
|
cmd.selfId = device->GetWireId();
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
cmd.result = ObjectHandle{querySet->id, objectAndSerial->generation};
|
cmd.result = querySet->GetWireHandle();
|
||||||
wireClient->SerializeCommand(cmd);
|
wireClient->SerializeCommand(cmd);
|
||||||
|
|
||||||
return ToAPI(querySet);
|
return ToAPI(querySet);
|
||||||
|
|
|
@ -44,7 +44,7 @@ void Queue::OnSubmittedWorkDone(uint64_t signalValue,
|
||||||
uint64_t serial = mOnWorkDoneRequests.Add({callback, userdata});
|
uint64_t serial = mOnWorkDoneRequests.Add({callback, userdata});
|
||||||
|
|
||||||
QueueOnSubmittedWorkDoneCmd cmd;
|
QueueOnSubmittedWorkDoneCmd cmd;
|
||||||
cmd.queueId = this->id;
|
cmd.queueId = GetWireId();
|
||||||
cmd.signalValue = signalValue;
|
cmd.signalValue = signalValue;
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ void Queue::WriteBuffer(WGPUBuffer cBuffer, uint64_t bufferOffset, const void* d
|
||||||
Buffer* buffer = FromAPI(cBuffer);
|
Buffer* buffer = FromAPI(cBuffer);
|
||||||
|
|
||||||
QueueWriteBufferCmd cmd;
|
QueueWriteBufferCmd cmd;
|
||||||
cmd.queueId = id;
|
cmd.queueId = GetWireId();
|
||||||
cmd.bufferId = buffer->id;
|
cmd.bufferId = buffer->GetWireId();
|
||||||
cmd.bufferOffset = bufferOffset;
|
cmd.bufferOffset = bufferOffset;
|
||||||
cmd.data = static_cast<const uint8_t*>(data);
|
cmd.data = static_cast<const uint8_t*>(data);
|
||||||
cmd.size = size;
|
cmd.size = size;
|
||||||
|
@ -70,7 +70,7 @@ void Queue::WriteTexture(const WGPUImageCopyTexture* destination,
|
||||||
const WGPUTextureDataLayout* dataLayout,
|
const WGPUTextureDataLayout* dataLayout,
|
||||||
const WGPUExtent3D* writeSize) {
|
const WGPUExtent3D* writeSize) {
|
||||||
QueueWriteTextureCmd cmd;
|
QueueWriteTextureCmd cmd;
|
||||||
cmd.queueId = id;
|
cmd.queueId = GetWireId();
|
||||||
cmd.destination = destination;
|
cmd.destination = destination;
|
||||||
cmd.data = static_cast<const uint8_t*>(data);
|
cmd.data = static_cast<const uint8_t*>(data);
|
||||||
cmd.dataSize = dataSize;
|
cmd.dataSize = dataSize;
|
||||||
|
|
|
@ -31,7 +31,7 @@ void ShaderModule::GetCompilationInfo(WGPUCompilationInfoCallback callback, void
|
||||||
uint64_t serial = mCompilationInfoRequests.Add({callback, userdata});
|
uint64_t serial = mCompilationInfoRequests.Add({callback, userdata});
|
||||||
|
|
||||||
ShaderModuleGetCompilationInfoCmd cmd;
|
ShaderModuleGetCompilationInfoCmd cmd;
|
||||||
cmd.shaderModuleId = this->id;
|
cmd.shaderModuleId = GetWireId();
|
||||||
cmd.requestSerial = serial;
|
cmd.requestSerial = serial;
|
||||||
|
|
||||||
client->SerializeCommand(cmd);
|
client->SerializeCommand(cmd);
|
||||||
|
|
|
@ -22,10 +22,9 @@ 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->client;
|
Client* wireClient = device->client;
|
||||||
auto* textureObjectAndSerial = wireClient->TextureAllocator().New(wireClient);
|
Texture* texture = wireClient->TextureAllocator().New(wireClient);
|
||||||
|
|
||||||
// Copy over descriptor data for reflection.
|
// Copy over descriptor data for reflection.
|
||||||
Texture* texture = textureObjectAndSerial->object.get();
|
|
||||||
texture->mSize = descriptor->size;
|
texture->mSize = descriptor->size;
|
||||||
texture->mMipLevelCount = descriptor->mipLevelCount;
|
texture->mMipLevelCount = descriptor->mipLevelCount;
|
||||||
texture->mSampleCount = descriptor->sampleCount;
|
texture->mSampleCount = descriptor->sampleCount;
|
||||||
|
@ -36,9 +35,9 @@ WGPUTexture Texture::Create(Device* device, const WGPUTextureDescriptor* descrip
|
||||||
// Send the Device::CreateTexture command without modifications.
|
// Send the Device::CreateTexture command without modifications.
|
||||||
DeviceCreateTextureCmd cmd;
|
DeviceCreateTextureCmd cmd;
|
||||||
cmd.self = ToAPI(device);
|
cmd.self = ToAPI(device);
|
||||||
cmd.selfId = device->id;
|
cmd.selfId = device->GetWireId();
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
cmd.result = ObjectHandle{texture->id, textureObjectAndSerial->generation};
|
cmd.result = texture->GetWireHandle();
|
||||||
wireClient->SerializeCommand(cmd);
|
wireClient->SerializeCommand(cmd);
|
||||||
|
|
||||||
return ToAPI(texture);
|
return ToAPI(texture);
|
||||||
|
|
Loading…
Reference in New Issue