Add a code profiler (stop-watch style).

- breaks MacOSX build for now (files need to be added there).
- Interface still needs to be discussed, so maybe wait a few days before using this.
- Not yet tested on Windows (will do that tomorrow)
- No VS project files yet for the profiling example (will do that tomorrow)


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4791 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2014-04-24 22:52:10 +00:00
parent c695a21f33
commit 1fa2ba2b61
30 changed files with 1778 additions and 12 deletions

View File

@ -1,6 +1,7 @@
--------------------------
Changes in 1.9 (not yet released)
- Add a code profiler (stop-watch style)
- Add override font to IGUITable
- IGUITable can now disable the active column.
- IGUIElement::getElementFromPoint now virtual

View File

@ -0,0 +1,66 @@
# Makefile for Irrlicht Examples
# It's usually sufficient to change just the target name and source file list
# and be sure that CXX is set to a valid compiler
# Name of the executable created (.exe will be added automatically if necessary)
Target := 30.Profiling
# List of source files, separated by spaces
Sources := main.cpp
# Path to Irrlicht directory, should contain include/ and lib/
IrrlichtHome := ../..
# Path for the executable. Note that Irrlicht.dll should usually also be there for win32 systems
BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too)
# preprocessor flags, e.g. defines and include paths
USERCPPFLAGS =
# compiler flags such as optimization flags
USERCXXFLAGS = -O3 -ffast-math
#USERCXXFLAGS = -g -Wall
# linker flags such as additional libraries and link paths
USERLDFLAGS =
####
#no changes necessary below this line
####
CPPFLAGS = -I$(IrrlichtHome)/include -I/usr/X11R6/include $(USERCPPFLAGS)
CXXFLAGS = $(USERCXXFLAGS)
LDFLAGS = $(USERLDFLAGS)
#default target is Linux
all: all_linux
# target specific settings
all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht
all_linux: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm -lXext -lX11 -lXcursor
all_linux clean_linux: SYSTEM=Linux
all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc
all_win32 clean_win32 static_win32: SUF=.exe
static_win32: CPPFLAGS += -D_IRR_STATIC_LIB_
all_win32: LDFLAGS += -lopengl32 -lm
static_win32: LDFLAGS += -lgdi32 -lwinspool -lcomdlg32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lopengl32
# name of the binary - only valid for targets which set SYSTEM
DESTPATH = $(BinPath)/$(Target)$(SUF)
all_linux all_win32 static_win32:
$(warning Building...)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS)
clean: clean_linux clean_win32
$(warning Cleaning...)
clean_linux clean_win32:
@$(RM) $(DESTPATH)
.PHONY: all all_win32 static_win32 clean clean_linux clean_win32
#multilib handling
ifeq ($(HOSTTYPE), x86_64)
LIBSELECT=64
endif
#solaris real-time features
ifeq ($(HOSTTYPE), sun4)
LDFLAGS += -lrt
endif

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="Irrlicht Example 30 Profiling" />
<Option pch_mode="0" />
<Option compiler="gcc" />
<Build>
<Target title="Windows">
<Option platforms="Windows;" />
<Option output="../../bin/Win32-gcc/Profiling" prefix_auto="0" extension_auto="1" />
<Option type="1" />
<Option compiler="gcc" />
<Option projectResourceIncludeDirsRelation="1" />
<Compiler>
<Add option="-g" />
</Compiler>
<Linker>
<Add directory="../../lib/Win32-gcc" />
</Linker>
</Target>
<Target title="Linux">
<Option platforms="Unix;" />
<Option output="../../bin/Linux/Profiling" prefix_auto="0" extension_auto="0" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
<Linker>
<Add library="Xxf86vm" />
<Add library="X11" />
<Add library="GL" />
<Add directory="../../lib/Linux" />
</Linker>
</Target>
</Build>
<VirtualTargets>
<Add alias="All" targets="Windows;Linux;" />
</VirtualTargets>
<Compiler>
<Add option="-g" />
<Add directory="../../include" />
</Compiler>
<Linker>
<Add library="Irrlicht" />
</Linker>
<Unit filename="main.cpp" />
<Extensions>
<code_completion />
<debugger />
<envvars />
</Extensions>
</Project>
</CodeBlocks_project_file>

View File

