blob: 3bb7bea43503fc968f153ea7911e57bd871045bf [file] [log] [blame]
joshualitt27a48dc2016-01-08 07:19:47 -08001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrAuditTrail_DEFINED
9#define GrAuditTrail_DEFINED
10
joshualitt5651ee62016-01-11 10:39:11 -080011#include "GrConfig.h"
joshualitt086cee12016-01-12 06:45:24 -080012#include "SkRect.h"
joshualitt27a48dc2016-01-08 07:19:47 -080013#include "SkString.h"
14#include "SkTArray.h"
joshualitt18d6b752016-02-26 08:07:50 -080015#include "SkTHash.h"
16
17class GrBatch;
joshualitt27a48dc2016-01-08 07:19:47 -080018
19/*
20 * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them
21 * to json.
ethannicholasc85d9fb2016-02-18 13:45:39 -080022 *
23 * Capturing this information is expensive and consumes a lot of memory, therefore it is important
24 * to enable auditing only when required and disable it promptly. The AutoEnable class helps to
25 * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt
26 * with, be sure to call reset(), or the log will simply keep growing.
joshualitt27a48dc2016-01-08 07:19:47 -080027 */
28class GrAuditTrail {
29public:
ethannicholasc85d9fb2016-02-18 13:45:39 -080030 GrAuditTrail()
joshualittb95c7722016-02-29 07:44:02 -080031 : fClientID(kGrAuditTrailInvalidID)
32 , fEnabled(false) {}
joshualitt87a721b2016-01-12 12:59:28 -080033
ethannicholasc85d9fb2016-02-18 13:45:39 -080034 class AutoEnable {
35 public:
36 AutoEnable(GrAuditTrail* auditTrail)
37 : fAuditTrail(auditTrail) {
38 SkASSERT(!fAuditTrail->isEnabled());
39 fAuditTrail->setEnabled(true);
40 }
41
42 ~AutoEnable() {
43 SkASSERT(fAuditTrail->isEnabled());
44 fAuditTrail->setEnabled(false);
45 }
46
47 private:
48 GrAuditTrail* fAuditTrail;
49 };
50
joshualitt18d6b752016-02-26 08:07:50 -080051 class AutoManageBatchList {
52 public:
53 AutoManageBatchList(GrAuditTrail* auditTrail)
54 : fAutoEnable(auditTrail)
55 , fAuditTrail(auditTrail) {
56 }
57
58 ~AutoManageBatchList() {
59 fAuditTrail->fullReset();
60 }
61
62 private:
63 AutoEnable fAutoEnable;
64 GrAuditTrail* fAuditTrail;
65 };
66
joshualittb95c7722016-02-29 07:44:02 -080067 class AutoCollectBatches {
68 public:
69 AutoCollectBatches(GrAuditTrail* auditTrail, int clientID)
70 : fAutoEnable(auditTrail)
71 , fAuditTrail(auditTrail) {
72 fAuditTrail->setClientID(clientID);
joshualitt87a721b2016-01-12 12:59:28 -080073 }
74
joshualittb95c7722016-02-29 07:44:02 -080075 ~AutoCollectBatches() { fAuditTrail->setClientID(kGrAuditTrailInvalidID); }
joshualitt27a48dc2016-01-08 07:19:47 -080076
joshualittb95c7722016-02-29 07:44:02 -080077 private:
78 AutoEnable fAutoEnable;
79 GrAuditTrail* fAuditTrail;
80 };
joshualitt87a721b2016-01-12 12:59:28 -080081
joshualittf55c3642016-03-02 08:11:34 -080082 void pushFrame(const char* framename) {
83 SkASSERT(fEnabled);
84 fCurrentStackTrace.push_back(SkString(framename));
85 }
86
joshualittb0666ad2016-03-08 10:43:41 -080087 void addBatch(const GrBatch* batch);
joshualitt086cee12016-01-12 06:45:24 -080088
joshualittb0666ad2016-03-08 10:43:41 -080089 void batchingResultCombined(const GrBatch* consumer, const GrBatch* consumed);
joshualitt18d6b752016-02-26 08:07:50 -080090
joshualittb95c7722016-02-29 07:44:02 -080091 // Because batching is heavily dependent on sequence of draw calls, these calls will only
92 // produce valid information for the given draw sequence which preceeded them.
93 // Specifically, future draw calls may change the batching and thus would invalidate
94 // the json. What this means is that for some sequence of draw calls N, the below toJson
95 // calls will only produce JSON which reflects N draw calls. This JSON may or may not be
96 // accurate for N + 1 or N - 1 draws depending on the actual batching algorithm used.
97 SkString toJson(bool prettyPrint = false) const;
98
99 // returns a json string of all of the batches associated with a given client id
100 SkString toJson(int clientID, bool prettyPrint = false) const;
joshualitt27a48dc2016-01-08 07:19:47 -0800101
ethannicholasc85d9fb2016-02-18 13:45:39 -0800102 bool isEnabled() { return fEnabled; }
103 void setEnabled(bool enabled) { fEnabled = enabled; }
104
joshualittb95c7722016-02-29 07:44:02 -0800105 void setClientID(int clientID) { fClientID = clientID; }
joshualitt18d6b752016-02-26 08:07:50 -0800106
joshualitt10d8fc22016-02-29 11:15:06 -0800107 // We could just return our internal bookkeeping struct if copying the data out becomes
108 // a performance issue, but until then its nice to decouple
109 struct BatchInfo {
110 SkRect fBounds;
joshualitt1d7decf2016-03-01 07:15:52 -0800111 uint32_t fRenderTargetUniqueID;
joshualitt10d8fc22016-02-29 11:15:06 -0800112 struct Batch {
113 int fClientID;
114 SkRect fBounds;
115 };
116 SkTArray<Batch> fBatches;
117 };
118
119 void getBoundsByClientID(SkTArray<BatchInfo>* outInfo, int clientID);
joshualitt46b301d2016-03-02 08:32:37 -0800120 void getBoundsByBatchListID(BatchInfo* outInfo, int batchListID);
joshualitt10d8fc22016-02-29 11:15:06 -0800121
joshualittdf3f2b02016-03-01 07:47:56 -0800122 void fullReset();
joshualitt27a48dc2016-01-08 07:19:47 -0800123
joshualittb95c7722016-02-29 07:44:02 -0800124 static const int kGrAuditTrailInvalidID;
125
joshualitt27a48dc2016-01-08 07:19:47 -0800126private:
joshualitt11fae872016-01-14 10:58:07 -0800127 // TODO if performance becomes an issue, we can move to using SkVarAlloc
joshualittb95c7722016-02-29 07:44:02 -0800128 struct Batch {
129 SkString toJson() const;
130 SkString fName;
joshualittf55c3642016-03-02 08:11:34 -0800131 SkTArray<SkString> fStackTrace;
joshualitt08fc8072016-02-29 06:32:24 -0800132 SkRect fBounds;
joshualittb95c7722016-02-29 07:44:02 -0800133 int fClientID;
134 int fBatchListID;
135 int fChildID;
joshualitt08fc8072016-02-29 06:32:24 -0800136 };
joshualittb95c7722016-02-29 07:44:02 -0800137 typedef SkTArray<SkAutoTDelete<Batch>, true> BatchPool;
138
139 typedef SkTArray<Batch*> Batches;
140
141 struct BatchNode {
142 SkString toJson() const;
143 SkRect fBounds;
144 Batches fChildren;
joshualitt1d7decf2016-03-01 07:15:52 -0800145 uint32_t fRenderTargetUniqueID;
joshualittb95c7722016-02-29 07:44:02 -0800146 };
147 typedef SkTArray<SkAutoTDelete<BatchNode>, true> BatchList;
joshualitt11fae872016-01-14 10:58:07 -0800148
joshualitt46b301d2016-03-02 08:32:37 -0800149 void copyOutFromBatchList(BatchInfo* outBatchInfo, int batchListID);
150
joshualitt18d6b752016-02-26 08:07:50 -0800151 template <typename T>
152 static void JsonifyTArray(SkString* json, const char* name, const T& array,
joshualittadab5a22016-02-18 05:04:39 -0800153 bool addComma);
joshualittb0666ad2016-03-08 10:43:41 -0800154
joshualittb95c7722016-02-29 07:44:02 -0800155 BatchPool fBatchPool;
joshualittb0666ad2016-03-08 10:43:41 -0800156 SkTHashMap<uint32_t, int> fIDLookup;
joshualittb95c7722016-02-29 07:44:02 -0800157 SkTHashMap<int, Batches*> fClientIDLookup;
158 BatchList fBatchList;
joshualittf55c3642016-03-02 08:11:34 -0800159 SkTArray<SkString> fCurrentStackTrace;
joshualittb95c7722016-02-29 07:44:02 -0800160
161 // The client cas pass in an optional client ID which we will use to mark the batches
162 int fClientID;
163 bool fEnabled;
joshualitt27a48dc2016-01-08 07:19:47 -0800164};
165
ethannicholasc85d9fb2016-02-18 13:45:39 -0800166#define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \
167 if (audit_trail->isEnabled()) { \
168 audit_trail->invoke(__VA_ARGS__); \
joshualitt5651ee62016-01-11 10:39:11 -0800169 }
170
joshualitt87a721b2016-01-12 12:59:28 -0800171#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \
joshualittf55c3642016-03-02 08:11:34 -0800172 GR_AUDIT_TRAIL_INVOKE_GUARD((audit_trail), pushFrame, framename);
joshualitt5651ee62016-01-11 10:39:11 -0800173
174#define GR_AUDIT_TRAIL_RESET(audit_trail) \
joshualittf55c3642016-03-02 08:11:34 -0800175 //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset);
joshualitt5651ee62016-01-11 10:39:11 -0800176
joshualittb0666ad2016-03-08 10:43:41 -0800177#define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batch) \
178 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batch);
joshualitt086cee12016-01-12 06:45:24 -0800179
joshualittb0666ad2016-03-08 10:43:41 -0800180#define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combineWith, batch) \
181 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combineWith, batch);
joshualitt18d6b752016-02-26 08:07:50 -0800182
183#define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \
joshualittb0666ad2016-03-08 10:43:41 -0800184 // Doesn't do anything now, one day...
joshualitt18d6b752016-02-26 08:07:50 -0800185
joshualitt27a48dc2016-01-08 07:19:47 -0800186#endif