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:
@ -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++;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user