@ -0,0 +1,456 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// Written by Michael Zeilfelder
/** Example 030 Profiling
Profiling is used to get runtime information about code code.
There exist several indepent profiling tools.
Examples for free profilers are "gprof" for the GNU toolchain and "very sleepy"
from codersnotes for Windows. Proprietary tools are for example "VTune" from
Intel or "AMD APP Profiler". Those tools work by sampling the running
application regularly to get statistic information about the called functions.
The way to use them is to compile your application with special flags
to include profiling information (some also work with debug information). They
also might allow to profile only certain parts of the code, although
most can't do that. The sampling is usually rather time-consuming which means
the application will be very slow when collecting the profiling data. It's often
useful to start with one of those tools to get an overview over the bottlenecks
in your application. Those tools have the advantage that they don't need any
modifications inside the code.
Once you need to dig deeper the Irrlicht profiler can help you. It works nearly
like a stopwatch. You add start/stop blocks into the parts of your code which
you need to check and the Irrlicht profiler will give you then the exact times
of execution for those parts. And unlike general profiler tools you don't just
get average information about the run-time but also worst-cases. Which tends
to be information you really for a stable framerate. Also the Irrlicht profiler
has a low overhead and affects only the areas which you want to time. So you
can profile applications with nearly original speed.
Irrlicht itself has such profiling information, which is useful to figure out
where the runtime inside the engine is spend. To get that profilng data you
need to recompile Irrlicht with _IRR_COMPILE_WITH_PROFILING_ enabled as
collecting profiling information is disabled by default for speed reasons.
*/
/*
It's usually a good idea to wrap all your profile code with a define.
That way you don't have to worry too much about the runtime profiling
itself takes. You can remove the profiling code completely when you release
the software by removing a single define.Or sometimes you might want to
have several such defines for different areas of your application code.
*/
#define ENABLE_MY_PROFILE // outcomment to remove the profiling code
#ifdef ENABLE_MY_PROFILE
// calls code X
#define MY_PROFILE(X) X
#else
// removes the code for X in the pre-processor
#define MY_PROFILE(X)
#endif // IRR_PROFILE
#include <irrlicht.h>
#include "driverChoice.h"
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
/*
We have the choice between working with fixed and with automatic profling id's.
Here are some fixed ID's we will be using.
*/
enum EProfiles
{
EP_APP_TIME_ONCE,
EP_APP_TIME_UPDATED,
EP_SCOPE1,
EP_SCOPE2,
EP_DRAW_SCENE
};
// For our example scenes
enum EScenes
{
ES_NONE, // no scene set
ES_CUBE,
ES_QUAKE_MAP,
ES_DWARVES,
ES_COUNT // counting how many scenes we have
};
/*
Controlling the profiling display is application specific behavior.
We use function keys in our case and play around with all the parameters.
In real applications you will likely only need something to make the
profiling-display visible/invisible and switch pages while the parameters
can be set to fixed values.
*/
class MyEventReceiver : public IEventReceiver
{
public:
// constructor
MyEventReceiver(ISceneManager * smgr) : GuiProfiler(0), IncludeOverview(true), ActiveScene(ES_NONE), SceneManager(smgr) {}
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_KEY_INPUT_EVENT)
{
if ( event.KeyInput.PressedDown )
{
/*
Catching keys to control the profiling display and the profiler itself
*/
switch ( event.KeyInput.Key )
{
case KEY_F1:
GuiProfiler->setVisible( !GuiProfiler->isVisible() );
break;
case KEY_F2:
GuiProfiler->nextPage(IncludeOverview);
break;
case KEY_F3:
GuiProfiler->previousPage(IncludeOverview);
break;
case KEY_F4:
GuiProfiler->firstPage(IncludeOverview);
break;
case KEY_F5:
IncludeOverview = !IncludeOverview;
break;
case KEY_F6:
GuiProfiler->setIgnoreUncalled( !GuiProfiler->getIgnoreUncalled() );
break;
case KEY_F8:
NextScene();
break;
case KEY_F9:
{
u32 index = 0;
if ( getProfiler().findGroupIndex(index, L"group a") )
{
getProfiler().resetGroup(index);
}
}
break;
case KEY_F10:
{
u32 index = 0;
if ( getProfiler().findDataIndex(index, L"scope 3") )
{
getProfiler().resetDataByIndex(index);
}
}
break;
case KEY_F11:
getProfiler().resetAll();
break;
default:
break;
}
}
}
return false;
}
/*
Some example scenes so we have something to profile
*/
void NextScene()
{
SceneManager->clear();
ActiveScene = (ActiveScene+1) % ES_COUNT;
if ( ActiveScene == 0 )
ActiveScene = ActiveScene+1;
switch ( ActiveScene )
{
case ES_CUBE:
{
/*
Simple scene with cube and light.
*/
MY_PROFILE(CProfileScope p(L"cube", L"scenes");)
SceneManager->addCameraSceneNode (0, core::vector3df(0, 0, 0),
core::vector3df(0, 0, 100),
-1);
SceneManager->addCubeSceneNode (30.0f, 0, -1,
core::vector3df(0, 20, 100),
core::vector3df(45, 45, 45),
core::vector3df(1.0f, 1.0f, 1.0f));
SceneManager->addLightSceneNode(0, core::vector3df(0, 0, 0),
video::SColorf(1.0f, 1.0f, 1.0f),
100.0f);
}
break;
case ES_QUAKE_MAP:
{
/*
Our typical Irrlicht example quake map.
*/
MY_PROFILE(CProfileScope p(L"quake map", L"scenes");)
scene::IAnimatedMesh* mesh = SceneManager->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;
if (mesh)
node = SceneManager->addOctreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
if (node)
node->setPosition(core::vector3df(-1300,-144,-1249));
SceneManager->addCameraSceneNodeFPS();
}
break;
case ES_DWARVES:
{
/*
Stress-test Irrlicht a little bit by creating many objects.
*/
MY_PROFILE(CProfileScope p(L"dwarfes", L"scenes");)
scene::IAnimatedMesh* aniMesh = SceneManager->getMesh( "../../media/dwarf.x" );
if (aniMesh)
{
scene::IMesh * mesh = aniMesh->getMesh (0);
if ( !mesh )
break;
/*
You can never have too many dwarves. So let's make some.
*/
const int nodesX = 30;
const int nodesY = 5;
const int nodesZ = 30;
aabbox3df bbox = mesh->getBoundingBox();
vector3df extent = bbox.getExtent();
const f32 GAP = 10.f;
f32 halfSizeX = 0.5f * (nodesX*extent.X + GAP*(nodesX-1));
f32 halfSizeY = 0.5f * (nodesY*extent.Y + GAP*(nodesY-1));
f32 halfSizeZ = 0.5f * (nodesZ*extent.Z + GAP*(nodesZ-1));
for ( int x = 0; x < nodesX; ++x )
{
irr::f32 gapX = x > 0 ? (x-1)*GAP : 0.f;
irr::f32 posX = -halfSizeX + x*extent.X + gapX;
for ( int y = 0; y < nodesY; ++y )
{
irr::f32 gapY = y > 0 ? (y-1)*GAP : 0.f;
irr::f32 posY = -halfSizeY + y*extent.Y + gapY;
for ( int z=0; z < nodesZ; ++z )
{
irr::f32 gapZ = z > 0 ? (z-1)*GAP : 0.f;
irr::f32 posZ = -halfSizeZ + z*extent.Z + gapZ;
scene::IMeshSceneNode * node = SceneManager->addMeshSceneNode (mesh, NULL, -1, vector3df(posX, posY, posZ) );
node->setMaterialFlag(video::EMF_LIGHTING, false);
}
}
}
irr::scene::ICameraSceneNode * camera = SceneManager->addCameraSceneNodeFPS(0, 20.f, 0.1f );
camera->updateAbsolutePosition();
camera->setTarget( vector3df(0,0,0) );
camera->updateAbsolutePosition();
camera->setPosition(irr::core::vector3df(halfSizeX+extent.X, halfSizeY+extent.Y, halfSizeZ+extent.Z));
camera->updateAbsolutePosition();
}
}
break;
}
}
IGUIProfiler * GuiProfiler;
bool IncludeOverview;
u32 ActiveScene;
scene::ISceneManager* SceneManager;
};
int main()
{
/*
Setup, nothing special here.
*/
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
IGUIEnvironment* env = device->getGUIEnvironment();
scene::ISceneManager* smgr = device->getSceneManager();
/*
A map we use for one of our test-scenes.
*/
device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3");
MyEventReceiver receiver(smgr);
device->setEventReceiver(&receiver);
receiver.NextScene();
/*
Show some info about the controls used in this example
*/
IGUIStaticText * staticText = env->addStaticText(
L"F1 to show/hide the profiling display\n"
L"F2 to show the next page\n"
L"F3 to show the previous page\n"
L"F4 to show the first page\n"
L"F5 to flip between including the group overview\n"
L"F6 to flip between ignoring and showing uncalled data\n"
L"F8 to change our scene\n"
L"F9 to reset the \"group a\" data\n"
L"F10 to reset the scope 3 data\n"
L"F11 to reset all data\n"
, recti(10,10, 250, 120), true, true, 0, -1, true);
staticText->setWordWrap(false);
/*
IGUIProfiler is can be used to show active profiling data at runtime.
*/
receiver.GuiProfiler = env->addProfilerDisplay(core::recti(40, 140, 600, 470));
/*
Get a monospaced font - it's nicer when working with rows of numbers.
*/
IGUIFont* font = env->getFont("../../media/fontcourier.bmp");
if (font)
receiver.GuiProfiler->setOverrideFont(font);
/*
Adding ID's has to be done before the start/stop calls.
This allows start/stop to be really fast and we still have nice information like
names and groups.
Groups are created automatically each time an ID with a new group-name is added.
Groups exist to sort the display data in a nicer way.
*/
MY_PROFILE(
getProfiler().add(EP_APP_TIME_ONCE, L"full time", L"group a");
getProfiler().add(EP_APP_TIME_UPDATED, L"full time updated", L"group a");
getProfiler().add(EP_SCOPE1, L"scope 1", L"group a");
getProfiler().add(EP_DRAW_SCENE, L"draw scene", L"group a");
)
/*
Two timers which run the whole time. One will be continuosly updated the other won't.
*/
MY_PROFILE(getProfiler().start(EP_APP_TIME_ONCE);)
MY_PROFILE(getProfiler().start(EP_APP_TIME_UPDATED);)
s32 lastFPS = -1;
while(device->run() && driver)
{
if (device->isWindowActive())
{
/*
For comparison show the FPS in the title bar
*/
s32 fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"FPS: ";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
/*
Times are only updated on stop() calls. So if we want a long-running timer
to update we have to stop() and start() it in between.
Note that this will also update the call-counter and is rarely needed.
*/
MY_PROFILE(getProfiler().stop(EP_APP_TIME_UPDATED);)
MY_PROFILE(getProfiler().start(EP_APP_TIME_UPDATED);)
/*
The following CProfileScope's will all do the same thing:
they measure the time this loop takes. They call start()
when the object is created and call stop() when it
is destroyed.
The first one creates an ID on it's first call and will
do constant string-comparisons for the name. It's
the slowest, but most comfortable solution. Use it when you
just need to run a quick check without the hassle of setting
up id's.
*/
MY_PROFILE(CProfileScope p3(L"scope 3", L"group a");)
/*
Second CProfileScope solution will create a data block on first
call. So it's a little bit slower on the first run. But usually
that's hardly noticable.
*/
MY_PROFILE(CProfileScope p2(EP_SCOPE2, L"scope 2", L"group a");)
/*
Last CProfileScope solution is the fastest one. But you must add
the id before you can use it like that.
*/
MY_PROFILE(CProfileScope p1(EP_SCOPE1));
driver->beginScene(true, true, SColor(0,200,200,200));
/*
If you want to profile only some lines and not a complete scope
then you have to work with start() and stop() calls.
*/
MY_PROFILE(getProfiler().start(EP_DRAW_SCENE);)
smgr->drawAll();
MY_PROFILE(getProfiler().stop(EP_DRAW_SCENE);)
/*
If it doesn't matter if the profiler takes some time you can also
be lazy and create id's automatically on the spot:
*/
MY_PROFILE(s32 pEnv = getProfiler().add(L"draw env", L"group a");)
MY_PROFILE(getProfiler().start(pEnv);)
env->drawAll();
MY_PROFILE(getProfiler().stop(pEnv);)
driver->endScene();
}
}
/*
Shutdown.
*/
device->drop();
/*
The profiler is independent of an device - so we can still work with it.
*/
MY_PROFILE(getProfiler().stop(EP_APP_TIME_UPDATED));
MY_PROFILE(getProfiler().stop(EP_APP_TIME_ONCE));
/*
Print a complete overview of the profiling data to the console.
*/
MY_PROFILE(core::stringw output);
MY_PROFILE(getProfiler().printAll(output));
MY_PROFILE(printf("%s", core::stringc(output).c_str() ));
return 0;
}
/*
**/

View File

@ -2,7 +2,7 @@
<CodeBlocks_workspace_file>
<Workspace title="Build all examples">
<Project filename="../source/Irrlicht/Irrlicht-gcc.cbp" />
<Project filename="01.HelloWorld/HelloWorld.cbp" active="1" />
<Project filename="01.HelloWorld/HelloWorld.cbp" />
<Project filename="02.Quake3Map/Quake3Map.cbp" />
<Project filename="03.CustomSceneNode/CustomSceneNode.cbp" />
<Project filename="04.Movement/Movement.cbp" />
@ -27,6 +27,7 @@
<Project filename="24.CursorControl/CursorControl.cbp" />
<Project filename="25.XmlHandling/XmlHandling.cbp" />
<Project filename="26.OcclusionQuery/OcclusionQuery.cbp" />
<Project filename="30.Profiling/Profiling.cbp" />
<Project filename="Demo/demo.cbp" />
<Project filename="../tools/GUIEditor/GUIEditor_gcc.cbp" />
<Project filename="../tools/MeshConverter/MeshConverter.cbp" />

319
include/CProfiler.h Normal file
View File

