Browse Source

Always use hsTimer for profile stats.

This fixes the weird flickering and inaccurate numbers that were showing up on Windows.
Darryl Pogue 11 years ago
parent
commit
f5b2bddbb2
  1. 136
      Sources/Plasma/NucleusLib/inc/plProfileManager.cpp

136
Sources/Plasma/NucleusLib/inc/plProfileManager.cpp

@ -42,134 +42,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plProfileManager.h" #include "plProfileManager.h"
#include "plProfile.h" #include "plProfile.h"
#include "hsTimer.h" #include "hsTimer.h"
#include "hsWindows.h"
static uint32_t gCyclesPerMS = 0;
#ifdef HS_BUILD_FOR_WIN32
#define USE_FAST_TIMER
#endif
#ifdef USE_FAST_TIMER
#pragma warning (push)
#pragma warning (disable : 4035) // disable no return value warning
#ifdef _MSC_VER
#define forceinline __forceinline
#else
#define forceinline inline
#endif
forceinline uint32_t GetPentiumCounter()
{
#ifdef _MSC_VER
__asm {
xor eax,eax // VC won't realize that eax is modified w/out this
// instruction to modify the val.
// Problem shows up in release mode builds
_emit 0x0F // Pentium high-freq counter to edx;eax
_emit 0x31 // only care about low 32 bits in eax
xor edx,edx // so VC gets that edx is modified
}
#endif
}
#pragma warning (pop)
static uint32_t GetProcSpeed()
{
const char* keypath[] =
{
"HARDWARE",
"DESCRIPTION",
"System",
"CentralProcessor",
"0"
};
HKEY hKey = HKEY_LOCAL_MACHINE;
int numKeys = sizeof(keypath) / sizeof(char*);
for (int i = 0; i < numKeys; i++)
{
HKEY thisKey = NULL;
bool success = (RegOpenKeyEx(hKey, keypath[i], 0, KEY_READ, &thisKey) == ERROR_SUCCESS);
RegCloseKey(hKey);
hKey = thisKey;
if (!success)
return 0;
}
DWORD value=0, size=sizeof(DWORD);
bool success = (RegQueryValueEx(hKey, "~MHz", 0, NULL, (BYTE*)&value, &size) == ERROR_SUCCESS);
RegCloseKey(hKey);
return value*1000000;
}
uint32_t GetProcSpeedAlt()
{
const uint32_t kSamplePeriodMS = 250;
// Raise priority to avoid interference from other threads.
int priority = GetThreadPriority(GetCurrentThread());
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
uint32_t startTicks, endTicks;
uint64_t pcStart, pcEnd;
// Count number of processor cycles inside the specified interval
QueryPerformanceCounter((LARGE_INTEGER*)&pcStart);
startTicks = plProfileManager::GetTime();
Sleep(kSamplePeriodMS);
endTicks = plProfileManager::GetTime();
QueryPerformanceCounter((LARGE_INTEGER*)&pcEnd);
// Restore thread priority.
SetThreadPriority(GetCurrentThread(), priority);
// Calculate Rdtsc/PerformanceCounter ratio;
uint32_t numTicks = endTicks - startTicks;
uint64_t pcDiff = pcEnd - pcStart;
double ratio = double(numTicks) / double(pcDiff);
uint64_t pcFreq;
QueryPerformanceFrequency((LARGE_INTEGER*)&pcFreq);
// Calculate CPU frequency.
uint64_t cpuFreq = uint64_t(pcFreq * ratio);
return (uint32_t)cpuFreq;
}
#define GetProfileTicks() GetPentiumCounter()
#define TicksToMSec(t) (float(t) / float(gCyclesPerMS))
#else
#define GetProfileTicks() hsTimer::GetTicks()
#define TicksToMSec(t) hsTimer::GetMilliSeconds<float>(t)
#endif // USE_FAST_TIMER
plProfileManager::plProfileManager() : fLastAvgTime(0), fProcessorSpeed(0) plProfileManager::plProfileManager() : fLastAvgTime(0), fProcessorSpeed(0)
{ {
#ifdef USE_FAST_TIMER
fProcessorSpeed = GetProcSpeed();
// Registry stuff only works on NT OS's, have to calc it otherwise
if (fProcessorSpeed == 0)
fProcessorSpeed = GetProcSpeedAlt();
gCyclesPerMS = fProcessorSpeed / 1000;
#endif
} }
plProfileManager::~plProfileManager() plProfileManager::~plProfileManager()
@ -251,7 +127,7 @@ void plProfileManager::EndFrame()
uint64_t plProfileManager::GetTime() uint64_t plProfileManager::GetTime()
{ {
return GetProfileTicks(); return hsTimer::GetTicks();
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -301,7 +177,7 @@ void plProfileBase::UpdateAvg()
uint64_t plProfileBase::GetValue() uint64_t plProfileBase::GetValue()
{ {
if (hsCheckBits(fDisplayFlags, kDisplayTime)) if (hsCheckBits(fDisplayFlags, kDisplayTime))
return (uint64_t)TicksToMSec(fValue); return hsTimer::GetMilliSeconds<uint64_t>(fValue);
else else
return fValue; return fValue;
} }
@ -346,11 +222,11 @@ void plProfileBase::IPrintValue(uint64_t value, char* buf, bool printType)
} }
else if (hsCheckBits(fDisplayFlags, kDisplayFPS)) else if (hsCheckBits(fDisplayFlags, kDisplayFPS))
{ {
sprintf(buf, "%.2f", 1000.0f / TicksToMSec(value)); sprintf(buf, "%.2f", 1000.0f / hsTimer::GetMilliSeconds<float>(value));
} }
else if (hsCheckBits(fDisplayFlags, kDisplayTime)) else if (hsCheckBits(fDisplayFlags, kDisplayTime))
{ {
sprintf(buf, "%.2f", TicksToMSec(value)); sprintf(buf, "%.2f", hsTimer::GetMilliSeconds<float>(value));
if (printType) if (printType)
strcat(buf, " ms"); strcat(buf, " ms");
} }
@ -524,12 +400,12 @@ void plProfileVar::IBeginTiming()
if( hsCheckBits( fDisplayFlags, kDisplayResetEveryBegin ) ) if( hsCheckBits( fDisplayFlags, kDisplayResetEveryBegin ) )
fValue = 0; fValue = 0;
fValue -= GetProfileTicks(); fValue -= hsTimer::GetTicks();
} }
void plProfileVar::IEndTiming() void plProfileVar::IEndTiming()
{ {
fValue += GetProfileTicks(); fValue += hsTimer::GetTicks();
fTimerSamples++; fTimerSamples++;

Loading…
Cancel
Save