1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-18 11:19:10 +00:00

Always use hsTimer for profile stats.

This fixes the weird flickering and inaccurate numbers that were showing up on Windows.
This commit is contained in:
Darryl Pogue
2014-06-28 21:39:17 -07:00
parent a0da984cdc
commit f5b2bddbb2

View File

@ -42,134 +42,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plProfileManager.h"
#include "plProfile.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)
{
#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()
@ -251,7 +127,7 @@ void plProfileManager::EndFrame()
uint64_t plProfileManager::GetTime()
{
return GetProfileTicks();
return hsTimer::GetTicks();
}
///////////////////////////////////////////////////////////////////////////////
@ -301,7 +177,7 @@ void plProfileBase::UpdateAvg()
uint64_t plProfileBase::GetValue()
{
if (hsCheckBits(fDisplayFlags, kDisplayTime))
return (uint64_t)TicksToMSec(fValue);
return hsTimer::GetMilliSeconds<uint64_t>(fValue);
else
return fValue;
}
@ -346,11 +222,11 @@ void plProfileBase::IPrintValue(uint64_t value, char* buf, bool printType)
}
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))
{
sprintf(buf, "%.2f", TicksToMSec(value));
sprintf(buf, "%.2f", hsTimer::GetMilliSeconds<float>(value));
if (printType)
strcat(buf, " ms");
}
@ -524,12 +400,12 @@ void plProfileVar::IBeginTiming()
if( hsCheckBits( fDisplayFlags, kDisplayResetEveryBegin ) )
fValue = 0;
fValue -= GetProfileTicks();
fValue -= hsTimer::GetTicks();
}
void plProfileVar::IEndTiming()
{
fValue += GetProfileTicks();
fValue += hsTimer::GetTicks();
fTimerSamples++;