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 #include "dawn_wire/server/Server.h" 16 17 namespace dawn_wire { namespace server { 18 19 namespace { 20 21 template <ObjectType objectType, typename Pipeline> HandleCreateRenderPipelineAsyncCallbackResult(KnownObjects<Pipeline> * knownObjects,WGPUCreatePipelineAsyncStatus status,Pipeline pipeline,CreatePipelineAsyncUserData * data)22 void HandleCreateRenderPipelineAsyncCallbackResult(KnownObjects<Pipeline>* knownObjects, 23 WGPUCreatePipelineAsyncStatus status, 24 Pipeline pipeline, 25 CreatePipelineAsyncUserData* data) { 26 // May be null if the device was destroyed. Device destruction destroys child 27 // objects on the wire. 28 auto* pipelineObject = 29 knownObjects->Get(data->pipelineObjectID, AllocationState::Reserved); 30 // Should be impossible to fail. ObjectIds can't be freed by a destroy command until 31 // they move from Reserved to Allocated, or if they are destroyed here. 32 ASSERT(pipelineObject != nullptr); 33 34 if (status == WGPUCreatePipelineAsyncStatus_Success) { 35 // Assign the handle and allocated status if the pipeline is created successfully. 36 pipelineObject->state = AllocationState::Allocated; 37 pipelineObject->handle = pipeline; 38 39 // This should be impossible to fail. It would require a command to be sent that 40 // creates a duplicate ObjectId, which would fail validation. 41 bool success = TrackDeviceChild(pipelineObject->deviceInfo, objectType, 42 data->pipelineObjectID); 43 ASSERT(success); 44 } else { 45 // Otherwise, free the ObjectId which will make it unusable. 46 knownObjects->Free(data->pipelineObjectID); 47 ASSERT(pipeline == nullptr); 48 } 49 } 50 51 } // anonymous namespace 52 OnUncapturedError(ObjectHandle device,WGPUErrorType type,const char * message)53 void Server::OnUncapturedError(ObjectHandle device, WGPUErrorType type, const char* message) { 54 ReturnDeviceUncapturedErrorCallbackCmd cmd; 55 cmd.device = device; 56 cmd.type = type; 57 cmd.message = message; 58 59 SerializeCommand(cmd); 60 } 61 OnDeviceLost(ObjectHandle device,WGPUDeviceLostReason reason,const char * message)62 void Server::OnDeviceLost(ObjectHandle device, 63 WGPUDeviceLostReason reason, 64 const char* message) { 65 ReturnDeviceLostCallbackCmd cmd; 66 cmd.device = device; 67 cmd.reason = reason; 68 cmd.message = message; 69 70 SerializeCommand(cmd); 71 } 72 OnLogging(ObjectHandle device,WGPULoggingType type,const char * message)73 void Server::OnLogging(ObjectHandle device, WGPULoggingType type, const char* message) { 74 ReturnDeviceLoggingCallbackCmd cmd; 75 cmd.device = device; 76 cmd.type = type; 77 cmd.message = message; 78 79 SerializeCommand(cmd); 80 } 81 DoDevicePopErrorScope(ObjectId deviceId,uint64_t requestSerial)82 bool Server::DoDevicePopErrorScope(ObjectId deviceId, uint64_t requestSerial) { 83 auto* device = DeviceObjects().Get(deviceId); 84 if (device == nullptr) { 85 return false; 86 } 87 88 auto userdata = MakeUserdata<ErrorScopeUserdata>(); 89 userdata->requestSerial = requestSerial; 90 userdata->device = ObjectHandle{deviceId, device->generation}; 91 92 ErrorScopeUserdata* unownedUserdata = userdata.release(); 93 bool success = mProcs.devicePopErrorScope( 94 device->handle, 95 ForwardToServer<decltype( 96 &Server::OnDevicePopErrorScope)>::Func<&Server::OnDevicePopErrorScope>(), 97 unownedUserdata); 98 if (!success) { 99 delete unownedUserdata; 100 } 101 return success; 102 } 103 OnDevicePopErrorScope(WGPUErrorType type,const char * message,ErrorScopeUserdata * userdata)104 void Server::OnDevicePopErrorScope(WGPUErrorType type, 105 const char* message, 106 ErrorScopeUserdata* userdata) { 107 ReturnDevicePopErrorScopeCallbackCmd cmd; 108 cmd.device = userdata->device; 109 cmd.requestSerial = userdata->requestSerial; 110 cmd.type = type; 111 cmd.message = message; 112 113 SerializeCommand(cmd); 114 } 115 DoDeviceCreateComputePipelineAsync(ObjectId deviceId,uint64_t requestSerial,ObjectHandle pipelineObjectHandle,const WGPUComputePipelineDescriptor * descriptor)116 bool Server::DoDeviceCreateComputePipelineAsync( 117 ObjectId deviceId, 118 uint64_t requestSerial, 119 ObjectHandle pipelineObjectHandle, 120 const WGPUComputePipelineDescriptor* descriptor) { 121 auto* device = DeviceObjects().Get(deviceId); 122 if (device == nullptr) { 123 return false; 124 } 125 126 auto* resultData = 127 ComputePipelineObjects().Allocate(pipelineObjectHandle.id, AllocationState::Reserved); 128 if (resultData == nullptr) { 129 return false; 130 } 131 132 resultData->generation = pipelineObjectHandle.generation; 133 resultData->deviceInfo = device->info.get(); 134 135 auto userdata = MakeUserdata<CreatePipelineAsyncUserData>(); 136 userdata->device = ObjectHandle{deviceId, device->generation}; 137 userdata->requestSerial = requestSerial; 138 userdata->pipelineObjectID = pipelineObjectHandle.id; 139 140 mProcs.deviceCreateComputePipelineAsync( 141 device->handle, descriptor, 142 ForwardToServer<decltype(&Server::OnCreateComputePipelineAsyncCallback)>::Func< 143 &Server::OnCreateComputePipelineAsyncCallback>(), 144 userdata.release()); 145 return true; 146 } 147 OnCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,WGPUComputePipeline pipeline,const char * message,CreatePipelineAsyncUserData * data)148 void Server::OnCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status, 149 WGPUComputePipeline pipeline, 150 const char* message, 151 CreatePipelineAsyncUserData* data) { 152 HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::ComputePipeline>( 153 &ComputePipelineObjects(), status, pipeline, data); 154 155 ReturnDeviceCreateComputePipelineAsyncCallbackCmd cmd; 156 cmd.device = data->device; 157 cmd.status = status; 158 cmd.requestSerial = data->requestSerial; 159 cmd.message = message; 160 161 SerializeCommand(cmd); 162 } 163 DoDeviceCreateRenderPipelineAsync(ObjectId deviceId,uint64_t requestSerial,ObjectHandle pipelineObjectHandle,const WGPURenderPipelineDescriptor * descriptor)164 bool Server::DoDeviceCreateRenderPipelineAsync(ObjectId deviceId, 165 uint64_t requestSerial, 166 ObjectHandle pipelineObjectHandle, 167 const WGPURenderPipelineDescriptor* descriptor) { 168 auto* device = DeviceObjects().Get(deviceId); 169 if (device == nullptr) { 170 return false; 171 } 172 173 auto* resultData = 174 RenderPipelineObjects().Allocate(pipelineObjectHandle.id, AllocationState::Reserved); 175 if (resultData == nullptr) { 176 return false; 177 } 178 179 resultData->generation = pipelineObjectHandle.generation; 180 resultData->deviceInfo = device->info.get(); 181 182 auto userdata = MakeUserdata<CreatePipelineAsyncUserData>(); 183 userdata->device = ObjectHandle{deviceId, device->generation}; 184 userdata->requestSerial = requestSerial; 185 userdata->pipelineObjectID = pipelineObjectHandle.id; 186 187 mProcs.deviceCreateRenderPipelineAsync( 188 device->handle, descriptor, 189 ForwardToServer<decltype(&Server::OnCreateRenderPipelineAsyncCallback)>::Func< 190 &Server::OnCreateRenderPipelineAsyncCallback>(), 191 userdata.release()); 192 return true; 193 } 194 OnCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,WGPURenderPipeline pipeline,const char * message,CreatePipelineAsyncUserData * data)195 void Server::OnCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status, 196 WGPURenderPipeline pipeline, 197 const char* message, 198 CreatePipelineAsyncUserData* data) { 199 HandleCreateRenderPipelineAsyncCallbackResult<ObjectType::RenderPipeline>( 200 &RenderPipelineObjects(), status, pipeline, data); 201 202 ReturnDeviceCreateRenderPipelineAsyncCallbackCmd cmd; 203 cmd.device = data->device; 204 cmd.status = status; 205 cmd.requestSerial = data->requestSerial; 206 cmd.message = message; 207 208 SerializeCommand(cmd); 209 } 210 211 }} // namespace dawn_wire::server 212