Store GrMeshDrawOps' meshes in GrOpFlushState's arena.

Remove late draw consolidation in GrOpFlushState. Rarely did anything
and doesn't work with new allocation strategy. Ops can use GrMesh arrays
to acheive the same thing. (Each Op that cared to would have to implement
but it isn't applicable to most Ops).

Modify GrMeshDrawOp::Target::draw() to take array of meshes, with single
mesh as a special case.

Change-Id: I552677de47b9ffd2fcaf55af85f70f290e5aa9c7
Reviewed-on: https://skia-review.googlesource.com/145426
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2018-08-05 21:30:33 -04:00 committed by Skia Commit-Bot
parent c0b03d8dfc
commit b948572c78
29 changed files with 214 additions and 205 deletions

View File

@ -199,9 +199,9 @@ private:
}
}
GrMesh mesh(GrPrimitiveType::kTriangleStrip);
mesh.setNonIndexedNonInstanced(kVertexCount);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangleStrip);
mesh->setNonIndexedNonInstanced(kVertexCount);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = target->makePipeline(0, GrProcessorSet::MakeEmptySet(),
target->detachAppliedClip());
target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);

View File

@ -92,9 +92,9 @@ private:
: INHERITED(std::move(gp), rect, color, ClassID()) {}
void onPrepareDraws(Target* target) override {
QuadHelper helper;
SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(SkPoint));
SkPoint* pts = reinterpret_cast<SkPoint*>(helper.init(target, sizeof(SkPoint), 1));
QuadHelper helper(target, sizeof(SkPoint), 1);
SkPoint* pts = reinterpret_cast<SkPoint*>(helper.vertices());
if (!pts) {
return;
}
@ -284,9 +284,9 @@ private:
};
void onPrepareDraws(Target* target) override {
QuadHelper helper;
SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, sizeof(Vertex), 1));
QuadHelper helper(target, sizeof(Vertex), 1);
Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
if (!verts) {
return;
}
@ -506,9 +506,9 @@ private:
};
void onPrepareDraws(Target* target) override {
QuadHelper helper;
SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, sizeof(Vertex), 1));
QuadHelper helper(target, sizeof(Vertex), 1);
Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
if (!verts) {
return;
}

View File

@ -87,8 +87,8 @@ private:
SkMatrix::I()));
SkASSERT(gp->debugOnly_vertexStride() == sizeof(SkPoint));
QuadHelper helper;
SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(target, sizeof(SkPoint), 1));
QuadHelper helper(target, sizeof(SkPoint), 1);
SkPoint* verts = reinterpret_cast<SkPoint*>(helper.vertices());
if (!verts) {
return;
}

View File

