blob: ad57668261cf5393cc5ecc8d49ceb05604ed764c [file] [log] [blame]
bsalomon@google.com1c13c962011-02-14 16:51:21 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
bsalomon@google.com1c13c962011-02-14 16:51:21 +00006 */
7
bsalomon@google.com1c13c962011-02-14 16:51:21 +00008#ifndef GrBufferAllocPool_DEFINED
9#define GrBufferAllocPool_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkTypes.h"
12#include "include/private/GrTypesPriv.h"
13#include "include/private/SkNoncopyable.h"
14#include "include/private/SkTArray.h"
15#include "include/private/SkTDArray.h"
16#include "src/gpu/GrCpuBuffer.h"
Chris Daltona6a3d052021-02-07 20:56:36 -070017#include "src/gpu/GrDrawIndirectCommand.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrNonAtomicRef.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000019
bsalomon@google.com1c13c962011-02-14 16:51:21 +000020class GrGpu;
21
22/**
23 * A pool of geometry buffers tied to a GrGpu.
24 *
25 * The pool allows a client to make space for geometry and then put back excess
26 * space if it over allocated. When a client is ready to draw from the pool
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000027 * it calls unmap on the pool ensure buffers are ready for drawing. The pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +000028 * can be reset after drawing is completed to recycle space.
29 *
30 * At creation time a minimum per-buffer size can be specified. Additionally,
31 * a number of buffers to preallocate can be specified. These will
32 * be allocated at the min size and kept around until the pool is destroyed.
33 */
commit-bot@chromium.orge3beb6b2014-04-07 19:34:38 +000034class GrBufferAllocPool : SkNoncopyable {
bsalomon@google.com11f0b512011-03-29 20:52:23 +000035public:
Brian Salomon58f153c2018-10-18 21:51:15 -040036 static constexpr size_t kDefaultBufferSize = 1 << 15;
37
bsalomon@google.com11f0b512011-03-29 20:52:23 +000038 /**
Brian Salomon601ac802019-02-07 13:37:16 -050039 * A cache object that can be shared by multiple GrBufferAllocPool instances. It caches
40 * cpu buffer allocations to avoid reallocating them.
41 */
42 class CpuBufferCache : public GrNonAtomicRef<CpuBufferCache> {
43 public:
44 static sk_sp<CpuBufferCache> Make(int maxBuffersToCache);
45
46 sk_sp<GrCpuBuffer> makeBuffer(size_t size, bool mustBeInitialized);
47 void releaseAll();
48
49 private:
50 CpuBufferCache(int maxBuffersToCache);
51
52 struct Buffer {
53 sk_sp<GrCpuBuffer> fBuffer;
54 bool fCleared = false;
55 };
56 std::unique_ptr<Buffer[]> fBuffers;
57 int fMaxBuffersToCache = 0;
58 };
59
60 /**
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000061 * Ensures all buffers are unmapped and have all data written to them.
bsalomon@google.com11f0b512011-03-29 20:52:23 +000062 * Call before drawing using buffers from the pool.
63 */
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000064 void unmap();
bsalomon@google.com11f0b512011-03-29 20:52:23 +000065
66 /**
67 * Invalidates all the data in the pool, unrefs non-preallocated buffers.
68 */
69 void reset();
70
71 /**
bsalomon@google.com11f0b512011-03-29 20:52:23 +000072 * Frees data from makeSpaces in LIFO order.
73 */
74 void putBack(size_t bytes);
75
bsalomon@google.com11f0b512011-03-29 20:52:23 +000076protected:
77 /**
bsalomon@google.com1c13c962011-02-14 16:51:21 +000078 * Constructor
79 *
80 * @param gpu The GrGpu used to create the buffers.
81 * @param bufferType The type of buffers to create.
Brian Salomon601ac802019-02-07 13:37:16 -050082 * @param cpuBufferCache If non-null a cache for client side array buffers
83 * or staging buffers used before data is uploaded to
84 * GPU buffer objects.
bsalomon@google.com1c13c962011-02-14 16:51:21 +000085 */
Brian Salomon601ac802019-02-07 13:37:16 -050086 GrBufferAllocPool(GrGpu* gpu, GrGpuBufferType bufferType, sk_sp<CpuBufferCache> cpuBufferCache);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000087
Brian Salomon58f153c2018-10-18 21:51:15 -040088 virtual ~GrBufferAllocPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +000089
bsalomon@google.com1c13c962011-02-14 16:51:21 +000090 /**
bsalomon@google.com1c13c962011-02-14 16:51:21 +000091 * Returns a block of memory to hold data. A buffer designated to hold the
92 * data is given to the caller. The buffer may or may not be locked. The
93 * returned ptr remains valid until any of the following:
94 * *makeSpace is called again.
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000095 * *unmap is called.
bsalomon@google.com1c13c962011-02-14 16:51:21 +000096 * *reset is called.
97 * *this object is destroyed.
98 *
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +000099 * Once unmap on the pool is called the data is guaranteed to be in the
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000100 * buffer at the offset indicated by offset. Until that time it may be
101 * in temporary storage and/or the buffer may be locked.
102 *
103 * @param size the amount of data to make space for
104 * @param alignment alignment constraint from start of buffer
105 * @param buffer returns the buffer that will hold the data.
106 * @param offset returns the offset into buffer of the data.
107 * @return pointer to where the client should write the data.
108 */
Brian Salomon12d22642019-01-29 14:38:50 -0500109 void* makeSpace(size_t size, size_t alignment, sk_sp<const GrBuffer>* buffer, size_t* offset);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000110
Brian Osman49b7b6f2017-06-20 14:43:58 -0400111 /**
112 * Returns a block of memory to hold data. A buffer designated to hold the
113 * data is given to the caller. The buffer may or may not be locked. The
114 * returned ptr remains valid until any of the following:
115 * *makeSpace is called again.
116 * *unmap is called.
117 * *reset is called.
118 * *this object is destroyed.
119 *
120 * Once unmap on the pool is called the data is guaranteed to be in the
121 * buffer at the offset indicated by offset. Until that time it may be
122 * in temporary storage and/or the buffer may be locked.
123 *
124 * The caller requests a minimum number of bytes, but the block may be (much)
125 * larger. Assuming that a new block must be allocated, it will be fallbackSize bytes.
126 * The actual block size is returned in actualSize.
127 *
128 * @param minSize the minimum amount of data to make space for
129 * @param fallbackSize the amount of data to make space for if a new block is needed
130 * @param alignment alignment constraint from start of buffer
131 * @param buffer returns the buffer that will hold the data.
132 * @param offset returns the offset into buffer of the data.
133 * @param actualSize returns the capacity of the block
134 * @return pointer to where the client should write the data.
135 */
136 void* makeSpaceAtLeast(size_t minSize,
137 size_t fallbackSize,
138 size_t alignment,
Brian Salomon12d22642019-01-29 14:38:50 -0500139 sk_sp<const GrBuffer>* buffer,
Brian Osman49b7b6f2017-06-20 14:43:58 -0400140 size_t* offset,
141 size_t* actualSize);
142
Brian Salomon12d22642019-01-29 14:38:50 -0500143 sk_sp<GrBuffer> getBuffer(size_t size);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000144
145private:
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000146 struct BufferBlock {
Brian Salomon12d22642019-01-29 14:38:50 -0500147 size_t fBytesFree;
148 sk_sp<GrBuffer> fBuffer;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000149 };
150
151 bool createBlock(size_t requestSize);
152 void destroyBlock();
robertphillips1b8e1b52015-06-24 06:54:10 -0700153 void deleteBlocks();
bsalomon3512eda2014-06-26 12:56:22 -0700154 void flushCpuData(const BufferBlock& block, size_t flushSize);
Brian Salomon601ac802019-02-07 13:37:16 -0500155 void resetCpuData(size_t newSize);
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000156#ifdef SK_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000157 void validate(bool unusedBlockAllowed = false) const;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000158#endif
Brian Salomon58f153c2018-10-18 21:51:15 -0400159 size_t fBytesInUse = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000160
Brian Salomon58f153c2018-10-18 21:51:15 -0400161 SkTArray<BufferBlock> fBlocks;
Brian Salomon601ac802019-02-07 13:37:16 -0500162 sk_sp<CpuBufferCache> fCpuBufferCache;
163 sk_sp<GrCpuBuffer> fCpuStagingBuffer;
Brian Salomon58f153c2018-10-18 21:51:15 -0400164 GrGpu* fGpu;
Brian Salomonae64c192019-02-05 09:41:37 -0500165 GrGpuBufferType fBufferType;
Brian Salomon58f153c2018-10-18 21:51:15 -0400166 void* fBufferPtr = nullptr;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000167};
168
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000169/**
170 * A GrBufferAllocPool of vertex buffers
171 */
172class GrVertexBufferAllocPool : public GrBufferAllocPool {
173public:
174 /**
175 * Constructor
176 *
177 * @param gpu The GrGpu used to create the vertex buffers.
Brian Salomon601ac802019-02-07 13:37:16 -0500178 * @param cpuBufferCache If non-null a cache for client side array buffers
179 * or staging buffers used before data is uploaded to
180 * GPU buffer objects.
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000181 */
Brian Salomon601ac802019-02-07 13:37:16 -0500182 GrVertexBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000183
184 /**
185 * Returns a block of memory to hold vertices. A buffer designated to hold
186 * the vertices given to the caller. The buffer may or may not be locked.
187 * The returned ptr remains valid until any of the following:
188 * *makeSpace is called again.
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000189 * *unmap is called.
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000190 * *reset is called.
191 * *this object is destroyed.
192 *
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000193 * Once unmap on the pool is called the vertices are guaranteed to be in
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000194 * the buffer at the offset indicated by startVertex. Until that time they
195 * may be in temporary storage and/or the buffer may be locked.
196 *
jvanverth@google.coma6338982013-01-31 21:34:25 +0000197 * @param vertexSize specifies size of a vertex to allocate space for
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000198 * @param vertexCount number of vertices to allocate space for
199 * @param buffer returns the vertex buffer that will hold the
200 * vertices.
201 * @param startVertex returns the offset into buffer of the first vertex.
202 * In units of the size of a vertex from layout param.
203 * @return pointer to first vertex.
204 */
jvanverth@google.coma6338982013-01-31 21:34:25 +0000205 void* makeSpace(size_t vertexSize,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000206 int vertexCount,
Brian Salomon12d22642019-01-29 14:38:50 -0500207 sk_sp<const GrBuffer>* buffer,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000208 int* startVertex);
209
Brian Osman49b7b6f2017-06-20 14:43:58 -0400210 /**
211 * Returns a block of memory to hold vertices. A buffer designated to hold
212 * the vertices given to the caller. The buffer may or may not be locked.
213 * The returned ptr remains valid until any of the following:
214 * *makeSpace is called again.
215 * *unmap is called.
216 * *reset is called.
217 * *this object is destroyed.
218 *
219 * Once unmap on the pool is called the vertices are guaranteed to be in
220 * the buffer at the offset indicated by startVertex. Until that time they
221 * may be in temporary storage and/or the buffer may be locked.
222 *
223 * The caller requests a minimum number of vertices, but the block may be (much)
224 * larger. Assuming that a new block must be allocated, it will be sized to hold
225 * fallbackVertexCount vertices. The actual block size (in vertices) is returned in
226 * actualVertexCount.
227 *
228 * @param vertexSize specifies size of a vertex to allocate space for
229 * @param minVertexCount minimum number of vertices to allocate space for
230 * @param fallbackVertexCount number of vertices to allocate space for if a new block is needed
231 * @param buffer returns the vertex buffer that will hold the vertices.
232 * @param startVertex returns the offset into buffer of the first vertex.
233 * In units of the size of a vertex from layout param.
234 * @param actualVertexCount returns the capacity of the block (in vertices)
235 * @return pointer to first vertex.
236 */
237 void* makeSpaceAtLeast(size_t vertexSize,
238 int minVertexCount,
239 int fallbackVertexCount,
Brian Salomon12d22642019-01-29 14:38:50 -0500240 sk_sp<const GrBuffer>* buffer,
Brian Osman49b7b6f2017-06-20 14:43:58 -0400241 int* startVertex,
242 int* actualVertexCount);
243
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000244private:
John Stiles7571f9e2020-09-02 22:42:33 -0400245 using INHERITED = GrBufferAllocPool;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000246};
247
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000248/**
249 * A GrBufferAllocPool of index buffers
250 */
251class GrIndexBufferAllocPool : public GrBufferAllocPool {
252public:
253 /**
254 * Constructor
255 *
256 * @param gpu The GrGpu used to create the index buffers.
Brian Salomon601ac802019-02-07 13:37:16 -0500257 * @param cpuBufferCache If non-null a cache for client side array buffers
258 * or staging buffers used before data is uploaded to
259 * GPU buffer objects.
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000260 */
Brian Salomon601ac802019-02-07 13:37:16 -0500261 GrIndexBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000262
263 /**
264 * Returns a block of memory to hold indices. A buffer designated to hold
265 * the indices is given to the caller. The buffer may or may not be locked.
266 * The returned ptr remains valid until any of the following:
267 * *makeSpace is called again.
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000268 * *unmap is called.
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000269 * *reset is called.
270 * *this object is destroyed.
271 *
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000272 * Once unmap on the pool is called the indices are guaranteed to be in the
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000273 * buffer at the offset indicated by startIndex. Until that time they may be
274 * in temporary storage and/or the buffer may be locked.
275 *
276 * @param indexCount number of indices to allocate space for
277 * @param buffer returns the index buffer that will hold the indices.
278 * @param startIndex returns the offset into buffer of the first index.
279 * @return pointer to first index.
280 */
Brian Salomon12d22642019-01-29 14:38:50 -0500281 void* makeSpace(int indexCount, sk_sp<const GrBuffer>* buffer, int* startIndex);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000282
Brian Osman49b7b6f2017-06-20 14:43:58 -0400283 /**
284 * Returns a block of memory to hold indices. A buffer designated to hold
285 * the indices is given to the caller. The buffer may or may not be locked.
286 * The returned ptr remains valid until any of the following:
287 * *makeSpace is called again.
288 * *unmap is called.
289 * *reset is called.
290 * *this object is destroyed.
291 *
292 * Once unmap on the pool is called the indices are guaranteed to be in the
293 * buffer at the offset indicated by startIndex. Until that time they may be
294 * in temporary storage and/or the buffer may be locked.
295 *
296 * The caller requests a minimum number of indices, but the block may be (much)
297 * larger. Assuming that a new block must be allocated, it will be sized to hold
298 * fallbackIndexCount indices. The actual block size (in indices) is returned in
299 * actualIndexCount.
300 *
301 * @param minIndexCount minimum number of indices to allocate space for
302 * @param fallbackIndexCount number of indices to allocate space for if a new block is needed
303 * @param buffer returns the index buffer that will hold the indices.
304 * @param startIndex returns the offset into buffer of the first index.
305 * @param actualIndexCount returns the capacity of the block (in indices)
306 * @return pointer to first index.
307 */
308 void* makeSpaceAtLeast(int minIndexCount,
309 int fallbackIndexCount,
Brian Salomon12d22642019-01-29 14:38:50 -0500310 sk_sp<const GrBuffer>* buffer,
Brian Osman49b7b6f2017-06-20 14:43:58 -0400311 int* startIndex,
312 int* actualIndexCount);
313
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000314private:
John Stiles7571f9e2020-09-02 22:42:33 -0400315 using INHERITED = GrBufferAllocPool;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000316};
317
Chris Dalton03fdf6a2020-04-07 12:31:59 -0600318class GrDrawIndirectBufferAllocPool : private GrBufferAllocPool {
319public:
320 GrDrawIndirectBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache)
321 : GrBufferAllocPool(gpu, GrGpuBufferType::kDrawIndirect, std::move(cpuBufferCache)) {}
322
Chris Daltona6a3d052021-02-07 20:56:36 -0700323 GrDrawIndirectWriter makeSpace(int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offset) {
324 return this->GrBufferAllocPool::makeSpace(drawCount * sizeof(GrDrawIndirectCommand), 4,
325 buffer, offset);
Chris Dalton03fdf6a2020-04-07 12:31:59 -0600326 }
327
Chris Dalton75125072020-11-24 09:30:51 -0700328 void putBack(int drawCount) {
Chris Daltona6a3d052021-02-07 20:56:36 -0700329 this->GrBufferAllocPool::putBack(drawCount * sizeof(GrDrawIndirectCommand));
Chris Dalton75125072020-11-24 09:30:51 -0700330 }
331
Chris Daltona6a3d052021-02-07 20:56:36 -0700332 GrDrawIndexedIndirectWriter makeIndexedSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
333 size_t* offset) {
334 return this->GrBufferAllocPool::makeSpace(
335 drawCount * sizeof(GrDrawIndexedIndirectCommand), 4, buffer, offset);
Chris Dalton03fdf6a2020-04-07 12:31:59 -0600336 }
337
Chris Dalton75125072020-11-24 09:30:51 -0700338 void putBackIndexed(int drawCount) {
Chris Daltona6a3d052021-02-07 20:56:36 -0700339 this->GrBufferAllocPool::putBack(drawCount * sizeof(GrDrawIndexedIndirectCommand));
Chris Dalton75125072020-11-24 09:30:51 -0700340 }
341
Chris Dalton03fdf6a2020-04-07 12:31:59 -0600342 using GrBufferAllocPool::unmap;
343 using GrBufferAllocPool::reset;
344};
345
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000346#endif