@ -0,0 +1,319 @@
#ifndef __PROFILER_H_INCLUDED__
#define __PROFILER_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "irrString.h"
#include "irrArray.h"
#include "ITimer.h"
namespace irr
{
class ITimer;
//! Used to store the profile data (and also used for profile group data).
struct SProfileData
{
friend class CProfiler;
SProfileData()
{
GroupIndex = 0;
reset();
}
bool operator<(const SProfileData& pd) const
{
return Id < pd.Id;
}
bool operator==(const SProfileData& pd) const
{
return Id == pd.Id;
}
u32 getGroupIndex() const
{
return GroupIndex;
}
const core::stringw& getName() const
{
return Name;
}
//! Each call to Profiler::stop for this data increases the counter by 1.
u32 getCallsCounter() const
{
return CountCalls;
}
//! Longest time any call from start/stop ever took for this id.
u32 getLongestTime() const
{
return LongestTime;
}
//! Time spend between start/stop
s32 getTimeSum() const
{
return TimeSum;
}
//! Convert the whole data into a string
core::stringw getAsString() const;
//! Return a string which describes the columns returned by getAsString
static core::stringw makeTitleString();
private:
// just to be used for searching as it does no initialization besides id
SProfileData(u32 id) : Id(id) {}
void reset();
s32 Id;
u32 GroupIndex;
core::stringw Name;
u32 CountCalls;
u32 LongestTime;
u32 TimeSum;
u32 LastTimeStarted;
};
//! Code-profiler. Please check the example in the Irrlicht examples folder about how to use it.
// Implementer notes:
// The design is all about allowing to use the central start/stop mechanism with minimal time overhead.
// This is why the class works without a virtual functions interface contrary to the usual Irrlicht design.
// And also why it works with id's instead of strings in the start/stop functions even if it makes using
// the class slightly harder.
// The class comes without reference-counting because the profiler-instance is never released (TBD).
// But it's _not_ a singleton (also TBD), life-time is only guaranteed after globals are intialized.
class CProfiler
{
public:
//! Constructor. You could use this to create a new profiler, but usually getProfiler() is used to access the global instance.
CProfiler();
~CProfiler();
//! Add an id with given name and group which can be used for profiling with start/stop
/** After calling this once you can start/stop profiling for the given id.
\param id: Should be >= 0 as negative id's are reserved for Irrlicht. Also very large numbers (near INT_MAX) might
have been added automatically by the other add function.
\param name: Name for displaying profile data.
\param groupName: Each id belongs into a group - this helps on displaying profile data. */
void add(s32 id, const core::stringw &name, const core::stringw &groupName);
//! Add an automatically generated for the given name and group which can be used for profiling with start/stop.
/** After calling this once you can start/stop profiling with the returned id.
\param name: Name for displaying profile data.
\param groupName: Each id belongs into a group - this helps on displaying profile data.
\return Automatic id's start at INT_MAX and count down for each new id. If the name already has an id then that id will be returned. */
s32 add(const core::stringw &name, const core::stringw &groupName);
//! Return the number of profile data blocks. There is one for each id.
u32 getProfileDataCount() const
{
return ProfileDatas.size();
}
//! Search for the index of the profile data by name
/** \param result Receives the resulting data index when one was found.
\param name String with name to search for
\return true when found, false when not found */
bool findDataIndex(u32 & result, const core::stringw &name) const;
//! Get the profile data
/** \param index A value between 0 and getProfileDataCount()-1. Indices can change when new id's are added.*/
const SProfileData& getProfileDataByIndex(u32 index) const
{
return ProfileDatas[index];
}
//! Get the profile data
/** \param id Same value as used in ::add
\return Profile data for the given id or 0 when it does not exist. */
const SProfileData* getProfileDataById(u32 id)
{
SProfileData data(id);
s32 idx = ProfileDatas.binary_search(data);
if ( idx >= 0 )
return &ProfileDatas[idx];
return NULL;
}
//! Get the number of profile groups. Will be at least 1.
/** NOTE: The first groups is always L"overview" which is an overview for all existing groups */
u32 getGroupCount() const
{
return ProfileGroups.size();
}
//! Get profile data for a group.
/** NOTE: The first groups is always L"overview" which is an overview for all existing groups */
const SProfileData& getGroupData(u32 index) const
{
return ProfileGroups[index];
}
//! Find the group index by the group-name
/** \param result Receives the resulting group index when one was found.
\param name String with name to search for
\return true when found, false when not found */
bool findGroupIndex(u32 & result, const core::stringw &name) const;
//! Start profile-timing for the given id
/** NOTE: you have to add the id first with one of the ::add functions */
inline void start(s32 id);
//! Stop profile-timing for the given id
/** NOTE: timer must have been started first with the ::start function */
inline void stop(s32 id);
//! Reset profile data for the given id
void resetDataById(s32 id);
//! Reset profile data for the given index
void resetDataByIndex(u32 index);
//! Reset profile data for a whole group
void resetGroup(u32 index);
//! Reset all profile data
/** NOTE: This is not deleting id's or groups, just resetting all timers to 0. */
void resetAll();
//! Write all profile-data into a string
/** \param result Receives the result string.
\param includeOverview When true a group-overview is attached first
\param suppressUncalled When true elements which got never called are not printed */
void printAll(core::stringw &result, bool includeOverview=false,bool suppressUncalled=true) const;
//! Write the profile data of one group into a string
/** \param result Receives the result string.
\param groupIndex_ */
void printGroup(core::stringw &result, u32 groupIndex, bool suppressUncalled) const;
protected:
u32 addGroup(const core::stringw &name);
private:
ITimer * Timer; // I would prefer using os::Timer, but os.h is not in the public interface so far.
s32 NextAutoId; // for giving out id's automatically
core::array<SProfileData> ProfileDatas;
core::array<SProfileData> ProfileGroups;
};
void CProfiler::start(s32 id)
{
s32 idx = ProfileDatas.binary_search(SProfileData(id));
if ( idx >= 0 && Timer )
{
ProfileDatas[idx].LastTimeStarted = Timer->getRealTime();
}
}
void CProfiler::stop(s32 id)
{
if ( Timer )
{
u32 timeNow = Timer->getRealTime();
s32 idx = ProfileDatas.binary_search(SProfileData(id));
if ( idx >= 0 )
{
SProfileData &data = ProfileDatas[idx];
if ( data.LastTimeStarted != 0 )
{
// update data for this id
++data.CountCalls;
u32 diffTime = timeNow - data.LastTimeStarted;
data.TimeSum += diffTime;
if ( diffTime > data.LongestTime )
data.LongestTime = diffTime;
data.LastTimeStarted = 0;
// update data of it's group
SProfileData & group = ProfileGroups[data.GroupIndex];
++group.CountCalls;
group.TimeSum += diffTime;
if ( diffTime > group.LongestTime )
group.LongestTime = diffTime;
group.LastTimeStarted = 0;
}
}
}
}
//! Access the Irrlicht profiler object.
/** Profiler is always accessible, except in destruction of global objects.
If you want to get internal profiling information about the engine itself
you will have to re-compile the engine with _IRR_COMPILE_WITH_PROFILING_ enabled.
But you can use the profiler for profiling your own projects without that. */
IRRLICHT_API CProfiler& IRRCALLCONV getProfiler();
//! Class where the objects profile their own life-time.
/** This is a compfort wrapper around the CProfiler start/stop mechanism which is easier to use
when you want to profile a scope. You only have to create an object and it will profile it's own lifetime
for the given id. */
class CProfileScope
{
public:
//! Construct with an known id.
/** This is the fastest scope constructor, but the id must have been added before.
\param id Any id which you did add to the profiler before. */
CProfileScope(s32 id)
: Id(id), Profiler(getProfiler())
{
Profiler.start(Id);
}
//! Object will create the given name, groupName combination for the id if it doesn't exist already
/** \param id: Should be >= 0 as negative id's are reserved for Irrlicht. Also very large numbers (near INT_MAX) might
have been created already by the autoamtic add function of ::CProfiler.
\param name: Name for displaying profile data.
\param groupName: Each id belongs into a group - this helps on displaying profile data. */
CProfileScope(s32 id, const core::stringw &name, const core::stringw &groupName)
: Id(id), Profiler(getProfiler())
{
Profiler.add(Id, name, groupName);
Profiler.start(Id);
}
//! Object will create an id for the given name, groupName combination if they don't exist already
/** Slowest scope constructor, but usually still fine unless speed is very critical.
\param name: Name for displaying profile data.
\param groupName: Each id belongs into a group - this helps on displaying profile data. */
CProfileScope(const core::stringw &name, const core::stringw &groupName)
: Profiler(getProfiler())
{
Id = Profiler.add(name, groupName);
Profiler.start(Id);
}
~CProfileScope()
{
Profiler.stop(Id);
}
protected:
s32 Id;
CProfiler& Profiler;
};
} // namespace irr
//! For internal engine use:
//! Code inside IRR_PROFILE is only executed when _IRR_COMPILE_WITH_PROFILING_ is set
//! This allows disabling all profiler code completely by changing that define.
//! It's generally useful to wrap profiler-calls in application code with a similar macro.
#ifdef _IRR_COMPILE_WITH_PROFILING_
#define IRR_PROFILE(X) X
#else
#define IRR_PROFILE(X)
#endif // IRR_PROFILE
#endif // __PROFILER_H_INCLUDED__

View File

@ -91,6 +91,9 @@ enum EGUI_ELEMENT_TYPE
//! The root of the GUI
EGUIET_ROOT,
//! IGUIProfiler
EGUIET_PROFILER,
//! Not an element, amount of elements in there
EGUIET_COUNT,
@ -127,6 +130,7 @@ const c8* const GUIElementTypeNames[] =
"window",
"element",
"root",
"profiler",
0
};

View File