@ -21,12 +21,12 @@ class GrPrimitiveProcessor;
*/
class GrMesh {
public:
GrMesh(GrPrimitiveType primitiveType)
: fPrimitiveType(primitiveType)
, fBaseVertex(0) {
GrMesh(GrPrimitiveType primitiveType = GrPrimitiveType::kTriangles)
: fPrimitiveType(primitiveType), fBaseVertex(0) {
SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
}
void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }

View File

@ -45,8 +45,7 @@ void GrOpFlushState::executeDrawsAndUploadsForMeshDrawOp(uint32_t opID, const Sk
SkASSERT(fCurrDraw->fPipeline->proxy() == this->drawOpArgs().fProxy);
this->rtCommandBuffer()->draw(*fCurrDraw->fGeometryProcessor, *fCurrDraw->fPipeline,
fCurrDraw->fFixedDynamicState, fCurrDraw->fDynamicStateArrays,
fMeshes.begin() + fCurrMesh, fCurrDraw->fMeshCnt, opBounds);
fCurrMesh += fCurrDraw->fMeshCnt;
fCurrDraw->fMeshes, fCurrDraw->fMeshCnt, opBounds);
fTokenTracker->flushToken();
++fCurrDraw;
}
@ -61,7 +60,6 @@ void GrOpFlushState::preExecuteDraws() {
// Setup execution iterators.
fCurrDraw = fDraws.begin();
fCurrUpload = fInlineUploads.begin();
fCurrMesh = 0;
}
void GrOpFlushState::reset() {
@ -73,8 +71,6 @@ void GrOpFlushState::reset() {
fASAPUploads.reset();
fInlineUploads.reset();
fDraws.reset();
fMeshes.reset();
fCurrMesh = 0;
fBaseDrawToken = GrDeferredUploadToken::AlreadyFlushedToken();
}
@ -106,29 +102,12 @@ GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&&
void GrOpFlushState::draw(sk_sp<const GrGeometryProcessor> gp, const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState,
const GrMesh& mesh) {
const GrMesh meshes[], int meshCnt) {
SkASSERT(fOpArgs);
SkASSERT(fOpArgs->fOp);
fMeshes.push_back(mesh);
bool firstDraw = fDraws.begin() == fDraws.end();
if (!firstDraw) {
Draw& lastDraw = *fDraws.begin();
// If the last draw shares a geometry processor and pipeline and there are no intervening
// uploads, add this mesh to it.
// Note, we could attempt to convert fixed dynamic states into dynamic state arrays here
// if everything else is equal. Maybe it's better to rely on Ops to do that?
if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline &&
lastDraw.fFixedDynamicState == fixedDynamicState) {
if (fInlineUploads.begin() == fInlineUploads.end() ||
fInlineUploads.tail()->fUploadBeforeToken != fTokenTracker->nextDrawToken()) {
++lastDraw.fMeshCnt;
return;
}
}
}
auto& draw = fDraws.append(&fArena);
GrDeferredUploadToken token = fTokenTracker->issueDrawToken();
for (int i = 0; i < gp->numTextureSamplers(); ++i) {
fixedDynamicState->fPrimitiveProcessorTextures[i]->addPendingRead();
}
@ -136,7 +115,8 @@ void GrOpFlushState::draw(sk_sp<const GrGeometryProcessor> gp, const GrPipeline*
draw.fPipeline = pipeline;
draw.fFixedDynamicState = fixedDynamicState;
draw.fDynamicStateArrays = nullptr;
draw.fMeshCnt = 1;
draw.fMeshes = meshes;
draw.fMeshCnt = meshCnt;
draw.fOpID = fOpArgs->fOp->uniqueID();
if (firstDraw) {
fBaseDrawToken = token;

View File

@ -73,9 +73,11 @@ public:
GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&&) final;
/** Overrides of GrMeshDrawOp::Target. */
void draw(sk_sp<const GrGeometryProcessor>, const GrPipeline*,
const GrPipeline::FixedDynamicState*, const GrMesh&) final;
void draw(sk_sp<const GrGeometryProcessor>,
const GrPipeline*,
const GrPipeline::FixedDynamicState*,
const GrMesh[],
int meshCount) final;
void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**,
int* startVertex) final;
uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) final;
@ -123,12 +125,13 @@ private:
fFixedDynamicState->fPrimitiveProcessorTextures[i]->completedRead();
}
}
int fMeshCnt = 0;
sk_sp<const GrGeometryProcessor> fGeometryProcessor;
const GrPipeline* fPipeline;
const GrPipeline* fPipeline = nullptr;
const GrPipeline::FixedDynamicState* fFixedDynamicState;
const GrPipeline::DynamicStateArrays* fDynamicStateArrays;
uint32_t fOpID;
const GrMesh* fMeshes = nullptr;
int fMeshCnt = 0;
uint32_t fOpID = SK_InvalidUniqueID;
};
// Storage for ops' pipelines, draws, and inline uploads.
@ -142,9 +145,6 @@ private:
SkArenaAllocList<GrDeferredTextureUploadFn> fASAPUploads;
SkArenaAllocList<InlineUpload> fInlineUploads;
SkArenaAllocList<Draw> fDraws;
// TODO: These should go in the arena. However, GrGpuCommandBuffer and other classes currently
// accept contiguous arrays of meshes.
SkSTArray<16, GrMesh> fMeshes;
// All draws we store have an implicit draw token. This is the draw token for the first draw
// in fDraws.
@ -161,7 +161,6 @@ private:
// Variables that are used to track where we are in lists as ops are executed
SkArenaAllocList<Draw>::Iter fCurrDraw;
int fCurrMesh;
SkArenaAllocList<InlineUpload>::Iter fCurrUpload;
// Used to track the proxies that need to be uninstantiated after we finish a flush

