mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-08 22:26:06 +00:00
dawn_wire::server: Simplify ForwardToServer usage with C++17
This uses template parameter type deduction to pass the member function pointer and then extract the types that compose it. Which means that the member function pointer only needs to be written once. The order of arguments of the Server::On*Callback methods is changed to put the userdata first. This helps make template type deduction simpler. Bug: dawn:824 Change-Id: I4e2bc33dfd52a11620dea51b40508eca6c878d72 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/75071 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Brandon Jones <bajones@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
2994d2e7b9
commit
31f12242da
@ -42,13 +42,11 @@ namespace dawn_wire { namespace server {
|
|||||||
// auto userdata = MakeUserdata<MyUserdata>();
|
// auto userdata = MakeUserdata<MyUserdata>();
|
||||||
// userdata->foo = 2;
|
// userdata->foo = 2;
|
||||||
//
|
//
|
||||||
// // TODO(enga): Make the template inference for ForwardToServer cleaner with C++17
|
|
||||||
// callMyCallbackHandler(
|
// callMyCallbackHandler(
|
||||||
// ForwardToServer<decltype(&Server::MyCallbackHandler)>::Func<
|
// ForwardToServer<&Server::MyCallbackHandler>,
|
||||||
// &Server::MyCallbackHandler>(),
|
|
||||||
// userdata.release());
|
// userdata.release());
|
||||||
//
|
//
|
||||||
// void Server::MyCallbackHandler(MyUserdata* userdata) { }
|
// void Server::MyCallbackHandler(MyUserdata* userdata, Other args) { }
|
||||||
struct CallbackUserdata {
|
struct CallbackUserdata {
|
||||||
Server* const server;
|
Server* const server;
|
||||||
std::weak_ptr<bool> const serverIsAlive;
|
std::weak_ptr<bool> const serverIsAlive;
|
||||||
@ -59,53 +57,35 @@ namespace dawn_wire { namespace server {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F>
|
template <auto F>
|
||||||
class ForwardToServer;
|
struct ForwardToServerHelper {
|
||||||
|
template <typename _>
|
||||||
|
struct ExtractedTypes;
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
// An internal structure used to unpack the various types that compose the type of F
|
||||||
class ForwardToServer<R (Server::*)(Args...)> {
|
template <typename Return, typename Class, typename Userdata, typename... Args>
|
||||||
private:
|
struct ExtractedTypes<Return (Class::*)(Userdata*, Args...)> {
|
||||||
// Get the type T of the last argument. It has CallbackUserdata as its base.
|
using UntypedCallback = Return (*)(Args..., void*);
|
||||||
using UserdataT = typename std::remove_pointer<typename std::decay<decltype(
|
static Return Callback(Args... args, void* userdata) {
|
||||||
std::get<sizeof...(Args) - 1>(std::declval<std::tuple<Args...>>()))>::type>::type;
|
|
||||||
|
|
||||||
static_assert(std::is_base_of<CallbackUserdata, UserdataT>::value,
|
|
||||||
"Last argument of callback handler should derive from CallbackUserdata.");
|
|
||||||
|
|
||||||
template <class T, class... Ts>
|
|
||||||
struct UntypedCallbackImpl;
|
|
||||||
|
|
||||||
template <std::size_t... I, class... Ts>
|
|
||||||
struct UntypedCallbackImpl<std::index_sequence<I...>, Ts...> {
|
|
||||||
template <R (Server::*Func)(Args...)>
|
|
||||||
static auto ForwardToServer(
|
|
||||||
// Unpack and forward the types of the parameter pack.
|
|
||||||
// Append void* as the last argument.
|
|
||||||
typename std::tuple_element<I, std::tuple<Ts...>>::type... args,
|
|
||||||
void* userdata) {
|
|
||||||
// Acquire the userdata, and cast it to UserdataT.
|
// Acquire the userdata, and cast it to UserdataT.
|
||||||
std::unique_ptr<UserdataT> data(static_cast<UserdataT*>(userdata));
|
std::unique_ptr<Userdata> data(static_cast<Userdata*>(userdata));
|
||||||
if (data->serverIsAlive.expired()) {
|
if (data->serverIsAlive.expired()) {
|
||||||
// Do nothing if the server has already been destroyed.
|
// Do nothing if the server has already been destroyed.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Forward the arguments and the typed userdata to the Server:: member function.
|
// Forward the arguments and the typed userdata to the Server:: member function.
|
||||||
(data->server->*Func)(std::forward<decltype(args)>(args)..., data.get());
|
(data->server->*F)(data.get(), std::forward<decltype(args)>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate a free function which has all of the same arguments, except the last
|
static constexpr typename ExtractedTypes<decltype(F)>::UntypedCallback Create() {
|
||||||
// userdata argument is void* instead of UserdataT*. Dawn's userdata args are void*.
|
return ExtractedTypes<decltype(F)>::Callback;
|
||||||
using UntypedCallback =
|
|
||||||
UntypedCallbackImpl<std::make_index_sequence<sizeof...(Args) - 1>, Args...>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <R (Server::*F)(Args...)>
|
|
||||||
static auto Func() {
|
|
||||||
return UntypedCallback::template ForwardToServer<F>;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <auto F>
|
||||||
|
constexpr auto ForwardToServer = ForwardToServerHelper<F>::Create();
|
||||||
|
|
||||||
struct MapUserdata : CallbackUserdata {
|
struct MapUserdata : CallbackUserdata {
|
||||||
using CallbackUserdata::CallbackUserdata;
|
using CallbackUserdata::CallbackUserdata;
|
||||||
|
|
||||||
@ -217,30 +197,30 @@ namespace dawn_wire { namespace server {
|
|||||||
void OnUncapturedError(ObjectHandle device, WGPUErrorType type, const char* message);
|
void OnUncapturedError(ObjectHandle device, WGPUErrorType type, const char* message);
|
||||||
void OnDeviceLost(ObjectHandle device, WGPUDeviceLostReason reason, const char* message);
|
void OnDeviceLost(ObjectHandle device, WGPUDeviceLostReason reason, const char* message);
|
||||||
void OnLogging(ObjectHandle device, WGPULoggingType type, const char* message);
|
void OnLogging(ObjectHandle device, WGPULoggingType type, const char* message);
|
||||||
void OnDevicePopErrorScope(WGPUErrorType type,
|
void OnDevicePopErrorScope(ErrorScopeUserdata* userdata,
|
||||||
const char* message,
|
WGPUErrorType type,
|
||||||
ErrorScopeUserdata* userdata);
|
const char* message);
|
||||||
void OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus status, MapUserdata* userdata);
|
void OnBufferMapAsyncCallback(MapUserdata* userdata, WGPUBufferMapAsyncStatus status);
|
||||||
void OnQueueWorkDone(WGPUQueueWorkDoneStatus status, QueueWorkDoneUserdata* userdata);
|
void OnQueueWorkDone(QueueWorkDoneUserdata* userdata, WGPUQueueWorkDoneStatus status);
|
||||||
void OnCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
|
void OnCreateComputePipelineAsyncCallback(CreatePipelineAsyncUserData* userdata,
|
||||||
|
WGPUCreatePipelineAsyncStatus status,
|
||||||
WGPUComputePipeline pipeline,
|
WGPUComputePipeline pipeline,
|
||||||
const char* message,
|
const char* message);
|
||||||
CreatePipelineAsyncUserData* userdata);
|
void OnCreateRenderPipelineAsyncCallback(CreatePipelineAsyncUserData* userdata,
|
||||||
void OnCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
|
WGPUCreatePipelineAsyncStatus status,
|
||||||
WGPURenderPipeline pipeline,
|
WGPURenderPipeline pipeline,
|
||||||
const char* message,
|
const char* message);
|
||||||
CreatePipelineAsyncUserData* userdata);
|
void OnShaderModuleGetCompilationInfo(ShaderModuleGetCompilationInfoUserdata* userdata,
|
||||||
void OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
|
WGPUCompilationInfoRequestStatus status,
|
||||||
const WGPUCompilationInfo* info,
|
const WGPUCompilationInfo* info);
|
||||||
ShaderModuleGetCompilationInfoUserdata* userdata);
|
void OnRequestAdapterCallback(RequestAdapterUserdata* userdata,
|
||||||
void OnRequestAdapterCallback(WGPURequestAdapterStatus status,
|
WGPURequestAdapterStatus status,
|
||||||
WGPUAdapter adapter,
|
WGPUAdapter adapter,
|
||||||
const char* message,
|
const char* message);
|
||||||
RequestAdapterUserdata* userdata);
|
void OnRequestDeviceCallback(RequestDeviceUserdata* userdata,
|
||||||
void OnRequestDeviceCallback(WGPURequestDeviceStatus status,
|
WGPURequestDeviceStatus status,
|
||||||
WGPUDevice device,
|
WGPUDevice device,
|
||||||
const char* message,
|
const char* message);
|
||||||
RequestDeviceUserdata* userdata);
|
|
||||||
|
|
||||||
#include "dawn_wire/server/ServerPrototypes_autogen.inc"
|
#include "dawn_wire/server/ServerPrototypes_autogen.inc"
|
||||||
|
|
||||||
|
@ -39,18 +39,16 @@ namespace dawn_wire { namespace server {
|
|||||||
userdata->requestSerial = requestSerial;
|
userdata->requestSerial = requestSerial;
|
||||||
userdata->deviceObjectId = deviceHandle.id;
|
userdata->deviceObjectId = deviceHandle.id;
|
||||||
|
|
||||||
mProcs.adapterRequestDevice(
|
mProcs.adapterRequestDevice(adapter->handle, descriptor,
|
||||||
adapter->handle, descriptor,
|
ForwardToServer<&Server::OnRequestDeviceCallback>,
|
||||||
ForwardToServer<decltype(
|
|
||||||
&Server::OnRequestDeviceCallback)>::Func<&Server::OnRequestDeviceCallback>(),
|
|
||||||
userdata.release());
|
userdata.release());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnRequestDeviceCallback(WGPURequestDeviceStatus status,
|
void Server::OnRequestDeviceCallback(RequestDeviceUserdata* data,
|
||||||
|
WGPURequestDeviceStatus status,
|
||||||
WGPUDevice device,
|
WGPUDevice device,
|
||||||
const char* message,
|
const char* message) {
|
||||||
RequestDeviceUserdata* data) {
|
|
||||||
auto* deviceObject = DeviceObjects().Get(data->deviceObjectId, AllocationState::Reserved);
|
auto* deviceObject = DeviceObjects().Get(data->deviceObjectId, AllocationState::Reserved);
|
||||||
// Should be impossible to fail. ObjectIds can't be freed by a destroy command until
|
// 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.
|
// they move from Reserved to Allocated, or if they are destroyed here.
|
||||||
|
@ -80,7 +80,7 @@ namespace dawn_wire { namespace server {
|
|||||||
// client does the default size computation, we should always have a valid actual size here
|
// client does the default size computation, we should always have a valid actual size here
|
||||||
// in server. All other invalid actual size can be caught by dawn native side validation.
|
// in server. All other invalid actual size can be caught by dawn native side validation.
|
||||||
if (offset64 > std::numeric_limits<size_t>::max() || size64 >= WGPU_WHOLE_MAP_SIZE) {
|
if (offset64 > std::numeric_limits<size_t>::max() || size64 >= WGPU_WHOLE_MAP_SIZE) {
|
||||||
OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus_Error, userdata.get());
|
OnBufferMapAsyncCallback(userdata.get(), WGPUBufferMapAsyncStatus_Error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,10 +90,8 @@ namespace dawn_wire { namespace server {
|
|||||||
userdata->offset = offset;
|
userdata->offset = offset;
|
||||||
userdata->size = size;
|
userdata->size = size;
|
||||||
|
|
||||||
mProcs.bufferMapAsync(
|
mProcs.bufferMapAsync(buffer->handle, mode, offset, size,
|
||||||
buffer->handle, mode, offset, size,
|
ForwardToServer<&Server::OnBufferMapAsyncCallback>,
|
||||||
ForwardToServer<decltype(
|
|
||||||
&Server::OnBufferMapAsyncCallback)>::Func<&Server::OnBufferMapAsyncCallback>(),
|
|
||||||
userdata.release());
|
userdata.release());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -227,7 +225,7 @@ namespace dawn_wire { namespace server {
|
|||||||
static_cast<size_t>(offset), static_cast<size_t>(size));
|
static_cast<size_t>(offset), static_cast<size_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus status, MapUserdata* data) {
|
void Server::OnBufferMapAsyncCallback(MapUserdata* data, WGPUBufferMapAsyncStatus status) {
|
||||||
// Skip sending the callback if the buffer has already been destroyed.
|
// Skip sending the callback if the buffer has already been destroyed.
|
||||||
auto* bufferData = BufferObjects().Get(data->buffer.id);
|
auto* bufferData = BufferObjects().Get(data->buffer.id);
|
||||||
if (bufferData == nullptr || bufferData->generation != data->buffer.generation) {
|
if (bufferData == nullptr || bufferData->generation != data->buffer.generation) {
|
||||||
|
@ -91,19 +91,16 @@ namespace dawn_wire { namespace server {
|
|||||||
|
|
||||||
ErrorScopeUserdata* unownedUserdata = userdata.release();
|
ErrorScopeUserdata* unownedUserdata = userdata.release();
|
||||||
bool success = mProcs.devicePopErrorScope(
|
bool success = mProcs.devicePopErrorScope(
|
||||||
device->handle,
|
device->handle, ForwardToServer<&Server::OnDevicePopErrorScope>, unownedUserdata);
|
||||||
ForwardToServer<decltype(
|
|
||||||
&Server::OnDevicePopErrorScope)>::Func<&Server::OnDevicePopErrorScope>(),
|
|
||||||
unownedUserdata);
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
delete unownedUserdata;
|
delete unownedUserdata;
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnDevicePopErrorScope(WGPUErrorType type,
|
void Server::OnDevicePopErrorScope(ErrorScopeUserdata* userdata,
|
||||||
const char* message,
|
WGPUErrorType type,
|
||||||
ErrorScopeUserdata* userdata) {
|
const char* message) {
|
||||||
ReturnDevicePopErrorScopeCallbackCmd cmd;
|
ReturnDevicePopErrorScopeCallbackCmd cmd;
|
||||||
cmd.device = userdata->device;
|
cmd.device = userdata->device;
|
||||||
cmd.requestSerial = userdata->requestSerial;
|
cmd.requestSerial = userdata->requestSerial;
|
||||||
@ -139,16 +136,14 @@ namespace dawn_wire { namespace server {
|
|||||||
|
|
||||||
mProcs.deviceCreateComputePipelineAsync(
|
mProcs.deviceCreateComputePipelineAsync(
|
||||||
device->handle, descriptor,
|
device->handle, descriptor,
|
||||||
ForwardToServer<decltype(&Server::OnCreateComputePipelineAsyncCallback)>::Func<
|
ForwardToServer<&Server::OnCreateComputePipelineAsyncCallback>, userdata.release());
|
||||||
&Server::OnCreateComputePipelineAsyncCallback>(),
|
|
||||||
userdata.release());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
|
void Server::OnCreateComputePipelineAsyncCallback(CreatePipelineAsyncUserData* data,
|
||||||
|
WGPUCreatePipelineAsyncStatus status,
|
||||||
WGPUComputePipeline pipeline,
|
WGPUComputePipeline pipeline,
|
||||||
const char* message,
|
const char* message) {
|
||||||
CreatePipelineAsyncUserData* data) {
|
|
||||||
HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::ComputePipeline>(
|
HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::ComputePipeline>(
|
||||||
&ComputePipelineObjects(), status, pipeline, data);
|
&ComputePipelineObjects(), status, pipeline, data);
|
||||||
|
|
||||||
@ -186,16 +181,14 @@ namespace dawn_wire { namespace server {
|
|||||||
|
|
||||||
mProcs.deviceCreateRenderPipelineAsync(
|
mProcs.deviceCreateRenderPipelineAsync(
|
||||||
device->handle, descriptor,
|
device->handle, descriptor,
|
||||||
ForwardToServer<decltype(&Server::OnCreateRenderPipelineAsyncCallback)>::Func<
|
ForwardToServer<&Server::OnCreateRenderPipelineAsyncCallback>, userdata.release());
|
||||||
&Server::OnCreateRenderPipelineAsyncCallback>(),
|
|
||||||
userdata.release());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
|
void Server::OnCreateRenderPipelineAsyncCallback(CreatePipelineAsyncUserData* data,
|
||||||
|
WGPUCreatePipelineAsyncStatus status,
|
||||||
WGPURenderPipeline pipeline,
|
WGPURenderPipeline pipeline,
|
||||||
const char* message,
|
const char* message) {
|
||||||
CreatePipelineAsyncUserData* data) {
|
|
||||||
HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::RenderPipeline>(
|
HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::RenderPipeline>(
|
||||||
&RenderPipelineObjects(), status, pipeline, data);
|
&RenderPipelineObjects(), status, pipeline, data);
|
||||||
|
|
||||||
|
@ -41,18 +41,16 @@ namespace dawn_wire { namespace server {
|
|||||||
userdata->requestSerial = requestSerial;
|
userdata->requestSerial = requestSerial;
|
||||||
userdata->adapterObjectId = adapterHandle.id;
|
userdata->adapterObjectId = adapterHandle.id;
|
||||||
|
|
||||||
mProcs.instanceRequestAdapter(
|
mProcs.instanceRequestAdapter(instance->handle, options,
|
||||||
instance->handle, options,
|
ForwardToServer<&Server::OnRequestAdapterCallback>,
|
||||||
ForwardToServer<decltype(
|
|
||||||
&Server::OnRequestAdapterCallback)>::Func<&Server::OnRequestAdapterCallback>(),
|
|
||||||
userdata.release());
|
userdata.release());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnRequestAdapterCallback(WGPURequestAdapterStatus status,
|
void Server::OnRequestAdapterCallback(RequestAdapterUserdata* data,
|
||||||
|
WGPURequestAdapterStatus status,
|
||||||
WGPUAdapter adapter,
|
WGPUAdapter adapter,
|
||||||
const char* message,
|
const char* message) {
|
||||||
RequestAdapterUserdata* data) {
|
|
||||||
auto* adapterObject =
|
auto* adapterObject =
|
||||||
AdapterObjects().Get(data->adapterObjectId, AllocationState::Reserved);
|
AdapterObjects().Get(data->adapterObjectId, AllocationState::Reserved);
|
||||||
// Should be impossible to fail. ObjectIds can't be freed by a destroy command until
|
// Should be impossible to fail. ObjectIds can't be freed by a destroy command until
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
namespace dawn_wire { namespace server {
|
namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
void Server::OnQueueWorkDone(WGPUQueueWorkDoneStatus status, QueueWorkDoneUserdata* data) {
|
void Server::OnQueueWorkDone(QueueWorkDoneUserdata* data, WGPUQueueWorkDoneStatus status) {
|
||||||
ReturnQueueWorkDoneCallbackCmd cmd;
|
ReturnQueueWorkDoneCallbackCmd cmd;
|
||||||
cmd.queue = data->queue;
|
cmd.queue = data->queue;
|
||||||
cmd.requestSerial = data->requestSerial;
|
cmd.requestSerial = data->requestSerial;
|
||||||
@ -38,9 +38,8 @@ namespace dawn_wire { namespace server {
|
|||||||
userdata->queue = ObjectHandle{queueId, queue->generation};
|
userdata->queue = ObjectHandle{queueId, queue->generation};
|
||||||
userdata->requestSerial = requestSerial;
|
userdata->requestSerial = requestSerial;
|
||||||
|
|
||||||
mProcs.queueOnSubmittedWorkDone(
|
mProcs.queueOnSubmittedWorkDone(queue->handle, signalValue,
|
||||||
queue->handle, signalValue,
|
ForwardToServer<&Server::OnQueueWorkDone>,
|
||||||
ForwardToServer<decltype(&Server::OnQueueWorkDone)>::Func<&Server::OnQueueWorkDone>(),
|
|
||||||
userdata.release());
|
userdata.release());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,14 @@ namespace dawn_wire { namespace server {
|
|||||||
userdata->requestSerial = requestSerial;
|
userdata->requestSerial = requestSerial;
|
||||||
|
|
||||||
mProcs.shaderModuleGetCompilationInfo(
|
mProcs.shaderModuleGetCompilationInfo(
|
||||||
shaderModule->handle,
|
shaderModule->handle, ForwardToServer<&Server::OnShaderModuleGetCompilationInfo>,
|
||||||
ForwardToServer<decltype(&Server::OnShaderModuleGetCompilationInfo)>::Func<
|
|
||||||
&Server::OnShaderModuleGetCompilationInfo>(),
|
|
||||||
userdata.release());
|
userdata.release());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
|
void Server::OnShaderModuleGetCompilationInfo(ShaderModuleGetCompilationInfoUserdata* data,
|
||||||
const WGPUCompilationInfo* info,
|
WGPUCompilationInfoRequestStatus status,
|
||||||
ShaderModuleGetCompilationInfoUserdata* data) {
|
const WGPUCompilationInfo* info) {
|
||||||
ReturnShaderModuleGetCompilationInfoCallbackCmd cmd;
|
ReturnShaderModuleGetCompilationInfoCallbackCmd cmd;
|
||||||
cmd.shaderModule = data->shaderModule;
|
cmd.shaderModule = data->shaderModule;
|
||||||
cmd.requestSerial = data->requestSerial;
|
cmd.requestSerial = data->requestSerial;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user