Convert GrMesh back to a class

Specific methods that limit the data to valid configurations are better
than a runtime mega-assert.

Bug: skia:
Change-Id: Ie15f2dc79659e44cfaddd16eb474795b110fda73
Reviewed-on: https://skia-review.googlesource.com/16577
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index abaf684..259c573 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -25,7 +25,7 @@
 class GrContext;
 struct GrContextOptions;
 class GrGLContext;
-struct GrMesh;
+class GrMesh;
 class GrPath;
 class GrPathRange;
 class GrPathRenderer;
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp
index a57a13f..ee7414e 100644
--- a/src/gpu/GrGpuCommandBuffer.cpp
+++ b/src/gpu/GrGpuCommandBuffer.cpp
@@ -37,10 +37,15 @@
 
 bool GrGpuCommandBuffer::draw(const GrPipeline& pipeline,
                               const GrPrimitiveProcessor& primProc,
-                              const GrMesh* mesh,
+                              const GrMesh meshes[],
                               int meshCount,
                               const SkRect& bounds) {
-    SkDEBUGCODE(mesh->validate());
+#ifdef SK_DEBUG
+    for (int i = 0; i < meshCount; ++i) {
+        SkASSERT(SkToBool(primProc.numAttribs()) == SkToBool(meshes[i].vertexBuffer()));
+    }
+#endif
+
     if (pipeline.isBad() || primProc.isBad()) {
         return false;
     }
@@ -50,7 +55,7 @@
         this->gpu()->stats()->incNumFailedDraws();
         return false;
     }
-    this->onDraw(pipeline, primProc, mesh, meshCount, bounds);
+    this->onDraw(pipeline, primProc, meshes, meshCount, bounds);
     return true;
 }
 
diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h
index fb54b2e..fb5dc00 100644
--- a/src/gpu/GrGpuCommandBuffer.h
+++ b/src/gpu/GrGpuCommandBuffer.h
@@ -14,7 +14,7 @@
 class GrOpFlushState;
 class GrFixedClip;
 class GrGpu;
-struct GrMesh;
+class GrMesh;
 class GrPipeline;
 class GrPrimitiveProcessor;
 class GrRenderTarget;
@@ -68,7 +68,7 @@
     // number of vertex attributes is too large).
     bool draw(const GrPipeline&,
               const GrPrimitiveProcessor&,
-              const GrMesh*,
+              const GrMesh[],
               int meshCount,
               const SkRect& bounds);
 
diff --git a/src/gpu/GrMesh.h b/src/gpu/GrMesh.h
index e2fd2df..6aed8d3 100644
--- a/src/gpu/GrMesh.h
+++ b/src/gpu/GrMesh.h
@@ -17,28 +17,88 @@
  * and draw-issuing responsibility to GrPrimitiveProcessor. The rest of the vertex info lives there
  * already (stride, attribute mappings).
  */
-struct GrMesh {
+class GrMesh {
+public:
+    GrMesh(GrPrimitiveType primitiveType)
+        : fPrimitiveType(primitiveType) {
+        SkDEBUGCODE(fVertexCount = 0;)
+        SkDEBUGCODE(fBaseVertex = -1;)
+    }
+
+    void setNonIndexed();
+    void setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex = 0);
+    void setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
+                             int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
+
+    void setVertices(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex = 0);
+
+    GrPrimitiveType primitiveType() const { return fPrimitiveType; }
+
+    bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
+    const GrBuffer* indexBuffer() const { return fIndexBuffer.get(); }
+    int indexCount() const { SkASSERT(this->isIndexed()); return fIndexCount; }
+    int baseIndex() const { SkASSERT(this->isIndexed()); return fBaseIndex; }
+
+    const GrBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
+    int vertexCount() const { SkASSERT(fVertexCount >= 1); return fVertexCount; }
+    int baseVertex() const { SkASSERT(fBaseVertex >= 0); return fBaseVertex; }
+
+    struct PatternBatch;
+
+private:
     using PendingBuffer = GrPendingIOResource<const GrBuffer, kRead_GrIOType>;
 
     GrPrimitiveType   fPrimitiveType;
 
     PendingBuffer     fIndexBuffer;
-    int               fIndexCount = 0;
-    int               fBaseIndex = 0;
+    int               fIndexCount;
+    int               fBaseIndex;
+    int               fPatternRepeatCount;
+    int               fMaxPatternRepetitionsInIndexBuffer;
 
     PendingBuffer     fVertexBuffer;
-    int               fVertexCount = 0;
-    int               fBaseVertex = 0;
+    int               fVertexCount;
+    int               fBaseVertex;
 
-    int               fPatternRepeatCount = 1;
-    int               fMaxPatternRepetitionsInIndexBuffer = 1;
-
-    struct PatternBatch;
     class PatternIterator;
-
-    SkDEBUGCODE(void validate() const;)
+    friend GrMesh::PatternIterator begin(const GrMesh&);
+    friend GrMesh::PatternIterator end(const GrMesh&);
 };
 