View File

@ -843,10 +843,10 @@ private:
extract_lines_only_verts(tess, verts, vertexStride, args.fColor, idxs,
fHelper.compatibleWithAlphaAsCoverage());
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexed(indexBuffer, tess.numIndices(), firstIndex, 0, tess.numPts() - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, tess.numIndices(), firstIndex, 0, tess.numPts() - 1,
GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
}
@ -928,17 +928,18 @@ private:
SkSTArray<kPreallocDrawCnt, Draw, true> draws;
create_vertices(segments, fanPt, args.fColor, &draws, verts, idxs);
GrMesh mesh(GrPrimitiveType::kTriangles);
GrMesh* meshes = target->allocMeshes(draws.count());
for (int j = 0; j < draws.count(); ++j) {
const Draw& draw = draws[j];
mesh.setIndexed(indexBuffer, draw.fIndexCnt, firstIndex, 0, draw.fVertexCnt - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
target->draw(quadProcessor, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
meshes[j].setPrimitiveType(GrPrimitiveType::kTriangles);
meshes[j].setIndexed(indexBuffer, draw.fIndexCnt, firstIndex, 0,
draw.fVertexCnt - 1, GrPrimitiveRestart::kNo);
meshes[j].setVertexData(vertexBuffer, firstVertex);
firstIndex += draw.fIndexCnt;
firstVertex += draw.fVertexCnt;
}
target->draw(quadProcessor, pipe.fPipeline, pipe.fFixedDynamicState, meshes,
draws.count());
}
}

View File

@ -265,10 +265,9 @@ private:
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
sk_sp<const GrBuffer> indexBuffer = get_index_buffer(target->resourceProvider());
PatternHelper helper(GrPrimitiveType::kTriangles);
void* vertices =
helper.init(target, vertexStride, indexBuffer.get(), kVertsPerAAFillRect,
kIndicesPerAAFillRect, fRectCnt);
PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
kVertsPerAAFillRect, kIndicesPerAAFillRect, fRectCnt);
void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -975,10 +975,10 @@ void AAHairlineOp::onPrepareDraws(Target* target) {
add_line(&lines[2*i], toSrc, this->coverage(), &verts);
}
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg, kLineSegNumVertices,
lineCount, kLineSegsNumInIdxBuffer);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexedPatterned(linesIndexBuffer.get(), kIdxsPerLineSeg, kLineSegNumVertices,
lineCount, kLineSegsNumInIdxBuffer);
mesh->setVertexData(vertexBuffer, firstVertex);
target->draw(std::move(lineGP), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
@ -1030,19 +1030,19 @@ void AAHairlineOp::onPrepareDraws(Target* target) {
}
if (quadCount > 0) {
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
quadCount, kQuadsNumInIdxBuffer);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
quadCount, kQuadsNumInIdxBuffer);
mesh->setVertexData(vertexBuffer, firstVertex);
target->draw(std::move(quadGP), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
firstVertex += quadCount * kQuadNumVertices;
}
if (conicCount > 0) {
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
conicCount, kQuadsNumInIdxBuffer);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexedPatterned(quadsIndexBuffer.get(), kIdxsPerQuad, kQuadNumVertices,
conicCount, kQuadsNumInIdxBuffer);
mesh->setVertexData(vertexBuffer, firstVertex);
target->draw(std::move(conicGP), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
}

View File

@ -217,7 +217,6 @@ private:
return;
}
const GrBuffer* vertexBuffer;
GrMesh mesh(GrPrimitiveType::kTriangles);
int firstVertex;
void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer,
&firstVertex);
@ -235,9 +234,10 @@ private:
return;
}
memcpy(idxs, indices, indexCount * sizeof(uint16_t));
mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1,
GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
target->draw(std::move(gp), pipeline, fixedDynamicState, mesh);
}

View File

