Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreProfiler.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

File size: 19.2 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-2013 Torus Knot Software Ltd
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25THE SOFTWARE.
26-----------------------------------------------------------------------------
27*/
28/*
29
30    Although the code is original, many of the ideas for the profiler were borrowed from
31"Real-Time In-Game Profiling" by Steve Rabin which can be found in Game Programming
32Gems 1.
33
34    This code can easily be adapted to your own non-Ogre project. The only code that is
35Ogre-dependent is in the visualization/logging routines and the use of the Timer class.
36
37    Enjoy!
38
39*/
40
41#ifndef __Profiler_H__
42#define __Profiler_H__
43
44#include "OgrePrerequisites.h"
45#include "OgreSingleton.h"
46#include "OgreString.h"
47#include "OgreHeaderPrefix.h"
48
49#if OGRE_PROFILING == 1
50#       define OgreProfile( a ) Ogre::Profile _OgreProfileInstance( (a) )
51#       define OgreProfileBegin( a ) Ogre::Profiler::getSingleton().beginProfile( (a) )
52#       define OgreProfileEnd( a ) Ogre::Profiler::getSingleton().endProfile( (a) )
53#       define OgreProfileGroup( a, g ) Ogre::Profile _OgreProfileInstance( (a), (g) )
54#       define OgreProfileBeginGroup( a, g ) Ogre::Profiler::getSingleton().beginProfile( (a), (g) )
55#       define OgreProfileEndGroup( a, g ) Ogre::Profiler::getSingleton().endProfile( (a), (g) )
56#       define OgreProfileBeginGPUEvent( g ) Ogre::Profiler::getSingleton().beginGPUEvent(g)
57#       define OgreProfileEndGPUEvent( g ) Ogre::Profiler::getSingleton().endGPUEvent(g)
58#       define OgreProfileMarkGPUEvent( e ) Ogre::Profiler::getSingleton().markGPUEvent(e)
59#else
60#   define OgreProfile( a )
61#   define OgreProfileBegin( a )
62#   define OgreProfileEnd( a )
63#       define OgreProfileGroup( a, g )
64#       define OgreProfileBeginGroup( a, g )
65#       define OgreProfileEndGroup( a, g )
66#       define OgreProfileBeginGPUEvent( e )
67#       define OgreProfileEndGPUEvent( e )
68#       define OgreProfileMarkGPUEvent( e )
69#endif
70
71namespace Ogre {
72        /** \addtogroup Core
73        *  @{
74        */
75        /** \addtogroup General
76        *  @{
77        */
78        /** List of reserved profiling masks
79        */
80        enum ProfileGroupMask
81        {
82                /// User default profile
83                OGREPROF_USER_DEFAULT = 0x00000001,
84                /// All in-built Ogre profiling will match this mask
85                OGREPROF_ALL = 0xFF000000,
86                /// General processing
87                OGREPROF_GENERAL = 0x80000000,
88                /// Culling
89                OGREPROF_CULLING = 0x40000000,
90                /// Rendering
91                OGREPROF_RENDERING = 0x20000000
92        };
93
94    /** An individual profile that will be processed by the Profiler
95        @remarks
96            Use the macro OgreProfile(name) instead of instantiating this profile directly
97        @remarks
98            We use this Profile to allow scoping rules to signify the beginning and end of
99            the profile. Use the Profiler singleton (through the macro OgreProfileBegin(name)
100            and OgreProfileEnd(name)) directly if you want a profile to last
101            outside of a scope (i.e. the main game loop).
102        @author Amit Mathew (amitmathew (at) yahoo (dot) com)
103    */
104        class _OgreExport Profile : 
105                public ProfilerAlloc
106        {
107
108        public:
109            Profile(const String& profileName, uint32 groupID = (uint32)OGREPROF_USER_DEFAULT);
110            ~Profile();
111
112        protected:
113
114            /// The name of this profile
115            String mName;
116                        /// The group ID
117                        uint32 mGroupID;
118                       
119    };
120
121        /** Represents the total timing information of a profile
122                since profiles can be called more than once each frame
123        */
124    struct ProfileFrame
125        {
126
127        /// The total time this profile has taken this frame
128        ulong   frameTime;
129
130        /// The number of times this profile was called this frame
131        uint    calls;
132
133        /// The hierarchical level of this profile, 0 being the main loop
134        uint    hierarchicalLvl;
135
136    };
137
138        /// Represents a history of each profile during the duration of the app
139    struct ProfileHistory
140        {
141        /// The current percentage of frame time this profile has taken
142        Real    currentTimePercent; 
143                /// The current frame time this profile has taken in milliseconds
144                Real    currentTimeMillisecs;
145
146        /// The maximum percentage of frame time this profile has taken
147        Real    maxTimePercent; 
148                /// The maximum frame time this profile has taken in milliseconds
149                Real    maxTimeMillisecs; 
150
151        /// The minimum percentage of frame time this profile has taken
152        Real    minTimePercent; 
153                /// The minimum frame time this profile has taken in milliseconds
154                Real    minTimeMillisecs; 
155
156        /// The number of times this profile has been called each frame
157        uint    numCallsThisFrame;
158
159        /// The total percentage of frame time this profile has taken
160        Real    totalTimePercent;
161                /// The total frame time this profile has taken in milliseconds
162                Real    totalTimeMillisecs;
163
164        /// The total number of times this profile was called
165        /// (used to calculate average)
166        ulong   totalCalls; 
167
168        /// The hierarchical level of this profile, 0 being the root profile
169        uint    hierarchicalLvl;
170
171        };
172
173        /// Represents an individual profile call
174        class ProfileInstance : public ProfilerAlloc
175        {
176                friend class Profiler;
177        public:
178                ProfileInstance(void);
179                virtual ~ProfileInstance(void);
180
181                typedef Ogre::map<String,ProfileInstance*>::type ProfileChildren;
182
183                void logResults();
184                void reset();
185
186                inline bool watchForMax(void) { return history.currentTimePercent == history.maxTimePercent; }
187                inline bool watchForMin(void) { return history.currentTimePercent == history.minTimePercent; }
188                inline bool watchForLimit(Real limit, bool greaterThan = true)
189                {
190                        if (greaterThan)
191                                return history.currentTimePercent > limit;
192                        else
193                                return history.currentTimePercent < limit;
194                }
195
196                bool watchForMax(const String& profileName);
197                bool watchForMin(const String& profileName);
198                bool watchForLimit(const String& profileName, Real limit, bool greaterThan = true);
199                               
200                /// The name of the profile
201                String          name;
202
203                /// The name of the parent, null if root
204                ProfileInstance* parent;
205
206                ProfileChildren children;
207
208                ProfileFrame frame;
209                ulong frameNumber;
210
211                ProfileHistory history;
212
213                /// The time this profile was started
214                ulong           currTime;
215
216                /// Represents the total time of all child profiles to subtract
217                /// from this profile
218                ulong           accum;
219
220                /// The hierarchical level of this profile, 0 being the root profile
221                uint            hierarchicalLvl;
222        };
223
224        /** ProfileSessionListener should be used to visualize profile results.
225                Concrete impl. could be done using Overlay's but its not limited to
226                them you can also create a custom listener which sends the profile
227                informtaion over a network.
228    */
229        class _OgreExport ProfileSessionListener
230        {
231        public:
232                enum DisplayMode
233                {
234                        /// Display % frame usage on the overlay
235                        DISPLAY_PERCENTAGE,
236                        /// Display milliseconds on the overlay
237                        DISPLAY_MILLISECONDS
238                };
239
240                ProfileSessionListener() : mDisplayMode(DISPLAY_MILLISECONDS) {}
241                virtual ~ProfileSessionListener() {}
242
243                /// Create the internal resources
244                virtual void initializeSession() = 0;
245
246                /// All internal resources should be deleted here
247                virtual void finializeSession() = 0;
248
249                /** If the profiler disables this listener then it
250                        should hide its panels (if any exists) or stop
251                        sending data over the network
252                */
253                virtual void changeEnableState(bool enabled) {}; 
254               
255                /// Here we get the real profiling information which we can use
256                virtual void displayResults(const ProfileInstance& instance, ulong maxTotalFrameTime) {};
257
258                /// Set the display mode for the overlay.
259                void setDisplayMode(DisplayMode d) { mDisplayMode = d; }
260       
261                /// Get the display mode for the overlay.
262                DisplayMode getDisplayMode() const { return mDisplayMode; }
263       
264        protected:
265                /// How to display the overlay
266                DisplayMode mDisplayMode;
267        };
268
269    /** The profiler allows you to measure the performance of your code
270        @remarks
271            Do not create profiles directly from this unless you want a profile to last
272            outside of its scope (i.e. the main game loop). For most cases, use the macro
273            OgreProfile(name) and braces to limit the scope. You must enable the Profile
274            before you can used it with setEnabled(true). If you want to disable profiling
275            in Ogre, simply set the macro OGRE_PROFILING to 0.
276        @author Amit Mathew (amitmathew (at) yahoo (dot) com)
277        @todo resolve artificial cap on number of profiles displayed
278        @todo fix display ordering of profiles not called every frame
279    */
280    class _OgreExport Profiler : 
281                public Singleton<Profiler>,
282                public ProfilerAlloc
283        {
284        public:
285            Profiler();
286            ~Profiler();
287
288            /** Sets the timer for the profiler */
289            void setTimer(Timer* t);
290
291            /** Retrieves the timer for the profiler */
292            Timer* getTimer();
293
294            /** Begins a profile
295            @remarks
296                Use the macro OgreProfileBegin(name) instead of calling this directly
297                so that profiling can be ignored in the release version of your app.
298            @remarks
299                You only use the macro (or this) if you want a profile to last outside
300                of its scope (i.e. the main game loop). If you use this function, make sure you
301                use a corresponding OgreProfileEnd(name). Usually you would use the macro
302                OgreProfile(name). This function will be ignored for a profile that has been
303                disabled or if the profiler is disabled.
304            @param profileName Must be unique and must not be an empty string
305                        @param groupID A profile group identifier, which can allow you to mask profiles
306            */
307            void beginProfile(const String& profileName, uint32 groupID = (uint32)OGREPROF_USER_DEFAULT);
308
309            /** Ends a profile
310            @remarks
311                Use the macro OgreProfileEnd(name) instead of calling this directly so that
312                profiling can be ignored in the release version of your app.
313            @remarks
314                This function is usually not called directly unless you want a profile to
315                last outside of its scope. In most cases, using the macro OgreProfile(name)
316                which will call this function automatically when it goes out of scope. Make
317                sure the name of this profile matches its corresponding beginProfile name.
318                This function will be ignored for a profile that has been disabled or if the
319                profiler is disabled.
320                        @param profileName Must be unique and must not be an empty string
321                        @param groupID A profile group identifier, which can allow you to mask profiles
322            */
323            void endProfile(const String& profileName, uint32 groupID = (uint32)OGREPROF_USER_DEFAULT);
324
325            /** Mark the beginning of a GPU event group
326             @remarks Can be safely called in the middle of the profile.
327             */
328            void beginGPUEvent(const String& event);
329
330            /** Mark the end of a GPU event group
331             @remarks Can be safely called in the middle of the profile.
332             */
333            void endGPUEvent(const String& event);
334
335            /** Mark a specific, ungrouped, GPU event
336             @remarks Can be safely called in the middle of the profile.
337             */
338            void markGPUEvent(const String& event);
339
340            /** Sets whether this profiler is enabled. Only takes effect after the
341                the frame has ended.
342                @remarks When this is called the first time with the parameter true,
343                it initializes the GUI for the Profiler
344            */
345            void setEnabled(bool enabled);
346
347            /** Gets whether this profiler is enabled */
348            bool getEnabled() const;
349
350            /** Enables a previously disabled profile
351            @remarks Can be safely called in the middle of the profile.
352            */
353            void enableProfile(const String& profileName);
354
355            /** Disables a profile
356            @remarks Can be safely called in the middle of the profile.
357            */
358            void disableProfile(const String& profileName);
359
360                        /** Set the mask which all profiles must pass to be enabled.
361                        */
362                        void setProfileGroupMask(uint32 mask) { mProfileMask = mask; }
363                        /** Get the mask which all profiles must pass to be enabled.
364                        */
365                        uint32 getProfileGroupMask() const { return mProfileMask; }
366
367            /** Returns true if the specified profile reaches a new frame time maximum
368            @remarks If this is called during a frame, it will be reading the results
369            from the previous frame. Therefore, it is best to use this after the frame
370            has ended.
371            */
372            bool watchForMax(const String& profileName);
373
374            /** Returns true if the specified profile reaches a new frame time minimum
375            @remarks If this is called during a frame, it will be reading the results
376            from the previous frame. Therefore, it is best to use this after the frame
377            has ended.
378            */
379            bool watchForMin(const String& profileName);
380
381            /** Returns true if the specified profile goes over or under the given limit
382                frame time
383            @remarks If this is called during a frame, it will be reading the results
384            from the previous frame. Therefore, it is best to use this after the frame
385            has ended.
386            @param limit A number between 0 and 1 representing the percentage of frame time
387            @param greaterThan If true, this will return whether the limit is exceeded. Otherwise,
388            it will return if the frame time has gone under this limit.
389            */
390            bool watchForLimit(const String& profileName, Real limit, bool greaterThan = true);
391
392            /** Outputs current profile statistics to the log */
393            void logResults();
394
395            /** Clears the profiler statistics */
396            void reset();
397
398            /** Sets the Profiler so the display of results are updated every n frames*/
399            void setUpdateDisplayFrequency(uint freq);
400
401            /** Gets the frequency that the Profiler display is updated */
402            uint getUpdateDisplayFrequency() const;
403
404                        /**
405                        @remarks
406                                Register a ProfileSessionListener from the Profiler
407                        @param listener
408                                A valid listener derived class
409                        */
410                        void addListener(ProfileSessionListener* listener);
411
412                        /**
413                        @remarks
414                                Unregister a ProfileSessionListener from the Profiler
415                        @param listener
416                                A valid listener derived class
417                        */
418                        void removeListener(ProfileSessionListener* listener);
419
420            /** Override standard Singleton retrieval.
421            @remarks
422            Why do we do this? Well, it's because the Singleton
423            implementation is in a .h file, which means it gets compiled
424            into anybody who includes it. This is needed for the
425            Singleton template to work, but we actually only want it
426            compiled into the implementation of the class based on the
427            Singleton, not all of them. If we don't change this, we get
428            link errors when trying to use the Singleton-based class from
429            an outside dll.
430            @par
431            This method just delegates to the template version anyway,
432            but the implementation stays in this single compilation unit,
433            preventing link errors.
434            */
435            static Profiler& getSingleton(void);
436            /** Override standard Singleton retrieval.
437            @remarks
438            Why do we do this? Well, it's because the Singleton
439            implementation is in a .h file, which means it gets compiled
440            into anybody who includes it. This is needed for the
441            Singleton template to work, but we actually only want it
442            compiled into the implementation of the class based on the
443            Singleton, not all of them. If we don't change this, we get
444            link errors when trying to use the Singleton-based class from
445            an outside dll.
446            @par
447            This method just delegates to the template version anyway,
448            but the implementation stays in this single compilation unit,
449            preventing link errors.
450            */
451            static Profiler* getSingletonPtr(void);
452
453        protected:
454                        friend class ProfileInstance;
455
456                        typedef vector<ProfileSessionListener*>::type TProfileSessionListener;
457                        TProfileSessionListener mListeners;
458
459            /** Initializes the profiler's GUI elements */
460            void initialize();
461
462                        void displayResults();
463
464                        /** Processes frame stats for all of the mRoot's children */
465                        void processFrameStats(void);
466            /** Processes specific ProfileInstance and it's children recursively.*/
467            void processFrameStats(ProfileInstance* instance, Real& maxFrameTime);
468
469            /** Handles a change of the profiler's enabled state*/
470            void changeEnableState();
471
472                        // lol. Uses typedef; put's original container type in name.
473            typedef set<String>::type DisabledProfileMap;
474                        typedef ProfileInstance::ProfileChildren ProfileChildren;
475
476                        ProfileInstance* mCurrent;
477                        ProfileInstance* mLast;
478                        ProfileInstance mRoot;
479
480            /// Holds the names of disabled profiles
481            DisabledProfileMap mDisabledProfiles;
482
483            /// Whether the GUI elements have been initialized
484            bool mInitialized;
485
486            /// The number of frames that must elapse before the current
487            /// frame display is updated
488            uint mUpdateDisplayFrequency;
489
490            /// The number of elapsed frame, used with mUpdateDisplayFrequency
491            uint mCurrentFrame;
492
493            /// The timer used for profiling
494            Timer* mTimer;
495
496            /// The total time each frame takes
497            ulong mTotalFrameTime;
498
499            /// Whether this profiler is enabled
500            bool mEnabled;
501
502            /// Keeps track of the new enabled/disabled state that the user has requested
503            /// which will be applied after the frame ends
504            bool mNewEnableState;
505
506                        /// Mask to decide whether a type of profile is enabled or not
507                        uint32 mProfileMask;
508
509                        /// The max frame time recorded
510                        ulong mMaxTotalFrameTime;
511
512                        /// Rolling average of millisecs
513                        Real mAverageFrameTime;
514                        bool mResetExtents;
515
516
517    }; // end class
518        /** @} */
519        /** @} */
520
521} // end namespace
522
523#include "OgreHeaderSuffix.h"
524
525#endif
Note: See TracBrowser for help on using the repository browser.