@ -59,6 +59,7 @@ class IGUIComboBox;
class IGUIToolBar;
class IGUIButton;
class IGUIWindow;
class IGUIProfiler;
class IGUIElementFactory;
//! GUI Environment. Used as factory and manager of all other GUI elements.
@ -540,6 +541,14 @@ public:
virtual IGUITable* addTable(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) =0;
//! Adds an element to display the information from the Irrlicht profiler
/** \param rectangle Rectangle specifying the borders of the element.
\param parent Parent of the element. When 0 the environment itself will
be the parent.
\param id An identifier for the element. */
virtual IGUIProfiler* addProfilerDisplay(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1) = 0;
//! Get the default element factory which can create all built-in elements
/** \return Pointer to the factory.
This pointer should not be dropped. See IReferenceCounted::drop() for

60
include/IGUIProfiler.h Normal file
View File

@ -0,0 +1,60 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef I_GUI_PROFILER_H_INCLUDED__
#define I_GUI_PROFILER_H_INCLUDED__
#include "IGUIElement.h"
namespace irr
{
namespace gui
{
class IGUIFont;
//! Element to display profiler information
class IGUIProfiler : public IGUIElement
{
public:
//! constructor
IGUIProfiler(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: IGUIElement(EGUIET_PROFILER, environment, parent, id, rectangle)
{}
//! Show first page of profile data
/** \param includeOverview When true show the group-overview page, when false show the profile data of the first group */
virtual void firstPage(bool includeOverview=true) = 0;
//! Show next page of profile data
/** \param includeOverview Include the group-overview page */
virtual void nextPage(bool includeOverview=true) = 0;
//! Show previous page of profile data
/** \param includeOverview Include the group-overview page */
virtual void previousPage(bool includeOverview=true) = 0;
//! Don't display stats for data which never got called
virtual void setIgnoreUncalled(bool ignore) = 0;
//! Check if we display stats for data which never got called
virtual bool getIgnoreUncalled() const = 0;
//! Sets another skin independent font.
/** If this is set to zero, the button uses the font of the skin.
\param font: New font to set. */
virtual void setOverrideFont(IGUIFont* font=0) = 0;
//! Gets the override font (if any)
/** \return The override font (may be 0) */
virtual IGUIFont* getOverrideFont(void) const = 0;
//! Get the font which is used right now for drawing
/** Currently this is the override font when one is set and the
font of the active skin otherwise */
virtual IGUIFont* getActiveFont() const = 0;
};
} // end namespace gui
} // end namespace irr
#endif

View File

@ -136,6 +136,15 @@
#undef _IRR_COMPILE_WITH_LEAK_HUNTER_
#endif
//! Enable profiling information in the engine
/** NOTE: The profiler itself always exists and can be used by applications.
This define is about the engine creating profile data
while it runs and enabling it will slow down the engine. */
//#define _IRR_COMPILE_WITH_PROFILING_
#ifdef NO_IRR_COMPILE_WITH_PROFILING_
#undef _IRR_COMPILE_WITH_PROFILING_
#endif
//! Define _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_COMPILE_WITH_DIRECT3D_9_ to
//! compile the Irrlicht engine with Direct3D8 and/or DIRECT3D9.
/** If you only want to use the software device or opengl you can disable those defines.

View File

@ -36,6 +36,7 @@
#include "CMeshBuffer.h"
#include "coreutil.h"
#include "CVertexBuffer.h"
#include "CProfiler.h"
#include "dimension2d.h"
#include "ECullingTypes.h"
#include "EDebugSceneTypes.h"
@ -97,6 +98,7 @@
#include "IGUIToolbar.h"
#include "IGUIWindow.h"
#include "IGUITreeView.h"
#include "IGUIProfiler.h"
#include "IImage.h"
#include "IImageLoader.h"
#include "IImageWriter.h"

View File

@ -27,6 +27,7 @@
#include "IGUIToolbar.h"
#include "IGUIWindow.h"
#include "IGUITreeView.h"
#include "IGUIProfiler.h"
namespace irr
{
@ -96,6 +97,8 @@ IGUIElement* CDefaultGUIElementFactory::addGUIElement(EGUI_ELEMENT_TYPE type, IG
return Environment->addSpinBox(L"0.0", core::rect<s32>(0,0,100,100), true, parent);
case EGUIET_TREE_VIEW:
return Environment->addTreeView(core::rect<s32>(0,0,100,100),parent);
case EGUIET_PROFILER:
return Environment->addProfilerDisplay(core::rect<s32>(0,0,100,100), parent);
default:
return 0;
}

View File

@ -35,6 +35,7 @@
#include "CGUIMenu.h"
#include "CGUIToolBar.h"
#include "CGUITable.h"
#include "CGUIProfiler.h"
#include "CDefaultGUIElementFactory.h"
#include "IWriteFile.h"
@ -1127,6 +1128,13 @@ IGUITable* CGUIEnvironment::addTable(const core::rect<s32>& rectangle, IGUIEleme
return b;
}
//! Adds an element to display the information from the Irrlicht profiler
IGUIProfiler* CGUIEnvironment::addProfilerDisplay(const core::rect<s32>& rectangle, IGUIElement* parent, s32 id)
{
CGUIProfiler* p = new CGUIProfiler(this, parent ? parent : this, id, rectangle);
p->drop();
return p;
}
//! Adds an image element.
IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d<s32> pos,

View File

@ -183,6 +183,10 @@ public:
virtual IGUITable* addTable(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) _IRR_OVERRIDE_;
//! Adds an element to display the information from the Irrlicht profiler
virtual IGUIProfiler* addProfilerDisplay(const core::rect<s32>& rectangle,
IGUIElement* parent=0, s32 id=-1) _IRR_OVERRIDE_;
//! sets the focus to an element
virtual bool setFocus(IGUIElement* element) _IRR_OVERRIDE_;

View File

@ -0,0 +1,209 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// TODO: We should have more pages for groups that don't fit into the display area.
// So additional to CurrentGroupIdx we would also have a current-page-for-current-group thing.
// The interface doesn't have to be changed for that - just the implementation.
#include "CGUIProfiler.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUITable.h"
#include "IGUIEnvironment.h"
#include "CProfiler.h"
namespace irr
{
namespace gui
{
//! constructor
CGUIProfiler::CGUIProfiler(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: IGUIProfiler(environment, parent, id, rectangle)
, DisplayTable(0), CurrentGroupIdx(0), IgnoreUncalled(false)
{
Profiler = &getProfiler();
core::recti r(0, 0, rectangle.getWidth(), rectangle.getHeight());
// Really just too lazy to code a complete new element for this.
// If anyone can do this nicer he's welcome.
DisplayTable = Environment->addTable(r, this, -1, true);
DisplayTable->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
DisplayTable->setSubElement(true);
rebuildColumns();
}
void CGUIProfiler::fillRow(u32 rowIndex, const SProfileData& data, bool overviewTitle, bool groupTitle)
{
DisplayTable->setCellText(rowIndex, 0, data.getName());
if ( !overviewTitle )
DisplayTable->setCellText(rowIndex, 1, core::stringw(data.getCallsCounter()));
if ( data.getCallsCounter() > 0 )
{
DisplayTable->setCellText(rowIndex, 2, core::stringw(data.getTimeSum()));
DisplayTable->setCellText(rowIndex, 3, core::stringw((u32)((f32)data.getTimeSum()/(f32)data.getCallsCounter())));
DisplayTable->setCellText(rowIndex, 4, core::stringw(data.getLongestTime()));
}
if ( overviewTitle || groupTitle )
{
const video::SColor titleColor(255, 0, 0, 255);
DisplayTable->setCellColor(rowIndex, 0, titleColor);
}
}
void CGUIProfiler::rebuildColumns()
{
if ( DisplayTable )
{
DisplayTable->clear();
DisplayTable->addColumn(L"name ");
DisplayTable->addColumn(L"count calls");
DisplayTable->addColumn(L"time(sum)");
DisplayTable->addColumn(L"time(avg)");
DisplayTable->addColumn(L"time(max) ");
DisplayTable->setActiveColumn(-1);
}
}
void CGUIProfiler::updateDisplay()
{
if ( DisplayTable )
{
DisplayTable->clearRows();
if ( CurrentGroupIdx < Profiler->getGroupCount() )
{
bool overview = CurrentGroupIdx == 0;
u32 rowIndex = 0;
const SProfileData& groupData = Profiler->getGroupData(CurrentGroupIdx);
if ( overview || !IgnoreUncalled || groupData.getCallsCounter() > 0 )
{
rowIndex = DisplayTable->addRow(rowIndex);
fillRow(rowIndex, groupData, overview, true);
++rowIndex;
}
// show overview over groups?
if ( overview )
{
for ( u32 i=1; i<Profiler->getGroupCount(); ++i )
{
const SProfileData& groupData = Profiler->getGroupData(i);
if ( !IgnoreUncalled || groupData.getCallsCounter() > 0 )
{
rowIndex = DisplayTable->addRow(rowIndex);
fillRow(rowIndex, groupData, false, false);
++rowIndex;
}
}
}
// show data for all elements in current group
else
{
for ( u32 i=0; i < Profiler->getProfileDataCount(); ++i )
{
const SProfileData& data = Profiler->getProfileDataByIndex(i);
if ( data.getGroupIndex() == CurrentGroupIdx
&& (!IgnoreUncalled || data.getCallsCounter() > 0) )
{
rowIndex = DisplayTable->addRow(rowIndex);
fillRow(rowIndex, data, false, false);
++rowIndex;
}
}
}
}
}
}
void CGUIProfiler::draw()
{
if ( isVisible() )
{
updateDisplay();
}
IGUIElement::draw();
}
void CGUIProfiler::nextPage(bool includeOverview)
{
if ( ++CurrentGroupIdx >= Profiler->getGroupCount() )
{
if ( includeOverview )
CurrentGroupIdx = 0;
else
CurrentGroupIdx = 1; // can be invalid
}
}
void CGUIProfiler::previousPage(bool includeOverview)
{
if ( CurrentGroupIdx > 0 )
--CurrentGroupIdx;
else
CurrentGroupIdx = Profiler->getGroupCount()-1;
if ( CurrentGroupIdx == 0 && !includeOverview )
{
if ( Profiler->getGroupCount() )
CurrentGroupIdx = Profiler->getGroupCount()-1;
if ( CurrentGroupIdx == 0 )
CurrentGroupIdx = 1; // invalid to avoid showing the overview
}
}
void CGUIProfiler::firstPage(bool includeOverview)
{
if ( includeOverview )
CurrentGroupIdx = 0;
else
CurrentGroupIdx = 1; // can be invalid
}
void CGUIProfiler::setIgnoreUncalled(bool ignore)
{
IgnoreUncalled = ignore;
}
bool CGUIProfiler::getIgnoreUncalled() const
{
return IgnoreUncalled;
}
//! Sets another skin independent font.
void CGUIProfiler::setOverrideFont(IGUIFont* font)
{
if ( DisplayTable )
{
DisplayTable->setOverrideFont(font);
rebuildColumns();
}
}
//! Gets the override font (if any)
IGUIFont * CGUIProfiler::getOverrideFont() const
{
if ( DisplayTable )
return DisplayTable->getOverrideFont();
return 0;
}
//! Get the font which is used right now for drawing
IGUIFont* CGUIProfiler::getActiveFont() const
{
if ( DisplayTable )
return DisplayTable->getActiveFont();
return 0;
}
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_

View File

@ -0,0 +1,79 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef C_GUI_PROFILER_H_INCLUDED__
#define C_GUI_PROFILER_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUIProfiler.h"
namespace irr
{
class CProfiler;
struct SProfileData;
namespace gui
{
class IGUITable;
//! Element to display profiler information
class CGUIProfiler : public IGUIProfiler
{
public:
//! constructor
CGUIProfiler(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
//! Show first page of profile data
virtual void firstPage(bool includeOverview) _IRR_OVERRIDE_;
//! Show next page of profile data
virtual void nextPage(bool includeOverview) _IRR_OVERRIDE_;
//! Show previous page of profile data
virtual void previousPage(bool includeOverview) _IRR_OVERRIDE_;
//! Don't display stats for data which never got called
/** Default is false */
virtual void setIgnoreUncalled(bool ignore) _IRR_OVERRIDE_;
//! Check if we display stats for data which never got called
virtual bool getIgnoreUncalled() const _IRR_OVERRIDE_;
//! Sets another skin independent font.
virtual void setOverrideFont(IGUIFont* font=0) _IRR_OVERRIDE_;
//! Gets the override font (if any)
virtual IGUIFont* getOverrideFont() const _IRR_OVERRIDE_;
//! Get the font which is used right now for drawing
virtual IGUIFont* getActiveFont() const _IRR_OVERRIDE_;
virtual IGUIElement* getElementFromPoint(const core::position2d<s32>& point) _IRR_OVERRIDE_
{
// This element should never get focus from mouse-clicks
return 0;
}
virtual void draw() _IRR_OVERRIDE_;
protected:
void updateDisplay();
void fillRow(u32 rowIndex, const SProfileData& data, bool overviewTitle, bool groupTitle);
void rebuildColumns();
CProfiler * Profiler;
irr::gui::IGUITable* DisplayTable;
irr::u32 CurrentGroupIdx;
bool IgnoreUncalled;
};
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
#endif // __C_GUI_IMAGE_H_INCLUDED__

