Add batch names and bounds to json debug information

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

Review URL: https://codereview.chromium.org/1577093003
This commit is contained in:
joshualitt 2016-01-12 06:45:24 -08:00 committed by Commit bot
parent 1ad0415b03
commit 086cee12de
6 changed files with 141 additions and 28 deletions

View File

@ -9,6 +9,7 @@
#define GrAuditTrail_DEFINED #define GrAuditTrail_DEFINED
#include "GrConfig.h" #include "GrConfig.h"
#include "SkRect.h"
#include "SkString.h" #include "SkString.h"
#include "SkTArray.h" #include "SkTArray.h"
@ -18,11 +19,18 @@
*/ */
class GrAuditTrail { class GrAuditTrail {
public: public:
void addOp(SkString name) { void addOp(const SkString& name) {
SkASSERT(GR_BATCH_DEBUGGING_OUTPUT); SkASSERT(GR_BATCH_DEBUGGING_OUTPUT);
fOps.push_back().fName = name; fOps.push_back().fName = name;
} }
void addBatch(const SkString& name, const SkRect& bounds) {
SkASSERT(GR_BATCH_DEBUGGING_OUTPUT);
Op::Batch& batch = fOps.back().fBatches.push_back();
batch.fName = name;
batch.fBounds = bounds;
}
SkString toJson() const; SkString toJson() const;
void reset() { SkASSERT(GR_BATCH_DEBUGGING_OUTPUT); fOps.reset(); } void reset() { SkASSERT(GR_BATCH_DEBUGGING_OUTPUT); fOps.reset(); }
@ -30,7 +38,14 @@ public:
private: private:
struct Op { struct Op {
SkString toJson() const; SkString toJson() const;
struct Batch {
SkString toJson() const;
SkString fName;
SkRect fBounds;
};
SkString fName; SkString fName;
SkTArray<Batch> fBatches;
}; };
SkTArray<Op> fOps; SkTArray<Op> fOps;
@ -41,11 +56,13 @@ private:
invoke(__VA_ARGS__); \ invoke(__VA_ARGS__); \
} }
#define GR_AUDIT_TRAIL_ADDOP(audit_trail, opname) \ #define GR_AUDIT_TRAIL_ADDOP(audit_trail, opname) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail->addOp, opname); GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail->addOp, opname);
#define GR_AUDIT_TRAIL_RESET(audit_trail) \ #define GR_AUDIT_TRAIL_RESET(audit_trail) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail->reset); GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail->reset);
#define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail->addBatch, SkString(batchname), bounds);
#endif #endif

View File

@ -7,26 +7,116 @@
#include "GrAuditTrail.h" #include "GrAuditTrail.h"
SkString GrAuditTrail::toJson() const { template <class T>
SkString json; static void jsonify_tarray(SkString* json, const SkTArray<T>& array) {
json.append("{\n"); for (int i = 0; i < array.count(); i++) {
json.append("\"Ops\": [\n"); json->append(array[i].toJson());
for (int i = 0; i < fOps.count(); i++) { if (i < array.count() - 1) {
json.append(fOps[i].toJson()); json->append(",");
if (i < fOps.count() - 1) {
json.append(",\n");
} }
} }
json.append("]\n"); }
json.append("}\n");
return json; // This will pretty print a very small subset of json
// The parsing rules are straightforward, aside from the fact that we do not want an extra newline
// before ',' and after '}', so we have a comma exception rule.
class PrettyPrintJson {
public:
SkString prettify(const SkString& json) {
fPrettyJson.reset();
fTabCount = 0;
fFreshLine = false;
fCommaException = false;
for (size_t i = 0; i < json.size(); i++) {
if ('[' == json[i] || '{' == json[i]) {
this->newline();
this->appendChar(json[i]);
fTabCount++;
this->newline();
} else if (']' == json[i] || '}' == json[i]) {
fTabCount--;
this->newline();
this->appendChar(json[i]);
fCommaException = true;
} else if (',' == json[i]) {
this->appendChar(json[i]);
this->newline();
} else {
this->appendChar(json[i]);
}
}
return fPrettyJson;
}
private:
void appendChar(char appendee) {
if (fCommaException && ',' != appendee) {
this->newline();
}
this->tab();
fPrettyJson += appendee;
fFreshLine = false;
fCommaException = false;
}
void tab() {
if (fFreshLine) {
for (int i = 0; i < fTabCount; i++) {
fPrettyJson += '\t';
}
}
}
void newline() {
if (!fFreshLine) {
fFreshLine = true;
fPrettyJson += '\n';
}
}
SkString fPrettyJson;
int fTabCount;
bool fFreshLine;
bool fCommaException;
};
static SkString pretty_print_json(SkString json) {
class PrettyPrintJson prettyPrintJson;
return prettyPrintJson.prettify(json);
}
SkString GrAuditTrail::toJson() const {
SkString json;
json.append("{");
json.append("\"Ops\": [");
jsonify_tarray(&json, fOps);
json.append("]");
json.append("}");
// TODO if this becomes a performance issue we should make pretty print configurable
return pretty_print_json(json);
} }
SkString GrAuditTrail::Op::toJson() const { SkString GrAuditTrail::Op::toJson() const {
SkString json; SkString json;
json.append("{\n"); json.append("{");
json.appendf("\"Name\": \"%s\"\n", fName.c_str()); json.appendf("\"Name\": \"%s\",", fName.c_str());
json.append("}\n"); json.append("\"Batches\": [");
jsonify_tarray(&json, fBatches);
json.append("]");
json.append("}");
return json; return json;
} }
SkString GrAuditTrail::Op::Batch::toJson() const {
SkString json;
json.append("{");
json.appendf("\"Name\": \"%s\",", fName.c_str());
json.append("\"Bounds\": {");
json.appendf("\"Left\": %f,", fBounds.fLeft);
json.appendf("\"Right\": %f,", fBounds.fRight);
json.appendf("\"Top\": %f,", fBounds.fTop);
json.appendf("\"Bottom\": %f", fBounds.fBottom);
json.append("}");
json.append("}");
return json;
}

