Home | History | Annotate | Download | only in gpu
      1 /*
      2  * 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.
      6  */
      7 
      8 #ifndef GrBufferAllocPool_DEFINED
      9 #define GrBufferAllocPool_DEFINED
     10 
     11 #include "SkTArray.h"
     12 #include "SkTDArray.h"
     13 #include "SkTypes.h"
     14 
     15 class GrGeometryBuffer;
     16 class GrGpu;
     17 
     18 /**
     19  * A pool of geometry buffers tied to a GrGpu.
     20  *
     21  * The pool allows a client to make space for geometry and then put back excess
     22  * space if it over allocated. When a client is ready to draw from the pool
     23  * it calls unmap on the pool ensure buffers are ready for drawing. The pool
     24  * can be reset after drawing is completed to recycle space.
     25  *
     26  * At creation time a minimum per-buffer size can be specified. Additionally,
     27  * a number of buffers to preallocate can be specified. These will
     28  * be allocated at the min size and kept around until the pool is destroyed.
     29  */
     30 class GrBufferAllocPool : SkNoncopyable {
     31 public:
     32     /**
     33      * Ensures all buffers are unmapped and have all data written to them.
     34      * Call before drawing using buffers from the pool.
     35      */
     36     void unmap();
     37 
     38     /**
     39      *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
     40      */
     41     void reset();
     42 
     43     /**
     44      * Gets the number of preallocated buffers that are yet to be used.
     45      */
     46     int preallocatedBuffersRemaining() const;
     47 
     48     /**
     49      * gets the number of preallocated buffers
     50      */
     51     int preallocatedBufferCount() const;
     52 
     53     /**
     54      * Frees data from makeSpaces in LIFO order.
     55      */
     56     void putBack(size_t bytes);
     57 
     58     /**
     59      * Gets the GrGpu that this pool is associated with.
     60      */
     61     GrGpu* getGpu() { return fGpu; }
     62 
     63 protected:
     64     /**
     65      * Used to determine what type of buffers to create. We could make the
     66      * createBuffer a virtual except that we want to use it in the cons for
     67      * pre-allocated buffers.
     68      */
     69     enum BufferType {
     70         kVertex_BufferType,
     71         kIndex_BufferType,
     72     };
     73 
     74     /**
     75      * Constructor
     76      *
     77      * @param gpu                   The GrGpu used to create the buffers.
     78      * @param bufferType            The type of buffers to create.
     79      * @param frequentResetHint     A hint that indicates that the pool
     80      *                              should expect frequent unmap() calls
     81      *                              (as opposed to many makeSpace / acquires
     82      *                              between resets).
     83      * @param bufferSize            The minimum size of created buffers.
     84      *                              This value will be clamped to some
     85      *                              reasonable minimum.
     86      * @param preallocBufferCnt     The pool will allocate this number of
     87      *                              buffers at bufferSize and keep them until it
     88      *                              is destroyed.
     89      */
     90      GrBufferAllocPool(GrGpu* gpu,
     91                        BufferType bufferType,
     92                        bool frequentResetHint,
     93                        size_t   bufferSize = 0,
     94                        int preallocBufferCnt = 0);
     95 
     96     virtual ~GrBufferAllocPool();
     97 
     98     /**
     99      * Gets the size of the preallocated buffers.
    100      *
    101      * @return the size of preallocated buffers.
    102      */
    103     size_t preallocatedBufferSize() const {
    104         return fPreallocBuffers.count() ? fMinBlockSize : 0;
    105     }
    106 
    107     /**
    108      * Returns a block of memory to hold data. A buffer designated to hold the
    109      * data is given to the caller. The buffer may or may not be locked. The
    110      * returned ptr remains valid until any of the following:
    111      *      *makeSpace is called again.
    112      *      *unmap is called.
    113      *      *reset is called.
    114      *      *this object is destroyed.
    115      *
    116      * Once unmap on the pool is called the data is guaranteed to be in the
    117      * buffer at the offset indicated by offset. Until that time it may be
    118      * in temporary storage and/or the buffer may be locked.
    119      *
    120      * @param size         the amount of data to make space for
    121      * @param alignment    alignment constraint from start of buffer
    122      * @param buffer       returns the buffer that will hold the data.
    123      * @param offset       returns the offset into buffer of the data.
    124      * @return pointer to where the client should write the data.
    125      */
    126     void* makeSpace(size_t size,
    127                     size_t alignment,
    128                     const GrGeometryBuffer** buffer,
    129                     size_t* offset);
    130 
    131     /**
    132      * Gets the number of items of a size that can be added to the current
    133      * buffer without spilling to another buffer. If the pool has been reset, or
    134      * the previous makeSpace completely exhausted a buffer then the returned
    135      * size will be the size of the next available preallocated buffer, or zero
    136      * if no preallocated buffer remains available. It is assumed that items
    137      * should be itemSize-aligned from the start of a buffer.
    138      *
    139      * @return the number of items that would fit in the current buffer.
    140      */
    141     int currentBufferItems(size_t itemSize) const;
    142 
    143     GrGeometryBuffer* createBuffer(size_t size);
    144 
    145 private:
    146 
    147     // The GrGpu must be able to clear the ref of pools it creates as members
    148     friend class GrGpu;
    149     void releaseGpuRef();
    150 
    151     struct BufferBlock {
    152         size_t              fBytesFree;
    153         GrGeometryBuffer*   fBuffer;
    154     };
    155 
    156     bool createBlock(size_t requestSize);
    157     void destroyBlock();
    158     void flushCpuData(const BufferBlock& block, size_t flushSize);
    159 #ifdef SK_DEBUG
    160     void validate(bool unusedBlockAllowed = false) const;
    161 #endif
    162 
    163     size_t                          fBytesInUse;
    164 
    165     GrGpu*                          fGpu;
    166     bool                            fGpuIsReffed;
    167     bool                            fFrequentResetHint;
    168     SkTDArray<GrGeometryBuffer*>    fPreallocBuffers;
    169     size_t                          fMinBlockSize;
    170     BufferType                      fBufferType;
    171 
    172     SkTArray<BufferBlock>           fBlocks;
    173     int                             fPreallocBuffersInUse;
    174     // We attempt to cycle through the preallocated buffers rather than
    175     // always starting from the first.
    176     int                             fPreallocBufferStartIdx;
    177     SkAutoMalloc                    fCpuData;
    178     void*                           fBufferPtr;
    179 };
    180 
    181 class GrVertexBuffer;
    182 
    183 /**
    184  * A GrBufferAllocPool of vertex buffers
    185  */
    186 class GrVertexBufferAllocPool : public GrBufferAllocPool {
    187 public:
    188     /**
    189      * Constructor
    190      *
    191      * @param gpu                   The GrGpu used to create the vertex buffers.
    192      * @param frequentResetHint     A hint that indicates that the pool
    193      *                              should expect frequent unmap() calls
    194      *                              (as opposed to many makeSpace / acquires
    195      *                              between resets).
    196      * @param bufferSize            The minimum size of created VBs This value
    197      *                              will be clamped to some reasonable minimum.
    198      * @param preallocBufferCnt     The pool will allocate this number of VBs at
    199      *                              bufferSize and keep them until it is
    200      *                              destroyed.
    201      */
    202     GrVertexBufferAllocPool(GrGpu* gpu,
    203                             bool frequentResetHint,
    204                             size_t bufferSize = 0,
    205                             int preallocBufferCnt = 0);
    206 
    207     /**
    208      * Returns a block of memory to hold vertices. A buffer designated to hold
    209      * the vertices given to the caller. The buffer may or may not be locked.
    210      * The returned ptr remains valid until any of the following:
    211      *      *makeSpace is called again.
    212      *      *unmap is called.
    213      *      *reset is called.
    214      *      *this object is destroyed.
    215      *
    216      * Once unmap on the pool is called the vertices are guaranteed to be in
    217      * the buffer at the offset indicated by startVertex. Until that time they
    218      * may be in temporary storage and/or the buffer may be locked.
    219      *
    220      * @param vertexSize   specifies size of a vertex to allocate space for
    221      * @param vertexCount  number of vertices to allocate space for
    222      * @param buffer       returns the vertex buffer that will hold the
    223      *                     vertices.
    224      * @param startVertex  returns the offset into buffer of the first vertex.
    225      *                     In units of the size of a vertex from layout param.
    226      * @return pointer to first vertex.
    227      */
    228     void* makeSpace(size_t vertexSize,
    229                     int vertexCount,
    230                     const GrVertexBuffer** buffer,
    231                     int* startVertex);
    232 
    233     /**
    234      * Shortcut to make space and then write verts into the made space.
    235      */
    236     bool appendVertices(size_t vertexSize,
    237                         int vertexCount,
    238                         const void* vertices,
    239                         const GrVertexBuffer** buffer,
    240                         int* startVertex);
    241 
    242     /**
    243      * Gets the number of vertices that can be added to the current VB without
    244      * spilling to another VB. If the pool has been reset, or the previous
    245      * makeSpace completely exhausted a VB then the returned number of vertices
    246      * would fit in the next available preallocated buffer. If any makeSpace
    247      * would force a new VB to be created the return value will be zero.
    248      *
    249      * @param   the size of a vertex to compute space for.
    250      * @return the number of vertices that would fit in the current buffer.
    251      */
    252     int currentBufferVertices(size_t vertexSize) const;
    253 
    254     /**
    255      * Gets the number of vertices that can fit in a  preallocated vertex buffer.
    256      * Zero if no preallocated buffers.
    257      *
    258      * @param   the size of a vertex to compute space for.
    259      *
    260      * @return number of vertices that fit in one of the preallocated vertex
    261      *         buffers.
    262      */
    263     int preallocatedBufferVertices(size_t vertexSize) const;
    264 
    265 private:
    266     typedef GrBufferAllocPool INHERITED;
    267 };
    268 
    269 class GrIndexBuffer;
    270 
    271 /**
    272  * A GrBufferAllocPool of index buffers
    273  */
    274 class GrIndexBufferAllocPool : public GrBufferAllocPool {
    275 public:
    276     /**
    277      * Constructor
    278      *
    279      * @param gpu                   The GrGpu used to create the index buffers.
    280      * @param frequentResetHint     A hint that indicates that the pool
    281      *                              should expect frequent unmap() calls
    282      *                              (as opposed to many makeSpace / acquires
    283      *                              between resets).
    284      * @param bufferSize            The minimum size of created IBs This value
    285      *                              will be clamped to some reasonable minimum.
    286      * @param preallocBufferCnt     The pool will allocate this number of VBs at
    287      *                              bufferSize and keep them until it is
    288      *                              destroyed.
    289      */
    290     GrIndexBufferAllocPool(GrGpu* gpu,
    291                            bool frequentResetHint,
    292                            size_t bufferSize = 0,
    293                            int preallocBufferCnt = 0);
    294 
    295     /**
    296      * Returns a block of memory to hold indices. A buffer designated to hold
    297      * the indices is given to the caller. The buffer may or may not be locked.
    298      * The returned ptr remains valid until any of the following:
    299      *      *makeSpace is called again.
    300      *      *unmap is called.
    301      *      *reset is called.
    302      *      *this object is destroyed.
    303      *
    304      * Once unmap on the pool is called the indices are guaranteed to be in the
    305      * buffer at the offset indicated by startIndex. Until that time they may be
    306      * in temporary storage and/or the buffer may be locked.
    307      *
    308      * @param indexCount   number of indices to allocate space for
    309      * @param buffer       returns the index buffer that will hold the indices.
    310      * @param startIndex   returns the offset into buffer of the first index.
    311      * @return pointer to first index.
    312      */
    313     void* makeSpace(int indexCount,
    314                     const GrIndexBuffer** buffer,
    315                     int* startIndex);
    316 
    317     /**
    318      * Shortcut to make space and then write indices into the made space.
    319      */
    320     bool appendIndices(int indexCount,
    321                        const void* indices,
    322                        const GrIndexBuffer** buffer,
    323                        int* startIndex);
    324 
    325     /**
    326      * Gets the number of indices that can be added to the current IB without
    327      * spilling to another IB. If the pool has been reset, or the previous
    328      * makeSpace completely exhausted a IB then the returned number of indices
    329      * would fit in the next available preallocated buffer. If any makeSpace
    330      * would force a new IB to be created the return value will be zero.
    331      */
    332     int currentBufferIndices() const;
    333 
    334     /**
    335      * Gets the number of indices that can fit in a preallocated index buffer.
    336      * Zero if no preallocated buffers.
    337      *
    338      * @return number of indices that fit in one of the preallocated index
    339      *         buffers.
    340      */
    341     int preallocatedBufferIndices() const;
    342 
    343 private:
    344     typedef GrBufferAllocPool INHERITED;
    345 };
    346 
    347 #endif
    348