+inline void GrMesh::setNonIndexed() {
+    fIndexBuffer.reset(nullptr);
+}
+
+inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex) {
+    SkASSERT(indexBuffer);
+    SkASSERT(indexCount >= 1);
+    SkASSERT(baseIndex >= 0);
+    fIndexBuffer.reset(indexBuffer);
+    fIndexCount = indexCount;
+    fBaseIndex = baseIndex;
+    fPatternRepeatCount = fMaxPatternRepetitionsInIndexBuffer = 1;
+}
+
+inline void GrMesh::setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
+                                        int patternRepeatCount,
+                                        int maxPatternRepetitionsInIndexBuffer) {
+    SkASSERT(indexBuffer);
+    SkASSERT(indexCount >= 1);
+    SkASSERT(patternRepeatCount >= 1);
+    SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
+    fIndexBuffer.reset(indexBuffer);
+    fIndexCount = indexCount;
+    fBaseIndex = 0;
+    fPatternRepeatCount = patternRepeatCount;
+    fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
+}
+
+inline void GrMesh::setVertices(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
+    fVertexBuffer.reset(vertexBuffer);
+    fVertexCount = vertexCount;
+    fBaseVertex = baseVertex;
+}
+
 struct GrMesh::PatternBatch {
     int   fBaseVertex;
     int   fRepeatCount;
@@ -49,7 +109,7 @@
     PatternIterator(const GrMesh& mesh, int repetitionIdx)
         : fMesh(mesh)
         , fRepetitionIdx(repetitionIdx) {
-        SkDEBUGCODE(mesh.validate());
+        SkASSERT(fMesh.isIndexed());
     }
 
     bool operator!=(const PatternIterator& that) {
@@ -83,18 +143,4 @@
     return GrMesh::PatternIterator(mesh, mesh.fPatternRepeatCount);
 }
 
-#ifdef SK_DEBUG
-inline void GrMesh::validate() const {
-    SkASSERT(!fIndexBuffer || fIndexCount > 0);
-    SkASSERT(fBaseIndex >= 0);
-
-    SkASSERT(fVertexBuffer);
-    SkASSERT(fVertexCount);
-    SkASSERT(fBaseVertex >= 0);
-
-    SkASSERT(fPatternRepeatCount > 0);
-    SkASSERT(fMaxPatternRepetitionsInIndexBuffer > 0);
-}
-#endif
-
 #endif
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 0343373..5a8809b 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2643,7 +2643,7 @@
 
     bool hasPoints = false;
     for (int i = 0; i < meshCount; ++i) {
-        if (meshes[i].fPrimitiveType == kPoints_GrPrimitiveType) {
+        if (meshes[i].primitiveType() == kPoints_GrPrimitiveType) {
             hasPoints = true;
             break;
         }
@@ -2658,36 +2658,32 @@
         }
 
         const GrMesh& mesh = meshes[i];
-        for (GrMesh::PatternBatch batch : mesh) {
-            this->setupGeometry(primProc, mesh.fIndexBuffer.get(), mesh.fVertexBuffer.get(),
-                                batch.fBaseVertex);
-            if (const GrBuffer* indexBuffer = mesh.fIndexBuffer.get()) {
-                GrGLvoid* indices = reinterpret_cast<void*>(indexBuffer->baseOffset() +
-                                                            sizeof(uint16_t) * mesh.fBaseIndex);
-                // mesh.fBaseVertex was accounted for by setupGeometry.
+        const GrGLenum primType = gPrimitiveType2GLMode[mesh.primitiveType()];
+
+        if (mesh.isIndexed()) {
+            GrGLvoid* indices = reinterpret_cast<void*>(mesh.indexBuffer()->baseOffset() +
+                                                        sizeof(uint16_t) * mesh.baseIndex());
+            for (const GrMesh::PatternBatch batch : mesh) {
+                this->setupGeometry(primProc, mesh.indexBuffer(), mesh.vertexBuffer(),
+                                    batch.fBaseVertex);
+                // mesh.baseVertex() was accounted for by setupGeometry.
                 if (this->glCaps().drawRangeElementsSupport()) {
                     // We assume here that the GrMeshDrawOps that generated the mesh used the full
                     // 0..vertexCount()-1 range.
                     int start = 0;
-                    int end = mesh.fVertexCount * batch.fRepeatCount - 1;
-                    GL_CALL(DrawRangeElements(gPrimitiveType2GLMode[mesh.fPrimitiveType],
-                                              start, end,
-                                              mesh.fIndexCount * batch.fRepeatCount,
-                                              GR_GL_UNSIGNED_SHORT,
-                                              indices));
+                    int end = mesh.vertexCount() * batch.fRepeatCount - 1;
+                    GL_CALL(DrawRangeElements(primType, start, end,
+                                              mesh.indexCount() * batch.fRepeatCount,
+                                              GR_GL_UNSIGNED_SHORT, indices));
                 } else {
-                    GL_CALL(DrawElements(gPrimitiveType2GLMode[mesh.fPrimitiveType],
-                                         mesh.fIndexCount * batch.fRepeatCount,
-                                         GR_GL_UNSIGNED_SHORT,
-                                         indices));
+                    GL_CALL(DrawElements(primType, mesh.indexCount() * batch.fRepeatCount,
+                                         GR_GL_UNSIGNED_SHORT, indices));
                 }
-            } else {
-                // Pass 0 for parameter first. We have to adjust glVertexAttribPointer() to account
-                // for mesh.fBaseVertex in the DrawElements case. So we always rely on setupGeometry
-                // to have accounted for mesh.fBaseVertex.
-                GL_CALL(DrawArrays(gPrimitiveType2GLMode[mesh.fPrimitiveType], 0,
-                                   mesh.fVertexCount * batch.fRepeatCount));
+                fStats.incNumDraws();
             }
+        } else {
+            this->setupGeometry(primProc, mesh.indexBuffer(), mesh.vertexBuffer(), 0);
+            GL_CALL(DrawArrays(primType, mesh.baseVertex(), mesh.vertexCount()));
             fStats.incNumDraws();
         }
     }
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index a06de27..161e96d 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -812,14 +812,9 @@
 
             extract_verts(tess, verts, vertexStride, fColor, idxs, canTweakAlphaForCoverage);
 
-            GrMesh mesh;
-            mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-            mesh.fIndexBuffer.reset(indexBuffer);
-            mesh.fIndexCount = tess.numIndices();
-            mesh.fBaseIndex = firstIndex;
-            mesh.fVertexBuffer.reset(vertexBuffer);
-            mesh.fVertexCount = tess.numPts();
-            mesh.fBaseVertex = firstVertex;
+            GrMesh mesh(kTriangles_GrPrimitiveType);
+            mesh.setIndexed(indexBuffer, tess.numIndices(), firstIndex);
+            mesh.setVertices(vertexBuffer, tess.numPts(), firstVertex);
             target->draw(gp.get(), this->pipeline(), mesh);
         }
     }
@@ -878,14 +873,12 @@
                 continue;
             }
 
