Fix glDrawRangeElements
Adds explicit min/max index value fields to GrMesh. This eliminates the
previous assumption that the index values were within the range
[0..vertexCount-1]. In the pattern case we still maintain this
assumption.
Updates GrMesh to hide its fields and handle its new complexity using a
"helper" interface instead.
Adds a unit test for GrMesh.
Bug: skia:
Change-Id: Ia23de72d510f8827cee56072b727fb70a6e46b8d
Reviewed-on: https://skia-review.googlesource.com/17964
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp
index 043c54f..0c7bb97 100644
--- a/src/gpu/GrGpuCommandBuffer.cpp
+++ b/src/gpu/GrGpuCommandBuffer.cpp
@@ -43,7 +43,7 @@
const SkRect& bounds) {
#ifdef SK_DEBUG
for (int i = 0; i < meshCount; ++i) {
- SkASSERT(SkToBool(primProc.numAttribs()) == SkToBool(meshes[i].vertexBuffer()));
+ SkASSERT(SkToBool(primProc.numAttribs()) == meshes[i].hasVertexData());
}
#endif
diff --git a/src/gpu/GrMesh.h b/src/gpu/GrMesh.h
index 6aed8d3..98f9911 100644
--- a/src/gpu/GrMesh.h
+++ b/src/gpu/GrMesh.h
@@ -11,6 +11,8 @@
#include "GrBuffer.h"
#include "GrGpuResourceRef.h"
+class GrPrimitiveProcessor;
+
/**
* Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to
* GrGpu. It also holds the primitive type for the draw. TODO: Consider moving ownership of this
@@ -20,28 +22,39 @@
class GrMesh {
public:
GrMesh(GrPrimitiveType primitiveType)
- : fPrimitiveType(primitiveType) {
- SkDEBUGCODE(fVertexCount = 0;)
- SkDEBUGCODE(fBaseVertex = -1;)
+ : fPrimitiveType(primitiveType)
+ , fBaseVertex(0) {
+ SkDEBUGCODE(fNonIndexData.fVertexCount = -1);
}
- void setNonIndexed();
- void setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex = 0);
- void setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
+ GrPrimitiveType primitiveType() const { return fPrimitiveType; }
+ bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
+ bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); }
+
+ void setNonIndexed(int vertexCount);
+ void setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
+ uint16_t minIndexValue, uint16_t maxIndexValue);
+ void setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount, int vertexCount,
int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
- void setVertices(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex = 0);
+ void setVertexData(const GrBuffer* vertexBuffer, int baseVertex = 0);
- GrPrimitiveType primitiveType() const { return fPrimitiveType; }
+ class SendToGpuImpl {
+ public:
+ virtual void sendMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
+ const GrBuffer* vertexBuffer, int vertexCount,
+ int baseVertex) = 0;
- 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; }
+ virtual void sendIndexedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
+ const GrBuffer* indexBuffer, int indexCount,
+ int baseIndex, uint16_t minIndexValue,
+ uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
+ int baseVertex) = 0;
- const GrBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
- int vertexCount() const { SkASSERT(fVertexCount >= 1); return fVertexCount; }
- int baseVertex() const { SkASSERT(fBaseVertex >= 0); return fBaseVertex; }
+ virtual ~SendToGpuImpl() {}
+ };
+
+ void sendToGpu(const GrPrimitiveProcessor&, SendToGpuImpl*) const;
struct PatternBatch;
@@ -49,98 +62,108 @@
using PendingBuffer = GrPendingIOResource<const GrBuffer, kRead_GrIOType>;
GrPrimitiveType fPrimitiveType;
-
PendingBuffer fIndexBuffer;
- int fIndexCount;
- int fBaseIndex;
- int fPatternRepeatCount;
- int fMaxPatternRepetitionsInIndexBuffer;
-
PendingBuffer fVertexBuffer;
- int fVertexCount;
int fBaseVertex;
- class PatternIterator;
- friend GrMesh::PatternIterator begin(const GrMesh&);
- friend GrMesh::PatternIterator end(const GrMesh&);
+ union {
+ struct { // When fIndexBuffer == nullptr.
+ int fVertexCount;
+ } fNonIndexData;
+
+ struct { // When fIndexBuffer != nullptr.
+ struct {
+ int fIndexCount;
+ int fPatternRepeatCount;
+ } fIndexData;
+
+ union {
+ struct { // When fPatternRepeatCount == 0.
+ int fBaseIndex;
+ uint16_t fMinIndexValue;
+ uint16_t fMaxIndexValue;
+ } fNonPatternIndexData;
+
+ struct { // When fPatternRepeatCount != 0.
+ int fVertexCount;
+ int fMaxPatternRepetitionsInIndexBuffer;
+ } fPatternData;
+ };
+ };
+ };
};
-inline void GrMesh::setNonIndexed() {
+inline void GrMesh::setNonIndexed(int vertexCount) {
fIndexBuffer.reset(nullptr);
+ fNonIndexData.fVertexCount = vertexCount;
}
-inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex) {
+inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
+ uint16_t minIndexValue, uint16_t maxIndexValue) {
SkASSERT(indexBuffer);
SkASSERT(indexCount >= 1);
SkASSERT(baseIndex >= 0);
+ SkASSERT(maxIndexValue > minIndexValue);
fIndexBuffer.reset(indexBuffer);
- fIndexCount = indexCount;
- fBaseIndex = baseIndex;
- fPatternRepeatCount = fMaxPatternRepetitionsInIndexBuffer = 1;
+ fIndexData.fIndexCount = indexCount;
+ fIndexData.fPatternRepeatCount = 0;
+ fNonPatternIndexData.fBaseIndex = baseIndex;
+ fNonPatternIndexData.fMinIndexValue = minIndexValue;
+ fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
}
inline void GrMesh::setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
- int patternRepeatCount,
+ int vertexCount, int patternRepeatCount,
int maxPatternRepetitionsInIndexBuffer) {
SkASSERT(indexBuffer);
SkASSERT(indexCount >= 1);
+ SkASSERT(vertexCount >= 1);
SkASSERT(patternRepeatCount >= 1);
SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
fIndexBuffer.reset(indexBuffer);
- fIndexCount = indexCount;
- fBaseIndex = 0;
- fPatternRepeatCount = patternRepeatCount;
- fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
+ fIndexData.fIndexCount = indexCount;
+ fIndexData.fPatternRepeatCount = patternRepeatCount;
+ fPatternData.fVertexCount = vertexCount;
+ fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
}
-inline void GrMesh::setVertices(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
+inline void GrMesh::setVertexData(const GrBuffer* vertexBuffer, int baseVertex) {
+ SkASSERT(baseVertex >= 0);
fVertexBuffer.reset(vertexBuffer);
- fVertexCount = vertexCount;
fBaseVertex = baseVertex;
}
-struct GrMesh::PatternBatch {
- int fBaseVertex;
- int fRepeatCount;
-};
-
-class GrMesh::PatternIterator {
-public:
- PatternIterator(const GrMesh& mesh, int repetitionIdx)
- : fMesh(mesh)
- , fRepetitionIdx(repetitionIdx) {
- SkASSERT(fMesh.isIndexed());
+inline void GrMesh::sendToGpu(const GrPrimitiveProcessor& primProc, SendToGpuImpl* impl) const {
+ if (!this->isIndexed()) {
+ SkASSERT(fNonIndexData.fVertexCount > 0);
+ impl->sendMeshToGpu(primProc, fPrimitiveType, fVertexBuffer.get(),
+ fNonIndexData.fVertexCount, fBaseVertex);
+ return;
}
- bool operator!=(const PatternIterator& that) {
- SkASSERT(&fMesh == &that.fMesh);
- return fRepetitionIdx != that.fRepetitionIdx;
+ if (0 == fIndexData.fPatternRepeatCount) {
+ impl->sendIndexedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(),
+ fIndexData.fIndexCount, fNonPatternIndexData.fBaseIndex,
+ fNonPatternIndexData.fMinIndexValue,
+ fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(),
+ fBaseVertex);
+ return;
}
- const PatternBatch operator*() {
- PatternBatch batch;
- batch.fBaseVertex = fMesh.fBaseVertex + fRepetitionIdx * fMesh.fVertexCount;
- batch.fRepeatCount = SkTMin(fMesh.fPatternRepeatCount - fRepetitionIdx,
- fMesh.fMaxPatternRepetitionsInIndexBuffer);
- return batch;
- }
-
- void operator++() {
- fRepetitionIdx = SkTMin(fRepetitionIdx + fMesh.fMaxPatternRepetitionsInIndexBuffer,
- fMesh.fPatternRepeatCount);
- }
-
-private:
- const GrMesh& fMesh;
- int fRepetitionIdx;
-};
-
-inline GrMesh::PatternIterator begin(const GrMesh& mesh) {
- return GrMesh::PatternIterator(mesh, 0);
-}
-
-inline GrMesh::PatternIterator end(const GrMesh& mesh) {
- return GrMesh::PatternIterator(mesh, mesh.fPatternRepeatCount);
+ SkASSERT(fIndexData.fPatternRepeatCount > 0);
+ int baseRepetition = 0;
+ do {
+ int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer,
+ fIndexData.fPatternRepeatCount - baseRepetition);
+ // A patterned index buffer must contain indices in the range [0..vertexCount].
+ int minIndexValue = 0;
+ int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
+ impl->sendIndexedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(),
+ fIndexData.fIndexCount * repeatCount, 0, minIndexValue,
+ maxIndexValue, fVertexBuffer.get(),
+ fBaseVertex + fPatternData.fVertexCount * baseRepetition);
+ baseRepetition += repeatCount;
+ } while (baseRepetition < fIndexData.fPatternRepeatCount);
}
#endif
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 81ee87c..045804c 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2450,41 +2450,7 @@
this->xferBarrier(pipeline.getRenderTarget(), barrierType);
}
- const GrMesh& mesh = meshes[i];
- 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);
- // batch.fBaseVertex 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.vertexCount() * batch.fRepeatCount - 1;
- GL_CALL(DrawRangeElements(primType, start, end,
- mesh.indexCount() * batch.fRepeatCount,
- GR_GL_UNSIGNED_SHORT, indices));
- } else {
- GL_CALL(DrawElements(primType, mesh.indexCount() * batch.fRepeatCount,
- GR_GL_UNSIGNED_SHORT, indices));
- }
- fStats.incNumDraws();
- }
- } else {
- if (this->glCaps().drawArraysBaseVertexIsBroken()) {
- this->setupGeometry(primProc, mesh.indexBuffer(), mesh.vertexBuffer(),
- mesh.baseVertex());
- GL_CALL(DrawArrays(primType, 0, mesh.vertexCount()));
- } else {
- this->setupGeometry(primProc, mesh.indexBuffer(), mesh.vertexBuffer(), 0);
- GL_CALL(DrawArrays(primType, mesh.baseVertex(), mesh.vertexCount()));
- }
- fStats.incNumDraws();
- }
+ meshes[i].sendToGpu(primProc, this);
}
#if SWAP_PER_DRAW
@@ -2501,6 +2467,40 @@
#endif
}
+void GrGLGpu::sendMeshToGpu(const GrPrimitiveProcessor& primProc, GrPrimitiveType primitiveType,
+ const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
+ const GrGLenum glPrimType = gPrimitiveType2GLMode[primitiveType];
+
+ if (this->glCaps().drawArraysBaseVertexIsBroken()) {
+ this->setupGeometry(primProc, nullptr, vertexBuffer, baseVertex);
+ GL_CALL(DrawArrays(glPrimType, 0, vertexCount));
+ } else {
+ this->setupGeometry(primProc, nullptr, vertexBuffer, 0);
+ GL_CALL(DrawArrays(glPrimType, baseVertex, vertexCount));
+ }
+ fStats.incNumDraws();
+}
+
+void GrGLGpu::sendIndexedMeshToGpu(const GrPrimitiveProcessor& primProc,
+ GrPrimitiveType primitiveType, const GrBuffer* indexBuffer,
+ int indexCount, int baseIndex, uint16_t minIndexValue,
+ uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
+ int baseVertex) {
+ const GrGLenum glPrimType = gPrimitiveType2GLMode[primitiveType];
+ GrGLvoid* const indices = reinterpret_cast<void*>(indexBuffer->baseOffset() +
+ sizeof(uint16_t) * baseIndex);
+
+ this->setupGeometry(primProc, indexBuffer, vertexBuffer, baseVertex);
+
+ if (this->glCaps().drawRangeElementsSupport()) {
+ GL_CALL(DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount,
+ GR_GL_UNSIGNED_SHORT, indices));
+ } else {
+ GL_CALL(DrawElements(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT, indices));
+ }
+ fStats.incNumDraws();
+}
+
void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
if (rt->needsResolve()) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index d19f2ef..c83ad85 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -17,6 +17,7 @@
#include "GrGLTexture.h"
#include "GrGLVertexArray.h"
#include "GrGpu.h"
+#include "GrMesh.h"
#include "GrTexturePriv.h"
#include "GrWindowRectsState.h"
#include "GrXferProcessor.h"
@@ -34,7 +35,7 @@
#define PROGRAM_CACHE_STATS
#endif
-class GrGLGpu final : public GrGpu {
+class GrGLGpu final : public GrGpu, private GrMesh::SendToGpuImpl {
public:
static GrGpu* Create(GrBackendContext backendContext, const GrContextOptions& options,
GrContext* context);
@@ -103,6 +104,17 @@
const GrMesh*,
int meshCount);
+
+ // GrMesh::SendToGpuImpl methods. These issue the actual GL draw calls.
+ // Marked final as a hint to the compiler to not use virtual dispatch.
+ void sendMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
+ const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) final;
+
+ void sendIndexedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
+ const GrBuffer* indexBuffer, int indexCount, int baseIndex,
+ uint16_t minIndexValue, uint16_t maxIndexValue,
+ const GrBuffer* vertexBuffer, int baseVertex) final;
+
// The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
// Thus this is the implementation of the clear call for the corresponding passthrough function
// on GrGLGpuCommandBuffer.
@@ -248,9 +260,7 @@
// willDrawPoints must be true if point primitives will be rendered after setting the GL state.
bool flushGLState(const GrPipeline&, const GrPrimitiveProcessor&, bool willDrawPoints);
- // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset
- // an into the index buffer. It does not account for vertices.startIndex() but rather the start
- // index is relative to the returned offset.
+ // Sets up vertex/instance attribute pointers and strides.
void setupGeometry(const GrPrimitiveProcessor&,
const GrBuffer* indexBuffer,
const GrBuffer* vertexBuffer,
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 161e96d..cd69c6a 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -813,8 +813,8 @@
extract_verts(tess, verts, vertexStride, fColor, idxs, canTweakAlphaForCoverage);
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexed(indexBuffer, tess.numIndices(), firstIndex);
- mesh.setVertices(vertexBuffer, tess.numPts(), firstVertex);
+ mesh.setIndexed(indexBuffer, tess.numIndices(), firstIndex, 0, tess.numPts() - 1);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp.get(), this->pipeline(), mesh);
}
}
@@ -901,8 +901,8 @@
for (int j = 0; j < draws.count(); ++j) {
const Draw& draw = draws[j];
- mesh.setIndexed(indexBuffer, draw.fIndexCnt, firstIndex);
- mesh.setVertices(vertexBuffer, draw.fVertexCnt, firstVertex);
+ mesh.setIndexed(indexBuffer, draw.fIndexCnt, firstIndex, 0, draw.fVertexCnt - 1);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(quadProcessor.get(), this->pipeline(), mesh);
firstIndex += draw.fIndexCnt;
firstVertex += draw.fVertexCnt;
diff --git a/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 5618fd1..26d58f4 100644
--- a/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -861,9 +861,9 @@
}
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg,
+ mesh.setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg, kLineSegNumVertices,
lineCount, kLineSegsNumInIdxBuffer);
- mesh.setVertices(vertexBuffer, kLineSegNumVertices, firstVertex);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(lineGP.get(), this->pipeline(), mesh);
}
@@ -918,18 +918,18 @@
if (quadCount > 0) {
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, quadCount,
- kQuadsNumInIdxBuffer);
- mesh.setVertices(vertexBuffer, kQuadNumVertices, firstVertex);
+ mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
+ quadCount, kQuadsNumInIdxBuffer);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(quadGP.get(), this->pipeline(), mesh);
firstVertex += quadCount * kQuadNumVertices;
}
if (conicCount > 0) {
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, conicCount,
- kQuadsNumInIdxBuffer);
- mesh.setVertices(vertexBuffer, kQuadNumVertices, firstVertex);
+ mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
+ conicCount, kQuadsNumInIdxBuffer);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(conicGP.get(), this->pipeline(), mesh);
}
}
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index b2d9599..5cfe5cb 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -208,8 +208,8 @@
return;
}
memcpy(idxs, indices, indexCount * sizeof(uint16_t));
- mesh.setIndexed(indexBuffer, indexCount, firstIndex);
- mesh.setVertices(vertexBuffer, vertexCount, firstVertex);
+ mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp, this->pipeline(), mesh);
}
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 21b7f6d..69e8b4e 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -151,9 +151,9 @@
GrMesh mesh(kTriangles_GrPrimitiveType);
int maxGlyphsPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
- mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph,
+ mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph,
flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
- mesh.setVertices(flushInfo->fVertexBuffer.get(), kVerticesPerGlyph, flushInfo->fVertexOffset);
+ mesh.setVertexData(flushInfo->fVertexBuffer.get(), 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 c696dda..7633868 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -248,10 +248,12 @@
}
GrMesh mesh(primitiveType);
- if (isIndexed) {
- mesh.setIndexed(indexBuffer, indexOffset, firstIndex);
+ if (!isIndexed) {
+ mesh.setNonIndexed(vertexOffset);
+ } else {
+ mesh.setIndexed(indexBuffer, indexOffset, firstIndex, 0, vertexOffset - 1);
}
- mesh.setVertices(vertexBuffer, vertexOffset, firstVertex);
+ mesh.setVertexData(vertexBuffer, 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 2a61f3c..1e04c68 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -217,10 +217,12 @@
}
GrMesh mesh(this->primitiveType());
- if (indices) {
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
+ if (!indices) {
+ mesh.setNonIndexed(fVertexCount);
+ } else {
+ mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1);
}
- mesh.setVertices(vertexBuffer, fVertexCount, firstVertex);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp.get(), this->pipeline(), mesh);
}
diff --git a/src/gpu/ops/GrMSAAPathRenderer.cpp b/src/gpu/ops/GrMSAAPathRenderer.cpp
index c3a5440..36faf2f 100644
--- a/src/gpu/ops/GrMSAAPathRenderer.cpp
+++ b/src/gpu/ops/GrMSAAPathRenderer.cpp
@@ -411,10 +411,13 @@
SkASSERT(lineVertexStride == lineGP->getVertexStride());
GrMesh lineMeshes(primitiveType);
- if (fIsIndexed) {
- lineMeshes.setIndexed(lineIndexBuffer, lineIndexOffset, firstLineIndex);
+ if (!fIsIndexed) {
+ lineMeshes.setNonIndexed(lineVertexOffset);
+ } else {
+ lineMeshes.setIndexed(lineIndexBuffer, lineIndexOffset, firstLineIndex,
+ 0, lineVertexOffset - 1);
}
- lineMeshes.setVertices(lineVertexBuffer, lineVertexOffset, firstLineVertex);
+ lineMeshes.setVertexData(lineVertexBuffer, 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
@@ -435,16 +438,19 @@
&firstQuadVertex);
memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset);
GrMesh quadMeshes(kTriangles_GrPrimitiveType);
- if (fIsIndexed) {
+ if (!fIsIndexed) {
+ quadMeshes.setNonIndexed(quadVertexOffset);
+ } else {
const GrBuffer* quadIndexBuffer;
int firstQuadIndex;
uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset,
&quadIndexBuffer,
&firstQuadIndex);
memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset);
- quadMeshes.setIndexed(quadIndexBuffer, quadIndexOffset, firstQuadIndex);
+ quadMeshes.setIndexed(quadIndexBuffer, quadIndexOffset, firstQuadIndex,
+ 0, quadVertexOffset - 1);
}
- quadMeshes.setVertices(quadVertexBuffer, quadVertexOffset, firstQuadVertex);
+ quadMeshes.setVertexData(quadVertexBuffer, firstQuadVertex);
target->draw(quadGP.get(), this->pipeline(), quadMeshes);
}
}
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index 9382fd7..d6c2ced 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -37,8 +37,9 @@
size_t ibSize = indexBuffer->gpuMemorySize();
int maxRepetitions = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerRepetition));
- fMesh.setIndexedPatterned(indexBuffer, indicesPerRepetition, repeatCount, maxRepetitions);
- fMesh.setVertices(vertexBuffer, verticesPerRepetition, firstVertex);
+ fMesh.setIndexedPatterned(indexBuffer, indicesPerRepetition, verticesPerRepetition,
+ repeatCount, maxRepetitions);
+ fMesh.setVertexData(vertexBuffer, firstVertex);
return vertices;
}
diff --git a/src/gpu/ops/GrNonAAStrokeRectOp.cpp b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
index 4e00847..f386984 100644
--- a/src/gpu/ops/GrNonAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrNonAAStrokeRectOp.cpp
@@ -157,7 +157,8 @@
}
GrMesh mesh(primType);
- mesh.setVertices(vertexBuffer, vertexCount, firstVertex);
+ mesh.setNonIndexed(vertexCount);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp.get(), this->pipeline(), mesh);
}
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 623ec7a..174dc40 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -1106,8 +1106,8 @@
}
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
- mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
+ mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp.get(), fHelper.makePipeline(target), mesh);
}
@@ -2030,8 +2030,8 @@
}
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
- mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
+ mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp.get(), fHelper.makePipeline(target), mesh);
}
diff --git a/src/gpu/ops/GrShadowRRectOp.cpp b/src/gpu/ops/GrShadowRRectOp.cpp
index a9d057c..af41bd4 100644
--- a/src/gpu/ops/GrShadowRRectOp.cpp
+++ b/src/gpu/ops/GrShadowRRectOp.cpp
@@ -629,8 +629,8 @@
}
GrMesh mesh(kTriangles_GrPrimitiveType);
- mesh.setIndexed(indexBuffer, fIndexCount, firstIndex);
- mesh.setVertices(vertexBuffer, fVertCount, firstVertex);
+ mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1);
+ mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(gp.get(), this->pipeline(), mesh);
}
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 9d9cf27..048351b 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -683,9 +683,9 @@
int maxInstancesPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerQuad,
- flushInfo->fInstancesToFlush, maxInstancesPerDraw);
- mesh.setVertices(flushInfo->fVertexBuffer.get(), kVerticesPerQuad,
- flushInfo->fVertexOffset);
+ kVerticesPerQuad, flushInfo->fInstancesToFlush,
+ maxInstancesPerDraw);
+ mesh.setVertexData(flushInfo->fVertexBuffer.get(), 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 45e9465..9860d9c 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -314,7 +314,8 @@
void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuffer* vb,
int firstVertex, int count) const {
GrMesh mesh(TESSELLATOR_WIREFRAME ? kLines_GrPrimitiveType : kTriangles_GrPrimitiveType);
- mesh.setVertices(vb, count, firstVertex);
+ mesh.setNonIndexed(count);
+ mesh.setVertexData(vb, firstVertex);
target->draw(gp, this->pipeline(), mesh);
}
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index ad2dc0c..2e9373b 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -544,8 +544,6 @@
return;
}
- CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
-
for (int i = 0; i < meshCount; ++i) {
const GrMesh& mesh = meshes[i];
if (mesh.primitiveType() != primitiveType) {
@@ -564,32 +562,12 @@
}
SkASSERT(pipelineState);
- this->bindGeometry(primProc, mesh.indexBuffer(), mesh.vertexBuffer());
-
- if (mesh.isIndexed()) {
- for (const GrMesh::PatternBatch batch : mesh) {
- cbInfo.currentCmdBuf()->drawIndexed(fGpu,
- mesh.indexCount() * batch.fRepeatCount,
- 1,
- mesh.baseIndex(),
- 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();
- }
+ mesh.sendToGpu(primProc, this);
}
- // Update command buffer bounds
+ CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
cbInfo.fBounds.join(bounds);
+ cbInfo.fIsEmpty = false;
// 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
@@ -597,3 +575,29 @@
pipelineState->freeTempResources(fGpu);
}
+void GrVkGpuCommandBuffer::sendMeshToGpu(const GrPrimitiveProcessor& primProc,
+ GrPrimitiveType,
+ const GrBuffer* vertexBuffer,
+ int vertexCount,
+ int baseVertex) {
+ CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
+ this->bindGeometry(primProc, nullptr, vertexBuffer);
+ cbInfo.currentCmdBuf()->draw(fGpu, vertexCount, 1, baseVertex, 0);
+ fGpu->stats()->incNumDraws();
+}
+
+void GrVkGpuCommandBuffer::sendIndexedMeshToGpu(const GrPrimitiveProcessor& primProc,
+ GrPrimitiveType,
+ const GrBuffer* indexBuffer,
+ int indexCount,
+ int baseIndex,
+ uint16_t /*minIndexValue*/,
+ uint16_t /*maxIndexValue*/,
+ const GrBuffer* vertexBuffer,
+ int baseVertex) {
+ CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo];
+ this->bindGeometry(primProc, indexBuffer, vertexBuffer);
+ cbInfo.currentCmdBuf()->drawIndexed(fGpu, indexCount, 1, baseIndex, baseVertex, 0);
+ fGpu->stats()->incNumDraws();
+}
+
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index 3d4d3ee..b1e96a3 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -11,6 +11,7 @@
#include "GrGpuCommandBuffer.h"
#include "GrColor.h"
+#include "GrMesh.h"
#include "GrTypes.h"
#include "GrVkPipelineState.h"
@@ -20,7 +21,7 @@
class GrVkRenderTarget;
class GrVkSecondaryCommandBuffer;
-class GrVkGpuCommandBuffer : public GrGpuCommandBuffer {
+class GrVkGpuCommandBuffer : public GrGpuCommandBuffer, private GrMesh::SendToGpuImpl {
public:
GrVkGpuCommandBuffer(GrVkGpu* gpu,
const LoadAndStoreInfo& colorInfo,
@@ -59,6 +60,16 @@
int meshCount,
const SkRect& bounds) override;
+ // GrMesh::SendToGpuImpl methods. These issue the actual Vulkan draw commands.
+ // Marked final as a hint to the compiler to not use virtual dispatch.
+ void sendMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
+ const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) final;
+
+ void sendIndexedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType,
+ const GrBuffer* indexBuffer, int indexCount, int baseIndex,
+ uint16_t minIndexValue, uint16_t maxIndexValue,
+ const GrBuffer* vertexBuffer, int baseVertex) final;
+
void onClear(GrRenderTarget*, const GrFixedClip&, GrColor color) override;
void onClearStencilClip(GrRenderTarget*, const GrFixedClip&, bool insideStencilMask) override;