Update GrTextureOp to use index buffer offsets for draws
This should, hopefully, be faster on GL as we will only need to update the index-range for a draw rather than the offset into an vertex buffer.
Change-Id: I09e54c37262168661443fa8bf8d3b43cd8faa9db
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251757
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index 5837a4b..3a6a492 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -205,13 +205,14 @@
sk_sp<GrGeometryProcessor> gp = GrQuadPerEdgeAA::MakeProcessor(vertexSpec);
size_t vertexSize = gp->vertexStride();
- sk_sp<const GrBuffer> vbuffer;
+ sk_sp<const GrBuffer> vertexBuffer;
int vertexOffsetInBuffer = 0;
+ const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
+
// Fill the allocated vertex data
- void* vdata = target->makeVertexSpace(
- vertexSize, fQuads.count() * vertexSpec.verticesPerQuad(),
- &vbuffer, &vertexOffsetInBuffer);
+ void* vdata = target->makeVertexSpace(vertexSize, totalNumVertices,
+ &vertexBuffer, &vertexOffsetInBuffer);
if (!vdata) {
SkDebugf("Could not allocate vertices\n");
return;
@@ -229,13 +230,20 @@
info.fColor, iter.localQuad(), kEmptyDomain, info.fAAFlags);
}
+ sk_sp<const GrBuffer> indexBuffer;
+ if (vertexSpec.needsIndexBuffer()) {
+ indexBuffer = GrQuadPerEdgeAA::GetIndexBuffer(target, vertexSpec.indexBufferOption());
+ if (!indexBuffer) {
+ SkDebugf("Could not allocate indices\n");
+ return;
+ }
+ }
+
// Configure the mesh for the vertex data
GrMesh* mesh = target->allocMeshes(1);
- if (!GrQuadPerEdgeAA::ConfigureMeshIndices(target, mesh, vertexSpec, fQuads.count())) {
- SkDebugf("Could not allocate indices\n");
- return;
- }
- mesh->setVertexData(std::move(vbuffer), vertexOffsetInBuffer);
+ GrQuadPerEdgeAA::ConfigureMesh(mesh, vertexSpec, 0, fQuads.count(), totalNumVertices,
+ std::move(vertexBuffer), std::move(indexBuffer),
+ vertexOffsetInBuffer);
target->recordDraw(std::move(gp), mesh);
}
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index b9b2d65..8bdeeb8 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -131,50 +131,58 @@
return vb.fPtr;
}
-bool ConfigureMeshIndices(GrMeshDrawOp::Target* target, GrMesh* mesh, const VertexSpec& spec,
- int quadCount) {
+sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawOp::Target* target,
+ IndexBufferOption indexBufferOption) {
auto resourceProvider = target->resourceProvider();
- if (spec.usesCoverageAA()) {
- SkASSERT(spec.indexBufferOption() == IndexBufferOption::kPictureFramed);
+ switch (indexBufferOption) {
+ case IndexBufferOption::kPictureFramed: return resourceProvider->refAAQuadIndexBuffer();
+ case IndexBufferOption::kIndexedRects: return resourceProvider->refNonAAQuadIndexBuffer();
+ case IndexBufferOption::kTriStrips: // fall through
+ default: return nullptr;
+ }
+}
- // AA quads use 8 vertices, basically nested rectangles
- sk_sp<const GrGpuBuffer> ibuffer = resourceProvider->refAAQuadIndexBuffer();
- if (!ibuffer) {
- return false;
- }
- mesh->setPrimitiveType(GrPrimitiveType::kTriangles);
- mesh->setIndexedPatterned(std::move(ibuffer),
- GrResourceProvider::NumIndicesPerAAQuad(),
- GrResourceProvider::NumVertsPerAAQuad(),
- quadCount,
- GrResourceProvider::MaxNumAAQuads());
- } else {
- // Non-AA quads use 4 vertices, and regular triangle strip layout
- if (quadCount > 1) {
- SkASSERT(spec.indexBufferOption() == IndexBufferOption::kIndexedRects);
+void ConfigureMesh(GrMesh* mesh, const VertexSpec& spec,
+ int runningQuadCount, int quadsInDraw, int maxVerts,
+ sk_sp<const GrBuffer> vertexBuffer,
+ sk_sp<const GrBuffer> indexBuffer, int absVertBufferOffset) {
+ SkASSERT(vertexBuffer);
- sk_sp<const GrGpuBuffer> ibuffer = resourceProvider->refNonAAQuadIndexBuffer();
- if (!ibuffer) {
- return false;
- }
+ if (spec.indexBufferOption() == IndexBufferOption::kTriStrips) {
+ SkASSERT(!indexBuffer);
- mesh->setPrimitiveType(GrPrimitiveType::kTriangles);
- mesh->setIndexedPatterned(std::move(ibuffer),
- GrResourceProvider::NumIndicesPerNonAAQuad(),
- GrResourceProvider::NumVertsPerNonAAQuad(),
- quadCount,
- GrResourceProvider::MaxNumNonAAQuads());
- } else {
- SkASSERT(spec.indexBufferOption() != IndexBufferOption::kPictureFramed);
-
- mesh->setPrimitiveType(GrPrimitiveType::kTriangleStrip);
- mesh->setNonIndexedNonInstanced(4);
- }
+ mesh->setPrimitiveType(GrPrimitiveType::kTriangleStrip);
+ mesh->setNonIndexedNonInstanced(4);
+ int offset = absVertBufferOffset +
+ runningQuadCount * GrResourceProvider::NumVertsPerNonAAQuad();
+ mesh->setVertexData(std::move(vertexBuffer), offset);
+ return;
}
- return true;
+ SkASSERT(spec.indexBufferOption() == IndexBufferOption::kPictureFramed ||
+ spec.indexBufferOption() == IndexBufferOption::kIndexedRects);
+ SkASSERT(indexBuffer);
+
+ int baseIndex, numIndicesToDraw;
+
+ if (spec.indexBufferOption() == IndexBufferOption::kPictureFramed) {
+ SkASSERT(runningQuadCount + quadsInDraw <= GrResourceProvider::MaxNumAAQuads());
+ // AA uses 8 vertices and 30 indices per quad, basically nested rectangles
+ baseIndex = runningQuadCount * GrResourceProvider::NumIndicesPerAAQuad();
+ numIndicesToDraw = quadsInDraw * GrResourceProvider::NumIndicesPerAAQuad();
+ } else {
+ SkASSERT(runningQuadCount + quadsInDraw <= GrResourceProvider::MaxNumNonAAQuads());
+ // Non-AA uses 4 vertices and 6 indices per quad
+ baseIndex = runningQuadCount * GrResourceProvider::NumIndicesPerNonAAQuad();
+ numIndicesToDraw = quadsInDraw * GrResourceProvider::NumIndicesPerNonAAQuad();
+ }
+
+ mesh->setPrimitiveType(GrPrimitiveType::kTriangles);
+ mesh->setIndexed(std::move(indexBuffer), numIndicesToDraw, baseIndex, 0, maxVerts-1,
+ GrPrimitiveRestart::kNo);
+ mesh->setVertexData(std::move(vertexBuffer), absVertBufferOffset);
}
////////////////// VertexSpec Implementation
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.h b/src/gpu/ops/GrQuadPerEdgeAA.h
index 1a37de4..427e19c 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.h
+++ b/src/gpu/ops/GrQuadPerEdgeAA.h
@@ -96,6 +96,9 @@
CoverageMode coverageMode() const;
size_t vertexSize() const;
+ bool needsIndexBuffer() const { return this->indexBufferOption() !=
+ IndexBufferOption::kTriStrips; }
+
private:
static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type doesn't fit in 2 bits");
static_assert(kColorTypeCount <= 4, "Color doesn't fit in 2 bits");
@@ -134,13 +137,23 @@
const SkPMColor4f& color, const GrQuad& localQuad, const SkRect& domain,
GrQuadAAFlags aa);
- // The mesh will have its index data configured to meet the expectations of the Tessellate()
- // function, but it the calling code must handle filling a vertex buffer via Tessellate() and
- // then assigning it to the returned mesh.
+ // This method will return the correct index buffer for the specified indexBufferOption.
+ // It will, correctly, return nullptr if the indexBufferOption is kTriStrips.
+ sk_sp<const GrBuffer> GetIndexBuffer(GrMeshDrawOp::Target*, IndexBufferOption);
+
+ // This method will configure the vertex and index data of the provided 'mesh' to comply
+ // with the indexing method specified in the vertexSpec. It is up to the calling code
+ // to allocate and fill in the vertex data and acquire the correct indexBuffer if it is needed.
//
- // Returns false if the index data could not be allocated.
- bool ConfigureMeshIndices(GrMeshDrawOp::Target* target, GrMesh* mesh, const VertexSpec& spec,
- int quadCount);
+ // @param runningQuadCount the number of quads already stored in 'vertexBuffer' and
+ // 'indexBuffer' e.g., different GrMeshes have already been placed in
+ // the buffers to allow dynamic state changes.
+ // @param quadCount the number of quads that will be drawn by the provided 'mesh'.
+ // A subsequent ConfigureMesh call would the use
+ // 'runningQuadCount' + 'quadCount' for its new 'runningQuadCount'.
+ void ConfigureMesh(GrMesh* mesh, const VertexSpec&, int runningQuadCount, int quadCount,
+ int maxVerts, sk_sp<const GrBuffer> vertexBuffer,
+ sk_sp<const GrBuffer> indexBuffer, int absVertBufferOffset);
} // namespace GrQuadPerEdgeAA
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 7f5c593..d66aea8 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -538,10 +538,10 @@
static bool FillInData(TextureOp* texOp, PrePreparedDesc* desc,
char* pVertexData, GrMesh* meshes, int absBufferOffset,
- sk_sp<const GrBuffer> vertexBuffer, Target* target) {
- SkDEBUGCODE(int totQuadsSeen = 0;)
+ sk_sp<const GrBuffer> vertexBuffer,
+ sk_sp<const GrBuffer> indexBuffer) {
+ int totQuadsSeen = 0;
SkDEBUGCODE(int totVerticesSeen = 0;)
- int localVertexOffsetInBuffer = 0;
char* dst = pVertexData;
const size_t vertexSize = desc->fVertexSpec.vertexSize();
@@ -552,10 +552,8 @@
GrTextureProxy* proxy = op.fViewCountPairs[p].fProxyView.asTextureProxy();
int quadCnt = op.fViewCountPairs[p].fQuadCnt;
- SkDEBUGCODE(totQuadsSeen += quadCnt;)
- int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad();
- SkDEBUGCODE(totVerticesSeen += meshVertexCnt);
+ const int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad();
SkASSERT(meshIndex < desc->fNumProxies);
@@ -563,23 +561,21 @@
Tess(dst, desc->fVertexSpec, proxy, &iter, quadCnt, op.filter());
desc->setMeshProxy(meshIndex, proxy);
- SkASSERT(localVertexOffsetInBuffer * vertexSize == (size_t)(dst - pVertexData));
+ SkASSERT(totVerticesSeen * vertexSize == (size_t)(dst - pVertexData));
dst += vertexSize * meshVertexCnt;
}
if (meshes) {
- if (!GrQuadPerEdgeAA::ConfigureMeshIndices(target, &(meshes[meshIndex]),
- desc->fVertexSpec, quadCnt)) {
- SkDebugf("Could not allocate indices");
- return false;
- }
- meshes[meshIndex].setVertexData(vertexBuffer,
- localVertexOffsetInBuffer + absBufferOffset);
+ GrQuadPerEdgeAA::ConfigureMesh(&(meshes[meshIndex]), desc->fVertexSpec,
+ totQuadsSeen, quadCnt, desc->totalNumVertices(),
+ vertexBuffer, indexBuffer, absBufferOffset);
}
++meshIndex;
- localVertexOffsetInBuffer += meshVertexCnt;
+ totQuadsSeen += quadCnt;
+ SkDEBUGCODE(totVerticesSeen += meshVertexCnt);
+ SkASSERT(totQuadsSeen * desc->fVertexSpec.verticesPerQuad() == totVerticesSeen);
}
// If quad counts per proxy were calculated correctly, the entire iterator
@@ -722,6 +718,16 @@
return;
}
+ sk_sp<const GrBuffer> indexBuffer;
+ if (desc.fVertexSpec.needsIndexBuffer()) {
+ indexBuffer = GrQuadPerEdgeAA::GetIndexBuffer(target,
+ desc.fVertexSpec.indexBufferOption());
+ if (!indexBuffer) {
+ SkDebugf("Could not allocate indices\n");
+ return;
+ }
+ }
+
// Note: this allocation is always in the flush-time arena (i.e., the flushState)
GrMesh* meshes = target->allocMeshes(desc.fNumProxies);
@@ -731,11 +737,11 @@
// The above memcpy filled in the vertex data - just call FillInData to fill in the
// mesh data
result = FillInData(this, &desc, nullptr, meshes, vertexOffsetInBuffer,
- std::move(vbuffer), target);
+ std::move(vbuffer), std::move(indexBuffer));
} else {
// Fills in both vertex data and mesh data
result = FillInData(this, &desc, (char*) vdata, meshes, vertexOffsetInBuffer,
- std::move(vbuffer), target);
+ std::move(vbuffer), std::move(indexBuffer));
}
if (!result) {