in Shared/Graphics/Include/Graphics/StepTimer.h [104:176]
void Tick(const TUpdate& update)
{
// Query the current time.
uint64 currentTime = GetTicks();
uint64 timeDelta = currentTime - _qpcLastTime;
_qpcLastTime = currentTime;
_qpcSecondCounter += timeDelta;
// Clamp excessively large time deltas (e.g. after paused in the debugger).
if (timeDelta > _qpcMaxDelta)
{
timeDelta = _qpcMaxDelta;
}
// Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp.
timeDelta *= TicksPerSecond;
timeDelta /= _qpcFrequency;
uint32 lastFrameCount = _frameCount;
if (_isFixedTimeStep)
{
// Fixed timestep update logic
// If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp
// the clock to exactly match the target value. This prevents tiny and irrelevant errors
// from accumulating over time. Without this clamping, a game that requested a 60 fps
// fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually
// accumulate enough tiny errors that it would drop a frame. It is better to just round
// small deviations down to zero to leave things running smoothly.
if (abs(static_cast<int64>(timeDelta - _targetElapsedTicks)) < TicksPerSecond / 4000)
{
timeDelta = _targetElapsedTicks;
}
_leftOverTicks += timeDelta;
while (_leftOverTicks >= _targetElapsedTicks)
{
_elapsedTicks = _targetElapsedTicks;
_totalTicks += _targetElapsedTicks;
_leftOverTicks -= _targetElapsedTicks;
_frameCount++;
update();
}
}
else
{
// Variable timestep update logic.
_elapsedTicks = timeDelta;
_totalTicks += timeDelta;
_leftOverTicks = 0;
_frameCount++;
update();
}
// Track the current framerate.
if (_frameCount != lastFrameCount)
{
_framesThisSecond++;
}
if (_qpcSecondCounter >= static_cast<uint64>(_qpcFrequency))
{
_framesPerSecond = _framesThisSecond;
_framesThisSecond = 0;
_qpcSecondCounter %= _qpcFrequency;
}
}