-            GrMesh mesh;
-            mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-
             const GrBuffer* vertexBuffer;
+            int firstVertex;
+
             size_t vertexStride = quadProcessor->getVertexStride();
             QuadVertex* verts = reinterpret_cast<QuadVertex*>(target->makeVertexSpace(
-                vertexStride, vertexCount, &vertexBuffer, &mesh.fBaseVertex));
-            mesh.fVertexBuffer.reset(vertexBuffer);
+                vertexStride, vertexCount, &vertexBuffer, &firstVertex));
 
             if (!verts) {
                 SkDebugf("Could not allocate vertices\n");
@@ -893,23 +886,26 @@
             }
 
             const GrBuffer* indexBuffer;
-            uint16_t *idxs = target->makeIndexSpace(indexCount, &indexBuffer, &mesh.fBaseIndex);
+            int firstIndex;
+
+            uint16_t *idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
             if (!idxs) {
                 SkDebugf("Could not allocate indices\n");
                 return;
             }
-            mesh.fIndexBuffer.reset(indexBuffer);
 
             SkSTArray<kPreallocDrawCnt, Draw, true> draws;
             create_vertices(segments, fanPt, &draws, verts, idxs);
 
+            GrMesh mesh(kTriangles_GrPrimitiveType);
+
             for (int j = 0; j < draws.count(); ++j) {
                 const Draw& draw = draws[j];
-                mesh.fIndexCount = draw.fIndexCnt;
-                mesh.fVertexCount = draw.fVertexCnt;
+                mesh.setIndexed(indexBuffer, draw.fIndexCnt, firstIndex);
+                mesh.setVertices(vertexBuffer, draw.fVertexCnt, firstVertex);
                 target->draw(quadProcessor.get(), this->pipeline(), mesh);
-                mesh.fBaseIndex += draw.fIndexCnt;
-                mesh.fBaseVertex += draw.fVertexCnt;
+                firstIndex += draw.fIndexCnt;
+                firstVertex += draw.fVertexCnt;
             }
         }
     }
diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp
index ea85b4e..364c221 100644
--- a/src/gpu/ops/GrAAFillRectOp.cpp
+++ b/src/gpu/ops/GrAAFillRectOp.cpp
@@ -231,10 +231,10 @@
         size_t vertexStride = gp->getVertexStride();
 
         sk_sp<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
-        PatternHelper helper;
+        PatternHelper helper(kTriangles_GrPrimitiveType);
         void* vertices =
