SuperTuxKart
profiler.hpp
1 // SuperTuxKart - a fun racing game with go-kart
2 // Copyright (C) 2004-2015 SuperTuxKart-Team
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 3
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 
18 #ifndef PROFILER_HPP
19 #define PROFILER_HPP
20 
21 #include "utils/synchronised.hpp"
22 
23 #include <assert.h>
24 #include <atomic>
25 #include <iostream>
26 #include <list>
27 #include <map>
28 #include <ostream>
29 #include <stack>
30 #include <streambuf>
31 #include <string>
32 #include <vector>
33 
34 #include <vector2d.h>
35 #include <SColor.h>
36 using namespace irr;
37 
38 enum QueryPerf
39 {
40  Q_SHADOWS_CASCADE0,
41  Q_SHADOWS_CASCADE1,
42  Q_SHADOWS_CASCADE2,
43  Q_SHADOWS_CASCADE3,
44  Q_SOLID_PASS,
45  Q_ENVMAP,
46  Q_SUN,
47  Q_POINTLIGHTS,
48  Q_SSAO,
49  Q_LIGHTSCATTER,
50  Q_GLOW,
51  Q_COMBINE_DIFFUSE_COLOR,
52  Q_SKYBOX,
53  Q_TRANSPARENT,
54  Q_PARTICLES,
55  Q_DOF,
56  Q_GODRAYS,
57  Q_BLOOM,
58  Q_TONEMAP,
59  Q_MOTIONBLUR,
60  Q_LIGHTNING,
61  Q_MLAA,
62  Q_GUI,
63  Q_LAST
64 };
65 
66 class Profiler;
67 extern Profiler profiler;
68 
69 double getTimeMilliseconds();
70 
71 #define MAX_ANALYZED_FPS 1000
72 #define ENABLE_PROFILER
73 
74 #ifdef ENABLE_PROFILER
75  #define PROFILER_PUSH_CPU_MARKER(name, r, g, b) \
76  profiler.pushCPUMarker(name, video::SColor(0xFF, r, g, b))
77 
78  #define PROFILER_POP_CPU_MARKER() \
79  profiler.popCPUMarker()
80 
81  #define PROFILER_SYNC_FRAME() \
82  profiler.synchronizeFrame()
83 
84  #define PROFILER_DRAW() \
85  profiler.draw()
86 #else
87  #define PROFILER_PUSH_CPU_MARKER(name, r, g, b)
88  #define PROFILER_POP_CPU_MARKER()
89  #define PROFILER_SYNC_FRAME()
90  #define PROFILER_DRAW()
91 #endif
92 
93 using namespace irr;
94 
95 // ============================================================================
100 class Profiler
101 {
102 private:
103  // ------------------------------------------------------------------------
104  class Marker
105  {
106  private:
109  double m_start;
110 
114  double m_duration;
117  size_t m_layer;
118  public:
119  // --------------------------------------------------------------------
120  Marker() { m_start = 0; m_duration = 0; m_layer = 0; }
121 
122  // --------------------------------------------------------------------
123  Marker(double start, size_t layer=0)
124  : m_start(start), m_duration(0), m_layer(layer)
125  {
126  }
127  // --------------------------------------------------------------------
128  Marker(const Marker& ref)
129  : m_start(ref.m_start), m_duration(ref.m_duration),
130  m_layer(ref.m_layer)
131  {
132  }
133  // --------------------------------------------------------------------
135  double getStart() const { return m_start; }
136  // --------------------------------------------------------------------
138  double getEnd() const { return m_start+m_duration; }
139  // --------------------------------------------------------------------
141  double getDuration() const { return m_duration; }
142  // --------------------------------------------------------------------
143  size_t getLayer() const { return m_layer; }
144  // --------------------------------------------------------------------
147  void clear() { m_duration = 0; }
148  // --------------------------------------------------------------------
150  void setStart(double start, size_t layer = 0)
151  {
152  m_start = start; m_layer = layer;
153  } // setStart
154  // --------------------------------------------------------------------
156  void setEnd(double end)
157  {
158  m_duration += (end - m_start);
159  } // setEnd
160 
161  }; // class Marker
162 
163  // ========================================================================
167  class EventData
168  {
169  private:
171  video::SColor m_colour;
172 
174  std::vector<Marker> m_all_markers;
175 
176  public:
177  EventData() {}
178  EventData(video::SColor colour, int max_size)
179  {
180  m_all_markers.resize(max_size);
181  m_colour = colour;
182  } // EventData
183  // --------------------------------------------------------------------
185  void setStart(size_t frame, double start, int layer)
186  {
187  assert(frame < m_all_markers.capacity());
188  m_all_markers[frame].setStart(start, layer);
189  } // setStart
190  // --------------------------------------------------------------------
192  void setEnd(size_t frame, double end)
193  {
194  assert(frame < m_all_markers.capacity());
195  m_all_markers[frame].setEnd(end);
196  } // setEnd
197  // --------------------------------------------------------------------
198  const Marker& getMarker(int n) const { return m_all_markers[n]; }
199  Marker& getMarker(int n) { return m_all_markers[n]; }
200  // --------------------------------------------------------------------
202  video::SColor getColour() const { return m_colour; }
203  // --------------------------------------------------------------------
204  }; // EventData
205 
206  // ========================================================================
208  typedef std::map<std::string, EventData> AllEventData;
209  // ========================================================================
210  struct ThreadData
211  {
213  std::vector< std::string > m_event_stack;
214 
219  std::vector<std::string> m_ordered_headings;
220 
221  AllEventData m_all_event_data;
222  }; // class ThreadData
223 
224  // ========================================================================
225 
228  std::vector< ThreadData> m_all_threads_data;
229 
231  std::vector<int> m_gpu_times;
232 
234  std::atomic<int> m_threads_used;
235 
238 
244 
246  std::vector<int> m_frame_times;
247 
252 
255 
257  int m_slow_frames[MAX_ANALYZED_FPS];
258 
260  int m_time_spent_in_slow_frames[MAX_ANALYZED_FPS];
261 
263  int m_time_waited_in_slow_frames[MAX_ANALYZED_FPS];
264 
267 
270 
273 
276 
278  bool m_drawing;
279 
283 
287 
290 
294  std::vector<std::string> m_all_event_names;
295 
296  // Handling freeze/unfreeze by clicking on the display
297  enum FreezeState
298  {
299  UNFROZEN,
300  WAITING_FOR_FREEZE,
301  FROZEN,
302  WAITING_FOR_UNFREEZE,
303  };
304 
305  FreezeState m_freeze_state;
306 
307 private:
308  int getThreadID();
309  void drawBackground();
310 
311 public:
312  Profiler();
313  virtual ~Profiler();
314  void init();
315  void reset();
316  void pushCPUMarker(const char* name="N/A",
317  const video::SColor& color=video::SColor());
318  void popCPUMarker();
319  void activate();
320  void desactivate();
321  void synchronizeFrame();
322  void draw();
323  void onClick(const core::vector2di& mouse_pos);
324  void computeStableFPS();
325  void startBenchmark();
326  void writeToFile();
327 
328  // ------------------------------------------------------------------------
329  bool isFrozen() const { return m_freeze_state == FROZEN; }
330  // ------------------------------------------------------------------------
331  void setDrawing(bool drawing) { m_drawing = drawing; }
332 
333  int getTotalFrametime() { return m_total_frametime; }
334  int getTotalFrames() { return m_total_frames; }
335  int getFPSMetricsHigh() { return m_fps_metrics_high; }
336  int getFPSMetricsMid() { return m_fps_metrics_mid; }
337  int getFPSMetricsLow() { return m_fps_metrics_low; }
338 };
339 #endif // PROFILER_HPP
The data for one event.
Definition: profiler.hpp:168
void setStart(size_t frame, double start, int layer)
Records the start of an event for a given frame.
Definition: profiler.hpp:185
std::vector< Marker > m_all_markers
Vector of all buffered markers.
Definition: profiler.hpp:174
video::SColor getColour() const
Returns the colour for this event.
Definition: profiler.hpp:202
video::SColor m_colour
Colour to use in the on-screen display.
Definition: profiler.hpp:171
void setEnd(size_t frame, double end)
Records the end of an event for a given frame.
Definition: profiler.hpp:192
Definition: profiler.hpp:105
void setStart(double start, size_t layer=0)
Sets start time and layer for this event.
Definition: profiler.hpp:150
double m_start
An event that is started (pushed) stores the start time in this variable.
Definition: profiler.hpp:109
double m_duration
Duration of the event in this frame (accumulated if this event should be recorded more than once).
Definition: profiler.hpp:114
double getEnd() const
Returns the end time of this event marker.
Definition: profiler.hpp:138
double getDuration() const
Returns the duration of this event.
Definition: profiler.hpp:141
double getStart() const
Returns the start time of this event marker.
Definition: profiler.hpp:135
void setEnd(double end)
Sets the end time of this event.
Definition: profiler.hpp:156
size_t m_layer
Distance of marker from root (for nested events), used to adjust vertical height when drawing.
Definition: profiler.hpp:117
void clear()
Called when an entry in the cyclic buffer is reused.
Definition: profiler.hpp:147
class that allows run-time graphical profiling through the use of markers.
Definition: profiler.hpp:101
std::vector< int > m_gpu_times
Buffer for the GPU times (in ms).
Definition: profiler.hpp:231
int m_fps_metrics_mid
Store the highest FPS with <12% time in slow frames and < 2% time waited beyond maximum duration.
Definition: profiler.hpp:269
double m_time_between_sync
Time between now and last sync, used to scale the GUI bar.
Definition: profiler.hpp:289
std::vector< ThreadData > m_all_threads_data
Data structure containing all currently buffered markers.
Definition: profiler.hpp:228
std::vector< std::string > m_all_event_names
List of all event names.
Definition: profiler.hpp:294
Synchronised< bool > m_lock
We don't need the bool, but easiest way to get a lock for the whole instance (since we need to avoid ...
Definition: profiler.hpp:243
int m_fps_metrics_low
Store the highest FPS with < 1% time in slow frames and <0.1% time waited beyond maximum duration.
Definition: profiler.hpp:272
int m_total_frames
Stores the frame count.
Definition: profiler.hpp:254
bool m_drawing
True if the profiler UI should be rendered.
Definition: profiler.hpp:278
std::map< std::string, EventData > AllEventData
The mapping of event names to the corresponding EventData.
Definition: profiler.hpp:208
int m_max_frames
The maximum number of frames to be buffered.
Definition: profiler.hpp:282
int m_fps_metrics_high
Store the highest FPS with <50% time in slow frames and < 10% time waited beyond maximum duration.
Definition: profiler.hpp:266
double m_time_last_sync
Time of last sync.
Definition: profiler.hpp:286
std::atomic< int > m_threads_used
Counts the threads used.
Definition: profiler.hpp:234
int m_current_frame
Index of the current frame in the buffer.
Definition: profiler.hpp:237
bool m_has_wrapped_around
True if the circular buffer has wrapped around.
Definition: profiler.hpp:275
int m_total_frametime
Stores the total duration of the frames analyzed (in µs), once FPS metrics are computed.
Definition: profiler.hpp:251
std::vector< int > m_frame_times
Stores the frame times (in µs), once FPS metrics are computed.
Definition: profiler.hpp:246
Definition: profiler.hpp:211
std::vector< std::string > m_ordered_headings
This stores the event names in the order in which they occur.
Definition: profiler.hpp:219
std::vector< std::string > m_event_stack
Stack of events to detect nesting.
Definition: profiler.hpp:213