blob: 58908a0ce9fe398c8070b1373216abc1cdfdba2e [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkRect.h"
12#include "include/core/SkString.h"
13#include "include/gpu/GrConfig.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/private/SkTArray.h"
15#include "include/private/SkTHash.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000016#include "src/gpu/GrGpuResource.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040017#include "src/gpu/GrRenderTargetProxy.h"
joshualitt18d6b752016-02-26 08:07:50 -080018
Brian Salomon25a88092016-12-01 09:36:50 -050019class GrOp;
Brian Osmand8a90f92019-01-28 13:41:19 -050020class SkJSONWriter;
joshualitt27a48dc2016-01-08 07:19:47 -080021
22/*
23 * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them
24 * to json.
ethannicholasc85d9fb2016-02-18 13:45:39 -080025 *
26 * Capturing this information is expensive and consumes a lot of memory, therefore it is important
Ben Wagner63fd7602017-10-09 15:45:33 -040027 * to enable auditing only when required and disable it promptly. The AutoEnable class helps to
ethannicholasc85d9fb2016-02-18 13:45:39 -080028 * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt
29 * with, be sure to call reset(), or the log will simply keep growing.
joshualitt27a48dc2016-01-08 07:19:47 -080030 */
31class GrAuditTrail {
32public:
Ben Wagner63fd7602017-10-09 15:45:33 -040033 GrAuditTrail()
joshualittb95c7722016-02-29 07:44:02 -080034 : fClientID(kGrAuditTrailInvalidID)
35 , fEnabled(false) {}
joshualitt87a721b2016-01-12 12:59:28 -080036
ethannicholasc85d9fb2016-02-18 13:45:39 -080037 class AutoEnable {
38 public:
39 AutoEnable(GrAuditTrail* auditTrail)
40 : fAuditTrail(auditTrail) {
41 SkASSERT(!fAuditTrail->isEnabled());
42 fAuditTrail->setEnabled(true);
43 }
44
45 ~AutoEnable() {
46 SkASSERT(fAuditTrail->isEnabled());
47 fAuditTrail->setEnabled(false);
48 }
49
50 private:
51 GrAuditTrail* fAuditTrail;
52 };
53
Greg Danielf41b2bd2019-08-22 16:19:24 -040054 class AutoManageOpsTask {
joshualitt18d6b752016-02-26 08:07:50 -080055 public:
Greg Danielf41b2bd2019-08-22 16:19:24 -040056 AutoManageOpsTask(GrAuditTrail* auditTrail)
Brian Salomon42ad83a2016-12-20 16:14:45 -050057 : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {}
joshualitt18d6b752016-02-26 08:07:50 -080058
Greg Danielf41b2bd2019-08-22 16:19:24 -040059 ~AutoManageOpsTask() { fAuditTrail->fullReset(); }
joshualitt18d6b752016-02-26 08:07:50 -080060
61 private:
62 AutoEnable fAutoEnable;
63 GrAuditTrail* fAuditTrail;
64 };
65
Brian Salomon42ad83a2016-12-20 16:14:45 -050066 class AutoCollectOps {
joshualittb95c7722016-02-29 07:44:02 -080067 public:
Brian Salomon42ad83a2016-12-20 16:14:45 -050068 AutoCollectOps(GrAuditTrail* auditTrail, int clientID)
69 : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {
joshualittb95c7722016-02-29 07:44:02 -080070 fAuditTrail->setClientID(clientID);
joshualitt87a721b2016-01-12 12:59:28 -080071 }
72
Brian Salomon42ad83a2016-12-20 16:14:45 -050073 ~AutoCollectOps() { fAuditTrail->setClientID(kGrAuditTrailInvalidID); }
joshualitt27a48dc2016-01-08 07:19:47 -080074
joshualittb95c7722016-02-29 07:44:02 -080075 private:
76 AutoEnable fAutoEnable;
77 GrAuditTrail* fAuditTrail;
78 };
joshualitt87a721b2016-01-12 12:59:28 -080079
joshualittf55c3642016-03-02 08:11:34 -080080 void pushFrame(const char* framename) {
81 SkASSERT(fEnabled);
82 fCurrentStackTrace.push_back(SkString(framename));
83 }
84
Robert Phillips318c4192017-05-17 09:36:38 -040085 void addOp(const GrOp*, GrRenderTargetProxy::UniqueID proxyID);
joshualitt086cee12016-01-12 06:45:24 -080086
Brian Salomon42ad83a2016-12-20 16:14:45 -050087 void opsCombined(const GrOp* consumer, const GrOp* consumed);
joshualitt18d6b752016-02-26 08:07:50 -080088
Brian Salomon42ad83a2016-12-20 16:14:45 -050089 // Because op combining is heavily dependent on sequence of draw calls, these calls will only
90 // produce valid information for the given draw sequence which preceeded them. Specifically, ops
91 // of future draw calls may combine with previous ops and thus would invalidate the json. What
92 // this means is that for some sequence of draw calls N, the below toJson calls will only
93 // produce JSON which reflects N draw calls. This JSON may or may not be accurate for N + 1 or
94 // N - 1 draws depending on the actual combining algorithm used.
Brian Osmand8a90f92019-01-28 13:41:19 -050095 void toJson(SkJSONWriter& writer) const;
joshualittb95c7722016-02-29 07:44:02 -080096
Brian Salomon42ad83a2016-12-20 16:14:45 -050097 // returns a json string of all of the ops associated with a given client id
Brian Osmand8a90f92019-01-28 13:41:19 -050098 void toJson(SkJSONWriter& writer, int clientID) const;
joshualitt27a48dc2016-01-08 07:19:47 -080099
ethannicholasc85d9fb2016-02-18 13:45:39 -0800100 bool isEnabled() { return fEnabled; }
101 void setEnabled(bool enabled) { fEnabled = enabled; }
102
joshualittb95c7722016-02-29 07:44:02 -0800103 void setClientID(int clientID) { fClientID = clientID; }
joshualitt18d6b752016-02-26 08:07:50 -0800104
joshualitt10d8fc22016-02-29 11:15:06 -0800105 // We could just return our internal bookkeeping struct if copying the data out becomes
106 // a performance issue, but until then its nice to decouple
Brian Salomon42ad83a2016-12-20 16:14:45 -0500107 struct OpInfo {
Brian Salomon42ad83a2016-12-20 16:14:45 -0500108 struct Op {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400109 int fClientID;
joshualitt10d8fc22016-02-29 11:15:06 -0800110 SkRect fBounds;
111 };
Robert Phillipsf7a72612017-03-31 10:03:45 -0400112
113 SkRect fBounds;
Robert Phillipsf7a72612017-03-31 10:03:45 -0400114 GrSurfaceProxy::UniqueID fProxyUniqueID;
115 SkTArray<Op> fOps;
joshualitt10d8fc22016-02-29 11:15:06 -0800116 };
117
Brian Salomon42ad83a2016-12-20 16:14:45 -0500118 void getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID);
Greg Danielf41b2bd2019-08-22 16:19:24 -0400119 void getBoundsByOpsTaskID(OpInfo* outInfo, int opsTaskID);
joshualitt10d8fc22016-02-29 11:15:06 -0800120
joshualittdf3f2b02016-03-01 07:47:56 -0800121 void fullReset();
joshualitt27a48dc2016-01-08 07:19:47 -0800122
joshualittb95c7722016-02-29 07:44:02 -0800123 static const int kGrAuditTrailInvalidID;
124
joshualitt27a48dc2016-01-08 07:19:47 -0800125private:
joshualitt11fae872016-01-14 10:58:07 -0800126 // TODO if performance becomes an issue, we can move to using SkVarAlloc
Brian Salomon42ad83a2016-12-20 16:14:45 -0500127 struct Op {
Brian Osmand8a90f92019-01-28 13:41:19 -0500128 void toJson(SkJSONWriter& writer) const;
joshualittb95c7722016-02-29 07:44:02 -0800129 SkString fName;
joshualittf55c3642016-03-02 08:11:34 -0800130 SkTArray<SkString> fStackTrace;
joshualitt08fc8072016-02-29 06:32:24 -0800131 SkRect fBounds;
joshualittb95c7722016-02-29 07:44:02 -0800132 int fClientID;
Greg Danielf41b2bd2019-08-22 16:19:24 -0400133 int fOpsTaskID;
joshualittb95c7722016-02-29 07:44:02 -0800134 int fChildID;
joshualitt08fc8072016-02-29 06:32:24 -0800135 };
Brian Salomon42ad83a2016-12-20 16:14:45 -0500136 typedef SkTArray<std::unique_ptr<Op>, true> OpPool;
joshualittb95c7722016-02-29 07:44:02 -0800137
Brian Salomon42ad83a2016-12-20 16:14:45 -0500138 typedef SkTArray<Op*> Ops;
joshualittb95c7722016-02-29 07:44:02 -0800139
Brian Salomon42ad83a2016-12-20 16:14:45 -0500140 struct OpNode {
Robert Phillips318c4192017-05-17 09:36:38 -0400141 OpNode(const GrSurfaceProxy::UniqueID& proxyID) : fProxyUniqueID(proxyID) { }
Brian Osmand8a90f92019-01-28 13:41:19 -0500142 void toJson(SkJSONWriter& writer) const;
Robert Phillipsf7a72612017-03-31 10:03:45 -0400143
Robert Phillips294870f2016-11-11 12:38:40 -0500144 SkRect fBounds;
Robert Phillipsf7a72612017-03-31 10:03:45 -0400145 Ops fChildren;
Robert Phillipsf7a72612017-03-31 10:03:45 -0400146 const GrSurfaceProxy::UniqueID fProxyUniqueID;
joshualittb95c7722016-02-29 07:44:02 -0800147 };
Greg Danielf41b2bd2019-08-22 16:19:24 -0400148 typedef SkTArray<std::unique_ptr<OpNode>, true> OpsTask;
joshualitt11fae872016-01-14 10:58:07 -0800149
Greg Danielf41b2bd2019-08-22 16:19:24 -0400150 void copyOutFromOpsTask(OpInfo* outOpInfo, int opsTask);
joshualitt46b301d2016-03-02 08:32:37 -0800151
joshualitt18d6b752016-02-26 08:07:50 -0800152 template <typename T>
Brian Osmand8a90f92019-01-28 13:41:19 -0500153 static void JsonifyTArray(SkJSONWriter& writer, const char* name, const T& array);
bungeman6bd52842016-10-27 09:30:08 -0700154
Brian Salomon42ad83a2016-12-20 16:14:45 -0500155 OpPool fOpPool;
joshualittb0666ad2016-03-08 10:43:41 -0800156 SkTHashMap<uint32_t, int> fIDLookup;
Brian Salomon42ad83a2016-12-20 16:14:45 -0500157 SkTHashMap<int, Ops*> fClientIDLookup;
Greg Danielf41b2bd2019-08-22 16:19:24 -0400158 OpsTask fOpsTask;
joshualittf55c3642016-03-02 08:11:34 -0800159 SkTArray<SkString> fCurrentStackTrace;
joshualittb95c7722016-02-29 07:44:02 -0800160
Brian Salomon42ad83a2016-12-20 16:14:45 -0500161 // The client can pass in an optional client ID which we will use to mark the ops
joshualittb95c7722016-02-29 07:44:02 -0800162 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, ...) \
Brian Salomon23356442018-11-30 15:33:19 -0500167 if (audit_trail->isEnabled()) audit_trail->invoke(__VA_ARGS__)
joshualitt5651ee62016-01-11 10:39:11 -0800168
joshualitt87a721b2016-01-12 12:59:28 -0800169#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \
Brian Salomon23356442018-11-30 15:33:19 -0500170 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
Robert Phillips318c4192017-05-17 09:36:38 -0400175#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, proxy_id) \
Brian Salomon23356442018-11-30 15:33:19 -0500176 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, proxy_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) \
Brian Salomon23356442018-11-30 15:33:19 -0500179 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, opsCombined, combineWith, op)
joshualitt18d6b752016-02-26 08:07:50 -0800180
joshualitt27a48dc2016-01-08 07:19:47 -0800181#endif