tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_