Fix up GrAuditTrail to allow arbitrary reordering

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1765123002

Review URL: https://codereview.chromium.org/1765123002
This commit is contained in:
joshualitt 2016-03-08 10:43:41 -08:00 committed by Commit bot
parent d8a4f77211
commit b0666ad3a9
5 changed files with 74 additions and 52 deletions

View File

@ -84,11 +84,9 @@ public:
fCurrentStackTrace.push_back(SkString(framename)); fCurrentStackTrace.push_back(SkString(framename));
} }
void addBatch(const char* name, const SkRect& bounds); void addBatch(const GrBatch* batch);
void batchingResultCombined(GrBatch* combiner); void batchingResultCombined(const GrBatch* consumer, const GrBatch* consumed);
void batchingResultNew(GrBatch* batch);
// Because batching is heavily dependent on sequence of draw calls, these calls will only // Because batching is heavily dependent on sequence of draw calls, these calls will only
// produce valid information for the given draw sequence which preceeded them. // produce valid information for the given draw sequence which preceeded them.
@ -154,9 +152,8 @@ private:
static void JsonifyTArray(SkString* json, const char* name, const T& array, static void JsonifyTArray(SkString* json, const char* name, const T& array,
bool addComma); bool addComma);
Batch* fCurrentBatch;
BatchPool fBatchPool; BatchPool fBatchPool;
SkTHashMap<GrBatch*, int> fIDLookup; SkTHashMap<uint32_t, int> fIDLookup;
SkTHashMap<int, Batches*> fClientIDLookup; SkTHashMap<int, Batches*> fClientIDLookup;
BatchList fBatchList; BatchList fBatchList;
SkTArray<SkString> fCurrentStackTrace; SkTArray<SkString> fCurrentStackTrace;
@ -177,13 +174,13 @@ private:
#define GR_AUDIT_TRAIL_RESET(audit_trail) \ #define GR_AUDIT_TRAIL_RESET(audit_trail) \
//GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset); //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset);
#define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \ #define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batch) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batchname, bounds); GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batch);
#define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combiner) \ #define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combineWith, batch) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combiner); GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combineWith, batch);
#define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \ #define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultNew, batch); // Doesn't do anything now, one day...
#endif #endif

View File

