Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 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 GrMesh_DEFINED
      9 #define GrMesh_DEFINED
     10 
     11 #include "GrBuffer.h"
     12 #include "GrGpuResourceRef.h"
     13 
     14 class GrPrimitiveProcessor;
     15 
     16 /**
     17  * Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to
     18  * GrGpu. It also holds the primitive type for the draw. TODO: Consider moving ownership of this
     19  * and draw-issuing responsibility to GrPrimitiveProcessor. The rest of the vertex info lives there
     20  * already (stride, attribute mappings).
     21  */
     22 class GrMesh {
     23 public:
     24     GrMesh(GrPrimitiveType primitiveType)
     25         : fPrimitiveType(primitiveType)
     26         , fBaseVertex(0) {
     27         SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
     28     }
     29 
     30     GrPrimitiveType primitiveType() const { return fPrimitiveType; }
     31     bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
     32     bool isInstanced() const { return SkToBool(fInstanceBuffer.get()); }
     33     bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); }
     34 
     35     void setNonIndexedNonInstanced(int vertexCount);
     36 
     37     void setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
     38                     uint16_t minIndexValue, uint16_t maxIndexValue);
     39     void setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount, int vertexCount,
     40                              int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
     41 
     42     void setInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
     43                       int vertexCount);
     44     void setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount,
     45                              const GrBuffer* instanceBuffer, int instanceCount, int baseInstance=0);
     46 
     47     void setVertexData(const GrBuffer* vertexBuffer, int baseVertex = 0);
     48 
     49     class SendToGpuImpl {
     50     public:
     51         virtual void sendMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
     52                                    const GrBuffer* vertexBuffer, int vertexCount,
     53                                    int baseVertex) = 0;
     54 
     55         virtual void sendIndexedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
     56                                           const GrBuffer* indexBuffer, int indexCount,
     57                                           int baseIndex, uint16_t minIndexValue,
     58                                           uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
     59                                           int baseVertex) = 0;
     60 
     61         virtual void sendInstancedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
     62                                             const GrBuffer* vertexBuffer, int vertexCount,
     63                                             int baseVertex, const GrBuffer* instanceBuffer,
     64                                             int instanceCount, int baseInstance) = 0;
     65 
     66         virtual void sendIndexedInstancedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
     67                                                    const GrBuffer* indexBuffer, int indexCount,
     68                                                    int baseIndex, const GrBuffer* vertexBuffer,
     69                                                    int baseVertex, const GrBuffer* instanceBuffer,
     70                                                    int instanceCount, int baseInstance) = 0;
     71 
     72         virtual ~SendToGpuImpl() {}
     73     };
     74 
     75     void sendToGpu(const GrPrimitiveProcessor&, SendToGpuImpl*) const;
     76 
     77     struct PatternBatch;
     78 
     79 private:
     80     using PendingBuffer = GrPendingIOResource<const GrBuffer, kRead_GrIOType>;
     81 
     82     GrPrimitiveType   fPrimitiveType;
     83     PendingBuffer     fIndexBuffer;
     84     PendingBuffer     fInstanceBuffer;
     85     PendingBuffer     fVertexBuffer;
     86     int               fBaseVertex;
     87 
     88     union {
     89         struct { // When fIndexBuffer == nullptr and fInstanceBuffer == nullptr.
     90             int   fVertexCount;
     91         } fNonIndexNonInstanceData;
     92 
     93         struct { // When fIndexBuffer != nullptr and fInstanceBuffer == nullptr.
     94             struct {
     95                 int   fIndexCount;
     96                 int   fPatternRepeatCount;
     97             } fIndexData;
     98 
     99             union {
    100                 struct { // When fPatternRepeatCount == 0.
    101                     int        fBaseIndex;
    102                     uint16_t   fMinIndexValue;
    103                     uint16_t   fMaxIndexValue;
    104                 } fNonPatternIndexData;
    105 
    106                 struct { // When fPatternRepeatCount != 0.
    107                     int   fVertexCount;
    108                     int   fMaxPatternRepetitionsInIndexBuffer;
    109                 } fPatternData;
    110             };
    111         };
    112 
    113         struct { // When fInstanceBuffer != nullptr.
    114             struct {
    115                 int   fInstanceCount;
    116                 int   fBaseInstance;
    117             } fInstanceData;
    118 
    119             union { // When fIndexBuffer == nullptr.
    120                 struct {
    121                     int   fVertexCount;
    122                 } fInstanceNonIndexData;
    123 
    124                 struct { // When fIndexBuffer != nullptr.
    125                     int   fIndexCount;
    126                 } fInstanceIndexData;
    127             };
    128         };
    129     };
    130 };
    131 
    132 inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) {
    133     fIndexBuffer.reset(nullptr);
    134     fInstanceBuffer.reset(nullptr);
    135     fNonIndexNonInstanceData.fVertexCount = vertexCount;
    136 }
    137 
    138 inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
    139                                uint16_t minIndexValue, uint16_t maxIndexValue) {
    140     SkASSERT(indexBuffer);
    141     SkASSERT(indexCount >= 1);
    142     SkASSERT(baseIndex >= 0);
    143     SkASSERT(maxIndexValue >= minIndexValue);
    144     fIndexBuffer.reset(indexBuffer);
    145     fInstanceBuffer.reset(nullptr);
    146     fIndexData.fIndexCount = indexCount;
    147     fIndexData.fPatternRepeatCount = 0;
    148     fNonPatternIndexData.fBaseIndex = baseIndex;
    149     fNonPatternIndexData.fMinIndexValue = minIndexValue;
    150     fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
    151 }
    152 
    153 inline void GrMesh::setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
    154                                         int vertexCount, int patternRepeatCount,
    155                                         int maxPatternRepetitionsInIndexBuffer) {
    156     SkASSERT(indexBuffer);
    157     SkASSERT(indexCount >= 1);
    158     SkASSERT(vertexCount >= 1);
    159     SkASSERT(patternRepeatCount >= 1);
    160     SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
    161     fIndexBuffer.reset(indexBuffer);
    162     fInstanceBuffer.reset(nullptr);
    163     fIndexData.fIndexCount = indexCount;
    164     fIndexData.fPatternRepeatCount = patternRepeatCount;
    165     fPatternData.fVertexCount = vertexCount;
    166     fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
    167 }
    168 
    169 inline void GrMesh::setInstanced(const GrBuffer* instanceBuffer, int instanceCount,
    170                                  int baseInstance, int vertexCount) {
    171     SkASSERT(instanceBuffer);
    172     SkASSERT(instanceCount >= 1);
    173     SkASSERT(baseInstance >= 0);
    174     fIndexBuffer.reset(nullptr);
    175     fInstanceBuffer.reset(instanceBuffer);
    176     fInstanceData.fInstanceCount = instanceCount;
    177     fInstanceData.fBaseInstance = baseInstance;
    178     fInstanceNonIndexData.fVertexCount = vertexCount;
    179 }
    180 
    181 inline void GrMesh::setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount,
    182                                         const GrBuffer* instanceBuffer, int instanceCount,
    183                                         int baseInstance) {
    184     SkASSERT(indexBuffer);
    185     SkASSERT(indexCount >= 1);
    186     SkASSERT(instanceBuffer);
    187     SkASSERT(instanceCount >= 1);
    188     SkASSERT(baseInstance >= 0);
    189     fIndexBuffer.reset(indexBuffer);
    190     fInstanceBuffer.reset(instanceBuffer);
    191     fInstanceData.fInstanceCount = instanceCount;
    192     fInstanceData.fBaseInstance = baseInstance;
    193     fInstanceIndexData.fIndexCount = indexCount;
    194 }
    195 
    196 inline void GrMesh::setVertexData(const GrBuffer* vertexBuffer, int baseVertex) {
    197     SkASSERT(baseVertex >= 0);
    198     fVertexBuffer.reset(vertexBuffer);
    199     fBaseVertex = baseVertex;
    200 }
    201 
    202 inline void GrMesh::sendToGpu(const GrPrimitiveProcessor& primProc, SendToGpuImpl* impl) const {
    203     if (this->isInstanced()) {
    204         if (!this->isIndexed()) {
    205             impl->sendInstancedMeshToGpu(primProc, fPrimitiveType, fVertexBuffer.get(),
    206                                          fInstanceNonIndexData.fVertexCount, fBaseVertex,
    207                                          fInstanceBuffer.get(), fInstanceData.fInstanceCount,
    208                                          fInstanceData.fBaseInstance);
    209         } else {
    210             impl->sendIndexedInstancedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(),
    211                                                 fInstanceIndexData.fIndexCount, 0,
    212                                                 fVertexBuffer.get(), fBaseVertex,
    213                                                 fInstanceBuffer.get(), fInstanceData.fInstanceCount,
    214                                                 fInstanceData.fBaseInstance);
    215         }
    216         return;
    217     }
    218 
    219     if (!this->isIndexed()) {
    220         SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
    221         impl->sendMeshToGpu(primProc, fPrimitiveType, fVertexBuffer.get(),
    222                             fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
    223         return;
    224     }
    225 
    226     if (0 == fIndexData.fPatternRepeatCount) {
    227         impl->sendIndexedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(),
    228                                    fIndexData.fIndexCount, fNonPatternIndexData.fBaseIndex,
    229                                    fNonPatternIndexData.fMinIndexValue,
    230                                    fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(),
    231                                    fBaseVertex);
    232         return;
    233     }
    234 
    235     SkASSERT(fIndexData.fPatternRepeatCount > 0);
    236     int baseRepetition = 0;
    237     do {
    238         int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer,
    239                                  fIndexData.fPatternRepeatCount - baseRepetition);
    240         // A patterned index buffer must contain indices in the range [0..vertexCount].
    241         int minIndexValue = 0;
    242         int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
    243         impl->sendIndexedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(),
    244                                    fIndexData.fIndexCount * repeatCount, 0, minIndexValue,
    245                                    maxIndexValue, fVertexBuffer.get(),
    246                                    fBaseVertex + fPatternData.fVertexCount * baseRepetition);
    247         baseRepetition += repeatCount;
    248     } while (baseRepetition < fIndexData.fPatternRepeatCount);
    249 }
    250 
    251 #endif
    252