Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/OgreProfiler.h @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 16.5 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29/*
30
31    Although the code is original, many of the ideas for the profiler were borrowed from
32"Real-Time In-Game Profiling" by Steve Rabin which can be found in Game Programming
33Gems 1.
34
35    This code can easily be adapted to your own non-Ogre project. The only code that is
36Ogre-dependent is in the visualization/logging routines and the use of the Timer class.
37
38    Enjoy!
39
40*/
41
42#ifndef __Profiler_H__
43#define __Profiler_H__
44
45#include "OgrePrerequisites.h"
46#include "OgreSingleton.h"
47#include "OgreString.h"
48#include "OgreOverlay.h"
49
50#if OGRE_PROFILING == 1
51#   if OGRE_COMPILER != OGRE_COMPILER_BORL
52#       define OgreProfile( a ) Ogre::Profile _OgreProfileInstance( (a) )
53#       define OgreProfileBegin( a ) Ogre::Profiler::getSingleton().beginProfile( (a) )
54#       define OgreProfileEnd( a ) Ogre::Profiler::getSingleton().endProfile( (a) )
55#   else
56#           define OgreProfile( a ) Ogre::Profile _OgreProfileInstance( __FUNC__ )
57#           define OgreProfileBegin( a ) Ogre::Profiler::getSingleton().beginProfile( __FUNC__ )
58#           define OgreProfileEnd( a ) Ogre::Profiler::getSingleton().endProfile( __FUNC__ )
59#   endif
60#else
61#   define OgreProfile( a )
62#   define OgreProfileBegin( a )
63#   define OgreProfileEnd( a )
64#endif
65
66namespace Ogre {
67
68    /** An individual profile that will be processed by the Profiler
69        @remarks
70            Use the macro OgreProfile(name) instead of instantiating this profile directly
71        @remarks
72            We use this Profile to allow scoping rules to signify the beginning and end of
73            the profile. Use the Profiler singleton (through the macro OgreProfileBegin(name)
74            and OgreProfileEnd(name)) directly if you want a profile to last
75            outside of a scope (ie the main game loop).
76        @author Amit Mathew (amitmathew (at) yahoo (dot) com)
77    */
78    class _OgreExport Profile {
79
80        public:
81            Profile(const String& profileName);
82            ~Profile();
83
84        protected:
85
86            /// The name of this profile
87            String mName;
88                       
89
90    };
91
92    /** The profiler allows you to measure the performance of your code
93        @remarks
94            Do not create profiles directly from this unless you want a profile to last
95            outside of its scope (ie the main game loop). For most cases, use the macro
96            OgreProfile(name) and braces to limit the scope. You must enable the Profile
97            before you can used it with setEnabled(true). If you want to disable profiling
98            in Ogre, simply set the macro OGRE_PROFILING to 0.
99        @author Amit Mathew (amitmathew (at) yahoo (dot) com)
100        @todo resolve artificial cap on number of profiles displayed
101        @todo fix display ordering of profiles not called every frame
102    */
103    class _OgreExport Profiler : public Singleton<Profiler> {
104
105        public:
106            Profiler();
107            ~Profiler();
108
109            /** Sets the timer for the profiler */
110            void setTimer(Timer* t);
111
112            /** Retrieves the timer for the profiler */
113            Timer* getTimer();
114
115            /** Begins a profile
116            @remarks
117                Use the macro OgreProfileBegin(name) instead of calling this directly
118                so that profiling can be ignored in the release version of your app.
119            @remarks
120                You only use the macro (or this) if you want a profile to last outside
121                of its scope (ie the main game loop). If you use this function, make sure you
122                use a corresponding OgreProfileEnd(name). Usually you would use the macro
123                OgreProfile(name). This function will be ignored for a profile that has been
124                disabled or if the profiler is disabled.
125            @param profileName Must be unique and must not be an empty string
126            */
127            void beginProfile(const String& profileName);
128
129            /** Ends a profile
130            @remarks
131                Use the macro OgreProfileEnd(name) instead of calling this directly so that
132                profiling can be ignored in the release version of your app.
133            @remarks
134                This function is usually not called directly unless you want a profile to
135                last outside of its scope. In most cases, using the macro OgreProfile(name)
136                which will call this function automatically when it goes out of scope. Make
137                sure the name of this profile matches its corresponding beginProfile name.
138                This function will be ignored for a profile that has been disabled or if the
139                profiler is disabled.
140            */
141            void endProfile(const String& profileName);
142
143            /** Sets whether this profiler is enabled. Only takes effect after the
144                the frame has ended.
145                @remarks When this is called the first time with the parameter true,
146                it initializes the GUI for the Profiler
147            */
148            void setEnabled(bool enabled);
149
150            /** Gets whether this profiler is enabled */
151            bool getEnabled() const;
152
153            /** Enables a previously disabled profile
154            @remarks Only enables the profile if this function is not
155            called during the profile it is trying to enable.
156            */
157            void enableProfile(const String& profileName);
158
159            /** Disables a profile
160            @remarks Only disables the profile if this function is not called during
161            the profile it is trying to disable.
162            */
163            void disableProfile(const String& profileName);
164
165            /** Returns true if the specified profile reaches a new frame time maximum
166            @remarks If this is called during a frame, it will be reading the results
167            from the previous frame. Therefore, it is best to use this after the frame
168            has ended.
169            */
170            bool watchForMax(const String& profileName);
171
172            /** Returns true if the specified profile reaches a new frame time minimum
173            @remarks If this is called during a frame, it will be reading the results
174            from the previous frame. Therefore, it is best to use this after the frame
175            has ended.
176            */
177            bool watchForMin(const String& profileName);
178
179            /** Returns true if the specified profile goes over or under the given limit
180                frame time
181            @remarks If this is called during a frame, it will be reading the results
182            from the previous frame. Therefore, it is best to use this after the frame
183            has ended.
184            @param limit A number between 0 and 1 representing the percentage of frame time
185            @param greaterThan If true, this will return whether the limit is exceeded. Otherwise,
186            it will return if the frame time has gone under this limit.
187            */
188            bool watchForLimit(const String& profileName, Real limit, bool greaterThan = true);
189
190            /** Outputs current profile statistics to the log */
191            void logResults();
192
193            /** Clears the profiler statistics */
194            void reset();
195
196            /** Sets the Profiler so the display of results are updated ever n frames*/
197            void setUpdateDisplayFrequency(uint freq);
198
199            /** Gets the frequency that the Profiler display is updated */
200            uint getUpdateDisplayFrequency() const;
201
202            /** Override standard Singleton retrieval.
203            @remarks
204            Why do we do this? Well, it's because the Singleton
205            implementation is in a .h file, which means it gets compiled
206            into anybody who includes it. This is needed for the
207            Singleton template to work, but we actually only want it
208            compiled into the implementation of the class based on the
209            Singleton, not all of them. If we don't change this, we get
210            link errors when trying to use the Singleton-based class from
211            an outside dll.
212            @par
213            This method just delegates to the template version anyway,
214            but the implementation stays in this single compilation unit,
215            preventing link errors.
216            */
217            static Profiler& getSingleton(void);
218            /** Override standard Singleton retrieval.
219            @remarks
220            Why do we do this? Well, it's because the Singleton
221            implementation is in a .h file, which means it gets compiled
222            into anybody who includes it. This is needed for the
223            Singleton template to work, but we actually only want it
224            compiled into the implementation of the class based on the
225            Singleton, not all of them. If we don't change this, we get
226            link errors when trying to use the Singleton-based class from
227            an outside dll.
228            @par
229            This method just delegates to the template version anyway,
230            but the implementation stays in this single compilation unit,
231            preventing link errors.
232            */
233            static Profiler* getSingletonPtr(void);
234
235        protected:
236
237            /** Initializes the profiler's gui elements */
238            void initialize();
239
240            /** Prints the profiling results of each frame */
241            void displayResults();
242
243            /** Processes the profiler data after each frame */
244            void processFrameStats();
245
246            /** Handles a change of the profiler's enabled state*/
247            void changeEnableState();
248
249            /** An internal function to create the container which will hold our display elements*/
250            OverlayContainer* createContainer();
251
252            /** An internal function to create a text area */
253            OverlayElement* createTextArea(const String& name, Real width, Real height, Real top, Real left, 
254                                       uint fontSize, const String& caption, bool show = true);
255
256            /** An internal function to create a panel */
257            OverlayElement* createPanel(const String& name, Real width, Real height, Real top, Real left, 
258                                    const String& materialName, bool show = true);
259
260            /// Represents an individual profile call
261            struct ProfileInstance {
262
263                /// The name of the profile
264                String          name;
265
266                /// The name of the parent, empty string if root
267                String          parent;
268
269                /// The time this profile was started
270                ulong           currTime;
271
272                /// Represents the total time of all child profiles to subtract
273                /// from this profile
274                ulong           accum;
275
276                /// The hierarchical level of this profile, 0 being the root profile
277                uint            hierarchicalLvl;
278            };
279
280            /// Represents the total timing information of a profile
281            /// since profiles can be called more than once each frame
282            struct ProfileFrame {
283                               
284                /// The name of the profile
285                String  name;
286
287                /// The total time this profile has taken this frame
288                ulong   frameTime;
289
290                /// The number of times this profile was called this frame
291                uint    calls;
292
293                /// The hierarchical level of this profile, 0 being the main loop
294                uint    hierarchicalLvl;
295
296            };
297                       
298            /// Represents a history of each profile during the duration of the app
299            struct ProfileHistory {
300
301                /// The name of the profile
302                String  name;
303
304                /// The current percentage of frame time this profile has taken
305                Real    currentTime; // %
306
307                /// The maximum percentage of frame time this profile has taken
308                Real    maxTime; // %
309
310                /// The minimum percentage of frame time this profile has taken
311                Real    minTime; // %
312
313                /// The number of times this profile has been called each frame
314                uint    numCallsThisFrame;
315
316                /// The total percentage of frame time this profile has taken
317                /// (used to calculate average)
318                Real    totalTime; // %
319
320                /// The total number of times this profile was called
321                /// (used to calculate average)
322                ulong   totalCalls; // %
323
324                /// The hierarchical level of this profile, 0 being the root profile
325                uint    hierarchicalLvl;
326
327                        };
328
329                       
330            typedef std::list<ProfileInstance> ProfileStack;
331            typedef std::list<ProfileFrame> ProfileFrameList;
332            typedef std::list<ProfileHistory> ProfileHistoryList;
333            typedef std::map<String, ProfileHistoryList::iterator> ProfileHistoryMap;
334            typedef std::map<String, bool> DisabledProfileMap;
335
336            typedef std::list<OverlayElement*> ProfileBarList;
337
338            /// A stack for each individual profile per frame
339            ProfileStack mProfiles;
340
341            /// Accumulates the results of each profile per frame (since a profile can be called
342            /// more than once a frame)
343            ProfileFrameList mProfileFrame;
344
345            /// Keeps track of the statistics of each profile
346            ProfileHistoryList mProfileHistory;
347
348            /// We use this for quick look-ups of profiles in the history list
349            ProfileHistoryMap mProfileHistoryMap;
350
351            /// Holds the names of disabled profiles
352            DisabledProfileMap mDisabledProfiles;
353
354            /// Holds the display bars for each profile results
355            ProfileBarList mProfileBars;
356
357            /// Whether the GUI elements have been initialized
358            bool mInitialized;
359
360            /// The max number of profiles we can display
361            uint maxProfiles;
362
363            /// The overlay which contains our profiler results display
364            Overlay* mOverlay;
365
366            /// The window that displays the profiler results
367            OverlayContainer* mProfileGui;
368
369            /// The height of each bar
370            Real mBarHeight;
371
372            /// The height of the stats window
373            Real mGuiHeight;
374
375            /// The width of the stats window
376            Real mGuiWidth;
377
378            /// The size of the indent for each profile display bar
379            Real mBarIndent;
380
381            /// The width of the border between the profile window and each bar
382            Real mGuiBorderWidth;
383
384            /// The width of the min, avg, and max lines in a profile display
385            Real mBarLineWidth;
386
387            /// The number of frames that must elapse before the current
388            /// frame display is updated
389            uint mUpdateDisplayFrequency;
390
391            /// The number of elasped frame, used with mUpdateDisplayFrequency
392            uint mCurrentFrame;
393
394            /// The timer used for profiling
395            Timer* mTimer;
396
397            /// The total time each frame takes
398            ulong mTotalFrameTime;
399
400            /// Whether this profiler is enabled
401            bool mEnabled;
402
403            /// Keeps track of whether this profiler has
404            /// received a request to be enabled/disabled
405            bool mEnableStateChangePending;
406
407            /// Keeps track of the new enabled/disabled state that the user has requested
408            /// which will be applied after the frame ends
409            bool mNewEnableState;
410
411    }; // end class
412
413} // end namespace
414
415#endif
Note: See TracBrowser for help on using the repository browser.