Counters.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include "anki/util/StdTypes.h"
  7. #include "anki/util/Singleton.h"
  8. #include "anki/util/DArray.h"
  9. #include "anki/util/File.h"
  10. #include "anki/util/HighRezTimer.h"
  11. #include "anki/util/Atomic.h"
  12. #include "anki/util/Thread.h"
  13. #include "anki/core/Timestamp.h"
  14. namespace anki {
  15. /// Enumeration of counters
  16. enum class Counter
  17. {
  18. FPS,
  19. MAIN_RENDERER_TIME,
  20. RENDERER_MS_TIME,
  21. RENDERER_IS_TIME,
  22. RENDERER_PPS_TIME,
  23. RENDERER_SHADOW_PASSES,
  24. RENDERER_LIGHTS_COUNT,
  25. SCENE_UPDATE_TIME,
  26. SWAP_BUFFERS_TIME,
  27. GL_CLIENT_WAIT_TIME,
  28. GL_SERVER_WAIT_TIME,
  29. GL_DRAWCALLS_COUNT,
  30. GL_VERTICES_COUNT,
  31. GL_QUEUES_SIZE,
  32. GL_CLIENT_BUFFERS_SIZE,
  33. COUNT
  34. };
  35. /// The counters manager. It's been used with a singleton
  36. class CountersManager
  37. {
  38. public:
  39. CountersManager()
  40. {}
  41. ~CountersManager();
  42. ANKI_USE_RESULT Error create(
  43. HeapAllocator<U8> alloc, const CString& cacheDir,
  44. const Timestamp* globalTimestamp);
  45. void increaseCounter(Counter counter, F64 val);
  46. void increaseCounter(Counter counter, U64 val);
  47. /// Write the counters of the frame. Should be called after swapbuffers
  48. void resolveFrame();
  49. /// Resolve all counters and closes the files. Should be called when app
  50. /// terminates
  51. void flush();
  52. /// Start a timer of a specific counter
  53. void startTimer(Counter counter);
  54. /// Stop the timer and increase the counter
  55. void stopTimerIncreaseCounter(Counter counter);
  56. private:
  57. union Value
  58. {
  59. F64 m_float;
  60. U64 m_int;
  61. };
  62. const Timestamp* m_globalTimestamp = nullptr;
  63. HeapAllocator<U8> m_alloc;
  64. File m_perframeFile;
  65. File m_perrunFile;
  66. DArray<Value> m_perframeValues;
  67. DArray<Value> m_perrunValues;
  68. DArray<HighRezTimer::Scalar> m_counterTimes;
  69. };
  70. /// The singleton of the counters manager
  71. typedef Singleton<CountersManager> CountersManagerSingleton;
  72. // Macros that encapsulate the functionaly
  73. #if ANKI_ENABLE_COUNTERS
  74. # define ANKI_COUNTER_INC(counter_, val_) \
  75. CountersManagerSingleton::get().increaseCounter(Counter::counter_, val_)
  76. # define ANKI_COUNTER_START_TIMER(counter_) \
  77. CountersManagerSingleton::get().startTimer(Counter::counter_)
  78. # define ANKI_COUNTER_STOP_TIMER_INC(counter_) \
  79. CountersManagerSingleton::get(). \
  80. stopTimerIncreaseCounter(Counter::counter_)
  81. # define ANKI_COUNTERS_RESOLVE_FRAME() \
  82. CountersManagerSingleton::get().resolveFrame()
  83. # define ANKI_COUNTERS_FLUSH() \
  84. CountersManagerSingleton::get().flush()
  85. #else // !ANKI_ENABLE_COUNTERS
  86. # define ANKI_COUNTER_INC(counter_, val_) ((void)0)
  87. # define ANKI_COUNTER_START_TIMER(counter_) ((void)0)
  88. # define ANKI_COUNTER_STOP_TIMER_INC(counter_) ((void)0)
  89. # define ANKI_COUNTERS_RESOLVE_FRAME() ((void)0)
  90. # define ANKI_COUNTERS_FLUSH() ((void)0)
  91. #endif // ANKI_ENABLE_COUNTERS
  92. // Forward
  93. class ThreadTraceManager;
  94. /// Trace manager per process.
  95. class TraceManager
  96. {
  97. public:
  98. Array<ThreadTraceManager*, 32> m_threadData;
  99. Atomic<U32> m_threadCount = {0};
  100. File m_traceFile;
  101. Mutex m_fileMtx;
  102. TraceManager()
  103. {}
  104. ~TraceManager();
  105. ANKI_USE_RESULT Error create(
  106. HeapAllocator<U8>& alloc, const CString& storeDir);
  107. void flushAll();
  108. void flush(ThreadTraceManager& thread);
  109. };
  110. using TraceManagerSingleton = Singleton<TraceManager>;
  111. /// Trace manager per thread.
  112. class ThreadTraceManager
  113. {
  114. public:
  115. static const U MAX_DEPTH = 4;
  116. static const U BUFFERED_EVENTS_COUNT = 16;
  117. class Event
  118. {
  119. public:
  120. F64 m_startTime = 0.0;
  121. F64 m_stopTime = 0.0;
  122. const char* m_name;
  123. U32 m_depth = 0;
  124. };
  125. TraceManager* m_master = nullptr; ///< Cache it
  126. U32 m_id = 0;
  127. Array<Event, MAX_DEPTH> m_inflightEvents; ///< Stack
  128. U32 m_depth = 0;
  129. Array<Event, BUFFERED_EVENTS_COUNT> m_bufferedEvents;
  130. U32 m_bufferedEventsCount = 0;
  131. ThreadTraceManager();
  132. /// Begin a new event
  133. void pushEvent(const char* name);
  134. /// Stop an already started event
  135. void popEvent();
  136. };
  137. using ThreadTraceManagerSingleton = SingletonThreadSafe<ThreadTraceManager>;
  138. /// @name Trace macros.
  139. /// @{
  140. #if ANKI_ENABLE_COUNTERS
  141. # define ANKI_TRACE_PUSH_EVENT(name_) \
  142. ThreadTraceManagerSingleton::get().pushEvent(name_)
  143. # define ANKI_TRACE_POP_EVENT() \
  144. ThreadTraceManagerSingleton::get().popEvent()
  145. # define ANKI_TRACE_FLUSH() \
  146. TraceManagerSingleton::get().flushAll()
  147. #else
  148. # define ANKI_TRACE_PUSH_EVENT(name_) ((void)0)
  149. # define ANKI_TRACE_POP_EVENT() ((void)0)
  150. # define ANKI_TRACE_FLUSH() ((void)0)
  151. #endif
  152. /// @}
  153. } // end namespace anki