diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/vgui_vprofgraphpanel.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'engine/vgui_vprofgraphpanel.cpp')
| -rw-r--r-- | engine/vgui_vprofgraphpanel.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/engine/vgui_vprofgraphpanel.cpp b/engine/vgui_vprofgraphpanel.cpp new file mode 100644 index 0000000..81efcc1 --- /dev/null +++ b/engine/vgui_vprofgraphpanel.cpp @@ -0,0 +1,435 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#include "client_pch.h" + +#include "ivideomode.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include <vgui_controls/Panel.h> +#include <vgui_controls/Controls.h> +#include <vgui/ISurface.h> +#include <vgui/IScheme.h> +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/imesh.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/MaterialSystemUtil.h" +#include "client.h" +#include "gl_matsysiface.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifdef VPROF_ENABLED + +static ConVar vprof_graph ( "vprof_graph","0", 0, "Draw the vprof graph." ); +static ConVar vprof_graphwidth ( "vprof_graphwidth", "512", FCVAR_ARCHIVE ); +static ConVar vprof_graphheight( "vprof_graphheight", "256", FCVAR_ARCHIVE ); + +#define TIMINGS 256 // Number of values to track (must be power of 2) b/c of masking + +#define GRAPH_RED (0.9f * 255) +#define GRAPH_GREEN (0.9f * 255) +#define GRAPH_BLUE (0.7f * 255) + +#define LERP_HEIGHT 24 + + +//----------------------------------------------------------------------------- +// Purpose: Displays the netgraph +//----------------------------------------------------------------------------- +class CVProfGraphPanel : public vgui::Panel +{ + typedef vgui::Panel BaseClass; +private: + + vgui::HFont m_hFont; + +public: + CVProfGraphPanel( vgui::VPANEL parent ); + virtual ~CVProfGraphPanel( void ); + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void Paint(); + virtual void OnTick( void ); + + virtual bool ShouldDraw( void ); + + + struct CLineSegment + { + int x1, y1, x2, y2; + byte color[4]; + }; + + inline void DrawLine( vrect_t *rect, unsigned char *color, unsigned char alpha ); + + void DrawLineSegments(); + + void GraphGetXY( vrect_t *rect, int width, int *x, int *y ); + +private: + + void PaintLineArt( int x, int y, int w ); + + CMaterialReference m_WhiteMaterial; + + // VProf interface: + float m_Samples[ TIMINGS ][3]; + CVProfNode* m_Components; + + int m_CurrentSample; + + void GetNextSample(); + +public: + static CVProfNode* m_CurrentNode; +}; + +CVProfNode* CVProfGraphPanel::m_CurrentNode = NULL; + + +void IN_VProfPrevSibling(void) +{ + CVProfNode* n = CVProfGraphPanel::m_CurrentNode->GetPrevSibling(); + if( n ) + CVProfGraphPanel::m_CurrentNode = n; +} + +void IN_VProfNextSibling(void) +{ + CVProfNode* n = CVProfGraphPanel::m_CurrentNode->GetSibling(); + if( n ) + CVProfGraphPanel::m_CurrentNode = n; + +} + +void IN_VProfParent(void) +{ + CVProfNode* n = CVProfGraphPanel::m_CurrentNode->GetParent(); + if( n ) + CVProfGraphPanel::m_CurrentNode = n; + +} + +void IN_VProfChild(void) +{ + CVProfNode* n = CVProfGraphPanel::m_CurrentNode->GetChild(); + if( n ) + { + // Find the largest child: + CVProfGraphPanel::m_CurrentNode = n; + + for( ; n; n = n->GetSibling() ) + { + if( n->GetPrevTime() > CVProfGraphPanel::m_CurrentNode->GetPrevTime() ) + CVProfGraphPanel::m_CurrentNode = n; + } + } +} + +static ConCommand vprof_siblingprev ("vprof_prevsibling", IN_VProfPrevSibling); +static ConCommand vprof_siblingnext ("vprof_nextsibling", IN_VProfNextSibling); +static ConCommand vprof_parent ("vprof_parent", IN_VProfParent); +static ConCommand vprof_child ("vprof_child", IN_VProfChild); + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +//----------------------------------------------------------------------------- +CVProfGraphPanel::CVProfGraphPanel( vgui::VPANEL parent ) : BaseClass( NULL, "CVProfGraphPanel" ) +{ + SetParent( parent ); + SetSize( videomode->GetModeStereoWidth(), videomode->GetModeStereoHeight() ); + SetPos( 0, 0 ); + SetVisible( false ); + SetCursor( null ); + + m_hFont = 0; + + SetFgColor( Color( 0, 0, 0, 255 ) ); + SetPaintBackgroundEnabled( false ); + + memset( m_Samples, 0, sizeof( m_Samples ) ); + m_CurrentSample = 0; + m_CurrentNode = g_VProfCurrentProfile.GetRoot(); + + // Move down to an interesting node ( the render / sound / etc level) + if( m_CurrentNode->GetChild() ) + { + m_CurrentNode = m_CurrentNode->GetChild(); + + if( m_CurrentNode->GetChild() ) + { + m_CurrentNode = m_CurrentNode->GetChild(); + } + } + + vgui::ivgui()->AddTickSignal( GetVPanel() ); + + m_WhiteMaterial.Init( "vgui/white", TEXTURE_GROUP_OTHER ); + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CVProfGraphPanel::~CVProfGraphPanel( void ) +{ +} + +void CVProfGraphPanel::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + m_hFont = pScheme->GetFont( "DefaultVerySmall" ); + Assert( m_hFont ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Figure out x and y position for graph based on vprof_graphpos +// value. +// Input : *rect - +// width - +// *x - +// *y - +//----------------------------------------------------------------------------- +void CVProfGraphPanel::GraphGetXY( vrect_t *rect, int width, int *x, int *y ) +{ + *x = rect->x + rect->width - 5 - width; + *y = rect->y+rect->height - LERP_HEIGHT - 5; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CVProfGraphPanel::OnTick( void ) +{ + SetVisible( ShouldDraw() ); + +} + +bool CVProfGraphPanel::ShouldDraw( void ) +{ + return vprof_graph.GetBool(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CVProfGraphPanel::Paint() +{ + int x, y, w; + vrect_t vrect; + + if ( ( ShouldDraw() ) == false ) + return; + + // Get screen rectangle + vrect.x = 0; + vrect.y = 0; + vrect.width = videomode->GetModeStereoWidth(); + vrect.height = videomode->GetModeStereoHeight(); + + // Determine graph width + w = vprof_graphwidth.GetInt(); + if ( vrect.width < w + 10 ) + { + w = vrect.width - 10; + } + + // Get the graph's location: + GraphGetXY( &vrect, w, &x, &y ); + + PaintLineArt( x, y, w ); + + // Draw the text overlays: + + // Print it out + y -= vprof_graphheight.GetInt(); + + double RootTime = g_VProfCurrentProfile.GetRoot()->GetPrevTime(); + + char sz[256]; + if ( ( g_ClientGlobalVariables.absoluteframetime) > 0.f ) + { + Q_snprintf( sz, sizeof( sz ), "%s - %0.1f%%%%", m_CurrentNode->GetName(), ( m_CurrentNode->GetPrevTime() / RootTime ) * 100.f); + g_pMatSystemSurface->DrawColoredText( m_hFont, x, y, GRAPH_RED, GRAPH_GREEN, GRAPH_BLUE, 255, "%s", sz ); + } + + byte color[3][3] = + { + { 255, 0, 0 }, + { 0, 0, 255 }, + { 255, 255, 255 }, + }; + + const char *pTitles[3]; + pTitles[0] = m_CurrentNode->GetName(); + pTitles[1] = "Parent"; + pTitles[2] = "Total"; + + // Draw the legend: + x += w / 2; + for( int i = 3; --i >= 0; ) + { + Q_snprintf( sz, sizeof( sz ), "%07.3f ms (%s)", m_Samples[m_CurrentSample][i], pTitles[i] ); + y -= 10; + g_pMatSystemSurface->DrawColoredText( m_hFont, x, y, color[i][0], color[i][1], color[i][2], 180, "%s", sz ); + } +} + + +// VProf interface: +void CVProfGraphPanel::GetNextSample() +{ + // Increment to the next sample: + m_CurrentSample = ( m_CurrentSample + 1 ) % TIMINGS; + m_Samples[m_CurrentSample][0] = m_CurrentNode->GetPrevTime(); + m_Samples[m_CurrentSample][1] = m_CurrentNode->GetParent() ? m_CurrentNode->GetParent()->GetPrevTime() : m_CurrentNode->GetPrevTime(); + m_Samples[m_CurrentSample][2] = g_VProfCurrentProfile.GetRoot()->GetPrevTime(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CVProfGraphPanel::PaintLineArt( int x, int y, int w ) +{ + int nPanelHeight = vprof_graphheight.GetFloat() - LERP_HEIGHT - 2; + int h, a; + + // Update the sample graph: + GetNextSample(); + + CMatRenderContextPtr pRenderContext( materials ); + + IMesh* m_pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_WhiteMaterial ); + CMeshBuilder meshBuilder; + meshBuilder.Begin( m_pMesh, MATERIAL_LINES, 3 * w + 4 ); + + // Draw lines at 20, 30, 60 hz, and baseline + int i; + for ( i = 0; i < 4; ++i ) + { + int nLineY = y - (nPanelHeight / 3) * i; + + if ( i == 0 ) + { + meshBuilder.Color4ub( 255, 255, 255, 255 ); + } + else + { + meshBuilder.Color4ub( 128, 128, 128, 255 ); + } + + meshBuilder.TexCoord2f( 0, 0.0f, 0.0f ); + meshBuilder.Position3f( x, nLineY, 0 ); + meshBuilder.AdvanceVertex(); + + if ( i == 0 ) + { + meshBuilder.Color4ub( 255, 255, 255, 255 ); + } + else + { + meshBuilder.Color4ub( 128, 128, 128, 255 ); + } + + meshBuilder.TexCoord2f( 0, 0.0f, 0.0f ); + meshBuilder.Position3f( x + w, nLineY, 0 ); + meshBuilder.AdvanceVertex(); + } + + byte color[3][4] = + { + { 255, 0, 0, 255 }, + { 0, 0, 255, 255 }, + { 255, 255, 255, 255 }, + }; + + // 0.05f = 1/20 = 20Hz + float flMsToPixel = nPanelHeight / 50.0f; + float flDxDSample = (w <= TIMINGS) ? 1.0f : (float)w / (float)TIMINGS; + + for( i = 3; --i >= 0; ) + { + int sample = m_CurrentSample; + for (a=w; a >= 0; a-- ) + { + h = (int)(m_Samples[sample][i] * flMsToPixel + 0.5f); + + // Clamp the height: (though it shouldn't need it) + if ( h > nPanelHeight ) + { + h = nPanelHeight; + } + + int px = (int)(x + (w - a - 1) * flDxDSample + 0.5f); + int py = y - h; + + meshBuilder.Color4ubv( color[i] ); + meshBuilder.TexCoord2f( 0, 0.0f, 0.0f ); + meshBuilder.Position3f( px, py, 0 ); + meshBuilder.AdvanceVertex(); + + if ( ( a != w ) && ( a != 0 ) ) + { + meshBuilder.Color4ubv( color[i] ); + meshBuilder.TexCoord2f( 0, 0.0f, 0.0f ); + meshBuilder.Position3f( px, py, 0 ); + meshBuilder.AdvanceVertex(); + } + + // Move on to the next sample: + sample--; + if ( sample < 0 ) + { + sample = TIMINGS - 1; + } + } + } + + meshBuilder.End(); + m_pMesh->Draw(); +} + + +#endif // VPROF_ENABLED + + +//----------------------------------------------------------------------------- +// Creates/destroys the vprof graph panel +//----------------------------------------------------------------------------- + +#ifdef VPROF_ENABLED +static CVProfGraphPanel *s_pVProfGraphPanel = NULL; +#endif + +void CreateVProfGraphPanel( vgui::Panel *pParent ) +{ +#ifdef VPROF_ENABLED + s_pVProfGraphPanel = new CVProfGraphPanel( pParent->GetVPanel() ); +#endif +} + +void DestroyVProfGraphPanel() +{ +#ifdef VPROF_ENABLED + if ( s_pVProfGraphPanel ) + { + s_pVProfGraphPanel->SetParent( (vgui::Panel *)NULL ); + delete s_pVProfGraphPanel; + s_pVProfGraphPanel = NULL; + } +#endif +} + + + |