-                helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
-                            kVertsPerAAFillRect, kIndicesPerAAFillRect, fRectCnt);
+                helper.init(target, vertexStride, indexBuffer.get(), kVertsPerAAFillRect,
+                            kIndicesPerAAFillRect, fRectCnt);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 755a9f6..5618fd1 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -860,15 +860,10 @@
             add_line(&lines[2*i], toSrc, this->coverage(), &verts);
         }
 
-        GrMesh mesh;
-        mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-        mesh.fIndexBuffer.reset(linesIndexBuffer.get());
-        mesh.fIndexCount = kIdxsPerLineSeg;
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = kLineSegNumVertices;
-        mesh.fBaseVertex = firstVertex;
-        mesh.fPatternRepeatCount = lineCount;
-        mesh.fMaxPatternRepetitionsInIndexBuffer = kLineSegsNumInIdxBuffer;
+        GrMesh mesh(kTriangles_GrPrimitiveType);
+        mesh.setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg,
+                                 lineCount, kLineSegsNumInIdxBuffer);
+        mesh.setVertices(vertexBuffer, kLineSegNumVertices, firstVertex);
         target->draw(lineGP.get(), this->pipeline(), mesh);
     }
 
@@ -922,29 +917,19 @@
         }
 
         if (quadCount > 0) {
-            GrMesh mesh;
-            mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-            mesh.fIndexBuffer.reset(quadsIndexBuffer.get());
-            mesh.fIndexCount = kIdxsPerQuad;
-            mesh.fVertexBuffer.reset(vertexBuffer);
-            mesh.fVertexCount = kQuadNumVertices;
-            mesh.fBaseVertex = firstVertex;
-            mesh.fPatternRepeatCount = quadCount;
-            mesh.fMaxPatternRepetitionsInIndexBuffer = kQuadsNumInIdxBuffer;
+            GrMesh mesh(kTriangles_GrPrimitiveType);
+            mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, quadCount,
+                                     kQuadsNumInIdxBuffer);
+            mesh.setVertices(vertexBuffer, kQuadNumVertices, firstVertex);
             target->draw(quadGP.get(), this->pipeline(), mesh);
             firstVertex += quadCount * kQuadNumVertices;
         }
 
         if (conicCount > 0) {
-            GrMesh mesh;
-            mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-            mesh.fIndexBuffer.reset(quadsIndexBuffer.get());
-            mesh.fIndexCount = kIdxsPerQuad;
-            mesh.fVertexBuffer.reset(vertexBuffer);
-            mesh.fVertexCount = kQuadNumVertices;
-            mesh.fBaseVertex = firstVertex;
-            mesh.fPatternRepeatCount = conicCount;
-            mesh.fMaxPatternRepetitionsInIndexBuffer = kQuadsNumInIdxBuffer;
+            GrMesh mesh(kTriangles_GrPrimitiveType);
+            mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, conicCount,
+                                     kQuadsNumInIdxBuffer);
+            mesh.setVertices(vertexBuffer, kQuadNumVertices, firstVertex);
             target->draw(conicGP.get(), this->pipeline(), mesh);
         }
     }
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index af632f7..b2d9599 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -189,30 +189,27 @@
         if (vertexCount == 0 || indexCount == 0) {
             return;
         }
-
-        GrMesh mesh;
-        mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
         const GrBuffer* vertexBuffer;
+        GrMesh mesh(kTriangles_GrPrimitiveType);
+        int firstVertex;
         void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
-                                              &mesh.fBaseVertex);
+                                              &firstVertex);
         if (!verts) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = vertexCount;
         memcpy(verts, vertices, vertexCount * vertexStride);
 
         const GrBuffer* indexBuffer;
-        uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &mesh.fBaseIndex);
+        int firstIndex;
+        uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
         if (!idxs) {
             SkDebugf("Could not allocate indices\n");
             return;
         }
-        mesh.fIndexBuffer.reset(indexBuffer);
-        mesh.fIndexCount = indexCount;
         memcpy(idxs, indices, indexCount * sizeof(uint16_t));
-
+        mesh.setIndexed(indexBuffer, indexCount, firstIndex);
+        mesh.setVertices(vertexBuffer, vertexCount, firstVertex);
         target->draw(gp, this->pipeline(), mesh);
     }
 
diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp
index dc13ba1..7ec8b86 100644
--- a/src/gpu/ops/GrAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrAAStrokeRectOp.cpp
@@ -262,9 +262,9 @@
 
     const sk_sp<const GrBuffer> indexBuffer(
             GetIndexBuffer(target->resourceProvider(), this->miterStroke()));
-    PatternHelper helper;
+    PatternHelper helper(kTriangles_GrPrimitiveType);
     void* vertices =
