• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef DAWNWIRE_SERVER_SERVER_H_
16 #define DAWNWIRE_SERVER_SERVER_H_
17 
18 #include "dawn_wire/ChunkedCommandSerializer.h"
19 #include "dawn_wire/server/ServerBase_autogen.h"
20 
21 namespace dawn_wire { namespace server {
22 
23     class Server;
24     class MemoryTransferService;
25 
26     // CallbackUserdata and its derived classes are intended to be created by
27     // Server::MakeUserdata<T> and then passed as the userdata argument for Dawn
28     // callbacks.
29     // It contains a pointer back to the Server so that the callback can call the
30     // Server to perform operations like serialization, and it contains a weak pointer
31     // |serverIsAlive|. If the weak pointer has expired, it means the server has
32     // been destroyed and the callback must not use the Server pointer.
33     // To assist with checking |serverIsAlive| and lifetime management of the userdata,
34     // |ForwardToServer| (defined later in this file) can be used to acquire the userdata,
35     // return early if |serverIsAlive| has expired, and then forward the arguments
36     // to userdata->server->MyCallbackHandler.
37     //
38     // Example Usage:
39     //
40     // struct MyUserdata : CallbackUserdata { uint32_t foo; };
41     //
42     // auto userdata = MakeUserdata<MyUserdata>();
43     // userdata->foo = 2;
44     //
45     // // TODO(enga): Make the template inference for ForwardToServer cleaner with C++17
46     // callMyCallbackHandler(
47     //      ForwardToServer<decltype(&Server::MyCallbackHandler)>::Func<
48     //                      &Server::MyCallbackHandler>(),
49     //      userdata.release());
50     //
51     // void Server::MyCallbackHandler(MyUserdata* userdata) { }
52     struct CallbackUserdata {
53         Server* const server;
54         std::weak_ptr<bool> const serverIsAlive;
55 
56         CallbackUserdata() = delete;
CallbackUserdataCallbackUserdata57         CallbackUserdata(Server* server, const std::shared_ptr<bool>& serverIsAlive)
58             : server(server), serverIsAlive(serverIsAlive) {
59         }
60     };
61 
62     template <typename F>
63     class ForwardToServer;
64 
65     template <typename R, typename... Args>
66     class ForwardToServer<R (Server::*)(Args...)> {
67       private:
68         // Get the type T of the last argument. It has CallbackUserdata as its base.
69         using UserdataT = typename std::remove_pointer<typename std::decay<decltype(
70             std::get<sizeof...(Args) - 1>(std::declval<std::tuple<Args...>>()))>::type>::type;
71 
72         static_assert(std::is_base_of<CallbackUserdata, UserdataT>::value,
73                       "Last argument of callback handler should derive from CallbackUserdata.");
74 
75         template <class T, class... Ts>
76         struct UntypedCallbackImpl;
77 
78         template <std::size_t... I, class... Ts>
79         struct UntypedCallbackImpl<std::index_sequence<I...>, Ts...> {
80             template <R (Server::*Func)(Args...)>
81             static auto ForwardToServer(
82                 // Unpack and forward the types of the parameter pack.
83                 // Append void* as the last argument.
84                 typename std::tuple_element<I, std::tuple<Ts...>>::type... args,
85                 void* userdata) {
86                 // Acquire the userdata, and cast it to UserdataT.
87                 std::unique_ptr<UserdataT> data(static_cast<UserdataT*>(userdata));
88                 if (data->serverIsAlive.expired()) {
89                     // Do nothing if the server has already been destroyed.
90                     return;
91                 }
92                 // Forward the arguments and the typed userdata to the Server:: member function.
93                 (data->server->*Func)(std::forward<decltype(args)>(args)..., data.get());
94             }
95         };
96 
97         // Generate a free function which has all of the same arguments, except the last
98         // userdata argument is void* instead of UserdataT*. Dawn's userdata args are void*.
99         using UntypedCallback =
100             UntypedCallbackImpl<std::make_index_sequence<sizeof...(Args) - 1>, Args...>;
101 
102       public:
103         template <R (Server::*F)(Args...)>
104         static auto Func() {
105             return UntypedCallback::template ForwardToServer<F>;
106         }
107     };
108 
109     struct MapUserdata : CallbackUserdata {
110         using CallbackUserdata::CallbackUserdata;
111 
112         ObjectHandle buffer;
113         WGPUBuffer bufferObj;
114         uint64_t requestSerial;
115         uint64_t offset;
116         uint64_t size;
117         WGPUMapModeFlags mode;
118     };
119 
120     struct ErrorScopeUserdata : CallbackUserdata {
121         using CallbackUserdata::CallbackUserdata;
122 
123         ObjectHandle device;
124         uint64_t requestSerial;
125     };
126 
127     struct ShaderModuleGetCompilationInfoUserdata : CallbackUserdata {
128         using CallbackUserdata::CallbackUserdata;
129 
130         ObjectHandle shaderModule;
131         uint64_t requestSerial;
132     };
133 
134     struct QueueWorkDoneUserdata : CallbackUserdata {
135         using CallbackUserdata::CallbackUserdata;
136 
137         ObjectHandle queue;
138         uint64_t requestSerial;
139     };
140 
141     struct CreatePipelineAsyncUserData : CallbackUserdata {
142         using CallbackUserdata::CallbackUserdata;
143 
144         ObjectHandle device;
145         uint64_t requestSerial;
146         ObjectId pipelineObjectID;
147     };
148 
149     class Server : public ServerBase {
150       public:
151         Server(const DawnProcTable& procs,
152                CommandSerializer* serializer,
153                MemoryTransferService* memoryTransferService);
154         ~Server() override;
155 
156         // ChunkedCommandHandler implementation
157         const volatile char* HandleCommandsImpl(const volatile char* commands,
158                                                 size_t size) override;
159 
160         bool InjectTexture(WGPUTexture texture,
161                            uint32_t id,
162                            uint32_t generation,
163                            uint32_t deviceId,
164                            uint32_t deviceGeneration);
165 
166         bool InjectSwapChain(WGPUSwapChain swapchain,
167                              uint32_t id,
168                              uint32_t generation,
169                              uint32_t deviceId,
170                              uint32_t deviceGeneration);
171 
172         bool InjectDevice(WGPUDevice device, uint32_t id, uint32_t generation);
173 
174         WGPUDevice GetDevice(uint32_t id, uint32_t generation);
175 
176         template <typename T,
177                   typename Enable = std::enable_if<std::is_base_of<CallbackUserdata, T>::value>>
178         std::unique_ptr<T> MakeUserdata() {
179             return std::unique_ptr<T>(new T(this, mIsAlive));
180         }
181 
182       private:
183         template <typename Cmd>
184         void SerializeCommand(const Cmd& cmd) {
185             mSerializer.SerializeCommand(cmd);
186         }
187 
188         template <typename Cmd, typename ExtraSizeSerializeFn>
189         void SerializeCommand(const Cmd& cmd,
190                               size_t extraSize,
191                               ExtraSizeSerializeFn&& SerializeExtraSize) {
192             mSerializer.SerializeCommand(cmd, extraSize, SerializeExtraSize);
193         }
194 
195         void ClearDeviceCallbacks(WGPUDevice device);
196 
197         // Error callbacks
198         void OnUncapturedError(ObjectHandle device, WGPUErrorType type, const char* message);
199         void OnDeviceLost(ObjectHandle device, WGPUDeviceLostReason reason, const char* message);
200         void OnLogging(ObjectHandle device, WGPULoggingType type, const char* message);
201         void OnDevicePopErrorScope(WGPUErrorType type,
202                                    const char* message,
203                                    ErrorScopeUserdata* userdata);
204         void OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus status, MapUserdata* userdata);
205         void OnQueueWorkDone(WGPUQueueWorkDoneStatus status, QueueWorkDoneUserdata* userdata);
206         void OnCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
207                                                   WGPUComputePipeline pipeline,
208                                                   const char* message,
209                                                   CreatePipelineAsyncUserData* userdata);
210         void OnCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
211                                                  WGPURenderPipeline pipeline,
212                                                  const char* message,
213                                                  CreatePipelineAsyncUserData* userdata);
214         void OnShaderModuleGetCompilationInfo(WGPUCompilationInfoRequestStatus status,
215                                               const WGPUCompilationInfo* info,
216                                               ShaderModuleGetCompilationInfoUserdata* userdata);
217 
218 #include "dawn_wire/server/ServerPrototypes_autogen.inc"
219 
220         WireDeserializeAllocator mAllocator;
221         ChunkedCommandSerializer mSerializer;
222         DawnProcTable mProcs;
223         std::unique_ptr<MemoryTransferService> mOwnedMemoryTransferService = nullptr;
224         MemoryTransferService* mMemoryTransferService = nullptr;
225 
226         std::shared_ptr<bool> mIsAlive;
227     };
228 
229     bool TrackDeviceChild(DeviceInfo* device, ObjectType type, ObjectId id);
230     bool UntrackDeviceChild(DeviceInfo* device, ObjectType type, ObjectId id);
231 
232     std::unique_ptr<MemoryTransferService> CreateInlineMemoryTransferService();
233 
234 }}  // namespace dawn_wire::server
235 
236 #endif  // DAWNWIRE_SERVER_SERVER_H_
237