@ -10,23 +10,22 @@
const int GrAuditTrail::kGrAuditTrailInvalidID = -1; const int GrAuditTrail::kGrAuditTrailInvalidID = -1;
void GrAuditTrail::addBatch(const char* name, const SkRect& bounds) { void GrAuditTrail::addBatch(const GrBatch* batch) {
SkASSERT(fEnabled); SkASSERT(fEnabled);
Batch* batch = new Batch; Batch* auditBatch = new Batch;
fBatchPool.emplace_back(batch); fBatchPool.emplace_back(auditBatch);
batch->fName = name; auditBatch->fName = batch->name();
batch->fBounds = bounds; auditBatch->fBounds = batch->bounds();
batch->fClientID = kGrAuditTrailInvalidID; auditBatch->fClientID = kGrAuditTrailInvalidID;
batch->fBatchListID = kGrAuditTrailInvalidID; auditBatch->fBatchListID = kGrAuditTrailInvalidID;
batch->fChildID = kGrAuditTrailInvalidID; auditBatch->fChildID = kGrAuditTrailInvalidID;
// consume the current stack trace if any // consume the current stack trace if any
batch->fStackTrace = fCurrentStackTrace; auditBatch->fStackTrace = fCurrentStackTrace;
fCurrentStackTrace.reset(); fCurrentStackTrace.reset();
fCurrentBatch = batch;
if (fClientID != kGrAuditTrailInvalidID) { if (fClientID != kGrAuditTrailInvalidID) {
batch->fClientID = fClientID; auditBatch->fClientID = fClientID;
Batches** batchesLookup = fClientIDLookup.find(fClientID); Batches** batchesLookup = fClientIDLookup.find(fClientID);
Batches* batches = nullptr; Batches* batches = nullptr;
if (!batchesLookup) { if (!batchesLookup) {
@ -36,44 +35,61 @@ void GrAuditTrail::addBatch(const char* name, const SkRect& bounds) {
batches = *batchesLookup; batches = *batchesLookup;
} }
batches->push_back(fCurrentBatch); batches->push_back(auditBatch);
}
} }
void GrAuditTrail::batchingResultCombined(GrBatch* combiner) {
int* indexPtr = fIDLookup.find(combiner);
SkASSERT(indexPtr);
int index = *indexPtr;
SkASSERT(index < fBatchList.count());
BatchNode& batch = *fBatchList[index];
// set the ids for the child batch
fCurrentBatch->fBatchListID = index;
fCurrentBatch->fChildID = batch.fChildren.count();
// Update the bounds and store a pointer to the new batch
batch.fChildren.push_back(fCurrentBatch);
batch.fBounds = combiner->bounds();
}
void GrAuditTrail::batchingResultNew(GrBatch* batch) {
// Our algorithm doesn't bother to reorder inside of a BatchNode // Our algorithm doesn't bother to reorder inside of a BatchNode
// so the ChildID will start at 0 // so the ChildID will start at 0
fCurrentBatch->fBatchListID = fBatchList.count(); auditBatch->fBatchListID = fBatchList.count();
fCurrentBatch->fChildID = 0; auditBatch->fChildID = 0;
// We use the batch pointer as a key to find the batchnode we are 'glomming' batches onto // We use the batch pointer as a key to find the batchnode we are 'glomming' batches onto
fIDLookup.set(batch, fCurrentBatch->fBatchListID); fIDLookup.set(batch->uniqueID(), auditBatch->fBatchListID);
BatchNode* batchNode = new BatchNode; BatchNode* batchNode = new BatchNode;
batchNode->fBounds = fCurrentBatch->fBounds; batchNode->fBounds = batch->bounds();
batchNode->fRenderTargetUniqueID = batch->renderTargetUniqueID(); batchNode->fRenderTargetUniqueID = batch->renderTargetUniqueID();
batchNode->fChildren.push_back(fCurrentBatch); batchNode->fChildren.push_back(auditBatch);
fBatchList.emplace_back(batchNode); fBatchList.emplace_back(batchNode);
} }
void GrAuditTrail::batchingResultCombined(const GrBatch* consumer, const GrBatch* consumed) {
// Look up the batch we are going to glom onto
int* indexPtr = fIDLookup.find(consumer->uniqueID());
SkASSERT(indexPtr);
int index = *indexPtr;
SkASSERT(index < fBatchList.count() && fBatchList[index]);
BatchNode& consumerBatch = *fBatchList[index];
// Look up the batch which will be glommed
int* consumedPtr = fIDLookup.find(consumed->uniqueID());
SkASSERT(consumedPtr);
int consumedIndex = *consumedPtr;
SkASSERT(consumedIndex < fBatchList.count() && fBatchList[consumedIndex]);
BatchNode& consumedBatch = *fBatchList[consumedIndex];
// steal all of consumed's batches
for (int i = 0; i < consumedBatch.fChildren.count(); i++) {
Batch* childBatch = consumedBatch.fChildren[i];
// set the ids for the child batch
childBatch->fBatchListID = index;
childBatch->fChildID = consumerBatch.fChildren.count();
consumerBatch.fChildren.push_back(childBatch);
}
// Update the bounds for the combineWith node
consumerBatch.fBounds = consumer->bounds();
// remove the old node from our batchlist and clear the combinee's lookup
// NOTE: because we can't change the shape of the batchlist, we use a sentinel
fBatchList[consumedIndex].reset(nullptr);
fIDLookup.remove(consumed->uniqueID());
}
void GrAuditTrail::copyOutFromBatchList(BatchInfo* outBatchInfo, int batchListID) { void GrAuditTrail::copyOutFromBatchList(BatchInfo* outBatchInfo, int batchListID) {
SkASSERT(batchListID < fBatchList.count()); SkASSERT(batchListID < fBatchList.count());
const BatchNode* bn = fBatchList[batchListID]; const BatchNode* bn = fBatchList[batchListID];
SkASSERT(bn);
outBatchInfo->fBounds = bn->fBounds; outBatchInfo->fBounds = bn->fBounds;
outBatchInfo->fRenderTargetUniqueID = bn->fRenderTargetUniqueID; outBatchInfo->fRenderTargetUniqueID = bn->fRenderTargetUniqueID;
for (int j = 0; j < bn->fChildren.count(); j++) { for (int j = 0; j < bn->fChildren.count(); j++) {
@ -132,6 +148,10 @@ void GrAuditTrail::JsonifyTArray(SkString* json, const char* name, const T& arra
} }
json->appendf("\"%s\": [", name); json->appendf("\"%s\": [", name);
for (int i = 0; i < array.count(); i++) { for (int i = 0; i < array.count(); i++) {
// Handle sentinel nullptrs
if (!array[i]) {
continue;
}
json->append(array[i]->toJson()); json->append(array[i]->toJson());
if (i < array.count() - 1) { if (i < array.count() - 1) {
json->append(","); json->append(",");

View File

@ -461,7 +461,7 @@ void GrDrawTarget::recordBatch(GrBatch* batch) {
// 1) check every draw // 1) check every draw
// 2) intersect with something // 2) intersect with something
// 3) find a 'blocker' // 3) find a 'blocker'
GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch->name(), batch->bounds()); GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch);
GrBATCH_INFO("Re-Recording (%s, B%u)\n" GrBATCH_INFO("Re-Recording (%s, B%u)\n"
"\tBounds LRTB (%f, %f, %f, %f)\n", "\tBounds LRTB (%f, %f, %f, %f)\n",
batch->name(), batch->name(),
@ -484,7 +484,7 @@ void GrDrawTarget::recordBatch(GrBatch* batch) {
if (candidate->combineIfPossible(batch, *this->caps())) { if (candidate->combineIfPossible(batch, *this->caps())) {
GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(), GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
candidate->uniqueID()); candidate->uniqueID());
GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate); GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate, batch);
return; return;
} }
// Stop going backwards if we would cause a painter's order violation. // Stop going backwards if we would cause a painter's order violation.
@ -528,7 +528,7 @@ void GrDrawTarget::forwardCombine() {
} else if (batch->combineIfPossible(candidate, *this->caps())) { } else if (batch->combineIfPossible(candidate, *this->caps())) {
GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(), GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
candidate->uniqueID()); candidate->uniqueID());
GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate); GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, candidate);
fBatches[j].reset(SkRef(batch)); fBatches[j].reset(SkRef(batch));
fBatches[i].reset(nullptr); fBatches[i].reset(nullptr);
break; break;

View File

@ -334,6 +334,7 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index, int m) {
if (at) { if (at) {
// just in case there is global reordering, we flush the canvas before querying // just in case there is global reordering, we flush the canvas before querying
// GrAuditTrail // GrAuditTrail
GrAuditTrail::AutoEnable ae(at);
canvas->flush(); canvas->flush();
// we pick three colorblind-safe colors, 75% alpha // we pick three colorblind-safe colors, 75% alpha
@ -347,7 +348,6 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index, int m) {
uint32_t rtID = gbd->accessRenderTarget()->getUniqueID(); uint32_t rtID = gbd->accessRenderTarget()->getUniqueID();
// get the bounding boxes to draw // get the bounding boxes to draw
GrAuditTrail::AutoEnable ae(at);
SkTArray<GrAuditTrail::BatchInfo> childrenBounds; SkTArray<GrAuditTrail::BatchInfo> childrenBounds;
if (m == -1) { if (m == -1) {
at->getBoundsByClientID(&childrenBounds, index); at->getBoundsByClientID(&childrenBounds, index);
@ -434,9 +434,12 @@ Json::Value SkDebugCanvas::toJSON(UrlDataManager& urlDataManager, int n, SkCanva
} }
// in case there is some kind of global reordering // in case there is some kind of global reordering
{
GrAuditTrail::AutoEnable ae(at);
canvas->flush(); canvas->flush();
} }
} }
}
#endif #endif
// now collect json // now collect json
@ -459,6 +462,7 @@ Json::Value SkDebugCanvas::toJSON(UrlDataManager& urlDataManager, int n, SkCanva
} }
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
if (at) { if (at) {
GrAuditTrail::AutoEnable ae(at);
at->fullReset(); at->fullReset();
} }
#endif #endif

View File

@ -150,6 +150,7 @@ bool Request::initPictureFromStream(SkStream* stream) {
// for some reason we need to 'flush' the debug canvas by drawing all of the ops // for some reason we need to 'flush' the debug canvas by drawing all of the ops
fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp()); fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
this->getCanvas()->flush();
return true; return true;
} }