2023-09-11 22:20:24 +02:00
|
|
|
//===========================================================================//
|
|
|
|
//
|
2024-02-24 02:15:09 +01:00
|
|
|
// Purpose: High-precision frame rate limiter
|
2023-09-11 22:20:24 +02:00
|
|
|
//
|
|
|
|
//===========================================================================//
|
|
|
|
#include <dwmapi.h>
|
|
|
|
#include "tier0/platform_internal.h"
|
|
|
|
#include "windows/id3dx.h"
|
|
|
|
#include "sys_mainwind.h"
|
|
|
|
#include "framelimit.h"
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: constructor
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CFrameLimit::CFrameLimit(void)
|
|
|
|
{
|
|
|
|
m_MilliSeconds = 0.0;
|
|
|
|
m_FramesPerSecond = 0.0;
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
m_Start.QuadPart = 0;
|
2023-09-11 22:20:24 +02:00
|
|
|
m_Next.QuadPart = 0;
|
|
|
|
m_Time.QuadPart = 0;
|
|
|
|
|
|
|
|
m_Frames = 0;
|
|
|
|
m_bRestart = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: initializer
|
|
|
|
// Input : targetFps -
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void CFrameLimit::Reset(double targetFps)
|
|
|
|
{
|
|
|
|
m_MilliSeconds = 1000.0 / targetFps;
|
|
|
|
m_FramesPerSecond = targetFps;
|
|
|
|
|
|
|
|
QueryPerformanceCounter(&m_Start);
|
|
|
|
m_Next.QuadPart = 0ULL;
|
|
|
|
m_Time.QuadPart = 0ULL;
|
|
|
|
|
|
|
|
//m_Last.QuadPart = m_Start.QuadPart - (LONGLONG)((m_MilliSeconds / 1000.0) * g_pPerformanceFrequency->QuadPart);
|
|
|
|
m_Next.QuadPart = m_Start.QuadPart + (LONGLONG)((m_MilliSeconds / 1000.0) * g_pPerformanceFrequency->QuadPart);
|
|
|
|
|
|
|
|
m_Frames = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: runs the frame limiter logic
|
|
|
|
//-----------------------------------------------------------------------------
|
2024-02-24 02:15:09 +01:00
|
|
|
void CFrameLimit::Run(const double targetFps, const double sleepThreshold, const double maxTolerance)
|
2023-09-11 22:20:24 +02:00
|
|
|
{
|
|
|
|
if (m_FramesPerSecond != targetFps)
|
|
|
|
Reset(targetFps);
|
|
|
|
|
|
|
|
m_Frames++;
|
|
|
|
QueryPerformanceCounter(&m_Time);
|
|
|
|
|
|
|
|
// Actual frametime before we forced a delay
|
|
|
|
//m_EffectiveMilliSeconds = 1000.0 * ((double)(m_Time.QuadPart - m_Last.QuadPart) / (double)g_pPerformanceFrequency->QuadPart);
|
|
|
|
|
2024-02-24 02:15:09 +01:00
|
|
|
if ((double)(m_Time.QuadPart - m_Next.QuadPart) / (double)g_pPerformanceFrequency->QuadPart / (m_MilliSeconds / 1000.0) > (maxTolerance * m_FramesPerSecond))
|
2023-09-11 22:20:24 +02:00
|
|
|
{
|
|
|
|
DevMsg(eDLL_T::ENGINE, "%s: Frame time too long (expected: %3.01fx); restarting...\n",
|
2023-09-16 13:10:12 +02:00
|
|
|
__FUNCTION__, (double)(m_Time.QuadPart - m_Next.QuadPart) / (double)g_pPerformanceFrequency->QuadPart / (m_MilliSeconds / 1000.0) / m_FramesPerSecond );
|
2023-09-11 22:20:24 +02:00
|
|
|
m_bRestart = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_bRestart)
|
|
|
|
{
|
|
|
|
m_Frames = 0;
|
|
|
|
m_Start.QuadPart = m_Time.QuadPart + (LONGLONG)((m_MilliSeconds / 1000.0) * (double)g_pPerformanceFrequency->QuadPart);
|
|
|
|
m_bRestart = false;
|
|
|
|
//Reset (targetFps);
|
|
|
|
//return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Next.QuadPart = (LONGLONG)((m_Start.QuadPart + (double)m_Frames * (m_MilliSeconds / 1000.0) * (double)g_pPerformanceFrequency->QuadPart));
|
|
|
|
|
|
|
|
if (m_Next.QuadPart > 0ULL)
|
|
|
|
{
|
|
|
|
while (m_Time.QuadPart < m_Next.QuadPart)
|
|
|
|
{
|
2024-02-24 02:15:09 +01:00
|
|
|
if ((double)(m_Next.QuadPart - m_Time.QuadPart) > (sleepThreshold * (double)g_pPerformanceFrequency->QuadPart))
|
2023-09-11 22:20:24 +02:00
|
|
|
{
|
2023-09-13 17:37:09 +02:00
|
|
|
Sleep(10);
|
2023-09-11 22:20:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QueryPerformanceCounter(&m_Time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//m_Last.QuadPart = m_Time.QuadPart;
|
|
|
|
}
|