mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-13 19:01:24 +00:00
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": [
|
"shader module get compilation info": [
|
||||||
{ "name": "shader module id", "type": "ObjectId" },
|
{ "name": "shader module id", "type": "ObjectId" },
|
||||||
{ "name": "request serial", "type": "uint64_t" }
|
{ "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": {
|
"return commands": {
|
||||||
@ -137,6 +149,25 @@
|
|||||||
{ "name": "request serial", "type": "uint64_t" },
|
{ "name": "request serial", "type": "uint64_t" },
|
||||||
{ "name": "status", "type": "compilation info request status" },
|
{ "name": "status", "type": "compilation info request status" },
|
||||||
{ "name": "info", "type": "compilation info", "annotation": "const*", "optional": true }
|
{ "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": {
|
"special items": {
|
||||||
|
@ -65,6 +65,8 @@ dawn_component("dawn_wire") {
|
|||||||
"ChunkedCommandHandler.h",
|
"ChunkedCommandHandler.h",
|
||||||
"ChunkedCommandSerializer.cpp",
|
"ChunkedCommandSerializer.cpp",
|
||||||
"ChunkedCommandSerializer.h",
|
"ChunkedCommandSerializer.h",
|
||||||
|
"SupportedFeatures.cpp",
|
||||||
|
"SupportedFeatures.h",
|
||||||
"Wire.cpp",
|
"Wire.cpp",
|
||||||
"WireClient.cpp",
|
"WireClient.cpp",
|
||||||
"WireDeserializeAllocator.cpp",
|
"WireDeserializeAllocator.cpp",
|
||||||
@ -84,6 +86,8 @@ dawn_component("dawn_wire") {
|
|||||||
"client/Device.h",
|
"client/Device.h",
|
||||||
"client/Instance.cpp",
|
"client/Instance.cpp",
|
||||||
"client/Instance.h",
|
"client/Instance.h",
|
||||||
|
"client/LimitsAndFeatures.cpp",
|
||||||
|
"client/LimitsAndFeatures.h",
|
||||||
"client/ObjectAllocator.h",
|
"client/ObjectAllocator.h",
|
||||||
"client/Queue.cpp",
|
"client/Queue.cpp",
|
||||||
"client/Queue.h",
|
"client/Queue.h",
|
||||||
@ -93,9 +97,11 @@ dawn_component("dawn_wire") {
|
|||||||
"server/ObjectStorage.h",
|
"server/ObjectStorage.h",
|
||||||
"server/Server.cpp",
|
"server/Server.cpp",
|
||||||
"server/Server.h",
|
"server/Server.h",
|
||||||
|
"server/ServerAdapter.cpp",
|
||||||
"server/ServerBuffer.cpp",
|
"server/ServerBuffer.cpp",
|
||||||
"server/ServerDevice.cpp",
|
"server/ServerDevice.cpp",
|
||||||
"server/ServerInlineMemoryTransferService.cpp",
|
"server/ServerInlineMemoryTransferService.cpp",
|
||||||
|
"server/ServerInstance.cpp",
|
||||||
"server/ServerQueue.cpp",
|
"server/ServerQueue.cpp",
|
||||||
"server/ServerShaderModule.cpp",
|
"server/ServerShaderModule.cpp",
|
||||||
]
|
]
|
||||||
|
@ -37,6 +37,8 @@ target_sources(dawn_wire PRIVATE
|
|||||||
"ChunkedCommandHandler.h"
|
"ChunkedCommandHandler.h"
|
||||||
"ChunkedCommandSerializer.cpp"
|
"ChunkedCommandSerializer.cpp"
|
||||||
"ChunkedCommandSerializer.h"
|
"ChunkedCommandSerializer.h"
|
||||||
|
"SupportedFeatures.cpp"
|
||||||
|
"SupportedFeatures.h"
|
||||||
"Wire.cpp"
|
"Wire.cpp"
|
||||||
"WireClient.cpp"
|
"WireClient.cpp"
|
||||||
"WireDeserializeAllocator.cpp"
|
"WireDeserializeAllocator.cpp"
|
||||||
@ -56,6 +58,8 @@ target_sources(dawn_wire PRIVATE
|
|||||||
"client/Device.h"
|
"client/Device.h"
|
||||||
"client/Instance.cpp"
|
"client/Instance.cpp"
|
||||||
"client/Instance.h"
|
"client/Instance.h"
|
||||||
|
"client/LimitsAndFeatures.cpp"
|
||||||
|
"client/LimitsAndFeatures.h"
|
||||||
"client/ObjectAllocator.h"
|
"client/ObjectAllocator.h"
|
||||||
"client/Queue.cpp"
|
"client/Queue.cpp"
|
||||||
"client/Queue.h"
|
"client/Queue.h"
|
||||||
@ -65,9 +69,11 @@ target_sources(dawn_wire PRIVATE
|
|||||||
"server/ObjectStorage.h"
|
"server/ObjectStorage.h"
|
||||||
"server/Server.cpp"
|
"server/Server.cpp"
|
||||||
"server/Server.h"
|
"server/Server.h"
|
||||||
|
"server/ServerAdapter.cpp"
|
||||||
"server/ServerBuffer.cpp"
|
"server/ServerBuffer.cpp"
|
||||||
"server/ServerDevice.cpp"
|
"server/ServerDevice.cpp"
|
||||||
"server/ServerInlineMemoryTransferService.cpp"
|
"server/ServerInlineMemoryTransferService.cpp"
|
||||||
|
"server/ServerInstance.cpp"
|
||||||
"server/ServerQueue.cpp"
|
"server/ServerQueue.cpp"
|
||||||
"server/ServerShaderModule.cpp"
|
"server/ServerShaderModule.cpp"
|
||||||
)
|
)
|
||||||
|
48
src/dawn_wire/SupportedFeatures.cpp
Normal file
48
src/dawn_wire/SupportedFeatures.cpp
Normal file
@ -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
|
26
src/dawn_wire/SupportedFeatures.h
Normal file
26
src/dawn_wire/SupportedFeatures.h
Normal file
@ -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/Adapter.h"
|
||||||
|
|
||||||
|
#include "dawn_wire/client/Client.h"
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
bool Adapter::GetLimits(WGPUSupportedLimits* limits) const {
|
Adapter::~Adapter() {
|
||||||
UNREACHABLE();
|
mRequestDeviceRequests.CloseAll([](RequestDeviceData* request) {
|
||||||
|
request->callback(WGPURequestDeviceStatus_Unknown, nullptr,
|
||||||
|
"Adapter destroyed before callback", request->userdata);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Adapter::GetProperties(WGPUAdapterProperties* properties) const {
|
void Adapter::CancelCallbacksForDisconnect() {
|
||||||
UNREACHABLE();
|
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 {
|
bool Adapter::HasFeature(WGPUFeatureName feature) const {
|
||||||
UNREACHABLE();
|
return mLimitsAndFeatures.HasFeature(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Adapter::EnumerateFeatures(WGPUFeatureName* features) const {
|
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,
|
void Adapter::RequestDevice(const WGPUDeviceDescriptor* descriptor,
|
||||||
WGPURequestDeviceCallback callback,
|
WGPURequestDeviceCallback callback,
|
||||||
void* userdata) {
|
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
|
}} // namespace dawn_wire::client
|
||||||
|
@ -18,7 +18,10 @@
|
|||||||
#include <dawn/webgpu.h>
|
#include <dawn/webgpu.h>
|
||||||
|
|
||||||
#include "dawn_wire/WireClient.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/ObjectBase.h"
|
||||||
|
#include "dawn_wire/client/RequestTracker.h"
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
@ -26,13 +29,37 @@ namespace dawn_wire { namespace client {
|
|||||||
public:
|
public:
|
||||||
using ObjectBase::ObjectBase;
|
using ObjectBase::ObjectBase;
|
||||||
|
|
||||||
|
~Adapter();
|
||||||
|
void CancelCallbacksForDisconnect() override;
|
||||||
|
|
||||||
bool GetLimits(WGPUSupportedLimits* limits) const;
|
bool GetLimits(WGPUSupportedLimits* limits) const;
|
||||||
void GetProperties(WGPUAdapterProperties* properties) const;
|
|
||||||
bool HasFeature(WGPUFeatureName feature) const;
|
bool HasFeature(WGPUFeatureName feature) const;
|
||||||
uint32_t EnumerateFeatures(WGPUFeatureName* features) 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,
|
void RequestDevice(const WGPUDeviceDescriptor* descriptor,
|
||||||
WGPURequestDeviceCallback callback,
|
WGPURequestDeviceCallback callback,
|
||||||
void* userdata);
|
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
|
}} // 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) {
|
void Device::HandleError(WGPUErrorType errorType, const char* message) {
|
||||||
if (mErrorCallback) {
|
if (mErrorCallback) {
|
||||||
mErrorCallback(errorType, message, mErrorUserdata);
|
mErrorCallback(errorType, message, mErrorUserdata);
|
||||||
@ -196,20 +216,6 @@ namespace dawn_wire { namespace client {
|
|||||||
return Buffer::CreateError(this);
|
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() {
|
WGPUQueue Device::GetQueue() {
|
||||||
// The queue is lazily created because if a Device is created by
|
// The queue is lazily created because if a Device is created by
|
||||||
// Reserve/Inject, we cannot send the GetQueue message until
|
// Reserve/Inject, we cannot send the GetQueue message until
|
||||||
@ -269,7 +275,7 @@ namespace dawn_wire { namespace client {
|
|||||||
client->ComputePipelineAllocator().GetObject(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 both on the client side and the server side.
|
// free the allocation.
|
||||||
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
||||||
client->ComputePipelineAllocator().Free(pipelineAllocation);
|
client->ComputePipelineAllocator().Free(pipelineAllocation);
|
||||||
request.createComputePipelineAsyncCallback(status, nullptr, message, request.userdata);
|
request.createComputePipelineAsyncCallback(status, nullptr, message, request.userdata);
|
||||||
@ -320,7 +326,7 @@ namespace dawn_wire { namespace client {
|
|||||||
client->RenderPipelineAllocator().GetObject(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 both on the client side and the server side.
|
// free the allocation.
|
||||||
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
if (status != WGPUCreatePipelineAsyncStatus_Success) {
|
||||||
client->RenderPipelineAllocator().Free(pipelineAllocation);
|
client->RenderPipelineAllocator().Free(pipelineAllocation);
|
||||||
request.createRenderPipelineAsyncCallback(status, nullptr, message, request.userdata);
|
request.createRenderPipelineAsyncCallback(status, nullptr, message, request.userdata);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "common/LinkedList.h"
|
#include "common/LinkedList.h"
|
||||||
#include "dawn_wire/WireCmd_autogen.h"
|
#include "dawn_wire/WireCmd_autogen.h"
|
||||||
#include "dawn_wire/client/ApiObjects_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/ObjectBase.h"
|
||||||
#include "dawn_wire/client/RequestTracker.h"
|
#include "dawn_wire/client/RequestTracker.h"
|
||||||
|
|
||||||
@ -67,6 +68,9 @@ namespace dawn_wire { namespace client {
|
|||||||
bool GetLimits(WGPUSupportedLimits* limits) const;
|
bool GetLimits(WGPUSupportedLimits* limits) const;
|
||||||
bool HasFeature(WGPUFeatureName feature) const;
|
bool HasFeature(WGPUFeatureName feature) const;
|
||||||
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
|
uint32_t EnumerateFeatures(WGPUFeatureName* features) const;
|
||||||
|
void SetLimits(const WGPUSupportedLimits* limits);
|
||||||
|
void SetFeatures(const WGPUFeatureName* features, uint32_t featuresCount);
|
||||||
|
|
||||||
WGPUQueue GetQueue();
|
WGPUQueue GetQueue();
|
||||||
|
|
||||||
void CancelCallbacksForDisconnect() override;
|
void CancelCallbacksForDisconnect() override;
|
||||||
@ -74,6 +78,7 @@ namespace dawn_wire { namespace client {
|
|||||||
std::weak_ptr<bool> GetAliveWeakPtr();
|
std::weak_ptr<bool> GetAliveWeakPtr();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
LimitsAndFeatures mLimitsAndFeatures;
|
||||||
struct ErrorScopeData {
|
struct ErrorScopeData {
|
||||||
WGPUErrorCallback callback = nullptr;
|
WGPUErrorCallback callback = nullptr;
|
||||||
void* userdata = nullptr;
|
void* userdata = nullptr;
|
||||||
|
@ -14,12 +14,88 @@
|
|||||||
|
|
||||||
#include "dawn_wire/client/Instance.h"
|
#include "dawn_wire/client/Instance.h"
|
||||||
|
|
||||||
|
#include "dawn_wire/client/Client.h"
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
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,
|
void Instance::RequestAdapter(const WGPURequestAdapterOptions* options,
|
||||||
WGPURequestAdapterCallback callback,
|
WGPURequestAdapterCallback callback,
|
||||||
void* userdata) {
|
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
|
}} // namespace dawn_wire::client
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
#include <dawn/webgpu.h>
|
#include <dawn/webgpu.h>
|
||||||
|
|
||||||
#include "dawn_wire/WireClient.h"
|
#include "dawn_wire/WireClient.h"
|
||||||
|
#include "dawn_wire/WireCmd_autogen.h"
|
||||||
#include "dawn_wire/client/ObjectBase.h"
|
#include "dawn_wire/client/ObjectBase.h"
|
||||||
|
#include "dawn_wire/client/RequestTracker.h"
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
@ -26,9 +28,27 @@ namespace dawn_wire { namespace client {
|
|||||||
public:
|
public:
|
||||||
using ObjectBase::ObjectBase;
|
using ObjectBase::ObjectBase;
|
||||||
|
|
||||||
|
~Instance();
|
||||||
|
void CancelCallbacksForDisconnect() override;
|
||||||
|
|
||||||
void RequestAdapter(const WGPURequestAdapterOptions* options,
|
void RequestAdapter(const WGPURequestAdapterOptions* options,
|
||||||
WGPURequestAdapterCallback callback,
|
WGPURequestAdapterCallback callback,
|
||||||
void* userdata);
|
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
|
}} // namespace dawn_wire::client
|
||||||
|
63
src/dawn_wire/client/LimitsAndFeatures.cpp
Normal file
63
src/dawn_wire/client/LimitsAndFeatures.cpp
Normal file
@ -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
|
40
src/dawn_wire/client/LimitsAndFeatures.h
Normal file
40
src/dawn_wire/client/LimitsAndFeatures.h
Normal file
@ -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);
|
mProcs.deviceReference(device);
|
||||||
|
|
||||||
// Set callbacks to forward errors to the client.
|
// Set callbacks to forward errors to the client.
|
||||||
// Note: these callbacks are manually inlined here since they do not acquire and
|
SetForwardingDeviceCallbacks(data);
|
||||||
// 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());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +152,36 @@ namespace dawn_wire { namespace server {
|
|||||||
return data->handle;
|
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) {
|
void Server::ClearDeviceCallbacks(WGPUDevice device) {
|
||||||
// Un-set the error and lost callbacks since we cannot forward them
|
// Un-set the error and lost callbacks since we cannot forward them
|
||||||
// after the server has been destroyed.
|
// after the server has been destroyed.
|
||||||
|
@ -146,6 +146,22 @@ namespace dawn_wire { namespace server {
|
|||||||
ObjectId pipelineObjectID;
|
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 {
|
class Server : public ServerBase {
|
||||||
public:
|
public:
|
||||||
Server(const DawnProcTable& procs,
|
Server(const DawnProcTable& procs,
|
||||||
@ -194,6 +210,7 @@ namespace dawn_wire { namespace server {
|
|||||||
mSerializer.SerializeCommand(cmd, extraSize, SerializeExtraSize);
|
mSerializer.SerializeCommand(cmd, extraSize, SerializeExtraSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetForwardingDeviceCallbacks(ObjectData<WGPUDevice>* deviceObject);
|
||||||
void ClearDeviceCallbacks(WGPUDevice device);
|
void ClearDeviceCallbacks(WGPUDevice device);
|
||||||
|
|
||||||
// Error callbacks
|
// Error callbacks
|
||||||
@ -216,6 +233,14 @@ namespace dawn_wire { namespace server {
|
|||||||
void OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
|
void OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
|
||||||
const WGPUCompilationInfo* info,
|
const WGPUCompilationInfo* info,
|
||||||
ShaderModuleGetCompilationInfoUserdata* userdata);
|
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"
|
#include "dawn_wire/server/ServerPrototypes_autogen.inc"
|
||||||
|
|
||||||
|
112
src/dawn_wire/server/ServerAdapter.cpp
Normal file
112
src/dawn_wire/server/ServerAdapter.cpp
Normal file
@ -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
|
102
src/dawn_wire/server/ServerInstance.cpp
Normal file
102
src/dawn_wire/server/ServerInstance.cpp
Normal file
@ -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…
x
Reference in New Issue
Block a user