dawn_wire: Implement requestAdapter and requestDevice
This implements requestAdapter and requestDevice by forwarding commands the the server and relaying back replies. After an adapter or device is created, limits/properties/features are queried and also sent back to the client. Bug: dawn:689 Change-Id: Ie0c2984b8ebb661efb0c284a14ae8b74ae4af2ea Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/71522 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
736dd07303
commit
07e766728a
|
@ -84,6 +84,18 @@
|
|||
"shader module get compilation info": [
|
||||
{ "name": "shader module id", "type": "ObjectId" },
|
||||
{ "name": "request serial", "type": "uint64_t" }
|
||||
],
|
||||
"instance request adapter": [
|
||||
{ "name": "instance id", "type": "ObjectId" },
|
||||
{ "name": "request serial", "type": "uint64_t" },
|
||||
{ "name": "adapter object handle", "type": "ObjectHandle", "handle_type": "adapter"},
|
||||
{ "name": "options", "type": "request adapter options", "annotation": "const*" }
|
||||
],
|
||||
"adapter request device": [
|
||||
{ "name": "adapter id", "type": "ObjectId" },
|
||||
{ "name": "request serial", "type": "uint64_t" },
|
||||
{ "name": "device object handle", "type": "ObjectHandle", "handle_type": "device"},
|
||||
{ "name": "descriptor", "type": "device descriptor", "annotation": "const*" }
|
||||
]
|
||||
},
|
||||
"return commands": {
|
||||
|
@ -137,6 +149,25 @@
|
|||
{ "name": "request serial", "type": "uint64_t" },
|
||||
{ "name": "status", "type": "compilation info request status" },
|
||||
{ "name": "info", "type": "compilation info", "annotation": "const*", "optional": true }
|
||||
],
|
||||
"instance request adapter callback": [
|
||||
{ "name": "instance", "type": "ObjectHandle", "handle_type": "instance" },
|
||||
{ "name": "request serial", "type": "uint64_t" },
|
||||
{ "name": "status", "type": "request adapter status" },
|
||||
{ "name": "message", "type": "char", "annotation": "const*", "length": "strlen", "optional": true },
|
||||
{ "name": "properties", "type": "adapter properties", "annotation": "const*", "optional": "true" },
|
||||
{ "name": "limits", "type": "supported limits", "annotation": "const*", "optional": "true" },
|
||||
{ "name": "features count", "type": "uint32_t"},
|
||||
{ "name": "features", "type": "feature name", "annotation": "const*", "length": "features count"}
|
||||
],
|
||||
"adapter request device callback": [
|
||||
{ "name": "adapter", "type": "ObjectHandle", "handle_type": "adapter" },
|
||||
{ "name": "request serial", "type": "uint64_t" },
|
||||
{ "name": "status", "type": "request device status" },
|
||||
{ "name": "message", "type": "char", "annotation": "const*", "length": "strlen", "optional": true },
|
||||
{ "name": "limits", "type": "supported limits", "annotation": "const*", "optional": "true" },
|
||||
{ "name": "features count", "type": "uint32_t"},
|
||||
{ "name": "features", "type": "feature name", "annotation": "const*", "length": "features count"}
|
||||
]
|
||||
},
|
||||
"special items": {
|
||||
|
|
|
@ -65,6 +65,8 @@ dawn_component("dawn_wire") {
|
|||
"ChunkedCommandHandler.h",
|
||||
"ChunkedCommandSerializer.cpp",
|
||||
"ChunkedCommandSerializer.h",
|
||||
"SupportedFeatures.cpp",
|
||||
"SupportedFeatures.h",
|
||||
"Wire.cpp",
|
||||
"WireClient.cpp",
|
||||
"WireDeserializeAllocator.cpp",
|
||||
|
@ -84,6 +86,8 @@ dawn_component("dawn_wire") {
|
|||
"client/Device.h",
|
||||
"client/Instance.cpp",
|
||||
"client/Instance.h",
|
||||
"client/LimitsAndFeatures.cpp",
|
||||
"client/LimitsAndFeatures.h",
|
||||
"client/ObjectAllocator.h",
|
||||
"client/Queue.cpp",
|
||||
"client/Queue.h",
|
||||
|
@ -93,9 +97,11 @@ dawn_component("dawn_wire") {
|
|||
"server/ObjectStorage.h",
|
||||
"server/Server.cpp",
|
||||
"server/Server.h",
|
||||
"server/ServerAdapter.cpp",
|
||||
"server/ServerBuffer.cpp",
|
||||
"server/ServerDevice.cpp",
|
||||
"server/ServerInlineMemoryTransferService.cpp",
|
||||
"server/ServerInstance.cpp",
|
||||
"server/ServerQueue.cpp",
|
||||
"server/ServerShaderModule.cpp",
|
||||
]
|
||||
|
|
|
@ -37,6 +37,8 @@ target_sources(dawn_wire PRIVATE
|
|||
"ChunkedCommandHandler.h"
|
||||
"ChunkedCommandSerializer.cpp"
|
||||
"ChunkedCommandSerializer.h"
|
||||
"SupportedFeatures.cpp"
|
||||
"SupportedFeatures.h"
|
||||
"Wire.cpp"
|
||||
"WireClient.cpp"
|
||||
"WireDeserializeAllocator.cpp"
|
||||
|
@ -56,6 +58,8 @@ target_sources(dawn_wire PRIVATE
|
|||
"client/Device.h"
|
||||
"client/Instance.cpp"
|
||||
"client/Instance.h"
|
||||
"client/LimitsAndFeatures.cpp"
|
||||
"client/LimitsAndFeatures.h"
|
||||
"client/ObjectAllocator.h"
|
||||
"client/Queue.cpp"
|
||||
"client/Queue.h"
|
||||
|
@ -65,9 +69,11 @@ target_sources(dawn_wire PRIVATE
|
|||
"server/ObjectStorage.h"
|
||||
"server/Server.cpp"
|
||||
"server/Server.h"
|
||||
"server/ServerAdapter.cpp"
|
||||
"server/ServerBuffer.cpp"
|
||||
"server/ServerDevice.cpp"
|
||||
"server/ServerInlineMemoryTransferService.cpp"
|
||||
"server/ServerInstance.cpp"
|
||||
"server/ServerQueue.cpp"
|
||||
"server/ServerShaderModule.cpp"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2021 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/SupportedFeatures.h"
|
||||
|
||||
namespace dawn_wire {
|
||||
|
||||
// Note: Upon updating this list, please also update serialization/deserialization
|
||||
// of limit structs on Adapter/Device initialization.
|
||||
bool IsFeatureSupported(WGPUFeatureName feature) {
|
||||
switch (feature) {
|
||||
case WGPUFeatureName_Undefined:
|
||||
case WGPUFeatureName_Force32:
|
||||
return false;
|
||||
case WGPUFeatureName_Depth24UnormStencil8:
|
||||
case WGPUFeatureName_Depth32FloatStencil8:
|
||||
case WGPUFeatureName_TimestampQuery:
|
||||
case WGPUFeatureName_PipelineStatisticsQuery:
|
||||
case WGPUFeatureName_TextureCompressionBC:
|
||||
case WGPUFeatureName_TextureCompressionETC2:
|
||||
case WGPUFeatureName_TextureCompressionASTC:
|
||||
case WGPUFeatureName_IndirectFirstInstance:
|
||||
case WGPUFeatureName_DepthClamping:
|
||||
case WGPUFeatureName_DawnShaderFloat16:
|
||||
case WGPUFeatureName_DawnInternalUsages:
|
||||
case WGPUFeatureName_DawnMultiPlanarFormats:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Catch-all, for unsupported features.
|
||||
// "default:" is not used so we get compiler errors for
|
||||
// newly added, unhandled features, but still catch completely
|
||||
// unknown enums.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dawn_wire
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2021 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_SUPPORTEDFEATURES_H_
|
||||
#define DAWNWIRE_SUPPORTEDFEATURES_H_
|
||||
|
||||
#include <dawn/webgpu.h>
|
||||
|
||||
namespace dawn_wire {
|
||||
|
||||
bool IsFeatureSupported(WGPUFeatureName feature);
|
||||
|
||||
} // namespace dawn_wire
|
||||
|
||||
#endif // DAWNWIRE_SUPPORTEDFEATURES_H_
|
|
@ -14,28 +14,114 @@
|
|||
|
||||
#include "dawn_wire/client/Adapter.h"
|
||||
|
||||
#include "dawn_wire/client/Client.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
bool Adapter::GetLimits(WGPUSupportedLimits* limits) const {
|
||||
UNREACHABLE();
|
||||
Adapter::~Adapter() {
|
||||
mRequestDeviceRequests.CloseAll([](RequestDeviceData* request) {
|
||||
request->callback(WGPURequestDeviceStatus_Unknown, nullptr,
|
||||
"Adapter destroyed before callback", request->userdata);
|
||||
});
|
||||
}
|
||||
|
||||
void Adapter::GetProperties(WGPUAdapterProperties* properties) const {
|
||||
UNREACHABLE();
|
||||
void Adapter::CancelCallbacksForDisconnect() {
|
||||
mRequestDeviceRequests.CloseAll([](RequestDeviceData* request) {
|
||||
request->callback(WGPURequestDeviceStatus_Unknown, nullptr, "GPU connection lost",
|
||||
request->userdata);
|
||||
});
|
||||
}
|
||||
|
||||
bool Adapter::GetLimits(WGPUSupportedLimits* limits) const {
|
||||
return mLimitsAndFeatures.GetLimits(limits);
|
||||
}
|
||||
|
||||
bool Adapter::HasFeature(WGPUFeatureName feature) const {
|
||||
UNREACHABLE();
|
||||
return mLimitsAndFeatures.HasFeature(feature);
|
||||
}
|
||||
|
||||
uint32_t Adapter::EnumerateFeatures(WGPUFeatureName* features) const {
|
||||
UNREACHABLE();
|
||||
return mLimitsAndFeatures.EnumerateFeatures(features);
|
||||
}
|
||||
|
||||
void Adapter::SetLimits(const WGPUSupportedLimits* limits) {
|
||||
return mLimitsAndFeatures.SetLimits(limits);
|
||||
}
|
||||
|
||||
void Adapter::SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount) {
|
||||
return mLimitsAndFeatures.SetFeatures(features, featuresCount);
|
||||
}
|
||||
|
||||
void Adapter::SetProperties(const WGPUAdapterProperties* properties) {
|
||||
mProperties = *properties;
|
||||
mProperties.nextInChain = nullptr;
|
||||
}
|
||||
|
||||
void Adapter::GetProperties(WGPUAdapterProperties* properties) const {
|
||||
*properties = mProperties;
|
||||
}
|
||||
|
||||
void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
|
||||
WGPURequestDeviceCallback callback,
|
||||
void* userdata) {
|
||||
callback(WGPURequestDeviceStatus_Error, nullptr, "Not implemented", nullptr);
|
||||
if (client->IsDisconnected()) {
|
||||
callback(WGPURequestDeviceStatus_Error, nullptr, "GPU connection lost", userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* allocation = client->DeviceAllocator().New(client);
|
||||
uint64_t serial = mRequestDeviceRequests.Add({callback, allocation->object->id, userdata});
|
||||
|
||||
AdapterRequestDeviceCmd cmd;
|
||||
cmd.adapterId = this->id;
|
||||
cmd.requestSerial = serial;
|
||||
cmd.deviceObjectHandle = ObjectHandle(allocation->object->id, allocation->generation);
|
||||
cmd.descriptor = descriptor;
|
||||
|
||||
client->SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
bool Client::DoAdapterRequestDeviceCallback(Adapter* adapter,
|
||||
uint64_t requestSerial,
|
||||
WGPURequestDeviceStatus status,
|
||||
const char* message,
|
||||
const WGPUSupportedLimits* limits,
|
||||
uint32_t featuresCount,
|
||||
const WGPUFeatureName* features) {
|
||||
// May have been deleted or recreated so this isn't an error.
|
||||
if (adapter == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return adapter->OnRequestDeviceCallback(requestSerial, status, message, limits,
|
||||
featuresCount, features);
|
||||
}
|
||||
|
||||
bool Adapter::OnRequestDeviceCallback(uint64_t requestSerial,
|
||||
WGPURequestDeviceStatus status,
|
||||
const char* message,
|
||||
const WGPUSupportedLimits* limits,
|
||||
uint32_t featuresCount,
|
||||
const WGPUFeatureName* features) {
|
||||
RequestDeviceData request;
|
||||
if (!mRequestDeviceRequests.Acquire(requestSerial, &request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Device* device = client->DeviceAllocator().GetObject(request.deviceObjectId);
|
||||
|
||||
// If the return status is a failure we should give a null device to the callback and
|
||||
// free the allocation.
|
||||
if (status != WGPURequestDeviceStatus_Success) {
|
||||
client->DeviceAllocator().Free(device);
|
||||
request.callback(status, nullptr, message, request.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
device->SetLimits(limits);
|
||||
device->SetFeatures(features, featuresCount);
|
||||
|
||||
request.callback(status, ToAPI(device), message, request.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::client
|
||||
|
|
|
@ -18,7 +18,10 @@
|
|||
#include <dawn/webgpu.h>
|
||||
|
||||
#include "dawn_wire/WireClient.h"
|
||||
#include "dawn_wire/WireCmd_autogen.h"
|
||||
#include "dawn_wire/client/LimitsAndFeatures.h"
|
||||
#include "dawn_wire/client/ObjectBase.h"
|
||||
#include "dawn_wire/client/RequestTracker.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
|
@ -26,13 +29,37 @@ namespace dawn_wire { namespace client {
|
|||
public:
|
||||
using ObjectBase::ObjectBase;
|
||||
|
||||
~Adapter();
|
||||
void CancelCallbacksForDisconnect() override;
|
||||
|
||||
bool GetLimits(WGPUSupportedLimits* limits) const;
|
||||
void GetProperties(WGPUAdapterProperties* properties) const;
|
||||
bool HasFeature(WGPUFeatureName feature) const;
|
||||
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
|
||||
void SetLimits(const WGPUSupportedLimits* limits);
|
||||
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
|
||||
void SetProperties(const WGPUAdapterProperties* properties);
|
||||
void GetProperties(WGPUAdapterProperties* properties) const;
|
||||
void RequestDevice(const WGPUDeviceDescriptor* descriptor,
|
||||
WGPURequestDeviceCallback callback,
|
||||
void* userdata);
|
||||
|
||||
bool OnRequestDeviceCallback(uint64_t requestSerial,
|
||||
WGPURequestDeviceStatus status,
|
||||
const char* message,
|
||||
const WGPUSupportedLimits* limits,
|
||||
uint32_t featuresCount,
|
||||
const WGPUFeatureName* features);
|
||||
|
||||
private:
|
||||
LimitsAndFeatures mLimitsAndFeatures;
|
||||
WGPUAdapterProperties mProperties;
|
||||
|
||||
struct RequestDeviceData {
|
||||
WGPURequestDeviceCallback callback = nullptr;
|
||||
ObjectId deviceObjectId;
|
||||
void* userdata = nullptr;
|
||||
};
|
||||
RequestTracker<RequestDeviceData> mRequestDeviceRequests;
|
||||
};
|
||||
|
||||
}} // namespace dawn_wire::client
|
||||
|
|
|
@ -67,6 +67,26 @@ namespace dawn_wire { namespace client {
|
|||
});
|
||||
}
|
||||
|
||||
bool Device::GetLimits(WGPUSupportedLimits* limits) const {
|
||||
return mLimitsAndFeatures.GetLimits(limits);
|
||||
}
|
||||
|
||||
bool Device::HasFeature(WGPUFeatureName feature) const {
|
||||
return mLimitsAndFeatures.HasFeature(feature);
|
||||
}
|
||||
|
||||
uint32_t Device::EnumerateFeatures(WGPUFeatureName* features) const {
|
||||
return mLimitsAndFeatures.EnumerateFeatures(features);
|
||||
}
|
||||
|
||||
void Device::SetLimits(const WGPUSupportedLimits* limits) {
|
||||
return mLimitsAndFeatures.SetLimits(limits);
|
||||
}
|
||||
|
||||
void Device::SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount) {
|
||||
return mLimitsAndFeatures.SetFeatures(features, featuresCount);
|
||||
}
|
||||
|
||||
void Device::HandleError(WGPUErrorType errorType, const char* message) {
|
||||
if (mErrorCallback) {
|
||||
mErrorCallback(errorType, message, mErrorUserdata);
|
||||
|
@ -196,20 +216,6 @@ namespace dawn_wire { namespace client {
|
|||
return Buffer::CreateError(this);
|
||||
}
|
||||
|
||||
bool Device::GetLimits(WGPUSupportedLimits* limits) const {
|
||||
// Not implemented in the wire.
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Device::HasFeature(WGPUFeatureName feature) const {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
uint32_t Device::EnumerateFeatures(WGPUFeatureName* features) const {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
WGPUQueue Device::GetQueue() {
|
||||
// The queue is lazily created because if a Device is created by
|
||||
// Reserve/Inject, we cannot send the GetQueue message until
|
||||
|
@ -269,7 +275,7 @@ namespace dawn_wire { namespace client {
|
|||
client->ComputePipelineAllocator().GetObject(request.pipelineObjectID);
|
||||
|
||||
// If the return status is a failure we should give a null pipeline to the callback and
|
||||
// free the allocation both on the client side and the server side.
|
||||
// free the allocation.
|
||||
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
||||
client->ComputePipelineAllocator().Free(pipelineAllocation);
|
||||
request.createComputePipelineAsyncCallback(status, nullptr, message, request.userdata);
|
||||
|
@ -320,7 +326,7 @@ namespace dawn_wire { namespace client {
|
|||
client->RenderPipelineAllocator().GetObject(request.pipelineObjectID);
|
||||
|
||||
// If the return status is a failure we should give a null pipeline to the callback and
|
||||
// free the allocation both on the client side and the server side.
|
||||
// free the allocation.
|
||||
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
||||
client->RenderPipelineAllocator().Free(pipelineAllocation);
|
||||
request.createRenderPipelineAsyncCallback(status, nullptr, message, request.userdata);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "common/LinkedList.h"
|
||||
#include "dawn_wire/WireCmd_autogen.h"
|
||||
#include "dawn_wire/client/ApiObjects_autogen.h"
|
||||
#include "dawn_wire/client/LimitsAndFeatures.h"
|
||||
#include "dawn_wire/client/ObjectBase.h"
|
||||
#include "dawn_wire/client/RequestTracker.h"
|
||||
|
||||
|
@ -67,6 +68,9 @@ namespace dawn_wire { namespace client {
|
|||
bool GetLimits(WGPUSupportedLimits* limits) const;
|
||||
bool HasFeature(WGPUFeatureName feature) const;
|
||||
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
|
||||
void SetLimits(const WGPUSupportedLimits* limits);
|
||||
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
|
||||
|
||||
WGPUQueue GetQueue();
|
||||
|
||||
void CancelCallbacksForDisconnect() override;
|
||||
|
@ -74,6 +78,7 @@ namespace dawn_wire { namespace client {
|
|||
std::weak_ptr<bool> GetAliveWeakPtr();
|
||||
|
||||
private:
|
||||
LimitsAndFeatures mLimitsAndFeatures;
|
||||
struct ErrorScopeData {
|
||||
WGPUErrorCallback callback = nullptr;
|
||||
void* userdata = nullptr;
|
||||
|
|
|
@ -14,12 +14,88 @@
|
|||
|
||||
#include "dawn_wire/client/Instance.h"
|
||||
|
||||
#include "dawn_wire/client/Client.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
Instance::~Instance() {
|
||||
mRequestAdapterRequests.CloseAll([](RequestAdapterData* request) {
|
||||
request->callback(WGPURequestAdapterStatus_Unknown, nullptr,
|
||||
"Instance destroyed before callback", request->userdata);
|
||||
});
|
||||
}
|
||||
|
||||
void Instance::CancelCallbacksForDisconnect() {
|
||||
mRequestAdapterRequests.CloseAll([](RequestAdapterData* request) {
|
||||
request->callback(WGPURequestAdapterStatus_Unknown, nullptr, "GPU connection lost",
|
||||
request->userdata);
|
||||
});
|
||||
}
|
||||
|
||||
void Instance::RequestAdapter(const WGPURequestAdapterOptions* options,
|
||||
WGPURequestAdapterCallback callback,
|
||||
void* userdata) {
|
||||
callback(WGPURequestAdapterStatus_Error, nullptr, "Not implemented", nullptr);
|
||||
if (client->IsDisconnected()) {
|
||||
callback(WGPURequestAdapterStatus_Error, nullptr, "GPU connection lost", userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* allocation = client->AdapterAllocator().New(client);
|
||||
uint64_t serial = mRequestAdapterRequests.Add({callback, allocation->object->id, userdata});
|
||||
|
||||
InstanceRequestAdapterCmd cmd;
|
||||
cmd.instanceId = this->id;
|
||||
cmd.requestSerial = serial;
|
||||
cmd.adapterObjectHandle = ObjectHandle(allocation->object->id, allocation->generation);
|
||||
cmd.options = options;
|
||||
|
||||
client->SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
bool Client::DoInstanceRequestAdapterCallback(Instance* instance,
|
||||
uint64_t requestSerial,
|
||||
WGPURequestAdapterStatus status,
|
||||
const char* message,
|
||||
const WGPUAdapterProperties* properties,
|
||||
const WGPUSupportedLimits* limits,
|
||||
uint32_t featuresCount,
|
||||
const WGPUFeatureName* features) {
|
||||
// May have been deleted or recreated so this isn't an error.
|
||||
if (instance == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return instance->OnRequestAdapterCallback(requestSerial, status, message, properties,
|
||||
limits, featuresCount, features);
|
||||
}
|
||||
|
||||
bool Instance::OnRequestAdapterCallback(uint64_t requestSerial,
|
||||
WGPURequestAdapterStatus status,
|
||||
const char* message,
|
||||
const WGPUAdapterProperties* properties,
|
||||
const WGPUSupportedLimits* limits,
|
||||
uint32_t featuresCount,
|
||||
const WGPUFeatureName* features) {
|
||||
RequestAdapterData request;
|
||||
if (!mRequestAdapterRequests.Acquire(requestSerial, &request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Adapter* adapter = client->AdapterAllocator().GetObject(request.adapterObjectId);
|
||||
|
||||
// If the return status is a failure we should give a null adapter to the callback and
|
||||
// free the allocation.
|
||||
if (status != WGPURequestAdapterStatus_Success) {
|
||||
client->AdapterAllocator().Free(adapter);
|
||||
request.callback(status, nullptr, message, request.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
adapter->SetProperties(properties);
|
||||
adapter->SetLimits(limits);
|
||||
adapter->SetFeatures(features, featuresCount);
|
||||
|
||||
request.callback(status, ToAPI(adapter), message, request.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::client
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
#include <dawn/webgpu.h>
|
||||
|
||||
#include "dawn_wire/WireClient.h"
|
||||
#include "dawn_wire/WireCmd_autogen.h"
|
||||
#include "dawn_wire/client/ObjectBase.h"
|
||||
#include "dawn_wire/client/RequestTracker.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
|
@ -26,9 +28,27 @@ namespace dawn_wire { namespace client {
|
|||
public:
|
||||
using ObjectBase::ObjectBase;
|
||||
|
||||
~Instance();
|
||||
void CancelCallbacksForDisconnect() override;
|
||||
|
||||
void RequestAdapter(const WGPURequestAdapterOptions* options,
|
||||
WGPURequestAdapterCallback callback,
|
||||
void* userdata);
|
||||
bool OnRequestAdapterCallback(uint64_t requestSerial,
|
||||
WGPURequestAdapterStatus status,
|
||||
const char* message,
|
||||
const WGPUAdapterProperties* properties,
|
||||
const WGPUSupportedLimits* limits,
|
||||
uint32_t featuresCount,
|
||||
const WGPUFeatureName* features);
|
||||
|
||||
private:
|
||||
struct RequestAdapterData {
|
||||
WGPURequestAdapterCallback callback = nullptr;
|
||||
ObjectId adapterObjectId;
|
||||
void* userdata = nullptr;
|
||||
};
|
||||
RequestTracker<RequestAdapterData> mRequestAdapterRequests;
|
||||
};
|
||||
|
||||
}} // namespace dawn_wire::client
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2021 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/LimitsAndFeatures.h"
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "dawn_wire/SupportedFeatures.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
bool LimitsAndFeatures::GetLimits(WGPUSupportedLimits* limits) const {
|
||||
ASSERT(limits != nullptr);
|
||||
if (limits->nextInChain != nullptr) {
|
||||
return false;
|
||||
}
|
||||
*limits = mLimits;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LimitsAndFeatures::HasFeature(WGPUFeatureName feature) const {
|
||||
return mFeatures.count(feature) != 0;
|
||||
}
|
||||
|
||||
uint32_t LimitsAndFeatures::EnumerateFeatures(WGPUFeatureName* features) const {
|
||||
if (features != nullptr) {
|
||||
for (WGPUFeatureName f : mFeatures) {
|
||||
*features = f;
|
||||
++features;
|
||||
}
|
||||
}
|
||||
return mFeatures.size();
|
||||
}
|
||||
|
||||
void LimitsAndFeatures::SetLimits(const WGPUSupportedLimits* limits) {
|
||||
ASSERT(limits != nullptr);
|
||||
mLimits = *limits;
|
||||
mLimits.nextInChain = nullptr;
|
||||
}
|
||||
|
||||
void LimitsAndFeatures::SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount) {
|
||||
ASSERT(features != nullptr || featuresCount == 0);
|
||||
for (uint32_t i = 0; i < featuresCount; ++i) {
|
||||
// Filter out features that the server supports, but the client does not.
|
||||
// (Could be different versions)
|
||||
if (!IsFeatureSupported(features[i])) {
|
||||
continue;
|
||||
}
|
||||
mFeatures.insert(features[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::client
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2021 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_LIMITSANDFEATURES_H_
|
||||
#define DAWNWIRE_CLIENT_LIMITSANDFEATURES_H_
|
||||
|
||||
#include <dawn/webgpu.h>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
class LimitsAndFeatures {
|
||||
public:
|
||||
bool GetLimits(WGPUSupportedLimits* limits) const;
|
||||
bool HasFeature(WGPUFeatureName feature) const;
|
||||
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
|
||||
|
||||
void SetLimits(const WGPUSupportedLimits* limits);
|
||||
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
|
||||
|
||||
private:
|
||||
WGPUSupportedLimits mLimits;
|
||||
std::unordered_set<WGPUFeatureName> mFeatures;
|
||||
};
|
||||
|
||||
}} // namespace dawn_wire::client
|
||||
|
||||
#endif // DAWNWIRE_CLIENT_LIMITSANDFEATURES_H_
|
|
@ -122,34 +122,7 @@ namespace dawn_wire { namespace server {
|
|||
mProcs.deviceReference(device);
|
||||
|
||||
// Set callbacks to forward errors to the client.
|
||||
// Note: these callbacks are manually inlined here since they do not acquire and
|
||||
// free their userdata. Also unlike other callbacks, these are cleared and unset when
|
||||
// the server is destroyed, so we don't need to check if the server is still alive
|
||||
// inside them.
|
||||
mProcs.deviceSetUncapturedErrorCallback(
|
||||
device,
|
||||
[](WGPUErrorType type, const char* message, void* userdata) {
|
||||
DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
|
||||
info->server->OnUncapturedError(info->self, type, message);
|
||||
},
|
||||
data->info.get());
|
||||
// Set callback to post warning and other infomation to client.
|
||||
// Almost the same with UncapturedError.
|
||||
mProcs.deviceSetLoggingCallback(
|
||||
device,
|
||||
[](WGPULoggingType type, const char* message, void* userdata) {
|
||||
DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
|
||||
info->server->OnLogging(info->self, type, message);
|
||||
},
|
||||
data->info.get());
|
||||
mProcs.deviceSetDeviceLostCallback(
|
||||
device,
|
||||
[](WGPUDeviceLostReason reason, const char* message, void* userdata) {
|
||||
DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
|
||||
info->server->OnDeviceLost(info->self, reason, message);
|
||||
},
|
||||
data->info.get());
|
||||
|
||||
SetForwardingDeviceCallbacks(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -179,6 +152,36 @@ namespace dawn_wire { namespace server {
|
|||
return data->handle;
|
||||
}
|
||||
|
||||
void Server::SetForwardingDeviceCallbacks(ObjectData<WGPUDevice>* deviceObject) {
|
||||
// Note: these callbacks are manually inlined here since they do not acquire and
|
||||
// free their userdata. Also unlike other callbacks, these are cleared and unset when
|
||||
// the server is destroyed, so we don't need to check if the server is still alive
|
||||
// inside them.
|
||||
mProcs.deviceSetUncapturedErrorCallback(
|
||||
deviceObject->handle,
|
||||
[](WGPUErrorType type, const char* message, void* userdata) {
|
||||
DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
|
||||
info->server->OnUncapturedError(info->self, type, message);
|
||||
},
|
||||
deviceObject->info.get());
|
||||
// Set callback to post warning and other infomation to client.
|
||||
// Almost the same with UncapturedError.
|
||||
mProcs.deviceSetLoggingCallback(
|
||||
deviceObject->handle,
|
||||
[](WGPULoggingType type, const char* message, void* userdata) {
|
||||
DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
|
||||
info->server->OnLogging(info->self, type, message);
|
||||
},
|
||||
deviceObject->info.get());
|
||||
mProcs.deviceSetDeviceLostCallback(
|
||||
deviceObject->handle,
|
||||
[](WGPUDeviceLostReason reason, const char* message, void* userdata) {
|
||||
DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
|
||||
info->server->OnDeviceLost(info->self, reason, message);
|
||||
},
|
||||
deviceObject->info.get());
|
||||
}
|
||||
|
||||
void Server::ClearDeviceCallbacks(WGPUDevice device) {
|
||||
// Un-set the error and lost callbacks since we cannot forward them
|
||||
// after the server has been destroyed.
|
||||
|
|
|
@ -146,6 +146,22 @@ namespace dawn_wire { namespace server {
|
|||
ObjectId pipelineObjectID;
|
||||
};
|
||||
|
||||
struct RequestAdapterUserdata : CallbackUserdata {
|
||||
using CallbackUserdata::CallbackUserdata;
|
||||
|
||||
ObjectHandle instance;
|
||||
uint64_t requestSerial;
|
||||
ObjectId adapterObjectId;
|
||||
};
|
||||
|
||||
struct RequestDeviceUserdata : CallbackUserdata {
|
||||
using CallbackUserdata::CallbackUserdata;
|
||||
|
||||
ObjectHandle adapter;
|
||||
uint64_t requestSerial;
|
||||
ObjectId deviceObjectId;
|
||||
};
|
||||
|
||||
class Server : public ServerBase {
|
||||
public:
|
||||
Server(const DawnProcTable& procs,
|
||||
|
@ -194,6 +210,7 @@ namespace dawn_wire { namespace server {
|
|||
mSerializer.SerializeCommand(cmd, extraSize, SerializeExtraSize);
|
||||
}
|
||||
|
||||
void SetForwardingDeviceCallbacks(ObjectData<WGPUDevice>* deviceObject);
|
||||
void ClearDeviceCallbacks(WGPUDevice device);
|
||||
|
||||
// Error callbacks
|
||||
|
@ -216,6 +233,14 @@ namespace dawn_wire { namespace server {
|
|||
void OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
|
||||
const WGPUCompilationInfo* info,
|
||||
ShaderModuleGetCompilationInfoUserdata* userdata);
|
||||
void OnRequestAdapterCallback(WGPURequestAdapterStatus status,
|
||||
WGPUAdapter adapter,
|
||||
const char* message,
|
||||
RequestAdapterUserdata* userdata);
|
||||
void OnRequestDeviceCallback(WGPURequestDeviceStatus status,
|
||||
WGPUDevice device,
|
||||
const char* message,
|
||||
RequestDeviceUserdata* userdata);
|
||||
|
||||
#include "dawn_wire/server/ServerPrototypes_autogen.inc"
|
||||
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2021 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/server/Server.h"
|
||||
|
||||
#include "dawn_wire/SupportedFeatures.h"
|
||||
|
||||
namespace dawn_wire { namespace server {
|
||||
|
||||
bool Server::DoAdapterRequestDevice(ObjectId adapterId,
|
||||
uint64_t requestSerial,
|
||||
ObjectHandle deviceHandle,
|
||||
const WGPUDeviceDescriptor* descriptor) {
|
||||
auto* adapter = AdapterObjects().Get(adapterId);
|
||||
if (adapter == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* resultData = DeviceObjects().Allocate(deviceHandle.id, AllocationState::Reserved);
|
||||
if (resultData == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
resultData->generation = deviceHandle.generation;
|
||||
|
||||
auto userdata = MakeUserdata<RequestDeviceUserdata>();
|
||||
userdata->adapter = ObjectHandle{adapterId, adapter->generation};
|
||||
userdata->requestSerial = requestSerial;
|
||||
userdata->deviceObjectId = deviceHandle.id;
|
||||
|
||||
mProcs.adapterRequestDevice(
|
||||
adapter->handle, descriptor,
|
||||
ForwardToServer<decltype(
|
||||
&Server::OnRequestDeviceCallback)>::Func<&Server::OnRequestDeviceCallback>(),
|
||||
userdata.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::OnRequestDeviceCallback(WGPURequestDeviceStatus status,
|
||||
WGPUDevice device,
|
||||
const char* message,
|
||||
RequestDeviceUserdata* data) {
|
||||
auto* deviceObject = DeviceObjects().Get(data->deviceObjectId, AllocationState::Reserved);
|
||||
// Should be impossible to fail. ObjectIds can't be freed by a destroy command until
|
||||
// they move from Reserved to Allocated, or if they are destroyed here.
|
||||
ASSERT(deviceObject != nullptr);
|
||||
|
||||
ReturnAdapterRequestDeviceCallbackCmd cmd = {};
|
||||
cmd.adapter = data->adapter;
|
||||
cmd.requestSerial = data->requestSerial;
|
||||
cmd.status = status;
|
||||
cmd.message = message;
|
||||
|
||||
if (status != WGPURequestDeviceStatus_Success) {
|
||||
// Free the ObjectId which will make it unusable.
|
||||
DeviceObjects().Free(data->deviceObjectId);
|
||||
ASSERT(device == nullptr);
|
||||
SerializeCommand(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<WGPUFeatureName> features;
|
||||
|
||||
uint32_t featuresCount = mProcs.deviceEnumerateFeatures(device, nullptr);
|
||||
features.resize(featuresCount);
|
||||
mProcs.deviceEnumerateFeatures(device, features.data());
|
||||
|
||||
// The client should only be able to request supported features, so all enumerated
|
||||
// features that were enabled must also be supported by the wire.
|
||||
// Note: We fail the callback here, instead of immediately upon receiving
|
||||
// the request to preserve callback ordering.
|
||||
for (WGPUFeatureName f : features) {
|
||||
if (!IsFeatureSupported(f)) {
|
||||
// Release the device.
|
||||
mProcs.deviceRelease(device);
|
||||
// Free the ObjectId which will make it unusable.
|
||||
DeviceObjects().Free(data->deviceObjectId);
|
||||
|
||||
cmd.status = WGPURequestDeviceStatus_Error;
|
||||
cmd.message = "Requested feature not supported.";
|
||||
SerializeCommand(cmd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cmd.featuresCount = features.size();
|
||||
cmd.features = features.data();
|
||||
|
||||
WGPUSupportedLimits limits = {};
|
||||
mProcs.deviceGetLimits(device, &limits);
|
||||
cmd.limits = &limits;
|
||||
|
||||
// Assign the handle and allocated status if the device is created successfully.
|
||||
deviceObject->state = AllocationState::Allocated;
|
||||
deviceObject->handle = device;
|
||||
SetForwardingDeviceCallbacks(deviceObject);
|
||||
|
||||
SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::server
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2021 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/server/Server.h"
|
||||
|
||||
#include "dawn_wire/SupportedFeatures.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace dawn_wire { namespace server {
|
||||
|
||||
bool Server::DoInstanceRequestAdapter(ObjectId instanceId,
|
||||
uint64_t requestSerial,
|
||||
ObjectHandle adapterHandle,
|
||||
const WGPURequestAdapterOptions* options) {
|
||||
auto* instance = InstanceObjects().Get(instanceId);
|
||||
if (instance == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* resultData = AdapterObjects().Allocate(adapterHandle.id, AllocationState::Reserved);
|
||||
if (resultData == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
resultData->generation = adapterHandle.generation;
|
||||
|
||||
auto userdata = MakeUserdata<RequestAdapterUserdata>();
|
||||
userdata->instance = ObjectHandle{instanceId, instance->generation};
|
||||
userdata->requestSerial = requestSerial;
|
||||
userdata->adapterObjectId = adapterHandle.id;
|
||||
|
||||
mProcs.instanceRequestAdapter(
|
||||
instance->handle, options,
|
||||
ForwardToServer<decltype(
|
||||
&Server::OnRequestAdapterCallback)>::Func<&Server::OnRequestAdapterCallback>(),
|
||||
userdata.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::OnRequestAdapterCallback(WGPURequestAdapterStatus status,
|
||||
WGPUAdapter adapter,
|
||||
const char* message,
|
||||
RequestAdapterUserdata* data) {
|
||||
auto* adapterObject =
|
||||
AdapterObjects().Get(data->adapterObjectId, AllocationState::Reserved);
|
||||
// Should be impossible to fail. ObjectIds can't be freed by a destroy command until
|
||||
// they move from Reserved to Allocated, or if they are destroyed here.
|
||||
ASSERT(adapterObject != nullptr);
|
||||
|
||||
ReturnInstanceRequestAdapterCallbackCmd cmd = {};
|
||||
cmd.instance = data->instance;
|
||||
cmd.requestSerial = data->requestSerial;
|
||||
cmd.status = status;
|
||||
cmd.message = message;
|
||||
|
||||
if (status != WGPURequestAdapterStatus_Success) {
|
||||
// Free the ObjectId which will make it unusable.
|
||||
AdapterObjects().Free(data->adapterObjectId);
|
||||
ASSERT(adapter == nullptr);
|
||||
SerializeCommand(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
WGPUAdapterProperties properties = {};
|
||||
WGPUSupportedLimits limits = {};
|
||||
std::vector<WGPUFeatureName> features;
|
||||
|
||||
// Assign the handle and allocated status if the adapter is created successfully.
|
||||
adapterObject->state = AllocationState::Allocated;
|
||||
adapterObject->handle = adapter;
|
||||
|
||||
uint32_t featuresCount = mProcs.adapterEnumerateFeatures(adapter, nullptr);
|
||||
features.resize(featuresCount);
|
||||
mProcs.adapterEnumerateFeatures(adapter, features.data());
|
||||
|
||||
// Hide features the wire cannot support.
|
||||
auto it = std::partition(features.begin(), features.end(), IsFeatureSupported);
|
||||
|
||||
cmd.featuresCount = std::distance(features.begin(), it);
|
||||
cmd.features = features.data();
|
||||
|
||||
mProcs.adapterGetProperties(adapter, &properties);
|
||||
mProcs.adapterGetLimits(adapter, &limits);
|
||||
cmd.properties = &properties;
|
||||
cmd.limits = &limits;
|
||||
|
||||
SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::server
|
Loading…
Reference in New Issue