Tracer.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/Thread.h>
  7. #include <AnKi/Util/WeakArray.h>
  8. #include <AnKi/Util/DynamicArray.h>
  9. #include <AnKi/Util/Singleton.h>
  10. #include <AnKi/Util/String.h>
  11. #include <AnKi/Util/Logger.h>
  12. namespace anki {
  13. /// @addtogroup util_other
  14. /// @{
  15. #if ANKI_TRACING_ENABLED
  16. /// @memberof Tracer
  17. class TracerEventHandle
  18. {
  19. friend class Tracer;
  20. private:
  21. Second m_start;
  22. };
  23. /// @memberof Tracer
  24. class TracerEvent
  25. {
  26. public:
  27. CString m_name;
  28. Second m_start;
  29. Second m_duration;
  30. TracerEvent()
  31. {
  32. // No init
  33. }
  34. };
  35. /// @memberof Tracer
  36. class TracerCounter
  37. {
  38. public:
  39. CString m_name;
  40. U64 m_value;
  41. TracerCounter()
  42. {
  43. // No init
  44. }
  45. };
  46. /// Tracer flush callback.
  47. /// @memberof Tracer
  48. using TracerFlushCallback = void (*)(void* userData, ThreadId tid, ConstWeakArray<TracerEvent> events, ConstWeakArray<TracerCounter> counters);
  49. /// Tracer.
  50. class Tracer : public MakeSingleton<Tracer>
  51. {
  52. template<typename>
  53. friend class MakeSingleton;
  54. public:
  55. Tracer(const Tracer&) = delete; // Non-copyable
  56. Tracer& operator=(const Tracer&) = delete; // Non-copyable
  57. /// Begin a new event.
  58. /// @note It's thread-safe.
  59. [[nodiscard]] TracerEventHandle beginEvent(const char* eventName);
  60. /// End the event that got started with beginEvent().
  61. /// @note It's thread-safe.
  62. void endEvent(const char* eventName, TracerEventHandle event);
  63. /// Add a custom event.
  64. /// @note It's thread-safe.
  65. void addCustomEvent(const char* eventName, Second start, Second duration);
  66. /// Increment a counter.
  67. /// @note It's thread-safe.
  68. void incrementCounter(const char* counterName, U64 value);
  69. /// Flush all counters and events and start clean. The callback will be called multiple times.
  70. /// @note It's thread-safe.
  71. void flush(TracerFlushCallback callback, void* callbackUserData);
  72. Bool getEnabled() const
  73. {
  74. return m_enabled;
  75. }
  76. void setEnabled(Bool enabled)
  77. {
  78. ANKI_UTIL_LOGI("Tracing %s", (enabled) ? "enabled" : "disabled");
  79. m_enabled = enabled;
  80. }
  81. # if ANKI_OS_ANDROID
  82. Bool getStreamlineEnabled() const
  83. {
  84. return m_streamlineEnabled;
  85. }
  86. void setStreamlineEnabled(Bool enabled)
  87. {
  88. ANKI_UTIL_LOGI("Streamline annotations %s", (enabled) ? "enabled" : "disabled");
  89. m_streamlineEnabled = enabled;
  90. }
  91. # endif
  92. # if ANKI_GR_BACKEND_DIRECT3D
  93. Bool getPixEnabled() const
  94. {
  95. return m_pixEnabled;
  96. }
  97. void setPixEnabled(Bool enabled)
  98. {
  99. ANKI_UTIL_LOGI("PIX CPU annotations %s", (enabled) ? "enabled" : "disabled");
  100. m_pixEnabled = enabled;
  101. }
  102. # endif
  103. private:
  104. static constexpr U32 kEventsPerChunk = 256;
  105. static constexpr U32 kCountersPerChunk = 512;
  106. class ThreadLocal;
  107. class Chunk;
  108. static thread_local ThreadLocal* m_threadLocal;
  109. /// The Tracer should know about all the ThreadLocal.
  110. DynamicArray<ThreadLocal*, SingletonMemoryPoolWrapper<DefaultMemoryPool>> m_allThreadLocal;
  111. Mutex m_allThreadLocalMtx;
  112. Bool m_enabled = false;
  113. # if ANKI_OS_ANDROID
  114. Bool m_streamlineEnabled = false;
  115. # endif
  116. # if ANKI_GR_BACKEND_DIRECT3D
  117. Bool m_pixEnabled = true;
  118. # endif
  119. Tracer();
  120. ~Tracer();
  121. /// Get the thread local ThreadLocal structure.
  122. /// @note Thread-safe.
  123. ThreadLocal& getThreadLocal();
  124. /// Get or create a new chunk.
  125. Chunk& getOrCreateChunk(ThreadLocal& tlocal);
  126. };
  127. /// Scoped tracer event.
  128. class TracerScopedEvent
  129. {
  130. public:
  131. TracerScopedEvent(const char* name)
  132. : m_name(name)
  133. {
  134. m_handle = Tracer::getSingleton().beginEvent(name);
  135. }
  136. ~TracerScopedEvent()
  137. {
  138. Tracer::getSingleton().endEvent(m_name, m_handle);
  139. }
  140. private:
  141. const char* m_name;
  142. TracerEventHandle m_handle;
  143. };
  144. # define ANKI_TRACE_SCOPED_EVENT(name_) TracerScopedEvent _tse##name_(ANKI_STRINGIZE(ANKI_CONCATENATE(t, name_)))
  145. # define ANKI_TRACE_CUSTOM_EVENT(name_, start_, duration_) \
  146. Tracer::getSingleton().addCustomEvent(ANKI_STRINGIZE(ANKI_CONCATENATE(t, name_)), start_, duration_)
  147. # define ANKI_TRACE_FUNCTION() TracerScopedEvent ANKI_CONCATENATE(_tse, __LINE__)(ANKI_FUNC)
  148. # define ANKI_TRACE_INC_COUNTER(name_, val_) Tracer::getSingleton().incrementCounter(ANKI_STRINGIZE(ANKI_CONCATENATE(c, name_)), val_)
  149. #else
  150. # define ANKI_TRACE_SCOPED_EVENT(name_) ((void)0)
  151. # define ANKI_TRACE_CUSTOM_EVENT(name_, start_, duration_) ((void)0)
  152. # define ANKI_TRACE_FUNCTION() ((void)0)
  153. # define ANKI_TRACE_INC_COUNTER(name_, val_) ((void)0)
  154. #endif
  155. /// @}
  156. } // end namespace anki