But I noticed that it can be improved.
Code: Select all
#define OGRE_FRAME_STATS_SAMPLES 60
int mNextFrame;
unsigned long mBestFrameTime;
unsigned long mWorstFrameTime;
uint64 mLastTime;
unsigned long mFrameTimes[OGRE_FRAME_STATS_SAMPLES];
size_t mFramesSampled;
float getAvgTime(void) const
{
if( !mFramesSampled )
return 0.0f;
unsigned long avg = 0;
for( size_t i=0; i<mFramesSampled; ++i )
{
//idx is first in the range [(mNextFrame - mFramesSampled); mNextFrame),
//but then warped around mNextFrame
size_t idx = (i + mNextFrame + (mFramesSampled * 2 - 1)) % mFramesSampled;
avg += mFrameTimes[idx];
}
return avg / (float)mFramesSampled * 0.001f;
}
/// Adds a new measured time, in *microseconds*
void addSample( uint64 timeMs )
{
unsigned long frameTimeMs = static_cast<unsigned long>(timeMs - mLastTime);
mFrameTimes[mNextFrame] = frameTimeMs;
mBestFrameTime = std::min( frameTimeMs, mBestFrameTime );
mWorstFrameTime = std::max( frameTimeMs, mWorstFrameTime );
mFramesSampled = std::min<size_t>( (mFramesSampled + 1), OGRE_FRAME_STATS_SAMPLES );
mNextFrame = (mNextFrame + 1) % OGRE_FRAME_STATS_SAMPLES;
mLastTime = timeMs;
}
getAvgTime will add all the time in the buffer. addSample is use "%" for index round.
Here is my frame stats.
Code: Select all
enum
{
// [0x00, 0xFF] 0x40 = 64 .
// Very close to the commonly used 60 frame rate.
mmFrameStatsCacheSize = 0x40,
mmFrameStatsCacheMask = mmFrameStatsCacheSize - 1,
mmFrameStatsCacheTime = mmFrameStatsCacheSize * MM_USEC_PER_SEC,
};
// Frame rate statistics based on circular queues
struct mmFrameStats
{
// time clock.
struct mmClock clock;
// frame number, reset api can assign 0.
mmUInt64_t number;
// average fps.
double average;
// current frame interval.
double interval;
// cache index.
mmUInt8_t index;
// frame interval total.
double total;
// frame interval cache.
double cache[mmFrameStatsCacheSize];
};
MM_EXPORT_DLL void mmFrameStats_UpdateInterval(struct mmFrameStats* p, double interval)
{
// cache the last frame interval.
p->interval = interval;
// accumulate the frame number.
p->number++;
// sub the index cache interval.
p->total -= p->cache[p->index];
// insert to back current interval.
p->cache[p->index] = interval;
// add the current interval.
p->total += interval;
// index++
p->index++;
// index %= CacheSize
p->index &= mmFrameStatsCacheMask;
// fps value update.
// if interval_total == 0.0 the fps_avge will be +inf, but it's correct.
p->average = ((double)mmFrameStatsCacheTime) / p->total;
}
2. cache the average frequency.
3. cache the total time, and -= last index cache interval += current interval. Can quickly average.