Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.
 
 
 
 
 
 

561 lines
14 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// MEM_PROFILE.CPP
//
// Memory Profiling Display
//=====================================================================================//
#include "vxconsole.h"
#define PROFILE_MAXSAMPLES 512
#define PROFILE_MEMORYHEIGHT 100
#define PROFILE_NUMMINORTICKS 3
#define PROFILE_LABELWIDTH 50
#define PROFILE_SCALESTEPS 8
#define PROFILE_MINSCALE 0.2f
#define PROFILE_MAXSCALE 3.0f
#define PROFILE_NUMMINORTICKS 3
#define PROFILE_MAJORTICKMB 16
#define PROFILE_WARNINGMB 10
#define PROFILE_SEVEREMB 5
#define ID_MEMPROFILE 1
HWND g_memProfile_hWnd;
RECT g_memProfile_WindowRect;
int g_memProfile_tickMarks;
int g_memProfile_colors;
int g_memProfile_scale;
UINT_PTR g_memProfile_Timer;
int g_memProfile_numSamples;
int g_memProfile_samples[PROFILE_MAXSAMPLES];
//-----------------------------------------------------------------------------
// MemProfile_SaveConfig
//
//-----------------------------------------------------------------------------
void MemProfile_SaveConfig()
{
char buff[256];
WINDOWPLACEMENT wp;
// profile history
if ( g_memProfile_hWnd )
{
memset( &wp, 0, sizeof( wp ) );
wp.length = sizeof( WINDOWPLACEMENT );
GetWindowPlacement( g_memProfile_hWnd, &wp );
g_memProfile_WindowRect = wp.rcNormalPosition;
sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
Sys_SetRegistryString( "MemProfileWindowRect", buff );
}
Sys_SetRegistryInteger( "MemProfileScale", g_memProfile_scale );
Sys_SetRegistryInteger( "MemProfileTickMarks", g_memProfile_tickMarks );
Sys_SetRegistryInteger( "MemProfileColors", g_memProfile_colors );
}
//-----------------------------------------------------------------------------
// MemProfile_LoadConfig
//
//-----------------------------------------------------------------------------
void MemProfile_LoadConfig()
{
int numArgs;
char buff[256];
// profile history
Sys_GetRegistryString( "MemProfileWindowRect", buff, "", sizeof( buff ) );
numArgs = sscanf( buff, "%d %d %d %d", &g_memProfile_WindowRect.left, &g_memProfile_WindowRect.top, &g_memProfile_WindowRect.right, &g_memProfile_WindowRect.bottom );
if ( numArgs != 4 )
{
memset( &g_memProfile_WindowRect, 0, sizeof( g_memProfile_WindowRect ) );
}
Sys_GetRegistryInteger( "MemProfileScale", 0, g_memProfile_scale );
if ( g_memProfile_scale < -PROFILE_SCALESTEPS || g_memProfile_scale > PROFILE_SCALESTEPS )
{
g_memProfile_scale = 0;
}
Sys_GetRegistryInteger( "MemProfileTickMarks", 1, g_memProfile_tickMarks );
Sys_GetRegistryInteger( "MemProfileColors", 1, g_memProfile_colors );
}
//-----------------------------------------------------------------------------
// MemProfile_SetTitle
//
//-----------------------------------------------------------------------------
void MemProfile_SetTitle()
{
char titleBuff[128];
if ( g_memProfile_hWnd )
{
strcpy( titleBuff, "Free Memory Available" );
if ( g_memProfile_Timer )
{
strcat( titleBuff, " [ON]" );
}
SetWindowText( g_memProfile_hWnd, titleBuff );
}
}
//-----------------------------------------------------------------------------
// MemProfile_EnableProfiling
//
//-----------------------------------------------------------------------------
void MemProfile_EnableProfiling( bool bEnable )
{
if ( !g_memProfile_hWnd )
{
return;
}
UINT_PTR timer = TIMERID_MEMPROFILE;
if ( bEnable && !g_memProfile_Timer )
{
// run at 10Hz
g_memProfile_Timer = SetTimer( g_memProfile_hWnd, timer, 100, NULL );
}
else if ( !bEnable && g_memProfile_Timer )
{
KillTimer( g_memProfile_hWnd, timer );
g_memProfile_Timer = NULL;
}
}
//-----------------------------------------------------------------------------
// MemProfile_UpdateWindow
//
//-----------------------------------------------------------------------------
void MemProfile_UpdateWindow()
{
if ( g_memProfile_hWnd && !IsIconic( g_memProfile_hWnd ) )
{
// visible - force a client repaint
InvalidateRect( g_memProfile_hWnd, NULL, true );
}
}
//-----------------------------------------------------------------------------
// rc_FreeMemory
//
//-----------------------------------------------------------------------------
int rc_FreeMemory( char* commandPtr )
{
int errCode = -1;
int freeMemory;
char *cmdToken = GetToken( &commandPtr );
if ( !cmdToken[0] )
{
goto cleanUp;
}
sscanf( cmdToken, "%x", &freeMemory );
g_memProfile_samples[g_memProfile_numSamples % PROFILE_MAXSAMPLES] = freeMemory;
g_memProfile_numSamples++;
DebugCommand( "FreeMemory( 0x%8.8x )\n", freeMemory );
MemProfile_UpdateWindow();
// success
errCode = 0;
cleanUp:
return ( errCode );
}
//-----------------------------------------------------------------------------
// MemProfile_ZoomIn
//
//-----------------------------------------------------------------------------
void MemProfile_ZoomIn( int& scale, int numSteps )
{
scale++;
if ( scale > numSteps )
{
scale = numSteps;
return;
}
MemProfile_UpdateWindow();
}
//-----------------------------------------------------------------------------
// MemProfile_ZoomOut
//
//-----------------------------------------------------------------------------
void MemProfile_ZoomOut( int& scale, int numSteps )
{
scale--;
if ( scale < -numSteps )
{
scale = -numSteps;
return;
}
MemProfile_UpdateWindow();
}
//-----------------------------------------------------------------------------
// MemProfile_CalcScale
//
//-----------------------------------------------------------------------------
float MemProfile_CalcScale( int scale, int numSteps, float min, float max )
{
float t;
// from integral scale [-numSteps..numSteps] to float scale [min..max]
t = ( float )( scale + numSteps )/( float )( 2*numSteps );
t = min + t*( max-min );
return t;
}
//-----------------------------------------------------------------------------
// MemProfile_Draw
//
//-----------------------------------------------------------------------------
void MemProfile_Draw( HDC hdc, RECT* clientRect )
{
char labelBuff[128];
HPEN hBlackPen;
HPEN hPenOld;
HPEN hNullPen;
HPEN hGreyPen;
HBRUSH hColoredBrush;
HBRUSH hBrushOld;
HFONT hFontOld;
int currentSample;
int numTicks;
int memoryHeight;
int windowWidth;
int windowHeight;
int x;
int y;
int y0;
int i;
int j;
int h;
int numbars;
RECT rect;
float t;
float scale;
hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) );
hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) );
hNullPen = CreatePen( PS_NULL, 0, RGB( 0,0,0 ) );
hPenOld = ( HPEN )SelectObject( hdc, hBlackPen );
hFontOld = SelectFont( hdc, g_hProportionalFont );
// zoom
scale = MemProfile_CalcScale( g_memProfile_scale, PROFILE_SCALESTEPS, PROFILE_MINSCALE, PROFILE_MAXSCALE );
memoryHeight = ( int )( PROFILE_MEMORYHEIGHT*scale );
windowWidth = clientRect->right-clientRect->left;
windowHeight = clientRect->bottom-clientRect->top;
numTicks = windowHeight/memoryHeight + 2;
if ( numTicks < 0 )
{
numTicks = 1;
}
else if ( numTicks > 512/PROFILE_MAJORTICKMB + 1 )
{
numTicks = 512/PROFILE_MAJORTICKMB + 1;
}
SetBkColor( hdc, g_backgroundColor );
x = 0;
y = windowHeight;
for ( i=0; i<numTicks; i++ )
{
// major ticks
SelectObject( hdc, hBlackPen );
MoveToEx( hdc, 0, y, NULL );
LineTo( hdc, windowWidth, y );
if ( g_memProfile_tickMarks )
{
// could be very zoomed out, gap must be enough for label, otherwise don't draw
int gapY = memoryHeight/( PROFILE_NUMMINORTICKS+1 );
if ( gapY >= 10 )
{
// minor ticks
y0 = y;
SelectObject( hdc, hGreyPen );
for ( j=0; j<PROFILE_NUMMINORTICKS; j++ )
{
y0 += gapY;
MoveToEx( hdc, 0, y0, NULL );
LineTo( hdc, windowWidth, y0 );
}
}
}
// tick labels
if ( i )
{
rect.left = windowWidth - 50;
rect.right = windowWidth;
rect.top = y - 20;
rect.bottom = y;
sprintf( labelBuff, "%d MB", i*PROFILE_MAJORTICKMB );
DrawText( hdc, labelBuff, -1, &rect, DT_RIGHT|DT_SINGLELINE|DT_BOTTOM );
}
y -= memoryHeight;
}
// vertical bars
if ( g_memProfile_numSamples )
{
SelectObject( hdc, hNullPen );
numbars = windowWidth-PROFILE_LABELWIDTH;
currentSample = g_memProfile_numSamples-1;
for ( x=numbars-1; x>=0; x-=4 )
{
float sample = g_memProfile_samples[currentSample % PROFILE_MAXSAMPLES]/( 1024.0f * 1024.0f );
y = windowHeight;
t = sample/(float)PROFILE_MAJORTICKMB;
h = ( int )( t * ( float )memoryHeight );
if ( h )
{
if ( h > windowHeight )
h = windowHeight;
COLORREF barColor;
if ( sample >= PROFILE_WARNINGMB )
{
barColor = RGB( 100, 255, 100 );
}
else if ( sample >= PROFILE_SEVEREMB )
{
barColor = RGB( 255, 255, 100 );
}
else
{
barColor = RGB( 255, 0, 0 );
}
hColoredBrush = CreateSolidBrush( g_memProfile_colors ? barColor : RGB( 80, 80, 80 ) );
hBrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush );
Rectangle( hdc, x-4, y-h, x, y+1 );
y -= h;
SelectObject( hdc, hBrushOld );
DeleteObject( hColoredBrush );
}
currentSample--;
if ( currentSample < 0 )
{
// no data
break;
}
}
}
SelectObject( hdc, hFontOld );
SelectObject( hdc, hPenOld );
DeleteObject( hBlackPen );
DeleteObject( hGreyPen );
}
//-----------------------------------------------------------------------------
// MemProfile_TimerProc
//
//-----------------------------------------------------------------------------
void MemProfile_TimerProc( HWND hwnd, UINT_PTR idEvent )
{
static bool busy = false;
if ( busy )
{
return;
}
busy = true;
if ( g_connectedToApp )
{
// send as async
DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__memory__ quiet", false );
}
busy = false;
}
//-----------------------------------------------------------------------------
// MemProfile_WndProc
//
//-----------------------------------------------------------------------------
LRESULT CALLBACK MemProfile_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
WORD wID = LOWORD( wParam );
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
CREATESTRUCT *createStructPtr;
switch ( message )
{
case WM_CREATE:
// set the window identifier
createStructPtr = ( CREATESTRUCT* )lParam;
SetWindowLong( hwnd, GWL_USERDATA+0, ( LONG )createStructPtr->lpCreateParams );
// clear samples
g_memProfile_numSamples = 0;
memset( g_memProfile_samples, 0, sizeof( g_memProfile_samples ) );
return 0L;
case WM_DESTROY:
MemProfile_SaveConfig();
MemProfile_EnableProfiling( false );
g_memProfile_hWnd = NULL;
return 0L;
case WM_INITMENU:
CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_memProfile_tickMarks ? MF_CHECKED : MF_UNCHECKED ) );
CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_COLORS, MF_BYCOMMAND | ( g_memProfile_colors ? MF_CHECKED : MF_UNCHECKED ) );
CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_ENABLE, MF_BYCOMMAND | ( g_memProfile_Timer != NULL ? MF_CHECKED : MF_UNCHECKED ) );
return 0L;
case WM_PAINT:
GetClientRect( hwnd, &rect );
hdc = BeginPaint( hwnd, &ps );
MemProfile_Draw( hdc, &rect );
EndPaint( hwnd, &ps );
return 0L;
case WM_SIZE:
// force a redraw
MemProfile_UpdateWindow();
return 0L;
case WM_TIMER:
if ( wID == TIMERID_MEMPROFILE )
{
MemProfile_TimerProc( hwnd, TIMERID_MEMPROFILE );
return 0L;
}
break;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_INSERT:
MemProfile_ZoomIn( g_memProfile_scale, PROFILE_SCALESTEPS );
return 0L;
case VK_DELETE:
MemProfile_ZoomOut( g_memProfile_scale, PROFILE_SCALESTEPS );
return 0L;
}
break;
case WM_COMMAND:
switch ( wID )
{
case IDM_MEMPROFILE_TICKMARKS:
g_memProfile_tickMarks ^= 1;
MemProfile_UpdateWindow();
return 0L;
case IDM_MEMPROFILE_COLORS:
g_memProfile_colors ^= 1;
MemProfile_UpdateWindow();
return 0L;
case IDM_MEMPROFILE_ZOOMIN:
MemProfile_ZoomIn( g_memProfile_scale, PROFILE_SCALESTEPS );
return 0L;
case IDM_MEMPROFILE_ZOOMOUT:
MemProfile_ZoomOut( g_memProfile_scale, PROFILE_SCALESTEPS );
return 0L;
case IDM_MEMPROFILE_ENABLE:
bool bEnable = ( g_memProfile_Timer != NULL );
bEnable ^= 1;
MemProfile_EnableProfiling( bEnable );
MemProfile_SetTitle();
return 0L;
}
break;
}
return ( DefWindowProc( hwnd, message, wParam, lParam ) );
}
//-----------------------------------------------------------------------------
// MemProfile_Open
//
//-----------------------------------------------------------------------------
void MemProfile_Open()
{
HWND hWnd;
if ( g_memProfile_hWnd )
{
// only one profile instance
if ( IsIconic( g_memProfile_hWnd ) )
ShowWindow( g_memProfile_hWnd, SW_RESTORE );
SetForegroundWindow( g_memProfile_hWnd );
return;
}
hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"MEMPROFILECLASS",
"",
WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
0,
0,
600,
500,
g_hDlgMain,
NULL,
g_hInstance,
( void* )ID_MEMPROFILE );
g_memProfile_hWnd = hWnd;
MemProfile_EnableProfiling( true );
MemProfile_SetTitle();
if ( g_memProfile_WindowRect.right && g_memProfile_WindowRect.bottom )
MoveWindow( g_memProfile_hWnd, g_memProfile_WindowRect.left, g_memProfile_WindowRect.top, g_memProfile_WindowRect.right-g_memProfile_WindowRect.left, g_memProfile_WindowRect.bottom-g_memProfile_WindowRect.top, FALSE );
ShowWindow( g_memProfile_hWnd, SHOW_OPENWINDOW );
}
//-----------------------------------------------------------------------------
// MemProfile_Init
//
//-----------------------------------------------------------------------------
bool MemProfile_Init()
{
WNDCLASS wndclass;
// set up our window class
memset( &wndclass, 0, sizeof( wndclass ) );
wndclass.style = 0;
wndclass.lpfnWndProc = MemProfile_WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = g_hInstance;
wndclass.hIcon = g_hIcons[ICON_APPLICATION];
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndclass.hbrBackground = g_hBackgroundBrush;
wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_MEMPROFILE );
wndclass.lpszClassName = "MEMPROFILECLASS";
if ( !RegisterClass( &wndclass ) )
return false;
MemProfile_LoadConfig();
return true;
}