You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
5.0 KiB
158 lines
5.0 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "perfwizard.h"
|
|
#include "tier0/platform.h"
|
|
#include "con_nprint.h"
|
|
#include "server.h"
|
|
#include "client.h"
|
|
#include "filesystem.h"
|
|
#include "filesystem_engine.h"
|
|
#include "KeyValues.h"
|
|
#include "vstdlib/ICommandLine.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
ClientFPSTracker g_ClientFPSTracker;
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
ClientFPSTracker::ClientFPSTracker()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
void ClientFPSTracker::Reset( void )
|
|
{
|
|
m_validTime = 0.0f; // not valid yet
|
|
|
|
m_minNonServerFPS = -1.0f;
|
|
m_maxNonServerFPS = -1.0f;
|
|
|
|
m_nonServerFPSAverage = -1.0f;
|
|
|
|
m_minAvgNonServerFPS = -1.0f;
|
|
m_maxAvgNonServerFPS = -1.0f;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
bool ClientFPSTracker::IsValid( void ) const
|
|
{
|
|
return m_maxAvgNonServerFPS > 0.0f;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
void ClientFPSTracker::NPrint( int line ) const
|
|
{
|
|
#ifndef DEDICATED
|
|
Con_NPrintf ( line++, "Min non-server FPS: %.0f", m_minNonServerFPS );
|
|
Con_NPrintf ( line++, "Max non-server FPS: %.0f", m_maxNonServerFPS );
|
|
|
|
line++;
|
|
Con_NPrintf ( line++, "Avg non-server FPS: %.0f", m_nonServerFPSAverage );
|
|
Con_NPrintf ( line++, "Min avg non-server FPS: %.0f", m_minAvgNonServerFPS );
|
|
Con_NPrintf ( line++, "Max avg non-server FPS: %.0f", m_maxAvgNonServerFPS );
|
|
#endif // !DEDICATED
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
void ClientFPSTracker::WriteData( void ) const
|
|
{
|
|
if ( IsValid() && !CommandLine()->FindParm( "-makereslists" ) )
|
|
{
|
|
KeyValues *data = new KeyValues( "perfdata" );
|
|
data->SetFloat( "minClientFPS", m_minNonServerFPS );
|
|
data->SetFloat( "maxClientFPS", m_maxNonServerFPS );
|
|
data->SetFloat( "minAveragedClientFPS", m_minAvgNonServerFPS );
|
|
data->SetFloat( "maxAveragedClientFPS", m_maxAvgNonServerFPS );
|
|
data->SaveToFile( g_pFileSystem, "cfg/perfdata.vdf", "MOD" );
|
|
data->deleteThis();
|
|
}
|
|
else
|
|
{
|
|
//g_pFileSystem->RemoveFile( "cfg/perfdata.vdf", "MOD" );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
void ClientFPSTracker::MarkFrame( float fps, float input, float client, float server, float render, float sound, float cl_dll, float exec )
|
|
{
|
|
if ( sv.IsDedicated() ) // client-side only, so skip if we're a dedicated server
|
|
return;
|
|
|
|
if ( !cl.IsActive() ) // we only care about the time that a client is in the game
|
|
{
|
|
m_validTime = 0.0f;
|
|
return;
|
|
}
|
|
|
|
if ( m_validTime == 0.0f )
|
|
{
|
|
m_validTime = Plat_FloatTime() + 10.0f; // allow some settling down
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if ( m_validTime > Plat_FloatTime() )
|
|
{
|
|
return; // don't track fps in the settling-down phase after loading
|
|
}
|
|
}
|
|
|
|
// Construct a client FPS by using every time component but the server. This helps on listenservers,
|
|
// since the performance wizard won't be able to do anything about server perf anyway.
|
|
double nonServerFrameTime = (input + client + render + sound + cl_dll + exec) / 1000.0f;
|
|
double nonServerFps;
|
|
|
|
if ( nonServerFrameTime < 0.0001 )
|
|
{
|
|
nonServerFps = 999.0;
|
|
}
|
|
else
|
|
{
|
|
nonServerFps = 1.0 / nonServerFrameTime;
|
|
}
|
|
|
|
// Track min/max instantaneous FPS
|
|
if ( m_minNonServerFPS < 0.0f )
|
|
{
|
|
m_minNonServerFPS = m_maxNonServerFPS = nonServerFps;
|
|
}
|
|
else
|
|
{
|
|
if ( nonServerFps < m_minNonServerFPS ) m_minNonServerFPS = nonServerFps;
|
|
if ( nonServerFps > m_maxNonServerFPS ) m_maxNonServerFPS = nonServerFps;
|
|
}
|
|
|
|
// Construct an average FPS (this isn't really an average, since it weights the current frame AverageFraction, the previous frame by AverageFraction*AverageFraction, etc)
|
|
const float AverageFraction = 0.99f;
|
|
if ( m_nonServerFPSAverage < 0.0f )
|
|
{
|
|
m_nonServerFPSAverage = nonServerFps;
|
|
}
|
|
|
|
m_nonServerFPSAverage = m_nonServerFPSAverage * AverageFraction + ( 1.0f - AverageFraction ) * nonServerFps;
|
|
|
|
// Track min/max averaged FPS. These are the useful values for making performance recommendations.
|
|
if ( m_minAvgNonServerFPS < 0.0f )
|
|
{
|
|
m_minAvgNonServerFPS = m_maxAvgNonServerFPS = m_nonServerFPSAverage;
|
|
}
|
|
else
|
|
{
|
|
if ( m_nonServerFPSAverage < m_minAvgNonServerFPS ) m_minAvgNonServerFPS = m_nonServerFPSAverage;
|
|
if ( m_nonServerFPSAverage > m_maxAvgNonServerFPS ) m_maxAvgNonServerFPS = m_nonServerFPSAverage;
|
|
}
|
|
|
|
// Debug printing for test purposes.
|
|
//NPrint( 10 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|