diff options
Diffstat (limited to 'externals/g3dlite/G3D.lib/source/Stopwatch.cpp')
-rw-r--r-- | externals/g3dlite/G3D.lib/source/Stopwatch.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/externals/g3dlite/G3D.lib/source/Stopwatch.cpp b/externals/g3dlite/G3D.lib/source/Stopwatch.cpp new file mode 100644 index 00000000000..e55f689a9e2 --- /dev/null +++ b/externals/g3dlite/G3D.lib/source/Stopwatch.cpp @@ -0,0 +1,96 @@ +/** + @file Stopwatch.cpp + + @maintainer Morgan McGuire, matrix@graphics3d.com + + @created 2005-10-05 + @edited 2005-10-05 + + Copyright 2000-2003, Morgan McGuire. + All rights reserved. + */ + +#include "G3D/Stopwatch.h" +#include "G3D/System.h" + +namespace G3D { + +Stopwatch::Stopwatch() : inBetween(false), lastTockTime(-1), + lastDuration(0), lastCycleCount(0), m_fps(0), emwaFPS(0), + m_smoothFPS(0), emwaDuration(0) { + computeOverhead(); +} + + +void Stopwatch::computeOverhead() { + cycleOverhead = 0; + tick(); + tock(); + cycleOverhead = elapsedCycles(); +} + + +void Stopwatch::tick() { + // This is 'alwaysAssert' instead of 'debugAssert' + // since people rarely profile in debug mode. + alwaysAssertM(! inBetween, "Stopwatch::tick() called twice in a row."); + inBetween = true; + + // We read RDTSC twice here, but it is more abstract to implement this + // way and at least we're reading the cycle count last. + timeStart = System::time(); + System::beginCycleCount(cycleStart); +} + + +void Stopwatch::tock() { + System::endCycleCount(cycleStart); + RealTime now = System::time(); + lastDuration = now - timeStart; + if (abs(emwaDuration - lastDuration) > max(emwaDuration, lastDuration) * 0.50) { + // Off by more than 50% + emwaDuration = lastDuration; + } else { + emwaDuration = lastDuration * 0.05 + emwaDuration * 0.95; + } + + lastCycleCount = cycleStart - cycleOverhead; + if (lastCycleCount < 0) { + lastCycleCount = 0; + } + + if (lastTockTime != -1.0) { + m_fps = 1.0 / (now - lastTockTime); + + // Time smooth the average + emwaFPS = m_fps * 0.01 + emwaFPS * 0.99; + + if (abs(emwaFPS - m_fps) > max(emwaFPS, m_fps) * 0.08) { + // The difference between emwa and m_fps is way off + // update emwa directly. + emwaFPS = m_fps; + } + + // Update m_smoothFPS only when the value varies significantly + // We round so as to not mislead the user as to the accuracy of + // the number. + if (m_smoothFPS == 0) { + m_smoothFPS = m_fps; + } else if (emwaFPS <= 10) { + if (::fabs(m_smoothFPS - emwaFPS) > .75) { + m_smoothFPS = floor(emwaFPS * 10.0 + 0.5) / 10.0; + } + } else { + if (::fabs(m_smoothFPS - emwaFPS) > 1.25) { + m_smoothFPS = floor(emwaFPS + 0.5); + } + } + } + lastTockTime = now; + + alwaysAssertM(inBetween, "Stopwatch::tock() called without matching tick."); + inBetween = false; +} + +} + |