WebGPUParent.h (11316B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef WEBGPU_PARENT_H_ 7 #define WEBGPU_PARENT_H_ 8 9 #include <unordered_map> 10 11 #include "WebGPUTypes.h" 12 #include "base/timer.h" 13 #include "mozilla/WeakPtr.h" 14 #include "mozilla/ipc/SharedMemoryHandle.h" 15 #include "mozilla/webgpu/ExternalTexture.h" 16 #include "mozilla/webgpu/PWebGPUParent.h" 17 #include "mozilla/webgpu/ffi/wgpu.h" 18 #include "mozilla/webrender/WebRenderAPI.h" 19 20 namespace mozilla { 21 22 namespace layers { 23 class RemoteTextureOwnerClient; 24 } // namespace layers 25 26 namespace webgpu { 27 28 class SharedTexture; 29 class PresentationData; 30 31 // A fixed-capacity buffer for receiving textual error messages from 32 // `wgpu_bindings`. 33 // 34 // The `ToFFI` method returns an `ffi::WGPUErrorBuffer` pointing to our 35 // buffer, for you to pass to fallible FFI-visible `wgpu_bindings` 36 // functions. These indicate failure by storing an error message in the 37 // buffer, which you can retrieve by calling `GetError`. 38 // 39 // If you call `ToFFI` on this type, you must also call `GetError` to check for 40 // an error. Otherwise, the destructor asserts. 41 // 42 // TODO: refactor this to avoid stack-allocating the buffer all the time. 43 class ErrorBuffer { 44 // if the message doesn't fit, it will be truncated 45 static constexpr unsigned BUFFER_SIZE = 512; 46 ffi::WGPUErrorBufferType mType = ffi::WGPUErrorBufferType_None; 47 char mMessageUtf8[BUFFER_SIZE] = {}; 48 bool mAwaitingGetError = false; 49 RawId mDeviceId = 0; 50 51 public: 52 ErrorBuffer(); 53 ErrorBuffer(const ErrorBuffer&) = delete; 54 ~ErrorBuffer(); 55 56 ffi::WGPUErrorBuffer ToFFI(); 57 58 ffi::WGPUErrorBufferType GetType(); 59 60 static Maybe<dom::GPUErrorFilter> ErrorTypeToFilterType( 61 ffi::WGPUErrorBufferType aType); 62 63 struct Error { 64 dom::GPUErrorFilter type; 65 bool isDeviceLost; 66 nsCString message; 67 RawId deviceId; 68 }; 69 70 // Retrieve the error message was stored in this buffer. Asserts that 71 // this instance actually contains an error (viz., that `GetType() != 72 // ffi::WGPUErrorBufferType_None`). 73 // 74 // Mark this `ErrorBuffer` as having been handled, so its destructor 75 // won't assert. 76 Maybe<Error> GetError(); 77 78 void CoerceValidationToInternal(); 79 }; 80 81 // Destroy/Drop messages: 82 // - Messages with "Destroy" in their name request deallocation of resources 83 // owned by the 84 // object and put the object in a destroyed state without deleting the object. 85 // It is still safe to reffer to these objects. 86 // - Messages with "Drop" in their name can be thought of as C++ destructors. 87 // They completely 88 // delete the object, so future attempts at accessing to these objects will 89 // crash. The child process should *never* send a Drop message if it still 90 // holds references to the object. An object that has been destroyed still 91 // needs to be dropped when the last reference to it dies on the child 92 // process. 93 94 class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr { 95 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGPUParent, override) 96 97 public: 98 explicit WebGPUParent(const dom::ContentParentId& aContentId); 99 100 void PostAdapterRequestDevice(RawId aDeviceId); 101 void BufferUnmap(RawId aDeviceId, RawId aBufferId, bool aFlush); 102 ipc::IPCResult RecvMessages(uint32_t nrOfMessages, 103 ipc::ByteBuf&& aSerializedMessages, 104 nsTArray<ipc::ByteBuf>&& aDataBuffers, 105 nsTArray<MutableSharedMemoryHandle>&& aShmems); 106 ipc::IPCResult RecvCreateExternalTextureSource( 107 RawId aDeviceId, RawId aQueueId, RawId aExternalTextureSourceId, 108 const ExternalTextureSourceDescriptor& aDesc); 109 void QueueSubmit(RawId aQueueId, RawId aDeviceId, 110 Span<const RawId> aCommandBuffers, 111 Span<const RawId> aTextureIds, 112 Span<const RawId> aExternalTextureSourceIds); 113 void DeviceCreateSwapChain(RawId aDeviceId, RawId aQueueId, 114 const layers::RGBDescriptor& aDesc, 115 const nsTArray<RawId>& aBufferIds, 116 const layers::RemoteTextureOwnerId& aOwnerId, 117 bool aUseSharedTextureInSwapChain); 118 119 void SwapChainPresent(RawId aTextureId, RawId aCommandEncoderId, 120 RawId aCommandBufferId, 121 const layers::RemoteTextureId& aRemoteTextureId, 122 const layers::RemoteTextureOwnerId& aOwnerId); 123 void SwapChainDrop(const layers::RemoteTextureOwnerId& aOwnerId, 124 layers::RemoteTextureTxnType aTxnType, 125 layers::RemoteTextureTxnId aTxnId); 126 127 void DevicePushErrorScope(RawId aDeviceId, dom::GPUErrorFilter); 128 PopErrorScopeResult DevicePopErrorScope(RawId aDeviceId); 129 130 ipc::IPCResult GetFrontBufferSnapshot( 131 IProtocol* aProtocol, const layers::RemoteTextureOwnerId& aOwnerId, 132 const RawId& aCommandEncoderId, const RawId& aCommandBufferId, 133 Maybe<Shmem>& aShmem, gfx::IntSize& aSize, uint32_t& aByteStride); 134 135 void ActorDestroy(ActorDestroyReason aWhy) override; 136 137 struct BufferMapData { 138 std::shared_ptr<ipc::SharedMemoryMapping> mShmem; 139 // True if buffer's usage has MAP_READ or MAP_WRITE set. 140 bool mHasMapFlags; 141 uint64_t mMappedOffset; 142 uint64_t mMappedSize; 143 RawId mDeviceId; 144 }; 145 146 BufferMapData* GetBufferMapData(RawId aBufferId); 147 148 bool UseSharedTextureForSwapChain(ffi::WGPUSwapChainId aSwapChainId); 149 150 void DisableSharedTextureForSwapChain(ffi::WGPUSwapChainId aSwapChainId); 151 152 bool EnsureSharedTextureForSwapChain(ffi::WGPUSwapChainId aSwapChainId, 153 ffi::WGPUDeviceId aDeviceId, 154 ffi::WGPUTextureId aTextureId, 155 uint32_t aWidth, uint32_t aHeight, 156 struct ffi::WGPUTextureFormat aFormat, 157 ffi::WGPUTextureUsages aUsage); 158 159 void EnsureSharedTextureForReadBackPresent( 160 ffi::WGPUSwapChainId aSwapChainId, ffi::WGPUDeviceId aDeviceId, 161 ffi::WGPUTextureId aTextureId, uint32_t aWidth, uint32_t aHeight, 162 struct ffi::WGPUTextureFormat aFormat, ffi::WGPUTextureUsages aUsage); 163 164 std::shared_ptr<SharedTexture> CreateSharedTexture( 165 const layers::RemoteTextureOwnerId& aOwnerId, ffi::WGPUDeviceId aDeviceId, 166 ffi::WGPUTextureId aTextureId, uint32_t aWidth, uint32_t aHeight, 167 const struct ffi::WGPUTextureFormat aFormat, 168 ffi::WGPUTextureUsages aUsage); 169 170 std::shared_ptr<SharedTexture> GetSharedTexture(ffi::WGPUTextureId aId); 171 172 void PostSharedTexture(const std::shared_ptr<SharedTexture>&& aSharedTexture, 173 const layers::RemoteTextureId aRemoteTextureId, 174 const layers::RemoteTextureOwnerId aOwnerId); 175 176 bool ForwardError(ErrorBuffer& aError); 177 178 ffi::WGPUGlobal* GetContext() const { return mContext.get(); } 179 180 bool IsDeviceActive(const RawId aDeviceId) { 181 return mActiveDeviceIds.Contains(aDeviceId); 182 } 183 184 RefPtr<gfx::FileHandleWrapper> GetDeviceFenceHandle(const RawId aDeviceId); 185 186 void RemoveSharedTexture(RawId aTextureId); 187 188 const ExternalTextureSourceHost& GetExternalTextureSource( 189 ffi::WGPUExternalTextureSourceId aId) const; 190 void DestroyExternalTextureSource(RawId aId); 191 void DropExternalTextureSource(RawId aId); 192 193 void DeallocBufferShmem(RawId aBufferId); 194 void PreDeviceDrop(RawId aDeviceId); 195 196 #if defined(XP_WIN) 197 static Maybe<ffi::WGPUFfiLUID> GetCompositorDeviceLuid(); 198 #endif 199 200 struct MapRequest { 201 WeakPtr<WebGPUParent> mParent; 202 ffi::WGPUDeviceId mDeviceId; 203 ffi::WGPUBufferId mBufferId; 204 ffi::WGPUHostMap mHostMap; 205 uint64_t mOffset; 206 uint64_t mSize; 207 }; 208 209 static void MapCallback(/* std::unique_ptr<MapRequest> */ uint8_t* aUserData, 210 ffi::WGPUBufferMapAsyncStatus aStatus); 211 212 struct OnSubmittedWorkDoneRequest { 213 WeakPtr<WebGPUParent> mParent; 214 ffi::WGPUDeviceId mQueueId; 215 }; 216 217 static void OnSubmittedWorkDoneCallback( 218 /* std::unique_ptr<OnSubmittedWorkDoneRequest> */ uint8_t* userdata); 219 220 void ReportError(RawId aDeviceId, GPUErrorFilter, const nsCString& message); 221 222 std::vector<std::shared_ptr<ipc::SharedMemoryMapping>> mTempMappings; 223 224 /// A map from wgpu buffer ids to data about their shared memory segments. 225 /// Includes entries about mappedAtCreation, MAP_READ and MAP_WRITE buffers, 226 /// regardless of their state. 227 std::unordered_map<RawId, BufferMapData> mSharedMemoryMap; 228 229 const dom::ContentParentId mContentId; 230 231 private: 232 static void DeviceLostCallback(uint8_t* aUserData, uint8_t aReason, 233 const char* aMessage); 234 235 virtual ~WebGPUParent(); 236 void MaintainDevices(); 237 void LoseDevice(const RawId aDeviceId, uint8_t aReason, 238 const nsACString& aMessage); 239 240 UniquePtr<ffi::WGPUGlobal> mContext; 241 base::RepeatingTimer<WebGPUParent> mTimer; 242 243 /// Associated presentation data for each swapchain. 244 std::unordered_map<layers::RemoteTextureOwnerId, RefPtr<PresentationData>, 245 layers::RemoteTextureOwnerId::HashFn> 246 mPresentationDataMap; 247 248 RefPtr<layers::RemoteTextureOwnerClient> mRemoteTextureOwner; 249 250 /// Associated stack of error scopes for each device. 251 std::unordered_map<uint64_t, std::vector<ErrorScope>> 252 mErrorScopeStackByDevice; 253 254 std::unordered_map<ffi::WGPUTextureId, std::shared_ptr<SharedTexture>> 255 mSharedTextures; 256 257 std::unordered_map<RawId, ExternalTextureSourceHost> mExternalTextureSources; 258 259 // Store a set of DeviceIds that have been SendDeviceLost. We use this to 260 // limit each Device to one DeviceLost message. 261 nsTHashSet<RawId> mLostDeviceIds; 262 263 // Store active DeviceIds 264 nsTHashSet<RawId> mActiveDeviceIds; 265 266 // Shared handle of wgpu device's fence. 267 std::unordered_map<RawId, RefPtr<gfx::FileHandleWrapper>> mDeviceFenceHandles; 268 }; 269 270 #if defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID) 271 class VkImageHandle { 272 public: 273 explicit VkImageHandle(WebGPUParent* aParent, 274 const ffi::WGPUDeviceId aDeviceId, 275 ffi::WGPUVkImageHandle* aVkImageHandle) 276 : mParent(aParent), 277 mDeviceId(aDeviceId), 278 mVkImageHandle(aVkImageHandle) {} 279 280 const ffi::WGPUVkImageHandle* Get() { return mVkImageHandle; } 281 282 ~VkImageHandle(); 283 284 protected: 285 const WeakPtr<WebGPUParent> mParent; 286 const RawId mDeviceId; 287 ffi::WGPUVkImageHandle* mVkImageHandle; 288 }; 289 290 class VkSemaphoreHandle { 291 public: 292 explicit VkSemaphoreHandle(WebGPUParent* aParent, 293 const ffi::WGPUDeviceId aDeviceId, 294 ffi::WGPUVkSemaphoreHandle* aVkSemaphoreHandle) 295 : mParent(aParent), 296 mDeviceId(aDeviceId), 297 mVkSemaphoreHandle(aVkSemaphoreHandle) {} 298 299 const ffi::WGPUVkSemaphoreHandle* Get() { return mVkSemaphoreHandle; } 300 301 ~VkSemaphoreHandle(); 302 303 protected: 304 const WeakPtr<WebGPUParent> mParent; 305 const RawId mDeviceId; 306 ffi::WGPUVkSemaphoreHandle* mVkSemaphoreHandle; 307 }; 308 #endif 309 310 } // namespace webgpu 311 } // namespace mozilla 312 313 #endif // WEBGPU_PARENT_H_