GrAuditTrail.h 5.8 KB

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