blob: f1ae494c9b0fd1d6c74d9ac31e13f0daeaaf9a73 [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"
Robert Phillips294870f2016-11-11 12:38:40 -050012#include "GrGpuResource.h"
joshualitt086cee12016-01-12 06:45:24 -080013#include "SkRect.h"
joshualitt27a48dc2016-01-08 07:19:47 -080014#include "SkString.h"
15#include "SkTArray.h"
joshualitt18d6b752016-02-26 08:07:50 -080016#include "SkTHash.h"
17
Brian Salomon25a88092016-12-01 09:36:50 -050018class GrOp;
joshualitt27a48dc2016-01-08 07:19:47 -080019
20/*
21 * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them
22 * to json.
ethannicholasc85d9fb2016-02-18 13:45:39 -080023 *
24 * Capturing this information is expensive and consumes a lot of memory, therefore it is important
25 * to enable auditing only when required and disable it promptly. The AutoEnable class helps to
26 * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt
27 * with, be sure to call reset(), or the log will simply keep growing.
joshualitt27a48dc2016-01-08 07:19:47 -080028 */
29class GrAuditTrail {
30public:
ethannicholasc85d9fb2016-02-18 13:45:39 -080031 GrAuditTrail()
joshualittb95c7722016-02-29 07:44:02 -080032 : fClientID(kGrAuditTrailInvalidID)
33 , fEnabled(false) {}
joshualitt87a721b2016-01-12 12:59:28 -080034
ethannicholasc85d9fb2016-02-18 13:45:39 -080035 class AutoEnable {
36 public:
37 AutoEnable(GrAuditTrail* auditTrail)
38 : fAuditTrail(auditTrail) {
39 SkASSERT(!fAuditTrail->isEnabled());
40 fAuditTrail->setEnabled(true);
41 }
42
43 ~AutoEnable() {
44 SkASSERT(fAuditTrail->isEnabled());
45 fAuditTrail->setEnabled(false);
46 }
47
48 private:
49 GrAuditTrail* fAuditTrail;
50 };
51
Brian Salomon42ad83a2016-12-20 16:14:45 -050052 class AutoManageOpList {
joshualitt18d6b752016-02-26 08:07:50 -080053 public:
Brian Salomon42ad83a2016-12-20 16:14:45 -050054 AutoManageOpList(GrAuditTrail* auditTrail)
55 : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {}
joshualitt18d6b752016-02-26 08:07:50 -080056
Brian Salomon42ad83a2016-12-20 16:14:45 -050057 ~AutoManageOpList() { fAuditTrail->fullReset(); }
joshualitt18d6b752016-02-26 08:07:50 -080058
59 private:
60 AutoEnable fAutoEnable;
61 GrAuditTrail* fAuditTrail;
62 };
63
Brian Salomon42ad83a2016-12-20 16:14:45 -050064 class AutoCollectOps {
joshualittb95c7722016-02-29 07:44:02 -080065 public:
Brian Salomon42ad83a2016-12-20 16:14:45 -050066 AutoCollectOps(GrAuditTrail* auditTrail, int clientID)
67 : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {
joshualittb95c7722016-02-29 07:44:02 -080068 fAuditTrail->setClientID(clientID);
joshualitt87a721b2016-01-12 12:59:28 -080069 }
70
Brian Salomon42ad83a2016-12-20 16:14:45 -050071 ~AutoCollectOps() { fAuditTrail->setClientID(kGrAuditTrailInvalidID); }
joshualitt27a48dc2016-01-08 07:19:47 -080072
joshualittb95c7722016-02-29 07:44:02 -080073 private:
74 AutoEnable fAutoEnable;
75 GrAuditTrail* fAuditTrail;
76 };
joshualitt87a721b2016-01-12 12:59:28 -080077
joshualittf55c3642016-03-02 08:11:34 -080078 void pushFrame(const char* framename) {
79 SkASSERT(fEnabled);
80 fCurrentStackTrace.push_back(SkString(framename));
81 }
82
Brian Salomon69868af2016-12-22 15:42:51 -050083 void addOp(const GrOp*, GrGpuResource::UniqueID renderTargetID);
joshualitt086cee12016-01-12 06:45:24 -080084
Brian Salomon42ad83a2016-12-20 16:14:45 -050085 void opsCombined(const GrOp* consumer, const GrOp* consumed);
joshualitt18d6b752016-02-26 08:07:50 -080086
Brian Salomon42ad83a2016-12-20 16:14:45 -050087 // Because op combining is heavily dependent on sequence of draw calls, these calls will only
88 // produce valid information for the given draw sequence which preceeded them. Specifically, ops
89 // of future draw calls may combine with previous ops and thus would invalidate the json. What
90 // this means is that for some sequence of draw calls N, the below toJson calls will only
91 // produce JSON which reflects N draw calls. This JSON may or may not be accurate for N + 1 or
92 // N - 1 draws depending on the actual combining algorithm used.
joshualittb95c7722016-02-29 07:44:02 -080093 SkString toJson(bool prettyPrint = false) const;
94
Brian Salomon42ad83a2016-12-20 16:14:45 -050095 // returns a json string of all of the ops associated with a given client id
joshualittb95c7722016-02-29 07:44:02 -080096 SkString toJson(int clientID, bool prettyPrint = false) const;
joshualitt27a48dc2016-01-08 07:19:47 -080097
ethannicholasc85d9fb2016-02-18 13:45:39 -080098 bool isEnabled() { return fEnabled; }
99 void setEnabled(bool enabled) { fEnabled = enabled; }
100
joshualittb95c7722016-02-29 07:44:02 -0800101 void setClientID(int clientID) { fClientID = clientID; }
joshualitt18d6b752016-02-26 08:07:50 -0800102
joshualitt10d8fc22016-02-29 11:15:06 -0800103 // We could just return our internal bookkeeping struct if copying the data out becomes
104 // a performance issue, but until then its nice to decouple
Brian Salomon42ad83a2016-12-20 16:14:45 -0500105 struct OpInfo {
106 SkRect fBounds;
Robert Phillips294870f2016-11-11 12:38:40 -0500107 // TODO: switch over to GrSurfaceProxy::UniqueID
108 GrGpuResource::UniqueID fRenderTargetUniqueID;
Brian Salomon42ad83a2016-12-20 16:14:45 -0500109 struct Op {
joshualitt10d8fc22016-02-29 11:15:06 -0800110 int fClientID;
111 SkRect fBounds;
112 };
Brian Salomon42ad83a2016-12-20 16:14:45 -0500113 SkTArray<Op> fOps;
joshualitt10d8fc22016-02-29 11:15:06 -0800114 };
115
Brian Salomon42ad83a2016-12-20 16:14:45 -0500116 void getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID);
117 void getBoundsByOpListID(OpInfo* outInfo, int opListID);
joshualitt10d8fc22016-02-29 11:15:06 -0800118
joshualittdf3f2b02016-03-01 07:47:56 -0800119 void fullReset();
joshualitt27a48dc2016-01-08 07:19:47 -0800120
joshualittb95c7722016-02-29 07:44:02 -0800121 static const int kGrAuditTrailInvalidID;
122
joshualitt27a48dc2016-01-08 07:19:47 -0800123private:
joshualitt11fae872016-01-14 10:58:07 -0800124 // TODO if performance becomes an issue, we can move to using SkVarAlloc
Brian Salomon42ad83a2016-12-20 16:14:45 -0500125 struct Op {
joshualittb95c7722016-02-29 07:44:02 -0800126 SkString toJson() const;
127 SkString fName;
joshualittf55c3642016-03-02 08:11:34 -0800128 SkTArray<SkString> fStackTrace;
joshualitt08fc8072016-02-29 06:32:24 -0800129 SkRect fBounds;
joshualittb95c7722016-02-29 07:44:02 -0800130 int fClientID;
Brian Salomon42ad83a2016-12-20 16:14:45 -0500131 int fOpListID;
joshualittb95c7722016-02-29 07:44:02 -0800132 int fChildID;
joshualitt08fc8072016-02-29 06:32:24 -0800133 };
Brian Salomon42ad83a2016-12-20 16:14:45 -0500134 typedef SkTArray<std::unique_ptr<Op>, true> OpPool;
joshualittb95c7722016-02-29 07:44:02 -0800135
Brian Salomon42ad83a2016-12-20 16:14:45 -0500136 typedef SkTArray<Op*> Ops;
joshualittb95c7722016-02-29 07:44:02 -0800137
Brian Salomon42ad83a2016-12-20 16:14:45 -0500138 struct OpNode {
139 OpNode(const GrGpuResource::UniqueID& id) : fRenderTargetUniqueID(id) {}
joshualittb95c7722016-02-29 07:44:02 -0800140 SkString toJson() const;
Robert Phillips294870f2016-11-11 12:38:40 -0500141 SkRect fBounds;
Brian Salomon42ad83a2016-12-20 16:14:45 -0500142 Ops fChildren;
Robert Phillips294870f2016-11-11 12:38:40 -0500143 const GrGpuResource::UniqueID fRenderTargetUniqueID;
joshualittb95c7722016-02-29 07:44:02 -0800144 };
Brian Salomon42ad83a2016-12-20 16:14:45 -0500145 typedef SkTArray<std::unique_ptr<OpNode>, true> OpList;
joshualitt11fae872016-01-14 10:58:07 -0800146
Brian Salomon42ad83a2016-12-20 16:14:45 -0500147 void copyOutFromOpList(OpInfo* outOpInfo, int opListID);
joshualitt46b301d2016-03-02 08:32:37 -0800148
joshualitt18d6b752016-02-26 08:07:50 -0800149 template <typename T>
150 static void JsonifyTArray(SkString* json, const char* name, const T& array,
joshualittadab5a22016-02-18 05:04:39 -0800151 bool addComma);
bungeman6bd52842016-10-27 09:30:08 -0700152
Brian Salomon42ad83a2016-12-20 16:14:45 -0500153 OpPool fOpPool;
joshualittb0666ad2016-03-08 10:43:41 -0800154 SkTHashMap<uint32_t, int> fIDLookup;
Brian Salomon42ad83a2016-12-20 16:14:45 -0500155 SkTHashMap<int, Ops*> fClientIDLookup;
156 OpList fOpList;
joshualittf55c3642016-03-02 08:11:34 -0800157 SkTArray<SkString> fCurrentStackTrace;
joshualittb95c7722016-02-29 07:44:02 -0800158
Brian Salomon42ad83a2016-12-20 16:14:45 -0500159 // The client can pass in an optional client ID which we will use to mark the ops
joshualittb95c7722016-02-29 07:44:02 -0800160 int fClientID;
161 bool fEnabled;
joshualitt27a48dc2016-01-08 07:19:47 -0800162};
163
ethannicholasc85d9fb2016-02-18 13:45:39 -0800164#define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \
165 if (audit_trail->isEnabled()) { \
166 audit_trail->invoke(__VA_ARGS__); \
joshualitt5651ee62016-01-11 10:39:11 -0800167 }
168
joshualitt87a721b2016-01-12 12:59:28 -0800169#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \
joshualittf55c3642016-03-02 08:11:34 -0800170 GR_AUDIT_TRAIL_INVOKE_GUARD((audit_trail), pushFrame, framename);
joshualitt5651ee62016-01-11 10:39:11 -0800171
172#define GR_AUDIT_TRAIL_RESET(audit_trail) \
joshualittf55c3642016-03-02 08:11:34 -0800173 //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset);
joshualitt5651ee62016-01-11 10:39:11 -0800174
Brian Salomon69868af2016-12-22 15:42:51 -0500175#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, rt_id) \
176 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, rt_id);
joshualitt086cee12016-01-12 06:45:24 -0800177
Brian Salomon42ad83a2016-12-20 16:14:45 -0500178#define GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(audit_trail, combineWith, op) \
179 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, opsCombined, combineWith, op);
joshualitt18d6b752016-02-26 08:07:50 -0800180
Brian Salomon42ad83a2016-12-20 16:14:45 -0500181#define GR_AUDIT_TRAIL_OP_RESULT_NEW(audit_trail, op) // Doesn't do anything now, one day...
joshualitt18d6b752016-02-26 08:07:50 -0800182
joshualitt27a48dc2016-01-08 07:19:47 -0800183#endif