aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrBufferAllocPool.h
blob: 1b58ef45e4adac07b282b186511b92bb92bab285 (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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrBufferAllocPool_DEFINED
#define GrBufferAllocPool_DEFINED

#include "SkTArray.h"
#include "SkTDArray.h"
#include "SkTypes.h"
#include "GrTypesPriv.h"

class GrBuffer;
class GrGpu;

/**
 * A pool of geometry buffers tied to a GrGpu.
 *
 * The pool allows a client to make space for geometry and then put back excess
 * space if it over allocated. When a client is ready to draw from the pool
 * it calls unmap on the pool ensure buffers are ready for drawing. The pool
 * can be reset after drawing is completed to recycle space.
 *
 * At creation time a minimum per-buffer size can be specified. Additionally,
 * a number of buffers to preallocate can be specified. These will
 * be allocated at the min size and kept around until the pool is destroyed.
 */
class GrBufferAllocPool : SkNoncopyable {
public:
    /**
     * Ensures all buffers are unmapped and have all data written to them.
     * Call before drawing using buffers from the pool.
     */
    void unmap();

    /**
     *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
     */
    void reset();

    /**
     * Frees data from makeSpaces in LIFO order.
     */
    void putBack(size_t bytes);

protected:
    /**
     * Constructor
     *
     * @param gpu                   The GrGpu used to create the buffers.
     * @param bufferType            The type of buffers to create.
     * @param bufferSize            The minimum size of created buffers.
     *                              This value will be clamped to some
     *                              reasonable minimum.
     */
     GrBufferAllocPool(GrGpu* gpu,
                       GrBufferType bufferType,
                       size_t   bufferSize = 0);

     virtual ~GrBufferAllocPool();

    /**
     * Returns a block of memory to hold data. A buffer designated to hold the
     * data is given to the caller. The buffer may or may not be locked. The
     * returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unmap is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unmap on the pool is called the data is guaranteed to be in the
     * buffer at the offset indicated by offset. Until that time it may be
     * in temporary storage and/or the buffer may be locked.
     *
     * @param size         the amount of data to make space for
     * @param alignment    alignment constraint from start of buffer
     * @param buffer       returns the buffer that will hold the data.
     * @param offset       returns the offset into buffer of the data.
     * @return pointer to where the client should write the data.
     */
    void* makeSpace(size_t size,
                    size_t alignment,
                    const GrBuffer** buffer,
                    size_t* offset);

    /**
     * Returns a block of memory to hold data. A buffer designated to hold the
     * data is given to the caller. The buffer may or may not be locked. The
     * returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unmap is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unmap on the pool is called the data is guaranteed to be in the
     * buffer at the offset indicated by offset. Until that time it may be
     * in temporary storage and/or the buffer may be locked.
     *
     * The caller requests a minimum number of bytes, but the block may be (much)
     * larger. Assuming that a new block must be allocated, it will be fallbackSize bytes.
     * The actual block size is returned in actualSize.
     *
     * @param minSize        the minimum amount of data to make space for
     * @param fallbackSize   the amount of data to make space for if a new block is needed
     * @param alignment      alignment constraint from start of buffer
     * @param buffer         returns the buffer that will hold the data.
     * @param offset         returns the offset into buffer of the data.
     * @param actualSize     returns the capacity of the block
     * @return pointer to where the client should write the data.
     */
    void* makeSpaceAtLeast(size_t minSize,
                           size_t fallbackSize,
                           size_t alignment,
                           const GrBuffer** buffer,
                           size_t* offset,
                           size_t* actualSize);

    GrBuffer* getBuffer(size_t size);

private:
    struct BufferBlock {
        size_t      fBytesFree;
        GrBuffer*   fBuffer;
    };

    bool createBlock(size_t requestSize);
    void destroyBlock();
    void deleteBlocks();
    void flushCpuData(const BufferBlock& block, size_t flushSize);
    void* resetCpuData(size_t newSize);
#ifdef SK_DEBUG
    void validate(bool unusedBlockAllowed = false) const;
#endif
    size_t                          fBytesInUse;

    GrGpu*                          fGpu;
    size_t                          fMinBlockSize;
    GrBufferType                    fBufferType;

    SkTArray<BufferBlock>           fBlocks;
    void*                           fCpuData;
    void*                           fBufferPtr;
    size_t                          fBufferMapThreshold;
};

/**
 * A GrBufferAllocPool of vertex buffers
 */
class GrVertexBufferAllocPool : public GrBufferAllocPool {
public:
    /**
     * Constructor
     *
     * @param gpu                   The GrGpu used to create the vertex buffers.
     */
    GrVertexBufferAllocPool(GrGpu* gpu);

    /**
     * Returns a block of memory to hold vertices. A buffer designated to hold
     * the vertices given to the caller. The buffer may or may not be locked.
     * The returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unmap is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unmap on the pool is called the vertices are guaranteed to be in
     * the buffer at the offset indicated by startVertex. Until that time they
     * may be in temporary storage and/or the buffer may be locked.
     *
     * @param vertexSize   specifies size of a vertex to allocate space for
     * @param vertexCount  number of vertices to allocate space for
     * @param buffer       returns the vertex buffer that will hold the
     *                     vertices.
     * @param startVertex  returns the offset into buffer of the first vertex.
     *                     In units of the size of a vertex from layout param.
     * @return pointer to first vertex.
     */
    void* makeSpace(size_t vertexSize,
                    int vertexCount,
                    const GrBuffer** buffer,
                    int* startVertex);

    /**
     * Returns a block of memory to hold vertices. A buffer designated to hold
     * the vertices given to the caller. The buffer may or may not be locked.
     * The returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unmap is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unmap on the pool is called the vertices are guaranteed to be in
     * the buffer at the offset indicated by startVertex. Until that time they
     * may be in temporary storage and/or the buffer may be locked.
     *
     * The caller requests a minimum number of vertices, but the block may be (much)
     * larger. Assuming that a new block must be allocated, it will be sized to hold
     * fallbackVertexCount vertices. The actual block size (in vertices) is returned in
     * actualVertexCount.
     *
     * @param vertexSize           specifies size of a vertex to allocate space for
     * @param minVertexCount       minimum number of vertices to allocate space for
     * @param fallbackVertexCount  number of vertices to allocate space for if a new block is needed
     * @param buffer               returns the vertex buffer that will hold the vertices.
     * @param startVertex          returns the offset into buffer of the first vertex.
     *                             In units of the size of a vertex from layout param.
     * @param actualVertexCount    returns the capacity of the block (in vertices)
     * @return pointer to first vertex.
     */
    void* makeSpaceAtLeast(size_t vertexSize,
                           int minVertexCount,
                           int fallbackVertexCount,
                           const GrBuffer** buffer,
                           int* startVertex,
                           int* actualVertexCount);

private:
    typedef GrBufferAllocPool INHERITED;
};

/**
 * A GrBufferAllocPool of index buffers
 */
class GrIndexBufferAllocPool : public GrBufferAllocPool {
public:
    /**
     * Constructor
     *
     * @param gpu                   The GrGpu used to create the index buffers.
     */
    GrIndexBufferAllocPool(GrGpu* gpu);

    /**
     * Returns a block of memory to hold indices. A buffer designated to hold
     * the indices is given to the caller. The buffer may or may not be locked.
     * The returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unmap is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unmap on the pool is called the indices are guaranteed to be in the
     * buffer at the offset indicated by startIndex. Until that time they may be
     * in temporary storage and/or the buffer may be locked.
     *
     * @param indexCount   number of indices to allocate space for
     * @param buffer       returns the index buffer that will hold the indices.
     * @param startIndex   returns the offset into buffer of the first index.
     * @return pointer to first index.
     */
    void* makeSpace(int indexCount,
                    const GrBuffer** buffer,
                    int* startIndex);

    /**
     * Returns a block of memory to hold indices. A buffer designated to hold
     * the indices is given to the caller. The buffer may or may not be locked.
     * The returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unmap is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unmap on the pool is called the indices are guaranteed to be in the
     * buffer at the offset indicated by startIndex. Until that time they may be
     * in temporary storage and/or the buffer may be locked.
     *
     * The caller requests a minimum number of indices, but the block may be (much)
     * larger. Assuming that a new block must be allocated, it will be sized to hold
     * fallbackIndexCount indices. The actual block size (in indices) is returned in
     * actualIndexCount.
     *
     * @param minIndexCount        minimum number of indices to allocate space for
     * @param fallbackIndexCount   number of indices to allocate space for if a new block is needed
     * @param buffer               returns the index buffer that will hold the indices.
     * @param startIndex           returns the offset into buffer of the first index.
     * @param actualIndexCount     returns the capacity of the block (in indices)
     * @return pointer to first index.
     */
    void* makeSpaceAtLeast(int minIndexCount,
                           int fallbackIndexCount,
                           const GrBuffer** buffer,
                           int* startIndex,
                           int* actualIndexCount);

private:
    typedef GrBufferAllocPool INHERITED;
};

#endif