File: Buffer.h

package info (click to toggle)
firefox 144.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,637,504 kB
  • sloc: cpp: 7,576,692; javascript: 6,430,831; ansic: 3,748,119; python: 1,398,978; xml: 628,810; asm: 438,679; java: 186,194; sh: 63,212; makefile: 19,159; objc: 13,086; perl: 12,986; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (160 lines) | stat: -rw-r--r-- 5,952 bytes parent folder | download | duplicates (3)
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
/* -*- 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 GPU_BUFFER_H_
#define GPU_BUFFER_H_

#include <memory>

#include "ObjectModel.h"
#include "js/RootingAPI.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/ipc/SharedMemoryMapping.h"
#include "mozilla/webgpu/WebGPUTypes.h"
#include "nsTArray.h"

namespace mozilla {
namespace webgpu {
struct MappedView;
}  // namespace webgpu
}  // namespace mozilla

// Give `nsTArray` some advice on how to handle `MappedInfo::mViews`.
//
// In the `mozilla::webgpu` namespace, `MappedInfo::mViews` is an
// `nsTArray<MappedView>`, and `MappedView::mArrayBuffer` is a `JS::Heap`
// pointer. This arrangement requires special handling.
//
// Normally, `nsTArray` wants its element type to be movable with simple byte
// copies, so that an `nsTArray` can efficiently resize its element buffer.
// However, `JS::Heap` is marked `MOZ_NON_MEMMOVABLE`, meaning that it cannot be
// safely moved by a simple byte-by-byte copy. Normally, this would cause
// `nsTArray` to reject `JS::Heap` as an element type, but `nsTArray.h`
// specializes `nsTArray_RelocationStrategy` to indicate that `JS::Heap` can be
// moved safely using its move constructor. This causes `nsTArray<JS::Heap<T>>`
// to perform element buffer moves using element-by-element move constructor
// application: slower, but safe for `JS::Heap`.
//
// However, while `MappedView` is automatically marked `MOZ_NON_MEMMOVABLE`
// because of its `mArrayBuffer` member, the `nsTArray_RelocationStrategy`
// specialization is not somehow similarly magically carried over from
// `JS::Heap` to `MappedView`. To use `MappedView` in `nsTArray`, we must spell
// out a relocation strategy for it.
template <>
struct nsTArray_RelocationStrategy<mozilla::webgpu::MappedView> {
  // The default move constructors are fine for MappedView.
  using Type =
      nsTArray_RelocateUsingMoveConstructor<mozilla::webgpu::MappedView>;
};

namespace mozilla {
class ErrorResult;

namespace dom {
struct GPUBufferDescriptor;
template <typename T>
class Optional;
enum class GPUBufferMapState : uint8_t;
}  // namespace dom

namespace webgpu {

class Device;

// A portion of the current mapped buffer range that is currently
// visible to JS as an ArrayBuffer.
struct MappedView {
  BufferAddress mOffset;
  BufferAddress mRangeEnd;
  JS::Heap<JSObject*> mArrayBuffer;

  MappedView(BufferAddress aOffset, BufferAddress aRangeEnd,
             JSObject* aArrayBuffer)
      : mOffset(aOffset), mRangeEnd(aRangeEnd), mArrayBuffer(aArrayBuffer) {}
};

struct MappedInfo {
  // True if mapping is requested for writing.
  bool mWritable = false;
  // Populated by `GetMappedRange`.
  nsTArray<MappedView> mViews;
  BufferAddress mOffset;
  BufferAddress mSize;
  MappedInfo() = default;
  MappedInfo(const MappedInfo&) = delete;
};

class Buffer final : public nsWrapperCache,
                     public ObjectBase,
                     public ChildOf<Device> {
 public:
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Buffer)
  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Buffer)
  GPU_DECL_JS_WRAP(Buffer)

  static already_AddRefed<Buffer> Create(Device* aDevice, RawId aDeviceId,
                                         const dom::GPUBufferDescriptor& aDesc,
                                         ErrorResult& aRv);

  already_AddRefed<dom::Promise> MapAsync(uint32_t aMode, uint64_t aOffset,
                                          const dom::Optional<uint64_t>& aSize,
                                          ErrorResult& aRv);
  void GetMappedRange(JSContext* aCx, uint64_t aOffset,
                      const dom::Optional<uint64_t>& aSize,
                      JS::Rooted<JSObject*>* aObject, ErrorResult& aRv);
  void Unmap(JSContext* aCx, ErrorResult& aRv);
  void Destroy(JSContext* aCx, ErrorResult& aRv);

  uint64_t Size() const { return mSize; }
  uint32_t Usage() const { return mUsage; }
  dom::GPUBufferMapState MapState() const;

  void ResolveMapRequest(dom::Promise* aPromise, BufferAddress aOffset,
                         BufferAddress aSize, bool aWritable);
  void RejectMapRequest(dom::Promise* aPromise, const nsACString& message);
  void RejectMapRequestWithAbortError(dom::Promise* aPromise);

 private:
  Buffer(Device* const aParent, RawId aId, BufferAddress aSize, uint32_t aUsage,
         ipc::SharedMemoryMapping&& aShmem);
  virtual ~Buffer();
  void Cleanup();
  void UnmapArrayBuffers(JSContext* aCx, ErrorResult& aRv);
  void AbortMapRequest();
  void SetMapped(BufferAddress aOffset, BufferAddress aSize, bool aWritable);

  bool mValid = true;
  // Note: we can't map a buffer with the size that don't fit into `size_t`
  // (which may be smaller than `BufferAddress`), but general not all buffers
  // are mapped.
  const BufferAddress mSize;
  const uint32_t mUsage;
  nsString mLabel;
  // Information about the currently active mapping.
  Maybe<MappedInfo> mMapped;
  RefPtr<dom::Promise> mMapRequest;

  // A shared memory mapping for the entire buffer, or a zero-length
  // mapping.
  //
  // If `mUsage` contains `MAP_READ` or `MAP_WRITE`, this mapping is
  // created at `Buffer` construction, and destroyed at `Buffer`
  // destruction.
  //
  // If `mUsage` contains neither of those flags, but `this` is mapped
  // at creation, this mapping is created at `Buffer` construction,
  // and destroyed when we first unmap the buffer, by clearing this
  // `shared_ptr`.
  //
  // Otherwise, this points to `SharedMemoryMapping()` (the default
  // constructor), a zero-length mapping that doesn't point to any shared
  // memory.
  std::shared_ptr<ipc::SharedMemoryMapping> mShmem;
};

}  // namespace webgpu
}  // namespace mozilla

#endif  // GPU_BUFFER_H_