-            helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
+            helper.init(target, vertexStride, indexBuffer.get(),
                         verticesPerInstance, indicesPerInstance, instanceCount);
     if (!vertices || !indexBuffer) {
         SkDebugf("Could not allocate vertices\n");
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index f902cce..21b7f6d 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -148,17 +148,12 @@
 }
 
 void GrAtlasTextOp::flush(GrLegacyMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
-    GrMesh mesh;
+    GrMesh mesh(kTriangles_GrPrimitiveType);
     int maxGlyphsPerDraw =
             static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
-    mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-    mesh.fIndexBuffer.reset(flushInfo->fIndexBuffer.get());
-    mesh.fIndexCount = kIndicesPerGlyph;
-    mesh.fVertexBuffer.reset(flushInfo->fVertexBuffer.get());
-    mesh.fVertexCount = kVerticesPerGlyph;
-    mesh.fBaseVertex = flushInfo->fVertexOffset;
-    mesh.fPatternRepeatCount = flushInfo->fGlyphsToFlush;
-    mesh.fMaxPatternRepetitionsInIndexBuffer = maxGlyphsPerDraw;
+    mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph,
+                             flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
+    mesh.setVertices(flushInfo->fVertexBuffer.get(), kVerticesPerGlyph, flushInfo->fVertexOffset);
     target->draw(flushInfo->fGeometryProcessor.get(), this->pipeline(), mesh);
     flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;
     flushInfo->fGlyphsToFlush = 0;
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index 4193a39..c696dda 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -247,16 +247,11 @@
             SkASSERT(vertexOffset <= maxVertices && indexOffset <= maxIndices);
         }
 
-        GrMesh mesh;
-        mesh.fPrimitiveType = primitiveType;
+        GrMesh mesh(primitiveType);
         if (isIndexed) {
-            mesh.fIndexBuffer.reset(indexBuffer);
-            mesh.fIndexCount = indexOffset;
-            mesh.fBaseIndex = firstIndex;
+            mesh.setIndexed(indexBuffer, indexOffset, firstIndex);
         }
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = vertexOffset;
-        mesh.fBaseVertex = firstVertex;
+        mesh.setVertices(vertexBuffer, vertexOffset, firstVertex);
         target->draw(gp.get(), this->pipeline(), mesh);
 
         // put back reserves
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index 4921b42..557bb32 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -235,16 +235,11 @@
         vertexOffset += vertexCount;
     }
 
-    GrMesh mesh;
-    mesh.fPrimitiveType = this->primitiveType();
+    GrMesh mesh(this->primitiveType());
     if (indices) {
-        mesh.fIndexBuffer.reset(indexBuffer);
-        mesh.fIndexCount = fIndexCount;
-        mesh.fBaseIndex = firstIndex;
+        mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
     }
-    mesh.fVertexBuffer.reset(vertexBuffer);
-    mesh.fVertexCount = fVertexCount;
-    mesh.fBaseVertex = firstVertex;
+    mesh.setVertices(vertexBuffer, fVertexCount, firstVertex);
     target->draw(gp.get(), this->pipeline(), mesh);
 }
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 0ba0164..effab8c 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -86,9 +86,9 @@
         }
 
         sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
-        PatternHelper helper;
-        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                     indexBuffer.get(), kVertsPerRect, kIndicesPerRect, numRects);
+        PatternHelper helper(kTriangles_GrPrimitiveType);
+        void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect,
+                                     kIndicesPerRect, numRects);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
diff --git a/src/gpu/ops/GrMSAAPathRenderer.cpp b/src/gpu/ops/GrMSAAPathRenderer.cpp
index e2f12cf..c3a5440 100644
--- a/src/gpu/ops/GrMSAAPathRenderer.cpp
+++ b/src/gpu/ops/GrMSAAPathRenderer.cpp
@@ -410,16 +410,11 @@
             }
             SkASSERT(lineVertexStride == lineGP->getVertexStride());
 
-            GrMesh lineMeshes;
-            lineMeshes.fPrimitiveType = primitiveType;
+            GrMesh lineMeshes(primitiveType);
             if (fIsIndexed) {
-                lineMeshes.fIndexBuffer.reset(lineIndexBuffer);
-                lineMeshes.fIndexCount = lineIndexOffset;
-                lineMeshes.fBaseIndex = firstLineIndex;
+                lineMeshes.setIndexed(lineIndexBuffer, lineIndexOffset, firstLineIndex);
             }
-            lineMeshes.fVertexBuffer.reset(lineVertexBuffer);
-            lineMeshes.fVertexCount = lineVertexOffset;
-            lineMeshes.fBaseVertex = firstLineVertex;
+            lineMeshes.setVertices(lineVertexBuffer, lineVertexOffset, firstLineVertex);
 
             // We can get line vertices from path moveTos with no actual segments and thus no index
             // count. We assert that indexed draws contain a positive index count, so bail here in
@@ -439,21 +434,17 @@
                     target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
                                             &firstQuadVertex);
             memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset);