@ -282,11 +282,11 @@ void AAStrokeRectOp::onPrepareDraws(Target* target) {
int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt;
int instanceCount = fRects.count();
sk_sp<const GrBuffer> indexBuffer = GetIndexBuffer(target->resourceProvider(), this->miterStroke());
PatternHelper helper(GrPrimitiveType::kTriangles);
void* vertices =
helper.init(target, vertexStride, indexBuffer.get(),
verticesPerInstance, indicesPerInstance, instanceCount);
sk_sp<const GrBuffer> indexBuffer =
GetIndexBuffer(target->resourceProvider(), this->miterStroke());
PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
verticesPerInstance, indicesPerInstance, instanceCount);
void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -425,12 +425,12 @@ void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) co
samplerState);
}
}
GrMesh mesh(GrPrimitiveType::kTriangles);
int maxGlyphsPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph,
flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
mesh.setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph,
flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
mesh->setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
target->draw(flushInfo->fGeometryProcessor, flushInfo->fPipeline, flushInfo->fFixedDynamicState,
mesh);
flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;

View File

@ -625,7 +625,6 @@ private:
return;
}
QuadHelper helper;
size_t vertexStride;
if (fullDash) {
vertexStride =
@ -634,7 +633,8 @@ private:
vertexStride = sizeof(SkPoint);
}
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
void* vertices = helper.init(target, vertexStride, totalRectCount);
QuadHelper helper(target, vertexStride, totalRectCount);
void* vertices = helper.vertices();
if (!vertices) {
return;
}

View File

