127a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt/* 227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * Copyright 2016 Google Inc. 327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * 427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * Use of this source code is governed by a BSD-style license that can be 527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * found in the LICENSE file. 627a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt */ 727a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 827a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#ifndef GrAuditTrail_DEFINED 927a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#define GrAuditTrail_DEFINED 1027a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 115651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt#include "GrConfig.h" 12294870ff119b89fc902773643b054f14e5d1f554Robert Phillips#include "GrGpuResource.h" 13086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt#include "SkRect.h" 1427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#include "SkString.h" 1527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#include "SkTArray.h" 1618d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#include "SkTHash.h" 1718d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 1825a880960a9a689a745a01071ecba3fe494b5940Brian Salomonclass GrOp; 1927a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 2027a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt/* 2127a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them 2227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt * to json. 23c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas * 24c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas * Capturing this information is expensive and consumes a lot of memory, therefore it is important 25c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas * to enable auditing only when required and disable it promptly. The AutoEnable class helps to 26c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt 27c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas * with, be sure to call reset(), or the log will simply keep growing. 2827a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt */ 2927a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualittclass GrAuditTrail { 3027a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualittpublic: 31c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas GrAuditTrail() 32b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt : fClientID(kGrAuditTrailInvalidID) 33b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt , fEnabled(false) {} 3487a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt 35c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas class AutoEnable { 36c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas public: 37c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas AutoEnable(GrAuditTrail* auditTrail) 38c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas : fAuditTrail(auditTrail) { 39c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas SkASSERT(!fAuditTrail->isEnabled()); 40c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas fAuditTrail->setEnabled(true); 41c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas } 42c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas 43c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas ~AutoEnable() { 44c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas SkASSERT(fAuditTrail->isEnabled()); 45c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas fAuditTrail->setEnabled(false); 46c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas } 47c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas 48c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas private: 49c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas GrAuditTrail* fAuditTrail; 50c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas }; 51c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas 5242ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon class AutoManageOpList { 5318d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt public: 5442ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon AutoManageOpList(GrAuditTrail* auditTrail) 5542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {} 5618d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 5742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon ~AutoManageOpList() { fAuditTrail->fullReset(); } 5818d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 5918d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt private: 6018d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt AutoEnable fAutoEnable; 6118d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt GrAuditTrail* fAuditTrail; 6218d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt }; 6318d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 6442ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon class AutoCollectOps { 65b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt public: 6642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon AutoCollectOps(GrAuditTrail* auditTrail, int clientID) 6742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon : fAutoEnable(auditTrail), fAuditTrail(auditTrail) { 68b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt fAuditTrail->setClientID(clientID); 6987a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt } 7087a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt 7142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon ~AutoCollectOps() { fAuditTrail->setClientID(kGrAuditTrailInvalidID); } 7227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 73b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt private: 74b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt AutoEnable fAutoEnable; 75b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt GrAuditTrail* fAuditTrail; 76b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt }; 7787a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt 78f55c3644850409c9410051c7a7f18af8d65bf990joshualitt void pushFrame(const char* framename) { 79f55c3644850409c9410051c7a7f18af8d65bf990joshualitt SkASSERT(fEnabled); 80f55c3644850409c9410051c7a7f18af8d65bf990joshualitt fCurrentStackTrace.push_back(SkString(framename)); 81f55c3644850409c9410051c7a7f18af8d65bf990joshualitt } 82f55c3644850409c9410051c7a7f18af8d65bf990joshualitt 8369868af68403bd12aee040187347426affe41accBrian Salomon void addOp(const GrOp*, GrGpuResource::UniqueID renderTargetID); 84086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt 8542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon void opsCombined(const GrOp* consumer, const GrOp* consumed); 8618d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 8742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // Because op combining is heavily dependent on sequence of draw calls, these calls will only 8842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // produce valid information for the given draw sequence which preceeded them. Specifically, ops 8942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // of future draw calls may combine with previous ops and thus would invalidate the json. What 9042ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // this means is that for some sequence of draw calls N, the below toJson calls will only 9142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // produce JSON which reflects N draw calls. This JSON may or may not be accurate for N + 1 or 9242ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // N - 1 draws depending on the actual combining algorithm used. 93b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt SkString toJson(bool prettyPrint = false) const; 94b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt 9542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // returns a json string of all of the ops associated with a given client id 96b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt SkString toJson(int clientID, bool prettyPrint = false) const; 9727a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 98c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas bool isEnabled() { return fEnabled; } 99c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas void setEnabled(bool enabled) { fEnabled = enabled; } 100c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas 101b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt void setClientID(int clientID) { fClientID = clientID; } 10218d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 10310d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt // We could just return our internal bookkeeping struct if copying the data out becomes 10410d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt // a performance issue, but until then its nice to decouple 10542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon struct OpInfo { 10642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon SkRect fBounds; 107294870ff119b89fc902773643b054f14e5d1f554Robert Phillips // TODO: switch over to GrSurfaceProxy::UniqueID 108294870ff119b89fc902773643b054f14e5d1f554Robert Phillips GrGpuResource::UniqueID fRenderTargetUniqueID; 10942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon struct Op { 11010d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt int fClientID; 11110d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt SkRect fBounds; 11210d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt }; 11342ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon SkTArray<Op> fOps; 11410d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt }; 11510d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt 11642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon void getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID); 11742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon void getBoundsByOpListID(OpInfo* outInfo, int opListID); 11810d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt 119df3f2b0948507d20e72b16869f1b2bb1abdf4b40joshualitt void fullReset(); 12018d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 121b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt static const int kGrAuditTrailInvalidID; 12227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 12327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualittprivate: 12411fae87d39811882e3e99b4abc72c9713a38da55joshualitt // TODO if performance becomes an issue, we can move to using SkVarAlloc 12542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon struct Op { 126b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt SkString toJson() const; 127b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt SkString fName; 128f55c3644850409c9410051c7a7f18af8d65bf990joshualitt SkTArray<SkString> fStackTrace; 129b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt SkRect fBounds; 130b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt int fClientID; 13142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon int fOpListID; 132b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt int fChildID; 13327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt }; 13442ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon typedef SkTArray<std::unique_ptr<Op>, true> OpPool; 13527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 13642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon typedef SkTArray<Op*> Ops; 13711fae87d39811882e3e99b4abc72c9713a38da55joshualitt 13842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon struct OpNode { 13942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon OpNode(const GrGpuResource::UniqueID& id) : fRenderTargetUniqueID(id) {} 140b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt SkString toJson() const; 141294870ff119b89fc902773643b054f14e5d1f554Robert Phillips SkRect fBounds; 14242ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon Ops fChildren; 143294870ff119b89fc902773643b054f14e5d1f554Robert Phillips const GrGpuResource::UniqueID fRenderTargetUniqueID; 14411fae87d39811882e3e99b4abc72c9713a38da55joshualitt }; 14542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon typedef SkTArray<std::unique_ptr<OpNode>, true> OpList; 14611fae87d39811882e3e99b4abc72c9713a38da55joshualitt 14742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon void copyOutFromOpList(OpInfo* outOpInfo, int opListID); 14846b301d2222b60dd5ab495b917dea163e8be94efjoshualitt 14918d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt template <typename T> 15018d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt static void JsonifyTArray(SkString* json, const char* name, const T& array, 151adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt bool addComma); 1526bd5284415bd983b0628c4941dff5def40018f5abungeman 15342ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon OpPool fOpPool; 154b0666ad3a9e99ce1a6e6d9ea69ff9f1ddbe74594joshualitt SkTHashMap<uint32_t, int> fIDLookup; 15542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon SkTHashMap<int, Ops*> fClientIDLookup; 15642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon OpList fOpList; 157f55c3644850409c9410051c7a7f18af8d65bf990joshualitt SkTArray<SkString> fCurrentStackTrace; 158b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt 15942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon // The client can pass in an optional client ID which we will use to mark the ops 160b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt int fClientID; 161b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt bool fEnabled; 16227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt}; 16327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt 164c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \ 165c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas if (audit_trail->isEnabled()) { \ 166c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas audit_trail->invoke(__VA_ARGS__); \ 1675651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt } 1685651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt 16987a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \ 170f55c3644850409c9410051c7a7f18af8d65bf990joshualitt GR_AUDIT_TRAIL_INVOKE_GUARD((audit_trail), pushFrame, framename); 1715651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt 1725651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt#define GR_AUDIT_TRAIL_RESET(audit_trail) \ 173f55c3644850409c9410051c7a7f18af8d65bf990joshualitt //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset); 1745651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt 17569868af68403bd12aee040187347426affe41accBrian Salomon#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, rt_id) \ 17669868af68403bd12aee040187347426affe41accBrian Salomon GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, rt_id); 177086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt 17842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(audit_trail, combineWith, op) \ 17942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, opsCombined, combineWith, op); 18018d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 18142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define GR_AUDIT_TRAIL_OP_RESULT_NEW(audit_trail, op) // Doesn't do anything now, one day... 18218d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt 18327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#endif 184