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