summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/ipc/WebGPUParent.h
blob: 6ad539c21e50c7c1a9cb24e0cd00ac7d12623c0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef WEBGPU_PARENT_H_
#define WEBGPU_PARENT_H_

#include <unordered_map>

#include "mozilla/WeakPtr.h"
#include "mozilla/webgpu/ffi/wgpu.h"
#include "mozilla/webgpu/PWebGPUParent.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/ipc/RawShmem.h"
#include "WebGPUTypes.h"
#include "base/timer.h"

namespace mozilla {

namespace layers {
class RemoteTextureOwnerClient;
}  // namespace layers

namespace webgpu {

class ErrorBuffer;
class ExternalTexture;
class PresentationData;

// Destroy/Drop messages:
// - Messages with "Destroy" in their name request deallocation of resources
// owned by the
//   object and put the object in a destroyed state without deleting the object.
//   It is still safe to reffer to these objects.
// - Messages with "Drop" in their name can be thought of as C++ destructors.
// They completely
//   delete the object, so future attempts at accessing to these objects will
//   crash. The child process should *never* send a Drop message if it still
//   holds references to the object. An object that has been destroyed still
//   needs to be dropped when the last reference to it dies on the child
//   process.

class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGPUParent, override)

 public:
  explicit WebGPUParent();

  ipc::IPCResult RecvInstanceRequestAdapter(
      const dom::GPURequestAdapterOptions& aOptions,
      const nsTArray<RawId>& aTargetIds,
      InstanceRequestAdapterResolver&& resolver);
  ipc::IPCResult RecvAdapterRequestDevice(
      RawId aAdapterId, const ipc::ByteBuf& aByteBuf, RawId aDeviceId,
      AdapterRequestDeviceResolver&& resolver);
  ipc::IPCResult RecvAdapterDrop(RawId aAdapterId);
  ipc::IPCResult RecvDeviceDestroy(RawId aDeviceId);
  ipc::IPCResult RecvDeviceDrop(RawId aDeviceId);
  ipc::IPCResult RecvDeviceCreateBuffer(RawId aDeviceId, RawId aBufferId,
                                        dom::GPUBufferDescriptor&& aDesc,
                                        ipc::UnsafeSharedMemoryHandle&& aShmem);
  ipc::IPCResult RecvBufferMap(RawId aDeviceId, RawId aBufferId, uint32_t aMode,
                               uint64_t aOffset, uint64_t size,
                               BufferMapResolver&& aResolver);
  ipc::IPCResult RecvBufferUnmap(RawId aDeviceId, RawId aBufferId, bool aFlush);
  ipc::IPCResult RecvBufferDestroy(RawId aBufferId);
  ipc::IPCResult RecvBufferDrop(RawId aBufferId);
  ipc::IPCResult RecvTextureDestroy(RawId aTextureId, RawId aDeviceId);
  ipc::IPCResult RecvTextureDrop(RawId aTextureId);
  ipc::IPCResult RecvTextureViewDrop(RawId aTextureViewId);
  ipc::IPCResult RecvSamplerDrop(RawId aSamplerId);
  ipc::IPCResult RecvCommandEncoderFinish(
      RawId aEncoderId, RawId aDeviceId,
      const dom::GPUCommandBufferDescriptor& aDesc);
  ipc::IPCResult RecvCommandEncoderDrop(RawId aEncoderId);
  ipc::IPCResult RecvCommandBufferDrop(RawId aCommandBufferId);
  ipc::IPCResult RecvRenderBundleDrop(RawId aBundleId);
  ipc::IPCResult RecvQueueSubmit(RawId aQueueId, RawId aDeviceId,
                                 const nsTArray<RawId>& aCommandBuffers,
                                 const nsTArray<RawId>& aTextureIds);
  ipc::IPCResult RecvQueueOnSubmittedWorkDone(
      RawId aQueueId, std::function<void(mozilla::void_t)>&& aResolver);
  ipc::IPCResult RecvQueueWriteAction(RawId aQueueId, RawId aDeviceId,
                                      const ipc::ByteBuf& aByteBuf,
                                      ipc::UnsafeSharedMemoryHandle&& aShmem);
  ipc::IPCResult RecvBindGroupLayoutDrop(RawId aBindGroupLayoutId);
  ipc::IPCResult RecvPipelineLayoutDrop(RawId aPipelineLayoutId);
  ipc::IPCResult RecvBindGroupDrop(RawId aBindGroupId);
  ipc::IPCResult RecvShaderModuleDrop(RawId aModuleId);
  ipc::IPCResult RecvComputePipelineDrop(RawId aPipelineId);
  ipc::IPCResult RecvRenderPipelineDrop(RawId aPipelineId);
  ipc::IPCResult RecvImplicitLayoutDrop(RawId aImplicitPlId,
                                        const nsTArray<RawId>& aImplicitBglIds);
  ipc::IPCResult RecvDeviceCreateSwapChain(
      RawId aDeviceId, RawId aQueueId, const layers::RGBDescriptor& aDesc,
      const nsTArray<RawId>& aBufferIds,
      const layers::RemoteTextureOwnerId& aOwnerId,
      bool aUseExternalTextureInSwapChain);
  ipc::IPCResult RecvDeviceCreateShaderModule(
      RawId aDeviceId, RawId aModuleId, const nsString& aLabel,
      const nsCString& aCode, DeviceCreateShaderModuleResolver&& aOutMessage);