View File

@ -12,6 +12,8 @@
#include "IMaterialRenderer.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
#include "EProfileIDs.h"
#include "CProfiler.h"
namespace irr
{
@ -31,6 +33,16 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
#ifdef _DEBUG
setDebugName("COctreeSceneNode");
#endif
IRR_PROFILE(
static bool initProfile = false;
if (!initProfile )
{
initProfile = true;
getProfiler().add(EPID_OC_RENDER, L"render octnode", L"Irrlicht scene");
getProfiler().add(EPID_OC_CALCPOLYS, L"calc octnode", L"Irrlicht scene");
}
)
}
@ -89,6 +101,7 @@ void COctreeSceneNode::OnRegisterSceneNode()
//! renders the node.
void COctreeSceneNode::render()
{
IRR_PROFILE(CProfileScope psRender(EPID_OC_RENDER);)
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (VertexType == -1 || !driver)
@ -122,10 +135,12 @@ void COctreeSceneNode::render()
{
case video::EVT_STANDARD:
{
IRR_PROFILE(getProfiler().start(EPID_OC_CALCPOLYS));
if (BoxBased)
StdOctree->calculatePolys(box);
else
StdOctree->calculatePolys(frust);
IRR_PROFILE(getProfiler().stop(EPID_OC_CALCPOLYS));
const Octree<video::S3DVertex>::SIndexData* d = StdOctree->getIndexData();
@ -170,10 +185,12 @@ void COctreeSceneNode::render()
break;
case video::EVT_2TCOORDS:
{
IRR_PROFILE(getProfiler().start(EPID_OC_CALCPOLYS));
if (BoxBased)
LightMapOctree->calculatePolys(box);
else
LightMapOctree->calculatePolys(frust);
IRR_PROFILE(getProfiler().stop(EPID_OC_CALCPOLYS));
const Octree<video::S3DVertex2TCoords>::SIndexData* d = LightMapOctree->getIndexData();
@ -236,10 +253,12 @@ void COctreeSceneNode::render()
break;
case video::EVT_TANGENTS:
{
IRR_PROFILE(getProfiler().start(EPID_OC_CALCPOLYS));
if (BoxBased)
TangentsOctree->calculatePolys(box);
else
TangentsOctree->calculatePolys(frust);
IRR_PROFILE(getProfiler().stop(EPID_OC_CALCPOLYS));
const Octree<video::S3DVertexTangents>::SIndexData* d = TangentsOctree->getIndexData();

View File

@ -0,0 +1,247 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CProfiler.h"
#include "CTimer.h"
#include <limits.h>
namespace irr
{
IRRLICHT_API CProfiler& IRRCALLCONV getProfiler()
{
static CProfiler profiler;
return profiler;
}
//! Convert the whole data into a string
core::stringw SProfileData::getAsString() const
{
if ( CountCalls > 0 )
{
#ifdef _MSC_VER
#pragma warning(disable:4996) // 'sprintf' was declared deprecated
#endif
// Can't use swprintf as it fails on some platforms (especially mobile platforms)
// Can't use Irrlicht functions because we have no string formatting.
char dummy[1023];
sprintf(dummy, "%-15.15s%-12u%-12u%-12u%-12u",
core::stringc(Name).c_str(), CountCalls, TimeSum,
TimeSum / CountCalls, LongestTime);
dummy[1022] = 0;
return core::stringw(dummy);
#ifdef _MSC_VER
#pragma warning(default :4996) // 'sprintf' was declared deprecated
#endif
}
else
{
return Name;
}
}
//! Return a string which describes the columns returned by getAsString
core::stringw SProfileData::makeTitleString()
{
return core::stringw("name calls time(sum) time(avg) time(max)");
}
void SProfileData::reset()
{
CountCalls = 0;
LongestTime = 0;
TimeSum = 0;
LastTimeStarted = 0;
}
CProfiler::CProfiler()
: Timer(0)
, NextAutoId(INT_MAX)
{
Timer = new CTimer(true);
addGroup(L"overview");
}
CProfiler::~CProfiler()
{
if ( Timer )
Timer->drop();
}
s32 CProfiler::add(const core::stringw &name, const core::stringw &groupName)
{
u32 index;
if ( findDataIndex(index, name) )
{
add( ProfileDatas[index].Id, name, groupName );
return ProfileDatas[index].Id;
}
else
{
s32 id = NextAutoId;
--NextAutoId;
add( id, name, groupName );
return id;
}
}
void CProfiler::add(s32 id, const core::stringw &name, const core::stringw &groupName)
{
u32 groupIdx;
if ( !findGroupIndex(groupIdx, groupName) )
{
groupIdx = addGroup(groupName);
}
SProfileData data(id);
s32 idx = ProfileDatas.binary_search(data);
if ( idx < 0 )
{
data.reset();
data.GroupIndex = groupIdx;
data.Name = name;
ProfileDatas.push_back(data);
ProfileDatas.sort();
}
else
{
// only reset on group changes, otherwise we want to keep the data or coding CProfileScope would become tricky.
if ( groupIdx != ProfileDatas[idx].GroupIndex )
{
resetDataByIndex((u32)idx);
ProfileDatas[idx].GroupIndex = groupIdx;
}
ProfileDatas[idx].Name = name;
}
}
u32 CProfiler::addGroup(const core::stringw &name)
{
SProfileData group;
group.Id = -1; // Id for groups doesn't matter so far
group.Name = name;
ProfileGroups.push_back(group);
return ProfileGroups.size()-1;
}
bool CProfiler::findDataIndex(u32 & result, const core::stringw &name) const
{
for ( u32 i=0; i < ProfileDatas.size(); ++i )
{
if ( ProfileDatas[i].Name == name )
{
result = i;
return true;
}
}
return false;
}
bool CProfiler::findGroupIndex(u32 & result, const core::stringw &name) const
{
for ( u32 i=0; i < ProfileGroups.size(); ++i )
{
if ( ProfileGroups[i].Name == name )
{
result = i;
return true;
}
}
return false;
}
void CProfiler::resetDataById(s32 id)
{
s32 idx = ProfileDatas.binary_search(SProfileData(id));
if ( idx >= 0 )
{
resetDataByIndex((u32)idx);
}
}
void CProfiler::resetDataByIndex(u32 index)
{
SProfileData &data = ProfileDatas[index];
SProfileData & group = ProfileGroups[data.GroupIndex];
group.CountCalls -= data.CountCalls;
group.TimeSum -= data.TimeSum;
data.reset();
}
//! Reset profile data for a whole group
void CProfiler::resetGroup(u32 index)
{
for ( u32 i=0; i<ProfileDatas.size(); ++i )
{
if ( ProfileDatas[i].GroupIndex == index )
ProfileDatas[i].reset();
}
if ( index < ProfileGroups.size() )
ProfileGroups[index].reset();
}
void CProfiler::resetAll()
{
for ( u32 i=0; i<ProfileDatas.size(); ++i )
{
ProfileDatas[i].reset();
}
for ( u32 i=0; i<ProfileGroups.size(); ++i )
{
ProfileGroups[i].reset();
}
}
void CProfiler::printAll(core::stringw &ostream, bool includeOverview, bool suppressUncalled) const
{
ostream += SProfileData::makeTitleString();
ostream += L"\n";
for ( u32 i=includeOverview ?0:1; i<ProfileGroups.size(); ++i )
{
printGroup( ostream, i, suppressUncalled );
}
}
void CProfiler::printGroup(core::stringw &ostream, u32 idxGroup, bool suppressUncalled) const
{
ostream += ProfileGroups[idxGroup].getAsString();
ostream += L"\n";
// print overview for groups
if ( idxGroup == 0 )
{
for ( u32 i=0; i<ProfileGroups.size(); ++i )
{
if ( !suppressUncalled || ProfileGroups[i].CountCalls > 0)
{
ostream += ProfileGroups[i].getAsString();
ostream += L"\n";
}
}
}
// print all data in a group
else
{
for ( u32 i=0; i<ProfileDatas.size(); ++i )
{
if ( (!suppressUncalled || ProfileDatas[i].CountCalls > 0)
&& ProfileDatas[i].GroupIndex == idxGroup )
{
ostream += ProfileDatas[i].getAsString();
ostream += L"\n";
}
}
}
}
} // namespace irr

View File

@ -15,6 +15,8 @@
#include "IReadFile.h"
#include "IWriteFile.h"
#include "ISceneLoader.h"
#include "EProfileIDs.h"
#include "CProfiler.h"
#include "os.h"
@ -308,6 +310,24 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this, CursorControl);
registerSceneNodeAnimatorFactory(animatorFactory);
animatorFactory->drop();
IRR_PROFILE(
static bool initProfile = false;
if (!initProfile )
{
initProfile = true;
getProfiler().add(EPID_SM_DRAW_ALL, L"drawAll", L"Irrlicht scene");
getProfiler().add(EPID_SM_ANIMATE, L"animate", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_CAMERAS, L"cameras", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_LIGHTS, L"lights", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_SKYBOXES, L"skyboxes", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_DEFAULT, L"defaultnodes", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_SHADOWS, L"shadows", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_TRANSPARENT, L"transp.nodes", L"Irrlicht scene");
getProfiler().add(EPID_SM_RENDER_EFFECT, L"effectnodes", L"Irrlicht scene");
getProfiler().add(EPID_SM_REGISTER, L"reg.render.node", L"Irrlicht scene");
}
)
}
@ -1228,6 +1248,7 @@ bool CSceneManager::isCulled(const ISceneNode* node) const
//! registers a node for rendering it at a specific time.
u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass)
{
IRR_PROFILE(CProfileScope p1(EPID_SM_REGISTER);)
u32 taken = 0;
switch(pass)
@ -1345,6 +1366,8 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE
//! draws all scene nodes
void CSceneManager::drawAll()
{
IRR_PROFILE(CProfileScope psAll(EPID_SM_DRAW_ALL);)
if (!Driver)
return;
@ -1370,18 +1393,22 @@ void CSceneManager::drawAll()
Driver->setAllowZWriteOnTransparent(Parameters->getAttributeAsBool(ALLOW_ZWRITE_ON_TRANSPARENT));
// do animations and other stuff.
IRR_PROFILE(getProfiler().start(EPID_SM_ANIMATE));
OnAnimate(os::Timer::getTime());
IRR_PROFILE(getProfiler().stop(EPID_SM_ANIMATE));
/*!
First Scene Node for prerendering should be the active camera
consistent Camera is needed for culling
*/
IRR_PROFILE(getProfiler().start(EPID_SM_RENDER_CAMERAS));
camWorldPos.set(0,0,0);
if (ActiveCamera)
{
ActiveCamera->render();
camWorldPos = ActiveCamera->getAbsolutePosition();
}
IRR_PROFILE(getProfiler().stop(EPID_SM_RENDER_CAMERAS));
// let all nodes register themselves
OnRegisterSceneNode();
@ -1391,6 +1418,7 @@ void CSceneManager::drawAll()
//render camera scenes
{
IRR_PROFILE(CProfileScope psCam(EPID_SM_RENDER_CAMERAS);)
CurrentRenderPass = ESNRP_CAMERA;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
@ -1408,6 +1436,7 @@ void CSceneManager::drawAll()
//render lights scenes
{
IRR_PROFILE(CProfileScope psLights(EPID_SM_RENDER_LIGHTS);)
CurrentRenderPass = ESNRP_LIGHT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
@ -1452,6 +1481,7 @@ void CSceneManager::drawAll()
// render skyboxes
{
IRR_PROFILE(CProfileScope psSkyBox(EPID_SM_RENDER_SKYBOXES);)
CurrentRenderPass = ESNRP_SKY_BOX;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
@ -1481,6 +1511,7 @@ void CSceneManager::drawAll()
// render default objects
{
IRR_PROFILE(CProfileScope psDefault(EPID_SM_RENDER_DEFAULT);)
CurrentRenderPass = ESNRP_SOLID;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
@ -1514,6 +1545,7 @@ void CSceneManager::drawAll()
// render shadows
{
IRR_PROFILE(CProfileScope psShadow(EPID_SM_RENDER_SHADOWS);)
CurrentRenderPass = ESNRP_SHADOW;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
@ -1546,6 +1578,7 @@ void CSceneManager::drawAll()
// render transparent objects.
{
IRR_PROFILE(CProfileScope psTrans(EPID_SM_RENDER_TRANSPARENT);)
CurrentRenderPass = ESNRP_TRANSPARENT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
@ -1579,6 +1612,7 @@ void CSceneManager::drawAll()
// render transparent effect objects.
{
IRR_PROFILE(CProfileScope psEffect(EPID_SM_RENDER_EFFECT);)
CurrentRenderPass = ESNRP_TRANSPARENT_EFFECT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);

View File

@ -0,0 +1,37 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef E_PROFILE_IDS_H_INCLUDED__
#define E_PROFILE_IDS_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "limits.h"
namespace irr
{
#ifdef _IRR_COMPILE_WITH_PROFILING_
enum EPROFILE_ID
{
// We use negative ID's to avoid clashing with user application id's.
EPID_FIRST = -INT_MAX, // not used
//! scenemanager.
EPID_SM_DRAW_ALL,
EPID_SM_ANIMATE,
EPID_SM_RENDER_CAMERAS,
EPID_SM_RENDER_LIGHTS,
EPID_SM_RENDER_SKYBOXES,
EPID_SM_RENDER_DEFAULT,
EPID_SM_RENDER_SHADOWS,
EPID_SM_RENDER_TRANSPARENT,
EPID_SM_RENDER_EFFECT,
EPID_SM_REGISTER,
//! octrees
EPID_OC_RENDER,
EPID_OC_CALCPOLYS
};
#endif
} // end namespace irr
#endif // E_PROFILE_IDS_H_INCLUDED__

View File

@ -414,6 +414,7 @@
<Unit filename="../../include/CDynamicMeshBuffer.h" />
<Unit filename="../../include/CIndexBuffer.h" />
<Unit filename="../../include/CMeshBuffer.h" />
<Unit filename="../../include/CProfiler.h" />
<Unit filename="../../include/CVertexBuffer.h" />
<Unit filename="../../include/EAttributes.h" />
<Unit filename="../../include/ECullingTypes.h" />
@ -470,6 +471,7 @@
<Unit filename="../../include/IGUIInOutFader.h" />
<Unit filename="../../include/IGUIListBox.h" />
<Unit filename="../../include/IGUIMeshViewer.h" />
<Unit filename="../../include/IGUIProfiler.h" />
<Unit filename="../../include/IGUIScrollBar.h" />
<Unit filename="../../include/IGUISkin.h" />
<Unit filename="../../include/IGUISpinBox.h" />
@ -713,6 +715,8 @@
<Unit filename="CGUIMessageBox.h" />
<Unit filename="CGUIModalScreen.cpp" />
<Unit filename="CGUIModalScreen.h" />
<Unit filename="CGUIProfiler.cpp" />
<Unit filename="CGUIProfiler.h" />
<Unit filename="CGUIScrollBar.cpp" />
<Unit filename="CGUIScrollBar.h" />
<Unit filename="CGUISkin.cpp" />
@ -887,6 +891,7 @@
<Unit filename="CParticleSphereEmitter.h" />
<Unit filename="CParticleSystemSceneNode.cpp" />
<Unit filename="CParticleSystemSceneNode.h" />
<Unit filename="CProfiler.cpp" />
<Unit filename="CQ3LevelMesh.cpp" />
<Unit filename="CQ3LevelMesh.h" />
<Unit filename="CQuake3ShaderSceneNode.cpp" />
@ -1007,6 +1012,7 @@
<Unit filename="CZBuffer.h" />
<Unit filename="CZipReader.cpp" />
<Unit filename="CZipReader.h" />
<Unit filename="EProfileIDs.h" />
<Unit filename="IAttribute.h" />
<Unit filename="IBurningShader.cpp" />
<Unit filename="IBurningShader.h" />

View File

@ -835,6 +835,7 @@
<ClInclude Include="..\..\include\EMaterialFlags.h" />
<ClInclude Include="..\..\include\IAnimatedMeshMD3.h" />
<ClInclude Include="..\..\include\IEventReceiver.h" />
<ClInclude Include="..\..\include\CProfiler.h" />
<ClInclude Include="..\..\include\ILogger.h" />
<ClInclude Include="..\..\include\IOSOperator.h" />
<ClInclude Include="..\..\include\IRandomizer.h" />
@ -982,6 +983,7 @@
<ClInclude Include="..\..\include\IGUIInOutFader.h" />
<ClInclude Include="..\..\include\IGUIListBox.h" />
<ClInclude Include="..\..\include\IGUIMeshViewer.h" />
<ClInclude Include="..\..\include\IGUIProfiler.h" />
<ClInclude Include="..\..\include\IGUIScrollBar.h" />
<ClInclude Include="..\..\include\IGUISkin.h" />
<ClInclude Include="..\..\include\IGUISpinBox.h" />
@ -1149,6 +1151,7 @@
<ClInclude Include="COSOperator.h" />
<ClInclude Include="CTimer.h" />
<ClInclude Include="os.h" />
<ClInclude Include="EProfileIDs.h" />
<ClInclude Include="lzma\LzmaDec.h" />
<ClInclude Include="lzma\Types.h" />
<ClInclude Include="zlib\crc32.h" />
@ -1226,7 +1229,8 @@
<ClInclude Include="CGUIMeshViewer.h" />
<ClInclude Include="CGUIMessageBox.h" />
<ClInclude Include="CGUIModalScreen.h" />
<ClInclude Include="CGUIScrollBar.h" />
<ClInclude Include="CGUIProfiler.h" />
<ClInclude Include="CGUIScrollBar.h" />
<ClInclude Include="CGUISkin.h" />
<ClInclude Include="CGUISpinBox.h" />
<ClInclude Include="CGUISpriteBank.h" />
@ -1413,6 +1417,7 @@
<ClCompile Include="Irrlicht.cpp" />
<ClCompile Include="leakHunter.cpp" />
<ClCompile Include="os.cpp" />
<ClCompile Include="CProfiler.cpp" />
<ClCompile Include="lzma\LzmaDec.c" />
<ClCompile Include="zlib\adler32.c" />
<ClCompile Include="zlib\compress.c" />
@ -1542,7 +1547,8 @@
<ClCompile Include="CGUIMeshViewer.cpp" />
<ClCompile Include="CGUIMessageBox.cpp" />
<ClCompile Include="CGUIModalScreen.cpp" />
<ClCompile Include="CGUIScrollBar.cpp" />
<ClCompile Include="CGUIProfiler.cpp" />
<ClCompile Include="CGUIScrollBar.cpp" />
<ClCompile Include="CGUISkin.cpp" />
<ClCompile Include="CGUISpinBox.cpp" />
<ClCompile Include="CGUISpriteBank.cpp" />

View File

@ -105,7 +105,10 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\IEventReceiver.h">
<ClInclude Include="..\..\include\IEventReceiver.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\CProfiler.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\ILogger.h">
@ -539,6 +542,9 @@
</ClInclude>
<ClInclude Include="..\..\include\IGUIMeshViewer.h">
<Filter>include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\IGUIProfiler.h">
<Filter>include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\IGUIScrollBar.h">
<Filter>include\gui</Filter>
@ -1022,6 +1028,9 @@
</ClInclude>
<ClInclude Include="os.h">
<Filter>Irrlicht\irr</Filter>
</ClInclude>
<ClInclude Include="EProfileIDs.h">
<Filter>Irrlicht\irr</Filter>
</ClInclude>
<ClInclude Include="lzma\LzmaDec.h">
<Filter>Irrlicht\irr\extern</Filter>
@ -1254,7 +1263,10 @@
<ClInclude Include="CGUIModalScreen.h">
<Filter>Irrlicht\gui</Filter>
</ClInclude>
<ClInclude Include="CGUIScrollBar.h">
<ClInclude Include="CGUIProfiler.h">
<Filter>Irrlicht\gui</Filter>
</ClInclude>
<ClInclude Include="CGUIScrollBar.h">
<Filter>Irrlicht\gui</Filter>
</ClInclude>
<ClInclude Include="CGUISkin.h">
@ -1822,6 +1834,9 @@
</ClCompile>
<ClCompile Include="os.cpp">
<Filter>Irrlicht\irr</Filter>
</ClCompile>
<ClCompile Include="CProfiler.cpp">
<Filter>Irrlicht\irr</Filter>
</ClCompile>
<ClCompile Include="lzma\LzmaDec.c">
<Filter>Irrlicht\irr\extern</Filter>
@ -2210,7 +2225,10 @@
<ClCompile Include="CGUIModalScreen.cpp">
<Filter>Irrlicht\gui</Filter>
</ClCompile>
<ClCompile Include="CGUIScrollBar.cpp">
<ClCompile Include="CGUIProfiler.cpp">
<Filter>Irrlicht\gui</Filter>
</ClCompile>
<ClCompile Include="CGUIScrollBar.cpp">
<Filter>Irrlicht\gui</Filter>
</ClCompile>
<ClCompile Include="CGUISkin.cpp">

View File

@ -842,6 +842,7 @@
<ClInclude Include="..\..\include\EMaterialFlags.h" />
<ClInclude Include="..\..\include\IAnimatedMeshMD3.h" />
<ClInclude Include="..\..\include\IEventReceiver.h" />
<ClInclude Include="..\..\include\CProfiler.h" />
<ClInclude Include="..\..\include\ILogger.h" />
<ClInclude Include="..\..\include\IOSOperator.h" />
<ClInclude Include="..\..\include\IRandomizer.h" />
@ -989,6 +990,7 @@
<ClInclude Include="..\..\include\IGUIInOutFader.h" />
<ClInclude Include="..\..\include\IGUIListBox.h" />
<ClInclude Include="..\..\include\IGUIMeshViewer.h" />
<ClInclude Include="..\..\include\IGUIProfiler.h" />
<ClInclude Include="..\..\include\IGUIScrollBar.h" />
<ClInclude Include="..\..\include\IGUISkin.h" />
<ClInclude Include="..\..\include\IGUISpinBox.h" />
@ -1156,6 +1158,7 @@
<ClInclude Include="COSOperator.h" />
<ClInclude Include="CTimer.h" />
<ClInclude Include="os.h" />
<ClInclude Include="EProfileIDs.h" />
<ClInclude Include="lzma\LzmaDec.h" />
<ClInclude Include="lzma\Types.h" />
<ClInclude Include="zlib\crc32.h" />
@ -1233,7 +1236,8 @@
<ClInclude Include="CGUIMeshViewer.h" />
<ClInclude Include="CGUIMessageBox.h" />
<ClInclude Include="CGUIModalScreen.h" />
<ClInclude Include="CGUIScrollBar.h" />
<ClInclude Include="CGUIProfiler.h" />
<ClInclude Include="CGUIScrollBar.h" />
<ClInclude Include="CGUISkin.h" />
<ClInclude Include="CGUISpinBox.h" />
<ClInclude Include="CGUISpriteBank.h" />
@ -1419,6 +1423,7 @@
<ClCompile Include="COSOperator.cpp" />
<ClCompile Include="Irrlicht.cpp" />
<ClCompile Include="os.cpp" />
<ClCompile Include="CProfiler.cpp" />
<ClCompile Include="leakHunter.cpp" />
<ClCompile Include="lzma\LzmaDec.c" />
<ClCompile Include="zlib\adler32.c" />
@ -1549,7 +1554,8 @@
<ClCompile Include="CGUIMeshViewer.cpp" />
<ClCompile Include="CGUIMessageBox.cpp" />
<ClCompile Include="CGUIModalScreen.cpp" />
<ClCompile Include="CGUIScrollBar.cpp" />
<ClCompile Include="CGUIProfiler.cpp" />
<ClCompile Include="CGUIScrollBar.cpp" />
<ClCompile Include="CGUISkin.cpp" />
<ClCompile Include="CGUISpinBox.cpp" />
<ClCompile Include="CGUISpriteBank.cpp" />

View File

@ -107,6 +107,9 @@
<ItemGroup>
<ClInclude Include="..\..\include\IEventReceiver.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\CProfiler.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\ILogger.h">
<Filter>include</Filter>
@ -542,6 +545,9 @@
</ClInclude>
<ClInclude Include="..\..\include\IGUIMeshViewer.h">
<Filter>include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\IGUIProfiler.h">
<Filter>include\gui</Filter>
</ClInclude>
<ClInclude Include="..\..\include\IGUIScrollBar.h">
<Filter>include\gui</Filter>
@ -1025,6 +1031,9 @@
</ClInclude>
<ClInclude Include="os.h">
<Filter>Irrlicht\irr</Filter>
</ClInclude>
<ClInclude Include="EProfileIDs.h">
<Filter>Irrlicht\irr</Filter>
</ClInclude>
<ClInclude Include="lzma\LzmaDec.h">
<Filter>Irrlicht\irr\extern</Filter>
@ -1257,7 +1266,10 @@
<ClInclude Include="CGUIModalScreen.h">
<Filter>Irrlicht\gui</Filter>
</ClInclude>
<ClInclude Include="CGUIScrollBar.h">
<ClInclude Include="CGUIProfiler.h">
<Filter>Irrlicht\gui</Filter>
</ClInclude>
<ClInclude Include="CGUIScrollBar.h">
<Filter>Irrlicht\gui</Filter>
</ClInclude>
<ClInclude Include="CGUISkin.h">
@ -1822,6 +1834,9 @@
</ClCompile>
<ClCompile Include="os.cpp">
<Filter>Irrlicht\irr</Filter>
</ClCompile>
<ClCompile Include="CProfiler.cpp">
<Filter>Irrlicht\irr</Filter>
</ClCompile>
<ClCompile Include="leakHunter.cpp">
<Filter>Irrlicht\irr</Filter>
@ -2213,7 +2228,10 @@
<ClCompile Include="CGUIModalScreen.cpp">
<Filter>Irrlicht\gui</Filter>
</ClCompile>
<ClCompile Include="CGUIScrollBar.cpp">
<ClCompile Include="CGUIProfiler.cpp">
<Filter>Irrlicht\gui</Filter>
</ClCompile>
<ClCompile Include="CGUIScrollBar.cpp">
<Filter>Irrlicht\gui</Filter>
</ClCompile>
<ClCompile Include="CGUISkin.cpp">

View File

@ -586,6 +586,10 @@
RelativePath=".\..\..\include\IEventReceiver.h"
>
</File>
<File
RelativePath=".\..\..\include\CProfiler.h"
>
</File>
<File
RelativePath=".\..\..\include\ILogger.h"
>
@ -1198,6 +1202,10 @@
RelativePath=".\..\..\include\IGUIMeshViewer.h"
>
</File>
<File
RelativePath=".\..\..\include\IGUIProfiler.h"
>
</File>
<File
RelativePath=".\..\..\include\IGUIScrollBar.h"
>
@ -1391,6 +1399,14 @@
RelativePath="CGUIModalScreen.h"
>
</File>
<File
RelativePath=".\CGUIProfiler.cpp"
>
</File>
<File
RelativePath=".\CGUIProfiler.h"
>
</File>
<File
RelativePath=".\CGUIScrollBar.cpp"
>
@ -3001,6 +3017,14 @@
RelativePath="os.cpp"
>
</File>
<File
RelativePath="CProfiler.cpp"
>
</File>
<File
RelativePath="EProfileIDs.h"
>
</File>
<File
RelativePath="leakHunter.cpp"
>

View File

@ -685,6 +685,10 @@
RelativePath="..\..\include\IEventReceiver.h"
>
</File>
<File
RelativePath="..\..\include\CProfiler.h"
>
</File>
<File
RelativePath="..\..\include\ILogger.h"
>
@ -1296,6 +1300,10 @@
RelativePath="..\..\include\IGUIMeshViewer.h"
>
</File>
<File
RelativePath="..\..\include\IGUIProfiler.h"
>
</File>
<File
RelativePath="..\..\include\IGUIScrollBar.h"
>
@ -2728,6 +2736,14 @@
RelativePath="os.cpp"
>
</File>
<File
RelativePath="CProfiler.cpp"
>
</File>
<File
RelativePath="EProfileIDs.h"
>
</File>
<File
RelativePath="os.h"
>
@ -3592,6 +3608,14 @@
RelativePath="CGUIModalScreen.h"
>
</File>
<File
RelativePath="CGUIProfiler.cpp"
>
</File>
<File
RelativePath="CGUIProfiler.h"
>
</File>
<File
RelativePath="CGUIScrollBar.cpp"
>

View File

@ -329,6 +329,10 @@
RelativePath="..\..\include\IEventReceiver.h"
>
</File>
<File
RelativePath="..\..\include\CProfiler.h"
>
</File>
<File
RelativePath="..\..\include\ILogger.h"
>
@ -848,6 +852,10 @@
RelativePath="..\..\include\IGUIMeshViewer.h"
>
</File>
<File
RelativePath="..\..\include\IGUIProfiler.h"
>
</File>
<File
RelativePath="..\..\include\IGUIScrollBar.h"
>
@ -1033,6 +1041,14 @@
RelativePath="CGUIModalScreen.h"
>
</File>
<File
RelativePath="CGUIProfiler.cpp"
>
</File>
<File
RelativePath="CGUIProfiler.h"
>
</File>
<File
RelativePath="CGUIScrollBar.cpp"
>
@ -2574,6 +2590,14 @@
RelativePath="os.cpp"
>
</File>
<File
RelativePath="CProfiler.cpp"
>
</File>
<File
RelativePath="EProfileIDs.h"
>
</File>
<File
RelativePath="leakHunter.cpp"
>

View File

@ -309,6 +309,9 @@
<File
RelativePath="..\..\include\IEventReceiver.h">
</File>
<File
RelativePath="..\..\include\CProfiler.h">
</File>
<File
RelativePath="..\..\include\IFileArchive.h">
</File>
@ -372,6 +375,9 @@
<File
RelativePath="..\..\include\IGUIMeshViewer.h">
</File>
<File
RelativePath="..\..\include\IGUIProfiler.h">
</File>
<File
RelativePath="..\..\include\IGUIScrollBar.h">
</File>
@ -1434,6 +1440,12 @@
<File
RelativePath=".\os.cpp">
</File>
<File
RelativePath=".\CProfiler.cpp">
</File>
<File
RelativePath=".\EProfileIDs.h">
</File>
<File
RelativePath=".\leakHunter.cpp">
</File>
@ -1837,6 +1849,12 @@
<File
RelativePath=".\CGUIModalScreen.h">
</File>
<File
RelativePath=".\CGUIProfiler.cpp">
</File>
<File
RelativePath=".\CGUIProfiler.h">
</File>
<File
RelativePath=".\CGUIScrollBar.cpp">
</File>

View File

@ -44,8 +44,8 @@ IRRIMAGEOBJ = CColorConverter.o CImage.o CImageLoaderBMP.o CImageLoaderDDS.o CIm
IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ)
IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRNormalMap.o CTRStencilShadow.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o CTRTextureGouraudVertexAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o CTRGouraud2.o CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o
IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CWADReader.o CZipReader.o CPakReader.o CNPKReader.o CTarReader.o CMountPointReader.o irrXML.o CAttributes.o lzma/LzmaDec.o
IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CIrrDeviceFB.o CLogger.o COSOperator.o Irrlicht.o os.o leakHunter.o
IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o
IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CIrrDeviceFB.o CLogger.o COSOperator.o Irrlicht.o os.o leakHunter.o CProfiler.o
IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o CGUIProfiler.o
ZLIBOBJ = zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o
JPEGLIBOBJ = jpeglib/jcapimin.o jpeglib/jcapistd.o jpeglib/jccoefct.o jpeglib/jccolor.o jpeglib/jcdctmgr.o jpeglib/jchuff.o jpeglib/jcinit.o jpeglib/jcmainct.o jpeglib/jcmarker.o jpeglib/jcmaster.o jpeglib/jcomapi.o jpeglib/jcparam.o jpeglib/jcprepct.o jpeglib/jcsample.o jpeglib/jctrans.o jpeglib/jdapimin.o jpeglib/jdapistd.o jpeglib/jdatadst.o jpeglib/jdatasrc.o jpeglib/jdcoefct.o jpeglib/jdcolor.o jpeglib/jddctmgr.o jpeglib/jdhuff.o jpeglib/jdinput.o jpeglib/jdmainct.o jpeglib/jdmarker.o jpeglib/jdmaster.o jpeglib/jdmerge.o jpeglib/jdpostct.o jpeglib/jdsample.o jpeglib/jdtrans.o jpeglib/jerror.o jpeglib/jfdctflt.o jpeglib/jfdctfst.o jpeglib/jfdctint.o jpeglib/jidctflt.o jpeglib/jidctfst.o jpeglib/jidctint.o jpeglib/jmemmgr.o jpeglib/jmemnobs.o jpeglib/jquant1.o jpeglib/jquant2.o jpeglib/jutils.o jpeglib/jcarith.o jpeglib/jdarith.o jpeglib/jaricom.o
LIBPNGOBJ = libpng/png.o libpng/pngerror.o libpng/pngget.o libpng/pngmem.o libpng/pngpread.o libpng/pngread.o libpng/pngrio.o libpng/pngrtran.o libpng/pngrutil.o libpng/pngset.o libpng/pngtrans.o libpng/pngwio.o libpng/pngwrite.o libpng/pngwtran.o libpng/pngwutil.o