void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) { GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrDrawState& drawState = this->getDrawState(); AutoClipReenable acr; if (drawState.isClipState() && info.getDevBounds() && this->quickInsideClip(*info.getDevBounds())) { acr.set(this->drawState()); } this->recordClipIfNecessary(); this->recordStateIfNecessary(); const GrVertexBuffer* vb; if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) { vb = this->getGeomSrc().fVertexBuffer; } else { vb = poolState.fPoolVertexBuffer; } const GrIndexBuffer* ib = NULL; if (info.isIndexed()) { if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) { ib = this->getGeomSrc().fIndexBuffer; } else { ib = poolState.fPoolIndexBuffer; } } Draw* draw; if (info.isInstanced()) { int instancesConcated = this->concatInstancedDraw(info); if (info.instanceCount() > instancesConcated) { draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib)); draw->fInfo.adjustInstanceCount(-instancesConcated); } else { return; } } else { draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib)); } this->recordTraceMarkersIfNecessary(); // Adjust the starting vertex and index when we are using reserved or array sources to // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool. if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) { size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride(); poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes); draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex); } if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) { size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t); poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes); draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex); } }
int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) { GrAssert(info.isInstanced()); const GeometrySrcState& geomSrc = this->getGeomSrc(); const GrDrawState& drawState = this->getDrawState(); // we only attempt to concat the case when reserved verts are used with a client-specified index // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated // between draws. if (kReserved_GeometrySrcType != geomSrc.fVertexSrc || kBuffer_GeometrySrcType != geomSrc.fIndexSrc) { return 0; } // Check if there is a draw info that is compatible that uses the same VB from the pool and // the same IB if (kDraw_Cmd != fCmds.back()) { return 0; } DrawRecord* draw = &fDraws.back(); GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer; if (!draw->isInstanced() || draw->verticesPerInstance() != info.verticesPerInstance() || draw->indicesPerInstance() != info.indicesPerInstance() || draw->fVertexBuffer != vertexBuffer || draw->fIndexBuffer != geomSrc.fIndexBuffer) { return 0; } // info does not yet account for the offset from the start of the pool's VB while the previous // draw record does. int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex(); if (draw->startVertex() + draw->vertexCount() != adjustedStartVertex) { return 0; } GrAssert(poolState.fPoolStartVertex == draw->startVertex() + draw->vertexCount()); // how many instances can be concat'ed onto draw given the size of the index buffer int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance(); instancesToConcat -= draw->instanceCount(); instancesToConcat = GrMin(instancesToConcat, info.instanceCount()); // update the amount of reserved vertex data actually referenced in draws size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * drawState.getVertexSize(); poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw->adjustInstanceCount(instancesToConcat); return instancesToConcat; }
void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) { GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrDrawState& drawState = this->getDrawState(); AutoClipReenable acr; if (drawState.isClipState() && NULL != info.getDevBounds() && this->quickInsideClip(*info.getDevBounds())) { acr.set(this->drawState()); } if (this->needsNewClip()) { this->recordClip(); } if (this->needsNewState()) { this->recordState(); } DrawRecord* draw; if (info.isInstanced()) { int instancesConcated = this->concatInstancedDraw(info); if (info.instanceCount() > instancesConcated) { draw = this->recordDraw(info); draw->adjustInstanceCount(-instancesConcated); } else { return; } } else { draw = this->recordDraw(info); } switch (this->getGeomSrc().fVertexSrc) { case kBuffer_GeometrySrcType: draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer; break; case kReserved_GeometrySrcType: // fallthrough case kArray_GeometrySrcType: { size_t vertexBytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexSize(); poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw->fVertexBuffer = poolState.fPoolVertexBuffer; draw->adjustStartVertex(poolState.fPoolStartVertex); break; } default: GrCrash("unknown geom src type"); } draw->fVertexBuffer->ref(); if (info.isIndexed()) { switch (this->getGeomSrc().fIndexSrc) { case kBuffer_GeometrySrcType: draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer; break; case kReserved_GeometrySrcType: // fallthrough case kArray_GeometrySrcType: { size_t indexBytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t); poolState.fUsedPoolIndexBytes = GrMax(poolState.fUsedPoolIndexBytes, indexBytes); draw->fIndexBuffer = poolState.fPoolIndexBuffer; draw->adjustStartIndex(poolState.fPoolStartIndex); break; } default: GrCrash("unknown geom src type"); } draw->fIndexBuffer->ref(); } else { draw->fIndexBuffer = NULL; } }
int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) { SkASSERT(!fCmdBuffer.empty()); SkASSERT(info.isInstanced()); const GeometrySrcState& geomSrc = this->getGeomSrc(); const GrDrawState& drawState = this->getDrawState(); // we only attempt to concat the case when reserved verts are used with a client-specified index // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated // between draws. if (kReserved_GeometrySrcType != geomSrc.fVertexSrc || kBuffer_GeometrySrcType != geomSrc.fIndexSrc) { return 0; } // Check if there is a draw info that is compatible that uses the same VB from the pool and // the same IB if (kDraw_Cmd != strip_trace_bit(fCmdBuffer.back().fType)) { return 0; } Draw* draw = static_cast<Draw*>(&fCmdBuffer.back()); GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer; if (!draw->fInfo.isInstanced() || draw->fInfo.verticesPerInstance() != info.verticesPerInstance() || draw->fInfo.indicesPerInstance() != info.indicesPerInstance() || draw->vertexBuffer() != vertexBuffer || draw->indexBuffer() != geomSrc.fIndexBuffer) { return 0; } // info does not yet account for the offset from the start of the pool's VB while the previous // draw record does. int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex(); if (draw->fInfo.startVertex() + draw->fInfo.vertexCount() != adjustedStartVertex) { return 0; } SkASSERT(poolState.fPoolStartVertex == draw->fInfo.startVertex() + draw->fInfo.vertexCount()); // how many instances can be concat'ed onto draw given the size of the index buffer int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance(); instancesToConcat -= draw->fInfo.instanceCount(); instancesToConcat = SkTMin(instancesToConcat, info.instanceCount()); // update the amount of reserved vertex data actually referenced in draws size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * drawState.getVertexStride(); poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw->fInfo.adjustInstanceCount(instancesToConcat); // update last fGpuCmdMarkers to include any additional trace markers that have been added if (this->getActiveTraceMarkers().count() > 0) { if (cmd_has_trace_marker(draw->fType)) { fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers()); } else { fGpuCmdMarkers.push_back(this->getActiveTraceMarkers()); draw->fType = add_trace_bit(draw->fType); } } return instancesToConcat; }