//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "vgui_BudgetFPSPanel.H" #include "vgui_BudgetPanel.h" #include #include "tier0/vprof.h" #include "materialsystem/imaterialsystem.h" static ConVar budget_peaks_window( "budget_peaks_window", "30", FCVAR_ARCHIVE, "number of frames to look at when figuring out peak frametimes" ); static ConVar budget_averages_window( "budget_averages_window", "30", FCVAR_ARCHIVE, "number of frames to look at when figuring out average frametimes" ); static ConVar budget_show_peaks( "budget_show_peaks", "1", FCVAR_ARCHIVE, "enable/disable peaks in the budget panel" ); static ConVar budget_show_averages( "budget_show_averages", "0", FCVAR_ARCHIVE, "enable/disable averages in the budget panel" ); CBudgetFPSPanel::CBudgetFPSPanel( vgui::Panel *pParent, const char *pPanelName ) : BaseClass( pParent, pPanelName ) { SetProportional( false ); SetKeyBoardInputEnabled( false ); SetMouseInputEnabled( false ); SetSizeable( false ); SetVisible( true ); SetPaintBackgroundEnabled( false ); // hide the system buttons SetTitleBarVisible( false ); } CBudgetFPSPanel::~CBudgetFPSPanel() { } #define PIXELS_BETWEEN_BARS 4 void CBudgetFPSPanel::DrawBarAtIndex( int id, float percent ) { int panelWidth, panelHeight; GetSize( panelWidth, panelHeight ); int nGroups = g_VProfCurrentProfile.GetNumBudgetGroups(); int top = 2 + ( id * panelHeight ) / nGroups; int bottom = ( ( ( id + 1 ) * panelHeight ) / nGroups ) - PIXELS_BETWEEN_BARS; int left = 0; int right = panelWidth * percent; int red, green, blue, alpha; g_VProfCurrentProfile.GetBudgetGroupColor( id, red, green, blue, alpha ); // DrawFilledRect is panel relative vgui::surface()->DrawSetColor( 0, 0, 0, alpha ); vgui::surface()->DrawFilledRect( left, top-2, right+2, bottom+2 ); vgui::surface()->DrawSetColor( 255, 255, 255, alpha ); vgui::surface()->DrawFilledRect( left, top-1, right+1, bottom+1 ); vgui::surface()->DrawSetColor( red, green, blue, alpha ); vgui::surface()->DrawFilledRect( left, top, right, bottom ); } void CBudgetFPSPanel::DrawTickAtIndex( int id, float percent, int red, int green, int blue, int alpha ) { if( percent > 1.0f ) { percent = 1.0f; } int panelWidth, panelHeight; GetSize( panelWidth, panelHeight ); int nGroups = g_VProfCurrentProfile.GetNumBudgetGroups(); int top = 2 + ( id * panelHeight ) / nGroups; int bottom = ( ( ( id + 1 ) * panelHeight ) / nGroups ) - PIXELS_BETWEEN_BARS; int right = ( int )( panelWidth * percent + 1.0f ); int left = right - 2; // DrawFilledRect is panel relative vgui::surface()->DrawSetColor( 0, 0, 0, alpha ); vgui::surface()->DrawFilledRect( left-2, top-2, right+2, bottom+2 ); vgui::surface()->DrawSetColor( 255, 255, 255, alpha ); vgui::surface()->DrawFilledRect( left-1, top-1, right+1, bottom+1 ); vgui::surface()->DrawSetColor( red, green, blue, alpha ); vgui::surface()->DrawFilledRect( left, top, right, bottom ); } void CBudgetFPSPanel::DrawTimeLines( void ) { int panelWidth, panelHeight; GetSize( panelWidth, panelHeight ); int i; int left, right, top, bottom; top = 0; bottom = panelHeight; for( i = ( int )m_fRangeMin; i < ( int )( m_fRangeMax + 0.5f ); i++ ) { int alpha; if( i % 10 == 0 ) { alpha = 150; } else if( i % 5 == 0 ) { alpha = 100; } else { alpha = 50; } left = -0.5f + panelWidth * ( ( float )i - m_fRangeMin ) / ( m_fRangeMax - m_fRangeMin ); right = left + 1; vgui::surface()->DrawSetColor( 0, 0, 0, alpha ); vgui::surface()->DrawFilledRect( left-1, top, right+1, bottom ); vgui::surface()->DrawSetColor( 255, 255, 255, alpha ); vgui::surface()->DrawFilledRect( left, top+1, right, bottom-1 ); } } void CBudgetFPSPanel::DrawInstantaneous() { int nGroups, nSamplesPerGroup, nSampleOffset; const double *pBudgetGroupTimes = GetBudgetPanel()->GetBudgetGroupData( nGroups, nSamplesPerGroup, nSampleOffset ); if( !pBudgetGroupTimes ) { return; } int i; for( i = 0; i < nGroups; i++ ) { DrawBarAtIndex( i, ( pBudgetGroupTimes[nSamplesPerGroup * i + nSampleOffset] - m_fRangeMin ) / ( m_fRangeMax - m_fRangeMin ) ); } } void CBudgetFPSPanel::DrawPeaks() { int nGroups, nSamplesPerGroup, nSampleOffset; const double *pBudgetGroupTimes = GetBudgetPanel()->GetBudgetGroupData( nGroups, nSamplesPerGroup, nSampleOffset ); if( !pBudgetGroupTimes ) { return; } int numSamples = budget_peaks_window.GetInt(); int i; for( i = 0; i < nGroups; i++ ) { double max = 0; int j; for( j = 0; j < numSamples; j++ ) { double tmp; int offset = ( nSampleOffset - j + VPROF_HISTORY_COUNT ) % VPROF_HISTORY_COUNT; tmp = pBudgetGroupTimes[i * nSamplesPerGroup + offset]; if( tmp > max ) { max = tmp; } } float percent = ( max - m_fRangeMin ) / ( m_fRangeMax - m_fRangeMin ); DrawTickAtIndex( i, percent, 255, 0, 0, 255 ); } } void CBudgetFPSPanel::DrawAverages() { int nGroups, nSamplesPerGroup, nSampleOffset; const double *pBudgetGroupTimes = GetBudgetPanel()->GetBudgetGroupData( nGroups, nSamplesPerGroup, nSampleOffset ); if( !pBudgetGroupTimes ) { return; } int numSamples = budget_averages_window.GetInt(); int i; for( i = 0; i < nGroups; i++ ) { int red, green, blue, alpha; g_VProfCurrentProfile.GetBudgetGroupColor( i, red, green, blue, alpha ); double sum = 0; int j; for( j = 0; j < numSamples; j++ ) { int offset = ( nSampleOffset - j + VPROF_HISTORY_COUNT ) % VPROF_HISTORY_COUNT; sum += pBudgetGroupTimes[i * nSamplesPerGroup + offset]; } sum *= ( 1.0f / numSamples ); float percent = ( sum - m_fRangeMin ) / ( m_fRangeMax - m_fRangeMin ); DrawTickAtIndex( i, percent, red, green, blue, alpha ); } } void CBudgetFPSPanel::Paint( void ) { materials->Flush(); g_VProfCurrentProfile.Pause(); int width, height; GetSize( width, height ); DrawTimeLines(); DrawInstantaneous(); if( budget_show_peaks.GetBool() ) { DrawPeaks(); } if( budget_show_averages.GetBool() ) { DrawAverages(); } materials->Flush(); g_VProfCurrentProfile.Resume(); } void CBudgetFPSPanel::SetRange( float fMin, float fMax ) { m_fRangeMin = fMin; m_fRangeMax = fMax; }