View File

@ -8,6 +8,7 @@
#include "GrDrawTarget.h" #include "GrDrawTarget.h"
#include "GrAuditTrail.h"
#include "GrCaps.h" #include "GrCaps.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "GrPath.h" #include "GrPath.h"
@ -20,6 +21,8 @@
#include "GrTexture.h" #include "GrTexture.h"
#include "GrVertexBuffer.h" #include "GrVertexBuffer.h"
#include "SkStrokeRec.h"
#include "batches/GrClearBatch.h" #include "batches/GrClearBatch.h"
#include "batches/GrCopySurfaceBatch.h" #include "batches/GrCopySurfaceBatch.h"
#include "batches/GrDiscardBatch.h" #include "batches/GrDiscardBatch.h"
@ -28,17 +31,16 @@
#include "batches/GrRectBatchFactory.h" #include "batches/GrRectBatchFactory.h"
#include "batches/GrStencilPathBatch.h" #include "batches/GrStencilPathBatch.h"
#include "SkStrokeRec.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Experimentally we have found that most batching occurs within the first 10 comparisons. // Experimentally we have found that most batching occurs within the first 10 comparisons.
static const int kDefaultMaxBatchLookback = 10; static const int kDefaultMaxBatchLookback = 10;
GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider, GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider,
const Options& options) GrAuditTrail* auditTrail, const Options& options)
: fGpu(SkRef(gpu)) : fGpu(SkRef(gpu))
, fResourceProvider(resourceProvider) , fResourceProvider(resourceProvider)
, fAuditTrail(auditTrail)
, fFlags(0) , fFlags(0)
, fRenderTarget(rt) { , fRenderTarget(rt) {
// TODO: Stop extracting the context (currently needed by GrClipMaskManager) // TODO: Stop extracting the context (currently needed by GrClipMaskManager)
@ -466,7 +468,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());
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(),

View File

@ -34,6 +34,7 @@
//#define ENABLE_MDB 1 //#define ENABLE_MDB 1
class GrAuditTrail;
class GrBatch; class GrBatch;
class GrClip; class GrClip;
class GrCaps; class GrCaps;
@ -50,7 +51,7 @@ public:
int fMaxBatchLookback; int fMaxBatchLookback;
}; };
GrDrawTarget(GrRenderTarget*, GrGpu*, GrResourceProvider*, const Options&); GrDrawTarget(GrRenderTarget*, GrGpu*, GrResourceProvider*, GrAuditTrail*, const Options&);
~GrDrawTarget() override; ~GrDrawTarget() override;
@ -288,6 +289,7 @@ private:
GrContext* fContext; GrContext* fContext;
GrGpu* fGpu; GrGpu* fGpu;
GrResourceProvider* fResourceProvider; GrResourceProvider* fResourceProvider;
GrAuditTrail* fAuditTrail;
SkDEBUGCODE(int fDebugID;) SkDEBUGCODE(int fDebugID;)
uint32_t fFlags; uint32_t fFlags;

View File

@ -114,6 +114,13 @@ void GrDrawingManager::flush() {
fDrawTargets.reset(); fDrawTargets.reset();
#endif #endif
// Clear batch debugging output
if (GR_BATCH_DEBUGGING_OUTPUT) {
SkDebugf("%s\n", fContext->getAuditTrail()->toJson().c_str());
// TODO This currently crashes because not all ops are accounted for
//GR_AUDIT_TRAIL_RESET(fContext->getAuditTrail());
}
fFlushState.reset(); fFlushState.reset();
fFlushing = false; fFlushing = false;
} }
@ -162,7 +169,7 @@ GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
#endif #endif
GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(), GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
fOptionsForDrawTargets); fContext->getAuditTrail(), fOptionsForDrawTargets);
*fDrawTargets.append() = dt; *fDrawTargets.append() = dt;

View File

@ -411,6 +411,7 @@ static bool needs_antialiasing(SkCanvas::PointMode mode, size_t count, const SkP
void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
size_t count, const SkPoint pts[], const SkPaint& paint) { size_t count, const SkPoint pts[], const SkPaint& paint) {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPoints", fContext);
CHECK_FOR_ANNOTATION(paint); CHECK_FOR_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw); CHECK_SHOULD_DRAW(draw);
@ -1784,12 +1785,6 @@ void SkGpuDevice::flush() {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
DO_DEFERRED_CLEAR(); DO_DEFERRED_CLEAR();
fRenderTarget->prepareForExternalIO(); fRenderTarget->prepareForExternalIO();
// Clear batch debugging output
if (GR_BATCH_DEBUGGING_OUTPUT) {
SkDebugf("%s\n", fContext->getAuditTrail()->toJson().c_str());
GR_AUDIT_TRAIL_RESET(fContext->getAuditTrail());
}
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////