  ipc::IPCResult RecvSwapChainPresent(
      RawId aTextureId, RawId aCommandEncoderId,
      const layers::RemoteTextureId& aRemoteTextureId,
      const layers::RemoteTextureOwnerId& aOwnerId);
  ipc::IPCResult RecvSwapChainDrop(const layers::RemoteTextureOwnerId& aOwnerId,
                                   layers::RemoteTextureTxnType aTxnType,
                                   layers::RemoteTextureTxnId aTxnId);

  ipc::IPCResult RecvDeviceAction(RawId aDeviceId,
                                  const ipc::ByteBuf& aByteBuf);
  ipc::IPCResult RecvDeviceActionWithAck(
      RawId aDeviceId, const ipc::ByteBuf& aByteBuf,
      DeviceActionWithAckResolver&& aResolver);
  ipc::IPCResult RecvTextureAction(RawId aTextureId, RawId aDevice,
                                   const ipc::ByteBuf& aByteBuf);
  ipc::IPCResult RecvCommandEncoderAction(RawId aEncoderId, RawId aDeviceId,
                                          const ipc::ByteBuf& aByteBuf);
  ipc::IPCResult RecvBumpImplicitBindGroupLayout(RawId aPipelineId,
                                                 bool aIsCompute,
                                                 uint32_t aIndex,
                                                 RawId aAssignId);

  ipc::IPCResult RecvDevicePushErrorScope(RawId aDeviceId, dom::GPUErrorFilter);
  ipc::IPCResult RecvDevicePopErrorScope(
      RawId aDeviceId, DevicePopErrorScopeResolver&& aResolver);
  ipc::IPCResult RecvGenerateError(Maybe<RawId> aDeviceId, dom::GPUErrorFilter,
                                   const nsCString& message);

  ipc::IPCResult GetFrontBufferSnapshot(
      IProtocol* aProtocol, const layers::RemoteTextureOwnerId& aOwnerId,
      Maybe<Shmem>& aShmem, gfx::IntSize& aSize);

  void ActorDestroy(ActorDestroyReason aWhy) override;

  struct BufferMapData {
    ipc::WritableSharedMemoryMapping mShmem;
    // True if buffer's usage has MAP_READ or MAP_WRITE set.
    bool mHasMapFlags;
    uint64_t mMappedOffset;
    uint64_t mMappedSize;
    RawId mDeviceId;
  };

  BufferMapData* GetBufferMapData(RawId aBufferId);

  bool UseExternalTextureForSwapChain(ffi::WGPUSwapChainId aSwapChainId);