-            GrMesh quadMeshes;
-            quadMeshes.fPrimitiveType = kTriangles_GrPrimitiveType;
+            GrMesh quadMeshes(kTriangles_GrPrimitiveType);
             if (fIsIndexed) {
                 const GrBuffer* quadIndexBuffer;
+                int firstQuadIndex;
                 uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset,
                                                                            &quadIndexBuffer,
-                                                                           &quadMeshes.fBaseIndex);
-                quadMeshes.fIndexBuffer.reset(quadIndexBuffer);
-                quadMeshes.fIndexCount = quadIndexOffset;
+                                                                           &firstQuadIndex);
                 memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset);
+                quadMeshes.setIndexed(quadIndexBuffer, quadIndexOffset, firstQuadIndex);
             }
-            quadMeshes.fVertexBuffer.reset(quadVertexBuffer);
-            quadMeshes.fVertexCount = quadVertexOffset;
-            quadMeshes.fBaseVertex = firstQuadVertex;
-
+            quadMeshes.setVertices(quadVertexBuffer, quadVertexOffset, firstQuadVertex);
             target->draw(quadGP.get(), this->pipeline(), quadMeshes);
         }
     }
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index c452150..9382fd7 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -17,10 +17,9 @@
     this->onPrepareDraws(&target);
 }
 
-void* GrMeshDrawOp::PatternHelper::init(Target* target, GrPrimitiveType primType,
-                                          size_t vertexStride, const GrBuffer* indexBuffer,
-                                          int verticesPerRepetition, int indicesPerRepetition,
-                                          int repeatCount) {
+void* GrMeshDrawOp::PatternHelper::init(Target* target, size_t vertexStride,
+                                        const GrBuffer* indexBuffer, int verticesPerRepetition,
+                                        int indicesPerRepetition, int repeatCount) {
     SkASSERT(target);
     if (!indexBuffer) {
         return nullptr;
@@ -38,20 +37,13 @@
     size_t ibSize = indexBuffer->gpuMemorySize();
     int maxRepetitions = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerRepetition));
 
-    fMesh.fPrimitiveType = primType;
-    fMesh.fIndexBuffer.reset(indexBuffer);
-    fMesh.fIndexCount = indicesPerRepetition;
-    fMesh.fBaseIndex = 0;
-    fMesh.fVertexBuffer.reset(vertexBuffer);
-    fMesh.fVertexCount = verticesPerRepetition;
-    fMesh.fBaseVertex = firstVertex;
-    fMesh.fPatternRepeatCount = repeatCount;
-    fMesh.fMaxPatternRepetitionsInIndexBuffer = maxRepetitions;
+    fMesh.setIndexedPatterned(indexBuffer, indicesPerRepetition, repeatCount, maxRepetitions);
+    fMesh.setVertices(vertexBuffer, verticesPerRepetition, firstVertex);
     return vertices;
 }
 
 void GrMeshDrawOp::PatternHelper::recordDraw(Target* target, const GrGeometryProcessor* gp,
-                                               const GrPipeline* pipeline) {
+                                             const GrPipeline* pipeline) {
     target->draw(gp, pipeline, fMesh);
 }
 
@@ -61,9 +53,8 @@
         SkDebugf("Could not get quad index buffer.");
         return nullptr;
     }
-    return this->INHERITED::init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                 quadIndexBuffer.get(), kVerticesPerQuad, kIndicesPerQuad,
-                                 quadsToDraw);
+    return this->INHERITED::init(target, vertexStride, quadIndexBuffer.get(), kVerticesPerQuad,
+                                 kIndicesPerQuad, quadsToDraw);
 }
 
 void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
