blob: 14873cd78c36712064af54f92e520fbd618314b9 [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
82 void addBatch(const char* name, const SkRect& bounds) {
joshualittb95c7722016-02-29 07:44:02 -080083 SkASSERT(fEnabled);
joshualitt11fae872016-01-14 10:58:07 -080084 Batch* batch = new Batch;
joshualittb95c7722016-02-29 07:44:02 -080085 fBatchPool.emplace_back(batch);
joshualitt11fae872016-01-14 10:58:07 -080086 batch->fName = name;
87 batch->fBounds = bounds;
joshualittb95c7722016-02-29 07:44:02 -080088 batch->fClientID = kGrAuditTrailInvalidID;
89 batch->fBatchListID = kGrAuditTrailInvalidID;
90 batch->fChildID = kGrAuditTrailInvalidID;
joshualitt18d6b752016-02-26 08:07:50 -080091 fCurrentBatch = batch;
joshualittb95c7722016-02-29 07:44:02 -080092
93 if (fClientID != kGrAuditTrailInvalidID) {
94 batch->fClientID = fClientID;
95 Batches** batchesLookup = fClientIDLookup.find(fClientID);
96 Batches* batches = nullptr;
97 if (!batchesLookup) {
98 batches = new Batches;
99 fClientIDLookup.set(fClientID, batches);
100 } else {
101 batches = *batchesLookup;
102 }
103
104 batches->push_back(fCurrentBatch);
105 }
joshualitt086cee12016-01-12 06:45:24 -0800106 }
107
joshualitt18d6b752016-02-26 08:07:50 -0800108 void batchingResultCombined(GrBatch* combiner);
109
110 void batchingResultNew(GrBatch* batch);
111
joshualittb95c7722016-02-29 07:44:02 -0800112 // Because batching is heavily dependent on sequence of draw calls, these calls will only
113 // produce valid information for the given draw sequence which preceeded them.
114 // Specifically, future draw calls may change the batching and thus would invalidate
115 // the json. What this means is that for some sequence of draw calls N, the below toJson
116 // calls will only produce JSON which reflects N draw calls. This JSON may or may not be
117 // accurate for N + 1 or N - 1 draws depending on the actual batching algorithm used.
118 SkString toJson(bool prettyPrint = false) const;
119
120 // returns a json string of all of the batches associated with a given client id
121 SkString toJson(int clientID, bool prettyPrint = false) const;
joshualitt27a48dc2016-01-08 07:19:47 -0800122
ethannicholasc85d9fb2016-02-18 13:45:39 -0800123 bool isEnabled() { return fEnabled; }
124 void setEnabled(bool enabled) { fEnabled = enabled; }
125
joshualittb95c7722016-02-29 07:44:02 -0800126 void setClientID(int clientID) { fClientID = clientID; }
joshualitt18d6b752016-02-26 08:07:50 -0800127
joshualitt10d8fc22016-02-29 11:15:06 -0800128 // We could just return our internal bookkeeping struct if copying the data out becomes
129 // a performance issue, but until then its nice to decouple
130 struct BatchInfo {
131 SkRect fBounds;
joshualitt1d7decf2016-03-01 07:15:52 -0800132 uint32_t fRenderTargetUniqueID;
joshualitt10d8fc22016-02-29 11:15:06 -0800133 struct Batch {
134 int fClientID;
135 SkRect fBounds;
136 };
137 SkTArray<Batch> fBatches;
138 };
139
140 void getBoundsByClientID(SkTArray<BatchInfo>* outInfo, int clientID);
141
joshualitt18d6b752016-02-26 08:07:50 -0800142 void fullReset() {
143 SkASSERT(fEnabled);
joshualittb95c7722016-02-29 07:44:02 -0800144 fBatchList.reset();
145 fIDLookup.reset();
146 // free all client batches
147 fClientIDLookup.foreach([](const int&, Batches** batches) { delete *batches; });
148 fClientIDLookup.reset();
149 fBatchPool.reset(); // must be last, frees all of the memory
joshualitt18d6b752016-02-26 08:07:50 -0800150 }
joshualitt27a48dc2016-01-08 07:19:47 -0800151
joshualittb95c7722016-02-29 07:44:02 -0800152 static const int kGrAuditTrailInvalidID;
153
joshualitt27a48dc2016-01-08 07:19:47 -0800154private:
joshualitt11fae872016-01-14 10:58:07 -0800155 // TODO if performance becomes an issue, we can move to using SkVarAlloc
joshualittb95c7722016-02-29 07:44:02 -0800156 struct Batch {
157 SkString toJson() const;
158 SkString fName;
joshualitt08fc8072016-02-29 06:32:24 -0800159 SkRect fBounds;
joshualittb95c7722016-02-29 07:44:02 -0800160 int fClientID;
161 int fBatchListID;
162 int fChildID;
joshualitt08fc8072016-02-29 06:32:24 -0800163 };
joshualittb95c7722016-02-29 07:44:02 -0800164 typedef SkTArray<SkAutoTDelete<Batch>, true> BatchPool;
165
166 typedef SkTArray<Batch*> Batches;
167
168 struct BatchNode {
169 SkString toJson() const;
170 SkRect fBounds;
171 Batches fChildren;
joshualitt1d7decf2016-03-01 07:15:52 -0800172 uint32_t fRenderTargetUniqueID;
joshualittb95c7722016-02-29 07:44:02 -0800173 };
174 typedef SkTArray<SkAutoTDelete<BatchNode>, true> BatchList;
joshualitt11fae872016-01-14 10:58:07 -0800175
joshualitt18d6b752016-02-26 08:07:50 -0800176 template <typename T>
177 static void JsonifyTArray(SkString* json, const char* name, const T& array,
joshualittadab5a22016-02-18 05:04:39 -0800178 bool addComma);
joshualitt11fae872016-01-14 10:58:07 -0800179
joshualitt08fc8072016-02-29 06:32:24 -0800180 Batch* fCurrentBatch;
joshualittb95c7722016-02-29 07:44:02 -0800181 BatchPool fBatchPool;
joshualitt08fc8072016-02-29 06:32:24 -0800182 SkTHashMap<GrBatch*, int> fIDLookup;
joshualittb95c7722016-02-29 07:44:02 -0800183 SkTHashMap<int, Batches*> fClientIDLookup;
184 BatchList fBatchList;
185
186 // The client cas pass in an optional client ID which we will use to mark the batches
187 int fClientID;
188 bool fEnabled;
joshualitt27a48dc2016-01-08 07:19:47 -0800189};
190
ethannicholasc85d9fb2016-02-18 13:45:39 -0800191#define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \
192 if (audit_trail->isEnabled()) { \
193 audit_trail->invoke(__VA_ARGS__); \
joshualitt5651ee62016-01-11 10:39:11 -0800194 }
195
joshualitt87a721b2016-01-12 12:59:28 -0800196#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \
joshualittb95c7722016-02-29 07:44:02 -0800197 // TODO fill out the frame stuff
198 //GrAuditTrail::AutoFrame SK_MACRO_APPEND_LINE(auto_frame)(audit_trail, framename);
joshualitt5651ee62016-01-11 10:39:11 -0800199
200#define GR_AUDIT_TRAIL_RESET(audit_trail) \
joshualittb95c7722016-02-29 07:44:02 -0800201 //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, reset);
joshualitt5651ee62016-01-11 10:39:11 -0800202
joshualitt086cee12016-01-12 06:45:24 -0800203#define GR_AUDIT_TRAIL_ADDBATCH(audit_trail, batchname, bounds) \
ethannicholasc85d9fb2016-02-18 13:45:39 -0800204 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addBatch, batchname, bounds);
joshualitt086cee12016-01-12 06:45:24 -0800205
joshualitt18d6b752016-02-26 08:07:50 -0800206#define GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(audit_trail, combiner) \
207 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultCombined, combiner);
208
209#define GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(audit_trail, batch) \
210 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, batchingResultNew, batch);
211
joshualitt27a48dc2016-01-08 07:19:47 -0800212#endif