1 /* 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 11 #include "include/gpu/GrTypes.h" 12 13 #if SK_GPU_V1 14 15 #include "include/core/SkRect.h" 16 #include "include/core/SkString.h" 17 #include "include/gpu/GrConfig.h" 18 #include "include/private/SkTArray.h" 19 #include "include/private/SkTHash.h" 20 #include "src/gpu/GrRenderTargetProxy.h" 21 22 class GrOp; 23 class SkJSONWriter; 24 25 /* 26 * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them 27 * to json. 28 * 29 * Capturing this information is expensive and consumes a lot of memory, therefore it is important 30 * to enable auditing only when required and disable it promptly. The AutoEnable class helps to 31 * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt 32 * with, be sure to call reset(), or the log will simply keep growing. 33 */ 34 class GrAuditTrail { 35 public: GrAuditTrail()36 GrAuditTrail() : fClientID(kGrAuditTrailInvalidID), fEnabled(false) {} 37 38 class AutoEnable { 39 public: AutoEnable(GrAuditTrail * auditTrail)40 AutoEnable(GrAuditTrail* auditTrail) 41 : fAuditTrail(auditTrail) { 42 SkASSERT(!fAuditTrail->isEnabled()); 43 fAuditTrail->setEnabled(true); 44 } 45 ~AutoEnable()46 ~AutoEnable() { 47 SkASSERT(fAuditTrail->isEnabled()); 48 fAuditTrail->setEnabled(false); 49 } 50 51 private: 52 GrAuditTrail* fAuditTrail; 53 }; 54 55 class AutoManageOpsTask { 56 public: AutoManageOpsTask(GrAuditTrail * auditTrail)57 AutoManageOpsTask(GrAuditTrail* auditTrail) 58 : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {} 59 ~AutoManageOpsTask()60 ~AutoManageOpsTask() { fAuditTrail->fullReset(); } 61 62 private: 63 AutoEnable fAutoEnable; 64 GrAuditTrail* fAuditTrail; 65 }; 66 67 class AutoCollectOps { 68 public: AutoCollectOps(GrAuditTrail * auditTrail,int clientID)69 AutoCollectOps(GrAuditTrail* auditTrail, int clientID) 70 : fAutoEnable(auditTrail), fAuditTrail(auditTrail) { 71 fAuditTrail->setClientID(clientID); 72 } 73 ~AutoCollectOps()74 ~AutoCollectOps() { fAuditTrail->setClientID(kGrAuditTrailInvalidID); } 75 76 private: 77 AutoEnable fAutoEnable; 78 GrAuditTrail* fAuditTrail; 79 }; 80 pushFrame(const char * framename)81 void pushFrame(const char* framename) { 82 SkASSERT(fEnabled); 83 fCurrentStackTrace.push_back(SkString(framename)); 84 } 85 86 void addOp(const GrOp*, GrRenderTargetProxy::UniqueID proxyID); 87 88 void opsCombined(const GrOp* consumer, const GrOp* consumed); 89 90 // Because op combining is heavily dependent on sequence of draw calls, these calls will only 91 // produce valid information for the given draw sequence which preceeded them. Specifically, ops 92 // of future draw calls may combine with previous ops and thus would invalidate the json. What 93 // this means is that for some sequence of draw calls N, the below toJson calls will only 94 // produce JSON which reflects N draw calls. This JSON may or may not be accurate for N + 1 or 95 // N - 1 draws depending on the actual combining algorithm used. 96 void toJson(SkJSONWriter& writer) const; 97 98 // returns a json string of all of the ops associated with a given client id 99 void toJson(SkJSONWriter& writer, int clientID) const; 100 isEnabled()101 bool isEnabled() { return fEnabled; } setEnabled(bool enabled)102 void setEnabled(bool enabled) { fEnabled = enabled; } 103 setClientID(int clientID)104 void setClientID(int clientID) { fClientID = clientID; } 105 106 // We could just return our internal bookkeeping struct if copying the data out becomes 107 // a performance issue, but until then its nice to decouple 108 struct OpInfo { 109 struct Op { 110 int fClientID; 111 SkRect fBounds; 112 }; 113 114 SkRect fBounds; 115 GrSurfaceProxy::UniqueID fProxyUniqueID; 116 SkTArray<Op> fOps; 117 }; 118 119 void getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID); 120 void getBoundsByOpsTaskID(OpInfo* outInfo, int opsTaskID); 121 122 void fullReset(); 123 124 static const int kGrAuditTrailInvalidID; 125 126 private: 127 // TODO if performance becomes an issue, we can move to using SkVarAlloc 128 struct Op { 129 void toJson(SkJSONWriter& writer) const; 130 SkString fName; 131 SkTArray<SkString> fStackTrace; 132 SkRect fBounds; 133 int fClientID; 134 int fOpsTaskID; 135 int fChildID; 136 }; 137 typedef SkTArray<std::unique_ptr<Op>, true> OpPool; 138 139 typedef SkTArray<Op*> Ops; 140 141 struct OpNode { OpNodeOpNode142 OpNode(const GrSurfaceProxy::UniqueID& proxyID) : fProxyUniqueID(proxyID) { } 143 void toJson(SkJSONWriter& writer) const; 144 145 SkRect fBounds; 146 Ops fChildren; 147 const GrSurfaceProxy::UniqueID fProxyUniqueID; 148 }; 149 typedef SkTArray<std::unique_ptr<OpNode>, true> OpsTask; 150 151 void copyOutFromOpsTask(OpInfo* outOpInfo, int opsTask); 152 153 template <typename T> 154 static void JsonifyTArray(SkJSONWriter& writer, const char* name, const T& array); 155 156 OpPool fOpPool; 157 SkTHashMap<uint32_t, int> fIDLookup; 158 SkTHashMap<int, Ops*> fClientIDLookup; 159 OpsTask fOpsTask; 160 SkTArray<SkString> fCurrentStackTrace; 161 162 // The client can pass in an optional client ID which we will use to mark the ops 163 int fClientID; 164 bool fEnabled; 165 }; 166 167 #define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \ 168 if (audit_trail->isEnabled()) audit_trail->invoke(__VA_ARGS__) 169 170 #define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \ 171 GR_AUDIT_TRAIL_INVOKE_GUARD((audit_trail), pushFrame, framename) 172 173 #define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, proxy_id) \ 174 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, proxy_id) 175 176 #define GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(audit_trail, combineWith, op) \ 177 GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, opsCombined, combineWith, op) 178 179 #else // SK_GPU_V1 180 181 class GrAuditTrail { 182 }; 183 184 #define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) 185 #define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, proxy_id) 186 #define GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(audit_trail, combineWith, op) 187 188 #endif // SK_GPU_V1 189 #endif // GrAuditTrail_DEFINED 190