Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/mlgpu/SharedBufferMLGPU.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h
8
#define mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h
9
10
#include "ShaderDefinitionsMLGPU.h"
11
#include "MLGDevice.h"
12
#include "MLGDeviceTypes.h"
13
#include "StagingBuffer.h"
14
#include "mozilla/gfx/Logging.h"
15
16
namespace mozilla {
17
namespace layers {
18
19
class MLGBuffer;
20
21
class SharedBufferMLGPU
22
{
23
public:
24
  virtual ~SharedBufferMLGPU();
25
26
  bool Init();
27
28
  // Call before starting a new frame.
29
  void Reset();
30
31
  // Call to finish any pending uploads.
32
  void PrepareForUsage();
33
34
protected:
35
  SharedBufferMLGPU(MLGDevice* aDevice, MLGBufferType aType, size_t aDefaultSize);
36
37
  bool EnsureMappedBuffer(size_t aBytes);
38
  bool GrowBuffer(size_t aBytes);
39
  void ForgetBuffer();
40
  bool Map();
41
  void Unmap();
42
43
  uint8_t* GetBufferPointer(size_t aBytes, ptrdiff_t* aOutOffset, RefPtr<MLGBuffer>* aOutBuffer);
44
45
protected:
46
  // Note: RefPtr here would cause a cycle. Only MLGDevice should own
47
  // SharedBufferMLGPU objects for now.
48
  MLGDevice* mDevice;
49
  MLGBufferType mType;
50
  size_t mDefaultSize;
51
  bool mCanUseOffsetAllocation;
52
53
  // When |mBuffer| is non-null, mMaxSize is the buffer size. If mapped, the
54
  // position is between 0 and mMaxSize, otherwise it is always 0.
55
  RefPtr<MLGBuffer> mBuffer;
56
  ptrdiff_t mCurrentPosition;
57
  size_t mMaxSize;
58
59
  MLGMappedResource mMap;
60
  bool mMapped;
61
62
  // These are used to track how many frames come in under the default
63
  // buffer size in a row.
64
  size_t mBytesUsedThisFrame;
65
  size_t mNumSmallFrames;
66
};
67
68
class VertexBufferSection final
69
{
70
  friend class SharedVertexBuffer;
71
public:
72
  VertexBufferSection();
73
74
0
  uint32_t Stride() const {
75
0
    return mStride;
76
0
  }
77
0
  MLGBuffer* GetBuffer() const {
78
0
    return mBuffer;
79
0
  }
80
0
  ptrdiff_t Offset() const {
81
0
    MOZ_ASSERT(IsValid());
82
0
    return mOffset;
83
0
  }
84
0
  size_t NumVertices() const {
85
0
    return mNumVertices;
86
0
  }
87
0
  bool IsValid() const {
88
0
    return !!mBuffer;
89
0
  }
90
91
protected:
92
  void Init(MLGBuffer* aBuffer, ptrdiff_t aOffset, size_t aNumVertices, size_t aStride);
93
94
protected:
95
  RefPtr<MLGBuffer> mBuffer;
96
  ptrdiff_t mOffset;
97
  size_t mNumVertices;
98
  size_t mStride;
99
};
100
101
class ConstantBufferSection final
102
{
103
  friend class SharedConstantBuffer;
104
105
public:
106
  ConstantBufferSection();
107
108
0
  uint32_t NumConstants() const {
109
0
    return NumConstantsForBytes(mNumBytes);
110
0
  }
111
0
  size_t NumItems() const {
112
0
    return mNumItems;
113
0
  }
114
0
  uint32_t Offset() const {
115
0
    MOZ_ASSERT(IsValid());
116
0
    return mOffset / 16;
117
0
  }
118
0
  MLGBuffer* GetBuffer() const {
119
0
    return mBuffer;
120
0
  }
121
0
  bool IsValid() const {
122
0
    return !!mBuffer;
123
0
  }
124
0
  bool HasOffset() const {
125
0
    return mOffset != -1;
126
0
  }
127
128
protected:
129
0
  static constexpr size_t NumConstantsForBytes(size_t aBytes) {
130
0
    return (aBytes + ((256 - (aBytes % 256)) % 256)) / 16;
131
0
  }
132
133
  void Init(MLGBuffer* aBuffer, ptrdiff_t aOffset, size_t aBytes, size_t aNumItems);
134
135
protected:
136
  RefPtr<MLGBuffer> mBuffer;
137
  ptrdiff_t mOffset;
138
  size_t mNumBytes;
139
  size_t mNumItems;
140
};
141
142
// Vertex buffers don't need special alignment.
143
typedef StagingBuffer<0> VertexStagingBuffer;
144
145
class SharedVertexBuffer final : public SharedBufferMLGPU
146
{
147
public:
148
  SharedVertexBuffer(MLGDevice* aDevice, size_t aDefaultSize);
149
150
  // Allocate a buffer that can be uploaded immediately.
151
0
  bool Allocate(VertexBufferSection* aHolder, const VertexStagingBuffer& aStaging) {
152
0
    return Allocate(aHolder,
153
0
                    aStaging.NumItems(),
154
0
                    aStaging.SizeOfItem(),
155
0
                    aStaging.GetBufferStart());
156
0
  }
157
158
  // Allocate a buffer that can be uploaded immediately. This is the
159
  // direct access version, for cases where a StagingBuffer is not
160
  // needed.
161
  bool Allocate(VertexBufferSection* aHolder,
162
                size_t aNumItems,
163
                size_t aSizeOfItem,
164
                const void* aData);
165
166
  template <typename T>
167
  bool Allocate(VertexBufferSection* aHolder, const T& aItem) {
168
    return Allocate(aHolder, 1, sizeof(T), &aItem);
169
  }
170
};
171
172
// To support older Direct3D versions, we need to support one-off MLGBuffers,
173
// where data is uploaded immediately rather than at the end of all batch
174
// preparation. We achieve this through a small helper class.
175
//
176
// Note: the unmap is not inline sincce we don't include MLGDevice.h.
177
class MOZ_STACK_CLASS AutoBufferUploadBase
178
{
179
public:
180
  AutoBufferUploadBase();
181
  ~AutoBufferUploadBase();
182
183
0
  void Init(void* aPtr) {
184
0
    MOZ_ASSERT(!mPtr && aPtr);
185
0
    mPtr = aPtr;
186
0
  }
187
  void Init(void* aPtr, MLGDevice* aDevice, MLGBuffer* aBuffer);
188
0
  void* get() {
189
0
    return const_cast<void*>(mPtr);
190
0
  }
191
192
private:
193
  void UnmapBuffer();
194
195
protected:
196
  RefPtr<MLGDevice> mDevice;
197
  RefPtr<MLGBuffer> mBuffer;
198
  void* mPtr;
199
};
200
201
// This is a typed helper for AutoBufferUploadBase.
202
template <typename T>
203
class AutoBufferUpload : public AutoBufferUploadBase
204
{
205
public:
206
  AutoBufferUpload()
207
0
  {}
208
209
0
  T* operator ->() const {
210
0
    return reinterpret_cast<T*>(mPtr);
211
0
  }
212
};
213
214
class SharedConstantBuffer final : public SharedBufferMLGPU
215
{
216
public:
217
  SharedConstantBuffer(MLGDevice* aDevice, size_t aDefaultSize);
218
219
  // Allocate a buffer that can be immediately uploaded.
220
0
  bool Allocate(ConstantBufferSection* aHolder, const ConstantStagingBuffer& aStaging) {
221
0
    MOZ_ASSERT(aStaging.NumItems() * aStaging.SizeOfItem() == aStaging.NumBytes());
222
0
    return Allocate(aHolder, aStaging.NumItems(), aStaging.SizeOfItem(), aStaging.GetBufferStart());
223
0
  }
224
225
  // Allocate a buffer of one item that can be immediately uploaded.
226
  template <typename T>
227
0
  bool Allocate(ConstantBufferSection* aHolder, const T& aItem) {
228
0
    return Allocate(aHolder, 1, sizeof(aItem), &aItem);
229
0
  }
Unexecuted instantiation: bool mozilla::layers::SharedConstantBuffer::Allocate<mozilla::layers::mlg::MaskInformation>(mozilla::layers::ConstantBufferSection*, mozilla::layers::mlg::MaskInformation const&)
Unexecuted instantiation: bool mozilla::layers::SharedConstantBuffer::Allocate<mozilla::layers::mlg::WorldConstants>(mozilla::layers::ConstantBufferSection*, mozilla::layers::mlg::WorldConstants const&)
Unexecuted instantiation: bool mozilla::layers::SharedConstantBuffer::Allocate<mozilla::layers::mlg::ClearConstants>(mozilla::layers::ConstantBufferSection*, mozilla::layers::mlg::ClearConstants const&)
230
231
  // Allocate a buffer of N items that can be immediately uploaded.
232
  template <typename T>
233
0
  bool Allocate(ConstantBufferSection* aHolder, const T* aItems, size_t aNumItems) {
234
0
    return Allocate(aHolder, aNumItems, sizeof(T), aItems);
235
0
  }
Unexecuted instantiation: bool mozilla::layers::SharedConstantBuffer::Allocate<mozilla::layers::mlg::LayerConstants>(mozilla::layers::ConstantBufferSection*, mozilla::layers::mlg::LayerConstants const*, unsigned long)
Unexecuted instantiation: bool mozilla::layers::SharedConstantBuffer::Allocate<mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float> >(mozilla::layers::ConstantBufferSection*, mozilla::gfx::RectTyped<mozilla::gfx::UnknownUnits, float> const*, unsigned long)
236
237
  // Allocate a buffer that is uploaded after the caller has finished writing
238
  // to it. This should method should generally not be used unless copying T
239
  // is expensive, since the default immediate-upload version has an implicit
240
  // extra copy to the GPU. This version exposes the mapped memory directly.
241
  template <typename T>
242
0
  bool Allocate(ConstantBufferSection* aHolder, AutoBufferUpload<T>* aPtr) {
243
0
    MOZ_ASSERT(sizeof(T) % 16 == 0, "Items must be padded to 16 bytes");
244
0
245
0
    return Allocate(aHolder, aPtr, 1, sizeof(T));
246
0
  }
247
248
private:
249
  bool Allocate(ConstantBufferSection* aHolder,
250
                size_t aNumItems,
251
                size_t aSizeOfItem,
252
                const void* aData)
253
0
  {
254
0
    AutoBufferUploadBase ptr;
255
0
    if (!Allocate(aHolder, &ptr, aNumItems, aSizeOfItem)) {
256
0
      return false;
257
0
    }
258
0
    memcpy(ptr.get(), aData, aNumItems * aSizeOfItem);
259
0
    return true;
260
0
  }
261
262
  bool Allocate(ConstantBufferSection* aHolder,
263
                AutoBufferUploadBase* aPtr,
264
                size_t aNumItems,
265
                size_t aSizeOfItem);
266
267
  bool GetBufferPointer(AutoBufferUploadBase* aPtr,
268
                        size_t aBytes,
269
                        ptrdiff_t* aOutOffset,
270
                        RefPtr<MLGBuffer>* aOutBuffer)
271
0
  {
272
0
    if (!mCanUseOffsetAllocation) {
273
0
      uint8_t* ptr = AllocateNewBuffer(aBytes, aOutOffset, aOutBuffer);
274
0
      if (!ptr) {
275
0
        return false;
276
0
      }
277
0
      aPtr->Init(ptr, mDevice, *aOutBuffer);
278
0
      return true;
279
0
    }
280
0
281
0
    // Align up the allocation to 256 bytes, since D3D11 requires that
282
0
    // constant buffers start at multiples of 16 elements.
283
0
    size_t alignedBytes = AlignUp<256>::calc(aBytes);
284
0
285
0
    uint8_t* ptr = SharedBufferMLGPU::GetBufferPointer(alignedBytes, aOutOffset, aOutBuffer);
286
0
    if (!ptr) {
287
0
      return false;
288
0
    }
289
0
290
0
    aPtr->Init(ptr);
291
0
    return true;
292
0
  }
293
294
  uint8_t* AllocateNewBuffer(size_t aBytes, ptrdiff_t* aOutOffset, RefPtr<MLGBuffer>* aOutBuffer);
295
296
private:
297
  size_t mMaxConstantBufferBindSize;
298
};
299
300
} // namespace layers
301
} // namespace mozilla
302
303
#endif // mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h