@@ -96,7 +87,6 @@
 
 void GrMeshDrawOp::Target::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline,
                                 const GrMesh& mesh) {
-    SkDEBUGCODE(mesh.validate());
     GrMeshDrawOp* op = this->meshDrawOp();
     op->fMeshes.push_back(mesh);
     if (!op->fQueuedDraws.empty()) {
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index 92a4c1e..178ca29 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -33,11 +33,11 @@
         space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
     class PatternHelper {
     public:
-        PatternHelper() {}
+        PatternHelper(GrPrimitiveType primitiveType) : fMesh(primitiveType) {}
         /** Returns the allocated storage for the vertices. The caller should populate the vertices
             before calling recordDraws(). */
-        void* init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
-                   int verticesPerRepetition, int indicesPerRepetition, int repeatCount);
+        void* init(Target*, size_t vertexStride, const GrBuffer*, int verticesPerRepetition,
+                   int indicesPerRepetition, int repeatCount);
 
         /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
         void recordDraw(Target*, const GrGeometryProcessor*, const GrPipeline*);
@@ -52,7 +52,7 @@
     /** A specialization of InstanceHelper for quad rendering. */
     class QuadHelper : private PatternHelper {
     public:
-        QuadHelper() : INHERITED() {}
+        QuadHelper() : INHERITED(kTriangles_GrPrimitiveType) {}
         /** Finds the cached quad index buffer and reserves vertex space. Returns nullptr on failure
             and on success a pointer to the vertex data that the caller should populate before
             calling recordDraws(). */
diff --git a/src/gpu/ops/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp
index 2962e93..f50fcc0 100644
--- a/src/gpu/ops/GrNonAAFillRectOp.cpp
+++ b/src/gpu/ops/GrNonAAFillRectOp.cpp
@@ -174,9 +174,9 @@
         int rectCount = fRects.count();
 
         sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
-        PatternHelper helper;
-        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                     indexBuffer.get(), kVertsPerRect, kIndicesPerRect, rectCount);
+        PatternHelper helper(kTriangles_GrPrimitiveType);
+        void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect,
+                                     kIndicesPerRect, rectCount);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
@@ -295,9 +295,9 @@
         int rectCount = fRects.count();
 
         sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
-        PatternHelper helper;
-        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                     indexBuffer.get(), kVertsPerRect, kIndicesPerRect, rectCount);
+        PatternHelper helper(kTriangles_GrPrimitiveType);
+        void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect,
+                                     kIndicesPerRect, rectCount);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
index 09eaa97..4e00847 100644
--- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
@@ -156,11 +156,8 @@
             vertex[4].set(fRect.fLeft, fRect.fTop);
         }
 
-        GrMesh mesh;
-        mesh.fPrimitiveType = primType;
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = vertexCount;
-        mesh.fBaseVertex = firstVertex;
+        GrMesh mesh(primType);
+        mesh.setVertices(vertexBuffer, vertexCount, firstVertex);
         target->draw(gp.get(), this->pipeline(), mesh);
     }
 
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index f5cc2ec..a808182 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1096,14 +1096,9 @@
             vertices += circle_type_to_vert_count(geom.fStroked) * vertexStride;
         }
 
-        GrMesh mesh;
-        mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-        mesh.fIndexBuffer.reset(indexBuffer);
-        mesh.fIndexCount = fIndexCount;
-        mesh.fBaseIndex = firstIndex;
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = fVertCount;
-        mesh.fBaseVertex = firstVertex;
+        GrMesh mesh(kTriangles_GrPrimitiveType);
+        mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
+        mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
         target->draw(gp.get(), this->pipeline(), mesh);
     }
 
@@ -2002,14 +1997,9 @@
             currStartVertex += rrect_type_to_vert_count(args.fType);
         }
 
-        GrMesh mesh;
-        mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-        mesh.fIndexBuffer.reset(indexBuffer);
-        mesh.fIndexCount = fIndexCount;
-        mesh.fBaseIndex = firstIndex;
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = fVertCount;
-        mesh.fBaseVertex = firstVertex;
+        GrMesh mesh(kTriangles_GrPrimitiveType);
+        mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
+        mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
         target->draw(gp.get(), this->pipeline(), mesh);
     }
 
@@ -2195,10 +2185,10 @@
         sk_sp<const GrBuffer> indexBuffer(ref_rrect_index_buffer(
                 fStroked ? kStroke_RRectType : kFill_RRectType, target->resourceProvider()));
 
-        PatternHelper helper;
+        PatternHelper helper(kTriangles_GrPrimitiveType);
         EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
-                helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
-                            kVertsPerStandardRRect, indicesPerInstance, instanceCount));
+                helper.init(target, vertexStride, indexBuffer.get(), kVertsPerStandardRRect,
+                            indicesPerInstance, instanceCount));
         if (!verts || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 7c90ae7..62d7362 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -103,10 +103,10 @@
 
         size_t vertexStride = gp->getVertexStride();
         sk_sp<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
-        PatternHelper helper;
+        PatternHelper helper(kTriangles_GrPrimitiveType);
         void* vertices =
-                helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
-                            kVertsPerInstance, kIndicesPerInstance, numRects);
+                helper.init(target, vertexStride, indexBuffer.get(), kVertsPerInstance,
+                            kIndicesPerInstance, numRects);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index 69e33c7..a9d057c 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -628,14 +628,9 @@
             }
         }
 