@ -67,7 +67,7 @@ public:
PathGeoBuilder(GrPrimitiveType primitiveType, GrMeshDrawOp::Target* target,
sk_sp<const GrGeometryProcessor> geometryProcessor, const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState)
: fMesh(primitiveType)
: fPrimitiveType(primitiveType)
, fTarget(target)
, fVertexStride(sizeof(SkPoint))
, fGeometryProcessor(std::move(geometryProcessor))
@ -200,15 +200,15 @@ private:
* TODO: Cache some of these for better performance, rather than re-computing?
*/
bool isIndexed() const {
return GrPrimitiveType::kLines == fMesh.primitiveType() ||
GrPrimitiveType::kTriangles == fMesh.primitiveType();
return GrPrimitiveType::kLines == fPrimitiveType ||
GrPrimitiveType::kTriangles == fPrimitiveType;
}
bool isHairline() const {
return GrPrimitiveType::kLines == fMesh.primitiveType() ||
GrPrimitiveType::kLineStrip == fMesh.primitiveType();
return GrPrimitiveType::kLines == fPrimitiveType ||
GrPrimitiveType::kLineStrip == fPrimitiveType;
}
int indexScale() const {
switch (fMesh.primitiveType()) {
switch (fPrimitiveType) {
case GrPrimitiveType::kLines:
return 2;
case GrPrimitiveType::kTriangles:
@ -271,14 +271,15 @@ private:
SkASSERT(indexCount <= fIndicesInChunk);
if (this->isIndexed() ? SkToBool(indexCount) : SkToBool(vertexCount)) {
GrMesh* mesh = fTarget->allocMesh(fPrimitiveType);
if (!this->isIndexed()) {
fMesh.setNonIndexedNonInstanced(vertexCount);
mesh->setNonIndexedNonInstanced(vertexCount);
} else {
fMesh.setIndexed(fIndexBuffer, indexCount, fFirstIndex, 0, vertexCount - 1,
mesh->setIndexed(fIndexBuffer, indexCount, fFirstIndex, 0, vertexCount - 1,
GrPrimitiveRestart::kNo);
}
fMesh.setVertexData(fVertexBuffer, fFirstVertex);
fTarget->draw(fGeometryProcessor, fPipeline, fFixedDynamicState, fMesh);
mesh->setVertexData(fVertexBuffer, fFirstVertex);
fTarget->draw(fGeometryProcessor, fPipeline, fFixedDynamicState, mesh);
}
fTarget->putBackIndices((size_t)(fIndicesInChunk - indexCount));
@ -311,7 +312,7 @@ private:
}
}
GrMesh fMesh;
GrPrimitiveType fPrimitiveType;
GrMeshDrawOp::Target* fTarget;
size_t fVertexStride;
sk_sp<const GrGeometryProcessor> fGeometryProcessor;

View File

@ -130,9 +130,9 @@ void GrDrawAtlasOp::onPrepareDraws(Target* target) {
sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0);
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
QuadHelper helper;
int numQuads = this->quadCount();
void* verts = helper.init(target, vertexStride, numQuads);
QuadHelper helper(target, vertexStride, numQuads);
void* verts = helper.vertices();
if (!verts) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -470,15 +470,14 @@ void GrDrawVerticesOp::drawVertices(Target* target,
int firstVertex,
const GrBuffer* indexBuffer,
int firstIndex) {
GrMesh mesh(this->primitiveType());
GrMesh* mesh = target->allocMesh(this->primitiveType());
if (this->isIndexed()) {
mesh.setIndexed(indexBuffer, fIndexCount,
firstIndex, 0, fVertexCount - 1,
GrPrimitiveRestart::kNo);
mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1,
GrPrimitiveRestart::kNo);
} else {
mesh.setNonIndexedNonInstanced(fVertexCount);
mesh->setNonIndexedNonInstanced(fVertexCount);
}
mesh.setVertexData(vertexBuffer, firstVertex);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}

View File

@ -223,9 +223,9 @@ private:
}
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
PatternHelper helper(GrPrimitiveType::kTriangles);
void* vertices = helper.init(target, kVertexStide, indexBuffer.get(), kVertsPerRect,
kIndicesPerRect, numRects);
PatternHelper helper(target, GrPrimitiveType::kTriangles, kVertexStide, indexBuffer.get(),
kVertsPerRect, kIndicesPerRect, numRects);
void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -14,50 +14,61 @@ GrMeshDrawOp::GrMeshDrawOp(uint32_t classID) : INHERITED(classID) {}
void GrMeshDrawOp::onPrepare(GrOpFlushState* state) { this->onPrepareDraws(state); }
void* GrMeshDrawOp::PatternHelper::init(Target* target, size_t vertexStride,
const GrBuffer* indexBuffer, int verticesPerRepetition,
int indicesPerRepetition, int repeatCount) {
void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
state->executeDrawsAndUploadsForMeshDrawOp(this->uniqueID(), this->bounds());
}
//////////////////////////////////////////////////////////////////////////////
GrMeshDrawOp::PatternHelper::PatternHelper(Target* target, GrPrimitiveType primitiveType,
size_t vertexStride, const GrBuffer* indexBuffer,
int verticesPerRepetition, int indicesPerRepetition,
int repeatCount) {
this->init(target, primitiveType, vertexStride, indexBuffer, verticesPerRepetition,
indicesPerRepetition, repeatCount);
}
void GrMeshDrawOp::PatternHelper::init(Target* target, GrPrimitiveType primitiveType,
size_t vertexStride, const GrBuffer* indexBuffer,
int verticesPerRepetition, int indicesPerRepetition,
int repeatCount) {
SkASSERT(target);
if (!indexBuffer) {
return nullptr;
return;
}
const GrBuffer* vertexBuffer;
int firstVertex;
int vertexCount = verticesPerRepetition * repeatCount;
void* vertices =
target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
if (!vertices) {
SkDebugf("Vertices could not be allocated for instanced rendering.");
return nullptr;
fVertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
if (!fVertices) {
SkDebugf("Vertices could not be allocated for patterned rendering.");
return;
}
SkASSERT(vertexBuffer);
size_t ibSize = indexBuffer->gpuMemorySize();
int maxRepetitions = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerRepetition));
fMesh.setIndexedPatterned(indexBuffer, indicesPerRepetition, verticesPerRepetition,
repeatCount, maxRepetitions);
fMesh.setVertexData(vertexBuffer, firstVertex);
return vertices;
fMesh = target->allocMesh(primitiveType);
fMesh->setIndexedPatterned(indexBuffer, indicesPerRepetition, verticesPerRepetition,
repeatCount, maxRepetitions);
fMesh->setVertexData(vertexBuffer, firstVertex);
}
void GrMeshDrawOp::PatternHelper::recordDraw(
Target* target, sk_sp<const GrGeometryProcessor> gp, const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState) {
const GrPipeline::FixedDynamicState* fixedDynamicState) const {
target->draw(std::move(gp), pipeline, fixedDynamicState, fMesh);
}
void* GrMeshDrawOp::QuadHelper::init(Target* target, size_t vertexStride, int quadsToDraw) {
//////////////////////////////////////////////////////////////////////////////
GrMeshDrawOp::QuadHelper::QuadHelper(Target* target, size_t vertexStride, int quadsToDraw) {
sk_sp<const GrBuffer> quadIndexBuffer = target->resourceProvider()->refQuadIndexBuffer();
if (!quadIndexBuffer) {
SkDebugf("Could not get quad index buffer.");
return nullptr;
return;
}
return this->INHERITED::init(target, vertexStride, quadIndexBuffer.get(), kVerticesPerQuad,
kIndicesPerQuad, quadsToDraw);
}
void GrMeshDrawOp::onExecute(GrOpFlushState* state) {
state->executeDrawsAndUploadsForMeshDrawOp(this->uniqueID(), this->bounds());
this->init(target, GrPrimitiveType::kTriangles, vertexStride, quadIndexBuffer.get(),
kVerticesPerQuad, kIndicesPerQuad, quadsToDraw);
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -33,18 +33,23 @@ protected:
space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
class PatternHelper {
public:
PatternHelper(GrPrimitiveType primitiveType) : fMesh(primitiveType) {}
/** Returns the allocated storage for the vertices. The caller should populate the vertices
before calling recordDraws(). */
void* init(Target*, size_t vertexStride, const GrBuffer*, int verticesPerRepetition,
int indicesPerRepetition, int repeatCount);
PatternHelper(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
int verticesPerRepetition, int indicesPerRepetition, int repeatCount);
/** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
/** Called to issue draws to the GrMeshDrawOp::Target.*/
void recordDraw(Target*, sk_sp<const GrGeometryProcessor>, const GrPipeline*,
const GrPipeline::FixedDynamicState*);
const GrPipeline::FixedDynamicState*) const;
void* vertices() const { return fVertices; }
protected:
PatternHelper() = default;
void init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
int verticesPerRepetition, int indicesPerRepetition, int repeatCount);
private:
GrMesh fMesh;
void* fVertices = nullptr;
GrMesh* fMesh = nullptr;
};
static const int kVerticesPerQuad = 4;
@ -53,13 +58,11 @@ protected:
/** A specialization of InstanceHelper for quad rendering. */
class QuadHelper : private PatternHelper {
public:
QuadHelper() : INHERITED(GrPrimitiveType::kTriangles) {}
/** 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(). */
void* init(Target*, size_t vertexStride, int quadsToDraw);
QuadHelper() = delete;
QuadHelper(Target* target, size_t vertexStride, int quadsToDraw);
using PatternHelper::recordDraw;
using PatternHelper::vertices;
private:
typedef PatternHelper INHERITED;
@ -77,8 +80,19 @@ public:
virtual ~Target() {}
/** Adds a draw of a mesh. */
virtual void draw(sk_sp<const GrGeometryProcessor>, const GrPipeline*,
const GrPipeline::FixedDynamicState*, const GrMesh&) = 0;
virtual void draw(sk_sp<const GrGeometryProcessor>,
const GrPipeline*,
const GrPipeline::FixedDynamicState*,
const GrMesh[],
int meshCount) = 0;
/** Helper for drawing a single GrMesh. */
void draw(sk_sp<const GrGeometryProcessor> gp,
const GrPipeline* pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState,
const GrMesh* mesh) {
this->draw(std::move(gp), pipeline, fixedDynamicState, mesh, 1);
}
/**
* Makes space for vertex data. The returned pointer is the location where vertex data
@ -131,6 +145,12 @@ public:
return this->pipelineArena()->make<GrPipeline>(std::forward<Args>(args)...);
}
GrMesh* allocMesh(GrPrimitiveType primitiveType) {
return this->pipelineArena()->make<GrMesh>(primitiveType);
}
GrMesh* allocMeshes(int n) { return this->pipelineArena()->makeArray<GrMesh>(n); }
GrPipeline::FixedDynamicState* allocFixedDynamicState(const SkIRect& rect,
int numPrimitiveProcessorTextures = 0) {
auto result = this->pipelineArena()->make<GrPipeline::FixedDynamicState>(rect);

View File

@ -192,9 +192,9 @@ private:
int rectCount = fRects.count();
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
PatternHelper helper(GrPrimitiveType::kTriangles);
void* vertices = helper.init(target, kVertexStride, indexBuffer.get(), kVertsPerRect,
kIndicesPerRect, rectCount);
PatternHelper helper(target, GrPrimitiveType::kTriangles, kVertexStride, indexBuffer.get(),
kVertsPerRect, kIndicesPerRect, rectCount);
void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@ -325,9 +325,9 @@ private:
int rectCount = fRects.count();
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
PatternHelper helper(GrPrimitiveType::kTriangles);
void* vertices = helper.init(target, vertexStride, indexBuffer.get(), kVertsPerRect,
kIndicesPerRect, rectCount);
PatternHelper helper(target, GrPrimitiveType::kTriangles, vertexStride, indexBuffer.get(),
kVertsPerRect, kIndicesPerRect, rectCount);
void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -188,9 +188,9 @@ private:
vertex[4].set(fRect.fLeft, fRect.fTop);
}
GrMesh mesh(primType);
mesh.setNonIndexedNonInstanced(vertexCount);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(primType);
mesh->setNonIndexedNonInstanced(vertexCount);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}

View File

@ -1470,10 +1470,10 @@ private:
vertices += circle_type_to_vert_count(circle.fStroked) * vertexStride;
}
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
@ -1786,10 +1786,10 @@ private:
vertices += circle_type_to_vert_count(true) * kVertexStride;
}
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
@ -1984,10 +1984,9 @@ private:
// Setup geometry processor
sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix));
QuadHelper helper;
SkASSERT(sizeof(EllipseVertex) == gp->debugOnly_vertexStride());
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
helper.init(target, sizeof(EllipseVertex), fEllipses.count()));
QuadHelper helper(target, sizeof(EllipseVertex), fEllipses.count());
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(helper.vertices());
if (!verts) {
return;
}
@ -2219,9 +2218,8 @@ private:
new DIEllipseGeometryProcessor(this->viewMatrix(), this->style()));
SkASSERT(sizeof(DIEllipseVertex) == gp->debugOnly_vertexStride());
QuadHelper helper;
DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(
helper.init(target, sizeof(DIEllipseVertex), fEllipses.count()));
QuadHelper helper(target, sizeof(DIEllipseVertex), fEllipses.count());
DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(helper.vertices());
if (!verts) {
return;
}
@ -2725,10 +2723,10 @@ private:
currStartVertex += rrect_type_to_vert_count(rrect.fType);
}
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}
@ -2927,10 +2925,10 @@ private:
sk_sp<const GrBuffer> indexBuffer = get_rrect_index_buffer(
fStroked ? kStroke_RRectType : kFill_RRectType, target->resourceProvider());
PatternHelper helper(GrPrimitiveType::kTriangles);
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
helper.init(target, sizeof(EllipseVertex), indexBuffer.get(),
kVertsPerStandardRRect, indicesPerInstance, fRRects.count()));
PatternHelper helper(target, GrPrimitiveType::kTriangles, sizeof(EllipseVertex),
indexBuffer.get(), kVertsPerStandardRRect, indicesPerInstance,
fRRects.count());
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(helper.vertices());
if (!verts || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -129,9 +129,9 @@ private:
return;
}
sk_sp<const GrBuffer> indexBuffer = target->resourceProvider()->refQuadIndexBuffer();
PatternHelper helper(GrPrimitiveType::kTriangles);
void* vertices = helper.init(target, kVertexStride, indexBuffer.get(), kVertsPerInstance,
kIndicesPerInstance, numRects);
PatternHelper helper(target, GrPrimitiveType::kTriangles, kVertexStride, indexBuffer.get(),
kVertsPerInstance, kIndicesPerInstance, numRects);
void* vertices = helper.vertices();
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;

View File

@ -627,10 +627,10 @@ private:
auto pipe = target->makePipeline(kPipelineFlags, GrProcessorSet::MakeEmptySet(),
target->detachAppliedClip());
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertCount - 1,
GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}

View File

@ -833,13 +833,13 @@ private:
}
if (flushInfo->fInstancesToFlush) {
GrMesh mesh(GrPrimitiveType::kTriangles);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
int maxInstancesPerDraw =
static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
mesh.setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerQuad,
kVerticesPerQuad, flushInfo->fInstancesToFlush,
maxInstancesPerDraw);
mesh.setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
mesh->setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerQuad,
kVerticesPerQuad, flushInfo->fInstancesToFlush,
maxInstancesPerDraw);
mesh->setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset);
target->draw(flushInfo->fGeometryProcessor, flushInfo->fPipeline,
flushInfo->fFixedDynamicState, mesh);
flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush;

View File

@ -358,9 +358,10 @@ private:
void drawVertices(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrBuffer* vb,
int firstVertex, int count) {
GrMesh mesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines : GrPrimitiveType::kTriangles);
mesh.setNonIndexedNonInstanced(count);
mesh.setVertexData(vb, firstVertex);
GrMesh* mesh = target->allocMesh(TESSELLATOR_WIREFRAME ? GrPrimitiveType::kLines
: GrPrimitiveType::kTriangles);
mesh->setNonIndexedNonInstanced(count);
mesh->setVertexData(vb, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
}

View File

@ -858,19 +858,19 @@ __attribute__((no_sanitize("float-cast-overflow")))
GrPrimitiveType primitiveType =
fDraws.count() > 1 ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleStrip;
GrMesh mesh(primitiveType);
GrMesh* mesh = target->allocMesh(primitiveType);
if (fDraws.count() > 1) {
sk_sp<const GrBuffer> ibuffer = target->resourceProvider()->refQuadIndexBuffer();
if (!ibuffer) {
SkDebugf("Could not allocate quad indices\n");
return;
}
mesh.setIndexedPatterned(ibuffer.get(), 6, 4, fDraws.count(),
GrResourceProvider::QuadCountOfQuadBuffer());
mesh->setIndexedPatterned(ibuffer.get(), 6, 4, fDraws.count(),
GrResourceProvider::QuadCountOfQuadBuffer());
} else {
mesh.setNonIndexedNonInstanced(4);
mesh->setNonIndexedNonInstanced(4);
}
mesh.setVertexData(vbuffer, vstart);
mesh->setVertexData(vbuffer, vstart);
target->draw(std::move(gp), pipeline, fixedDynamicState, mesh);
}

View File

@ -159,9 +159,9 @@ private:
}
}
GrMesh mesh(GrPrimitiveType::kTriangles);
mesh.setIndexed(indexBuffer, 6, firstIndex, 0, 3, GrPrimitiveRestart::kNo);
mesh.setVertexData(vertexBuffer, firstVertex);
GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles);
mesh->setIndexed(indexBuffer, 6, firstIndex, 0, 3, GrPrimitiveRestart::kNo);
mesh->setVertexData(vertexBuffer, firstVertex);
auto pipe = fHelper.makePipeline(target);
target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh);

View File

@ -105,10 +105,10 @@ private:
typedef GrGeometryProcessor INHERITED;
};
sk_sp<GrGeometryProcessor> gp(new GP(fNumAttribs));
QuadHelper helper;
size_t vertexStride = fNumAttribs * GrVertexAttribTypeSize(kFloat2_GrVertexAttribType);
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
QuadHelper helper(target, vertexStride, 1);
SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.vertices());
SkPointPriv::SetRectTriStrip(vertices, 0.f, 0.f, 1.f, 1.f, vertexStride);
auto pipe = target->makePipeline(0, GrProcessorSet::MakeEmptySet(),
target->detachAppliedClip());