Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Unified Diff: src/gpu/GrTargetCommands.cpp

Issue 1073943004: Join non-overlapping Xfer barriers (Closed) Base URL: https://skia.googlesource.com/skia.git@upload_4_implementxferbarriers
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrTargetCommands.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrTargetCommands.cpp
diff --git a/src/gpu/GrTargetCommands.cpp b/src/gpu/GrTargetCommands.cpp
index a2b2d6e7beb28d81bb2311b61d7691f43fc120e6..1e119fe59c2ae8dd9a51fdb71462dcca67f76d4d 100644
--- a/src/gpu/GrTargetCommands.cpp
+++ b/src/gpu/GrTargetCommands.cpp
@@ -191,30 +191,38 @@ GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
transformValues, transformType,
count, &savedIndices, &savedTransforms);
- if (Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) {
- // The previous command was also DrawPaths. Try to collapse this call into the one
- // before. Note that stenciling all the paths at once, then covering, may not be
- // equivalent to two separate draw calls if there is overlap. Blending won't work,
- // and the combined calls may also cancel each other's winding numbers in some
- // places. For now the winding numbers are only an issue if the fill is even/odd,
- // because DrawPaths is currently only used for glyphs, and glyphs in the same
- // font tend to all wind in the same direction.
- DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
+ CmdBuffer::ReverseIter reverseIter(fCmdBuffer);
+ if (Cmd::kXferBarrier_CmdType == reverseIter->type()) {
+ // We can combine instanced path commands through Xfer barriers because they are implemented
+ // by a single (non-overlapping) cover operation and they use fullscreen barriers.
+ reverseIter.previous();
+ }
+
+ if (Cmd::kDrawPaths_CmdType == reverseIter->type()) {
+ // The previous command was also DrawPaths. Try to combine this call with the one before.
+ // Note that when there is overlap, this is not equivalent to two separate draw calls. We
+ // don't worry about that case because instanced path commands are only used for text.
+ DrawPaths* previous = static_cast<DrawPaths*>(reverseIter.get());
if (pathRange == previous->pathRange() &&
indexType == previous->fIndexType &&
transformType == previous->fTransformType &&
stencilSettings == previous->fStencilSettings &&
- path_fill_type_is_winding(stencilSettings) &&
- !pipelineInfo.willBlendWithDst(pathProc)) {
- const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
- const int xformSize = GrPathRendering::PathTransformSize(transformType);
- if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
- (0 == xformSize ||
- &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
- // Fold this DrawPaths call into the one previous.
- previous->fCount += count;
- return NULL;
+ path_fill_type_is_winding(stencilSettings)) {
+ const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
+ const int xformSize = GrPathRendering::PathTransformSize(transformType);
+ if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
+ (0 == xformSize ||
+ &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
+ // Fold this DrawPaths call into the one previous.
+ previous->fCount += count;
+ if (Cmd::kXferBarrier_CmdType == fCmdBuffer.back().type()) {
+ // Drop the barrier we fell through.
+ fCmdBuffer.pop_back();
+ SkASSERT(!fXferBarrier); // The Xfer barrier should have been fullscreen.
}
+ SkASSERT(previous == &fCmdBuffer.back());
+ return NULL;
+ }
}
}
@@ -279,6 +287,7 @@ void GrTargetCommands::reset() {
fCmdBuffer.reset();
fPrevState = NULL;
fDrawBatch = NULL;
+ fXferBarrier = NULL;
}
void GrTargetCommands::flush(GrInOrderDrawBuffer* iodb) {
@@ -404,12 +413,15 @@ void GrTargetCommands::CopySurface::execute(GrGpu* gpu, const SetState*) {
void GrTargetCommands::XferBarrier::execute(GrGpu* gpu, const SetState* state) {
SkASSERT(state);
+ SkASSERT(fRenderTarget == state->getRenderTarget());
if (kDstCopy_GrXferBarrierType == fType) {
GrDeviceCoordTexture dstCopy;
- gpu->setXferBarrier(fType, state->getRenderTarget(), fBounds, &dstCopy);
- state->getXferProcessor()->updateDstCopy(dstCopy);
+ gpu->setXferBarrier(fType, fRenderTarget, fReadBounds, &dstCopy);
+ for (int i = 0; i < fXferProcessors.count(); i++) {
+ fXferProcessors[i]->updateDstCopy(dstCopy);
+ }
} else {
- SkAssertResult(gpu->setXferBarrier(fType, state->getRenderTarget(), fBounds));
+ SkAssertResult(gpu->setXferBarrier(fType, fRenderTarget, fReadBounds));
}
}
@@ -487,25 +499,50 @@ bool GrTargetCommands::recordXferBarrierIfNecessary(GrInOrderDrawBuffer* iodb,
const GrDrawTarget::PipelineInfo& info) {
SkASSERT(fPrevState);
const GrXferProcessor& xp = *fPrevState->getXferProcessor();
+ GrRenderTarget* rt = fPrevState->getRenderTarget();
GrXferBarrierType xbType = xp.setupDstReadIfNecessary(*iodb->caps(), info.getCustomDstCopy());
if (kNone_GrXferBarrierType == xbType) {
- return true;
- }
+ // The XP doesn't need a barrier, but the draw may still affect one.
+ if (!fXferBarrier || rt != fXferBarrier->fRenderTarget) {
+ return true;
+ }
+ SkIRect drawBounds;
+ info.getQuickDrawBounds(&drawBounds);
+ fXferBarrier->fInvalidBounds.join(drawBounds);
+ } else {
+ SkIRect xferBounds;
+ if (!info.getConservativeDrawBounds(&xferBounds)) {
+ // Early reject was detected.
+ return false;
+ }
- SkIRect xferBounds;
- if (!info.getConservativeDrawBounds(&xferBounds)) {
- // Early reject was detected.
- return false;
- }
+ if (fXferBarrier && xbType == fXferBarrier->fType && rt == fXferBarrier->fRenderTarget &&
+ !SkIRect::IntersectsNoEmptyCheck(xferBounds, fXferBarrier->fInvalidBounds)) {
+ // We can join with the previous barrier since they match and there is no overlap.
+ fXferBarrier->fReadBounds.join(xferBounds);
+ fXferBarrier->fInvalidBounds.join(xferBounds);
+ if (fXferBarrier->fXferProcessors.back() != &xp) {
+ fXferBarrier->fXferProcessors.push_back(&xp);
+ }
+ } else {
+ // We need to set a new barrier for this draw.
+ this->closeBatch();
- this->closeBatch();
+ fXferBarrier = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, (xbType, rt));
+ fXferBarrier->fReadBounds = xferBounds;
+ fXferBarrier->fInvalidBounds = xferBounds;
+ fXferBarrier->fXferProcessors.push_back(&xp);
- XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, (xbType));
- xb->fBounds = xferBounds;
+ iodb->recordTraceMarkersIfNecessary(fXferBarrier);
+ }
+ }
- iodb->recordTraceMarkersIfNecessary(xb);
+ if (fXferBarrier->fInvalidBounds.contains(0, 0, rt->width(), rt->height())) {
+ // Close out the barrier since there is no valid area left.
+ fXferBarrier = NULL;
+ }
return true;
}
« no previous file with comments | « src/gpu/GrTargetCommands.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698