-        GrMesh mesh;
-        mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-        mesh.fIndexBuffer.reset(indexBuffer);
-        mesh.fIndexCount = fIndexCount;
-        mesh.fBaseIndex = firstIndex;
-        mesh.fVertexBuffer.reset(vertexBuffer);
-        mesh.fVertexCount = fVertCount;
-        mesh.fBaseVertex = firstVertex;
+        GrMesh mesh(kTriangles_GrPrimitiveType);
+        mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
+        mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
         target->draw(gp.get(), this->pipeline(), mesh);
     }
 
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 212605c..9d9cf27 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -679,17 +679,13 @@
 
     void flush(GrLegacyMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
         if (flushInfo->fInstancesToFlush) {
-            GrMesh mesh;
+            GrMesh mesh(kTriangles_GrPrimitiveType);
             int maxInstancesPerDraw =
                 static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
-            mesh.fPrimitiveType = kTriangles_GrPrimitiveType;
-            mesh.fIndexBuffer.reset(flushInfo->fIndexBuffer.get());
-            mesh.fIndexCount = kIndicesPerQuad;
-            mesh.fVertexBuffer.reset(flushInfo->fVertexBuffer.get());
-            mesh.fVertexCount = kVerticesPerQuad;
-            mesh.fBaseVertex = flushInfo->fVertexOffset;
-            mesh.fPatternRepeatCount = flushInfo->fInstancesToFlush;
-            mesh.fMaxPatternRepetitionsInIndexBuffer = maxInstancesPerDraw;
+            mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerQuad,
+                                     flushInfo->fInstancesToFlush, maxInstancesPerDraw);
+            mesh.setVertices(flushInfo->fVertexBuffer.get(), kVerticesPerQuad,
+                             flushInfo->fVertexOffset);
             target->draw(flushInfo->fGeometryProcessor.get(), this->pipeline(), mesh);
             flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush;
             flushInfo->fInstancesToFlush = 0;
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index 2a8714f..45e9465 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -313,13 +313,8 @@
 
     void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuffer* vb,
                       int firstVertex, int count) const {
-        GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? kLines_GrPrimitiveType
-                                                              : kTriangles_GrPrimitiveType;
-        GrMesh mesh;
-        mesh.fPrimitiveType = primitiveType;
-        mesh.fVertexBuffer.reset(vb);
-        mesh.fVertexCount = count;
-        mesh.fBaseVertex = firstVertex;
+        GrMesh mesh(TESSELLATOR_WIREFRAME ? kLines_GrPrimitiveType : kTriangles_GrPrimitiveType);
+        mesh.setVertices(vb, count, firstVertex);
         target->draw(gp, this->pipeline(), mesh);
     }
 
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index 0a5e0b8..124802d 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -537,7 +537,7 @@
         set_texture_layout(dstTexture, fGpu);
     }
 
-    GrPrimitiveType primitiveType = meshes[0].fPrimitiveType;
+    GrPrimitiveType primitiveType = meshes[0].primitiveType();
     sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
                                                                     primProc,
                                                                     primitiveType);
@@ -549,13 +549,13 @@
 
     for (int i = 0; i < meshCount; ++i) {
         const GrMesh& mesh = meshes[i];
-        if (mesh.fPrimitiveType != primitiveType) {
+        if (mesh.primitiveType() != primitiveType) {
             // Technically we don't have to call this here (since there is a safety check in
             // pipelineState:setData but this will allow for quicker freeing of resources if the
             // pipelineState sits in a cache for a while.
             pipelineState->freeTempResources(fGpu);
             SkDEBUGCODE(pipelineState = nullptr);
-            primitiveType = mesh.fPrimitiveType;
+            primitiveType = mesh.primitiveType();
             pipelineState = this->prepareDrawState(pipeline,
                                                    primProc,
                                                    primitiveType);
@@ -563,26 +563,28 @@
                 return;
             }
         }
-        for (GrMesh::PatternBatch batch : mesh) {
-            SkASSERT(pipelineState);
-            this->bindGeometry(primProc, mesh.fIndexBuffer.get(), mesh.fVertexBuffer.get());
 
-            if (mesh.fIndexBuffer) {
+        SkASSERT(pipelineState);
+        this->bindGeometry(primProc, mesh.indexBuffer(), mesh.vertexBuffer());
+
+        if (mesh.isIndexed()) {
+            for (const GrMesh::PatternBatch batch : mesh) {
                 cbInfo.currentCmdBuf()->drawIndexed(fGpu,
-                                                    mesh.fIndexCount * batch.fRepeatCount,
+                                                    mesh.indexCount() * batch.fRepeatCount,
                                                     1,
-                                                    mesh.fBaseIndex,
+                                                    mesh.baseIndex(),
                                                     batch.fBaseVertex,
                                                     0);
-            } else {
-                cbInfo.currentCmdBuf()->draw(fGpu,
-                                             mesh.fVertexCount * batch.fRepeatCount,
-                                             1,
-                                             batch.fBaseVertex,
-                                             0);
+                cbInfo.fIsEmpty = false;
+                fGpu->stats()->incNumDraws();
             }
+        } else {
+            cbInfo.currentCmdBuf()->draw(fGpu,
+                                         mesh.vertexCount(),
+                                         1,
+                                         mesh.baseVertex(),
+                                         0);
             cbInfo.fIsEmpty = false;
-
             fGpu->stats()->incNumDraws();
         }
     }