391
struct AutoProfile
{
AutoProfile(const char* name)
{
m_name = name;
m_startTime = QueryPerformanceCounter();
}
~AutoProfile()
{
__int64 endTime = QueryPerformanceCounter();
__int64 elapsedTime = endTime – m_startTime;
g_profileManager.storeSample(m_name, elapsedTime);
}
const char* m_name;
__int64 m_startTime;
};
#define PROFILE(name) AutoProfile p(name)
The problem with this simplistic approach is that it breaks down when
used within deeper levels of function call nesting. For example, if we embed
additional PROFILE() annotations within the RenderScene() function, we
need to understand the function call hierarchy in order to properly interpret
those measurements.
One solution to this problem is to allow the programmer who is an-
notating the code to indicate the hierarchical interrelationships between
profi ling samples. For example, any PROFILE(...) samples taken with-
in the RenderScene() function could be declared to be children of the
PROFILE("Rendering") sample. These relationships are usually set up sepa-
rately from the annotations themselves, by predeclaring all of the sample bins.
For example, we might set up the in-game profi ler during engine initialization
as follows:
// This code declares various profile sample "bins",
// listing the name of the bin and the name of its
// parent bin, if any.
ProfilerDeclareSampleBin("Rendering", NULL);
ProfilerDeclareSampleBin("Visibility", "Rendering");
ProfilerDeclareSampleBin("ShaderSetUp", "Rendering");
ProfilerDeclareSampleBin("Materials", "Shaders");
ProfilerDeclareSampleBin("SubmitGeo", "Rendering");
ProfilerDeclareSampleBin("Audio", NULL);
...
9.8. In-Game Profi ling