  bool EnsureExternalTextureForSwapChain(ffi::WGPUSwapChainId aSwapChainId,
                                         ffi::WGPUDeviceId aDeviceId,
                                         ffi::WGPUTextureId aTextureId,
                                         uint32_t aWidth, uint32_t aHeight,
                                         struct ffi::WGPUTextureFormat aFormat,
                                         ffi::WGPUTextureUsages aUsage);

  std::shared_ptr<ExternalTexture> CreateExternalTexture(
      ffi::WGPUDeviceId aDeviceId, ffi::WGPUTextureId aTextureId,
      uint32_t aWidth, uint32_t aHeight,
      const struct ffi::WGPUTextureFormat aFormat,
      ffi::WGPUTextureUsages aUsage);

  std::shared_ptr<ExternalTexture> GetExternalTexture(ffi::WGPUTextureId aId);

  void PostExternalTexture(
      const std::shared_ptr<ExternalTexture>&& aExternalTexture,
      const layers::RemoteTextureId aRemoteTextureId,
      const layers::RemoteTextureOwnerId aOwnerId);

  bool ForwardError(const RawId aDeviceId, ErrorBuffer& aError) {
    return ForwardError(Some(aDeviceId), aError);
  }

 private:
  static void MapCallback(ffi::WGPUBufferMapAsyncStatus aStatus,
                          uint8_t* aUserData);
  static void DeviceLostCallback(uint8_t* aUserData, uint8_t aReason,
                                 const char* aMessage);
  void DeallocBufferShmem(RawId aBufferId);

  void RemoveExternalTexture(RawId aTextureId);

  virtual ~WebGPUParent();
  void MaintainDevices();
  void LoseDevice(const RawId aDeviceId, Maybe<uint8_t> aReason,
                  const nsACString& aMessage);

  bool ForwardError(Maybe<RawId> aDeviceId, ErrorBuffer& aError);

  void ReportError(Maybe<RawId> aDeviceId, GPUErrorFilter,
                   const nsCString& message);

  static Maybe<ffi::WGPUFfiLUID> GetCompositorDeviceLuid();

  UniquePtr<ffi::WGPUGlobal> mContext;
  base::RepeatingTimer<WebGPUParent> mTimer;

  /// A map from wgpu buffer ids to data about their shared memory segments.
  /// Includes entries about mappedAtCreation, MAP_READ and MAP_WRITE buffers,
  /// regardless of their state.
  std::unordered_map<uint64_t, BufferMapData> mSharedMemoryMap;
  /// Associated presentation data for each swapchain.
  std::unordered_map<layers::RemoteTextureOwnerId, RefPtr<PresentationData>,
                     layers::RemoteTextureOwnerId::HashFn>
      mPresentationDataMap;

  RefPtr<layers::RemoteTextureOwnerClient> mRemoteTextureOwner;

  /// Associated stack of error scopes for each device.
  std::unordered_map<uint64_t, std::vector<ErrorScope>>
      mErrorScopeStackByDevice;

  std::unordered_map<ffi::WGPUTextureId, std::shared_ptr<ExternalTexture>>
      mExternalTextures;

  // Store a set of DeviceIds that have been SendDeviceLost. We use this to
  // limit each Device to one DeviceLost message.
  nsTHashSet<RawId> mLostDeviceIds;

  // Shared handle of wgpu device's fence.
  RefPtr<gfx::FileHandleWrapper> mFenceHandle;

  // Store DeviceLostRequest structs for each device as unique_ptrs mapped
  // to their device ids. We keep these unique_ptrs alive as long as the
  // device is alive.
  struct DeviceLostRequest {
    WeakPtr<WebGPUParent> mParent;
    RawId mDeviceId;
  };
  std::unordered_map<RawId, std::unique_ptr<DeviceLostRequest>>
      mDeviceLostRequests;
};

}  // namespace webgpu
}  // namespace mozilla

#endif  // WEBGPU_PARENT_H_