summaryrefslogtreecommitdiff
path: root/unittests/ihvtest1/ihvtest1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ihvtest1/ihvtest1.cpp')
-rw-r--r--unittests/ihvtest1/ihvtest1.cpp1508
1 files changed, 1508 insertions, 0 deletions
diff --git a/unittests/ihvtest1/ihvtest1.cpp b/unittests/ihvtest1/ihvtest1.cpp
new file mode 100644
index 0000000..b1253dc
--- /dev/null
+++ b/unittests/ihvtest1/ihvtest1.cpp
@@ -0,0 +1,1508 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// $Header: $
+// $NoKeywords: $
+//
+//=============================================================================
+
+#define PROTECTED_THINGS_DISABLE
+#if !defined( _X360 )
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+#include <time.h>
+#include "materialsystem/imaterialsystem.h"
+#include "materialsystem/IMaterialSystemHardwareConfig.h"
+#include "materialsystem/imaterialproxyfactory.h"
+#include "materialsystem/MaterialSystem_Config.h"
+#include "appframework/appframework.h"
+#include "datacache\idatacache.h"
+#include "datacache\imdlcache.h"
+#include "vphysics_interface.h"
+#include "filesystem.h"
+#include "IStudioRender.h"
+#include "studio.h"
+#include "clientstats.h"
+#include "bone_setup.h"
+#include "tier0/icommandline.h"
+#include "vstdlib/cvar.h"
+#include "tier0/vprof.h"
+#include "tier1/tier1.h"
+#include "optimize.h"
+#if defined( _X360 )
+#include "xbox\xbox_console.h"
+#include "xbox\xbox_win32stubs.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Main system interfaces
+//-----------------------------------------------------------------------------
+IMaterialSystem *g_pMaterialSystem = NULL;
+IStudioRender *g_pStudioRender = NULL;
+IFileSystem *g_pFileSystem = NULL;
+IMDLCache *g_pMDLCache = NULL;
+
+
+//-----------------------------------------------------------------------------
+// App control defines
+//-----------------------------------------------------------------------------
+//#define MATERIAL_OVERRIDE
+//#define USE_VTUNE
+//#define USE_VPROF
+
+#if USE_VTUNE
+#include "vtuneapi.h"
+#endif
+
+static bool g_WindowMode = false;
+static bool g_bUseEmptyShader = false;
+static bool g_BenchFinished = false;
+static bool g_BenchMode = false;
+static bool g_SoftwareTL = false;
+
+static int g_RenderWidth = 640;
+static int g_RenderHeight = 480;
+static int g_RefreshRate = 60;
+static int g_LOD = 0;
+static int g_BodyGroup = 0;
+
+static int g_NumRows = 10;
+static int g_NumCols = 10;
+
+static int g_dxLevel = 0;
+static int g_LightingCombination = -1;
+
+static FILE *g_IHVTestFP = NULL;
+static IMaterial *g_pForceMaterial = NULL;
+
+static bool g_bInError = false;
+
+#define MAX_LIGHTS 2
+#define NUM_LIGHT_TYPES 4
+#define LIGHTING_COMBINATION_COUNT 5
+
+static const char *g_LightCombinationNames[] =
+{
+ "DISABLE ",
+// "SPOT ",
+ "POINT ",
+ "DIRECTIONAL ",
+ "SPOT_SPOT ",
+// "SPOT_POINT ",
+// "SPOT_DIRECTIONAL ",
+// "POINT_POINT ",
+ "POINT_DIRECTIONAL ",
+ "DIRECTIONAL_DIRECTIONAL"
+};
+
+//-----------------------------------------------------------------------------
+// Test Model class
+//-----------------------------------------------------------------------------
+struct IHVTestModel
+{
+ MDLHandle_t hMdl;
+ studiohdr_t *pStudioHdr;
+ studiohwdata_t *pHardwareData;
+};
+
+//-----------------------------------------------------------------------------
+// The application object
+//-----------------------------------------------------------------------------
+class CIHVTestApp : public CDefaultAppSystemGroup< CSteamAppSystemGroup >
+{
+public:
+ // Methods of IApplication
+ virtual bool Create();
+ virtual bool PreInit();
+ virtual int Main();
+ virtual void PostShutdown();
+ virtual void Destroy();
+
+private:
+ bool CreateAppWindow( char const *pTitle, int w, int h );
+ void AppPumpMessages( void );
+ void RenderFrame( void );
+ void RenderScene( void );
+ bool SetupMaterialSystem();
+ bool SetupStudioRender();
+ bool LoadModels( void );
+ bool LoadModel( const char *pModelName, IHVTestModel *pModel );
+ bool CreateMainWindow( int width, int height, bool fullscreen );
+ matrix3x4_t* SetUpBones( studiohdr_t *pStudioHdr, const matrix3x4_t &shapeToWorld, int iRun, int model, int boneMask );
+
+ // Windproc
+ static LONG WINAPI WinAppWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ LONG WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ HWND m_hWnd;
+ bool m_bExitMainLoop;
+
+ IHVTestModel *m_pIHVTestModel;
+};
+
+static CIHVTestApp s_IHVTestApp;
+DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT_GLOBALVAR( CIHVTestApp, s_IHVTestApp );
+
+//-----------------------------------------------------------------------------
+// Create the application window
+//-----------------------------------------------------------------------------
+bool CIHVTestApp::CreateAppWindow( const char* pAppName, int width, int height )
+{
+ // Register the window class
+ WNDCLASSEX wc;
+ memset( &wc, 0, sizeof( wc ) );
+ wc.cbSize = sizeof( wc );
+ wc.style = CS_CLASSDC;
+ wc.lpfnWndProc = WinAppWindowProc;
+ wc.hInstance = (HINSTANCE)GetAppInstance();
+ wc.lpszClassName = pAppName;
+ wc.hIcon = NULL;
+ wc.hIconSm = wc.hIcon;
+
+ RegisterClassEx( &wc );
+
+ // Create the application's window
+ m_hWnd = CreateWindow( pAppName, pAppName,
+ WS_OVERLAPPEDWINDOW,
+ 0, 0, width, height,
+ GetDesktopWindow(), NULL, wc.hInstance, NULL );
+
+ ShowWindow (m_hWnd, SW_SHOWDEFAULT);
+
+ return (m_hWnd != 0);
+}
+
+//#define TREES
+
+// The maximum number of distinctive models each test may specify.
+#ifdef TREES
+const int g_nMaxModels = 1;
+#else
+const int g_nMaxModels = 9;
+#endif
+
+//-----------------------------------------------------------------------------
+// Benchmarking
+//-----------------------------------------------------------------------------
+struct BenchRunInfo
+{
+ const char *pModelName[g_nMaxModels];
+ int numFrames;
+ int rows;
+ int cols;
+ float modelSize;
+ int sequence1[g_nMaxModels];
+ int sequence2;
+};
+
+struct BenchResults
+{
+ BenchResults() : totalTime( 0.0f ), totalTris( 0 ) {}
+ float totalTime;
+ int totalTris;
+};
+
+
+#define NUM_BENCH_RUNS 1
+static BenchResults g_BenchResults[NUM_BENCH_RUNS][LIGHTING_COMBINATION_COUNT];
+
+#ifdef TREES
+
+#define MODEL_ROWS 13
+#define MODEL_COLUMNS 13
+static BenchRunInfo g_BenchRuns[NUM_BENCH_RUNS] =
+{
+ { { "models/props_foliage/tree_dead01.mdl"
+ }, 100, MODEL_ROWS, MODEL_COLUMNS, 1000.0f, { 0 }, -1 },
+};
+
+#else
+
+#define MODEL_ROWS 3
+#define MODEL_COLUMNS 3
+static BenchRunInfo g_BenchRuns[NUM_BENCH_RUNS] =
+{
+ { { "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ "models/alyx.mdl",
+ }, 100, MODEL_ROWS, MODEL_COLUMNS, 75.0f, { 1, 4, 20, 23, 25, 30, 34, 38, 1 }, -1 },
+};
+
+#endif
+
+// this is used in "-bench" mode
+static IHVTestModel g_BenchModels[NUM_BENCH_RUNS][g_nMaxModels];
+
+static void WriteBenchResults( void )
+{
+ if( !g_BenchMode )
+ {
+ return;
+ }
+
+ FILE *fp = fopen( "ihvtest1.csv", "a+" );
+ Assert( fp );
+ if( !fp )
+ {
+ return;
+ }
+
+ fprintf( fp, "------------------------------------------------------------------\n" );
+
+ time_t ltime;
+ time( &ltime );
+
+ fprintf( fp, "%s\n", GetCommandLine() );
+ fprintf( fp, "Run at: %s", ctime( &ltime ) );
+
+ int i;
+ for( i = 0; i < NUM_BENCH_RUNS; i++ )
+ {
+ int j;
+ fprintf( fp, "model,light combo,total tris,total time,tris/sec\n" );
+ for( j = 0; j < LIGHTING_COMBINATION_COUNT; j++ )
+ {
+ int k;
+ for( k = 0; k < g_nMaxModels; k++ )
+ {
+ if( g_BenchRuns[i].pModelName[k] )
+ {
+ fprintf( fp, "%s%s", k ? ", " : "", g_BenchRuns[i].pModelName[k] );
+ }
+ }
+ fprintf( fp, "," );
+ fprintf( fp, "%s,", g_LightCombinationNames[j] );
+ fprintf( fp, "%d,", g_BenchResults[i][j].totalTris );
+ fprintf( fp, "%0.5f,", ( float )g_BenchResults[i][j].totalTime );
+ fprintf( fp, "%0.0lf\n", ( double )g_BenchResults[i][j].totalTris /
+ ( double )g_BenchResults[i][j].totalTime );
+ Warning( "%f %d\n", ( float )g_BenchResults[i][j].totalTime, g_BenchResults[i][j].totalTris );
+ }
+ }
+
+ fclose( fp );
+}
+
+
+//-----------------------------------------------------------------------------
+// Destroy app
+//-----------------------------------------------------------------------------
+void CIHVTestApp::Destroy()
+{
+ // Close the window
+ if (m_hWnd)
+ DestroyWindow( m_hWnd );
+
+ WriteBenchResults();
+}
+
+
+//-----------------------------------------------------------------------------
+// Window size helper
+//-----------------------------------------------------------------------------
+static void CalcWindowSize( int desiredRenderingWidth, int desiredRenderingHeight,
+ int *windowWidth, int *windowHeight )
+{
+ int borderX, borderY;
+ borderX = (GetSystemMetrics(SM_CXFIXEDFRAME) + 1) * 2;
+ borderY = (GetSystemMetrics(SM_CYFIXEDFRAME) + 1) * 2 + GetSystemMetrics(SM_CYSIZE) + 1;
+ *windowWidth = desiredRenderingWidth + borderX;
+ *windowHeight = desiredRenderingHeight + borderY;
+}
+
+
+//-----------------------------------------------------------------------------
+// Spew function!
+//-----------------------------------------------------------------------------
+SpewRetval_t IHVTestSpewFunc( SpewType_t spewType, char const *pMsg )
+{
+ g_bInError = true;
+
+ OutputDebugString( pMsg );
+ switch( spewType )
+ {
+ case SPEW_MESSAGE:
+ case SPEW_WARNING:
+ case SPEW_LOG:
+ OutputDebugString( pMsg );
+ g_bInError = false;
+ return SPEW_CONTINUE;
+
+ case SPEW_ASSERT:
+ case SPEW_ERROR:
+ default:
+ ::MessageBox( NULL, pMsg, "Error!", MB_OK );
+ g_bInError = false;
+ return SPEW_DEBUGGER;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Spew function to write to ihvtest_vprof.txt
+//-----------------------------------------------------------------------------
+SpewRetval_t IHVTestVProfSpewFunc( SpewType_t spewType, char const *pMsg )
+{
+ g_bInError = true;
+
+ switch( spewType )
+ {
+ case SPEW_MESSAGE:
+ case SPEW_WARNING:
+ case SPEW_LOG:
+ fprintf( g_IHVTestFP, "%s", pMsg );
+ g_bInError = false;
+ return SPEW_CONTINUE;
+
+ case SPEW_ASSERT:
+ case SPEW_ERROR:
+ default:
+ ::MessageBox( NULL, pMsg, "Error!", MB_OK );
+ g_bInError = false;
+ return SPEW_DEBUGGER;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Warnings and Errors...
+//-----------------------------------------------------------------------------
+#define MAXPRINTMSG 4096
+void DisplayError( const char* pError, ... )
+{
+ va_list argptr;
+ char msg[1024];
+
+ g_bInError = true;
+
+ va_start( argptr, pError );
+ Q_vsnprintf( msg, sizeof( msg ), pError, argptr );
+ va_end( argptr );
+
+ MessageBox( 0, msg, 0, MB_OK );
+
+ exit( -1 );
+}
+
+static void MaterialSystem_Warning( const char *fmt, ... )
+{
+ va_list argptr;
+ char msg[MAXPRINTMSG];
+
+ va_start( argptr, fmt );
+ Q_vsnprintf( msg, sizeof ( msg ), fmt, argptr );
+ va_end( argptr );
+
+ OutputDebugString( msg );
+}
+
+// garymcthack
+static void MaterialSystem_Warning( char *fmt, ... )
+{
+ va_list argptr;
+ char msg[MAXPRINTMSG];
+
+ va_start( argptr, fmt );
+ Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
+ va_end( argptr );
+
+ OutputDebugString( msg );
+}
+
+static void MaterialSystem_Error( char *fmt, ... )
+{
+ va_list argptr;
+ char msg[MAXPRINTMSG];
+
+ g_bInError = true;
+
+ va_start( argptr, fmt );
+ Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
+ va_end( argptr );
+
+ MessageBox( NULL, (LPCTSTR)msg, "MaterialSystem Fatal Error", MB_OK | MB_ICONINFORMATION );
+
+#ifdef _DEBUG
+ Assert( 0 );
+#endif
+ exit( -1 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Engine Stats
+//-----------------------------------------------------------------------------
+// itty bitty interface for stat time
+class CStatTime : public IClientStatsTime
+{
+public:
+ float GetTime()
+ {
+ return Sys_FloatTime();
+ }
+};
+CStatTime g_StatTime;
+
+class CEngineStats
+{
+public:
+ CEngineStats() : m_InFrame( false ) {};
+ //
+ // stats input
+ //
+
+ void BeginRun( void );
+ void BeginFrame( void );
+
+ void EndFrame( void );
+ void EndRun( void );
+
+ //
+ // stats output
+ // call these outside of a BeginFrame/EndFrame pair
+ //
+
+ // return the frame time in seconds for the whole system (not just graphics)
+ double GetCurrentSystemFrameTime( void );
+ double GetRunTime( void );
+private:
+ // How many frames worth of data have we logged?
+ int m_totalNumFrames;
+
+ // frame timing data
+ double m_frameStartTime;
+ double m_frameEndTime;
+ double m_minFrameTime;
+ double m_maxFrameTime;
+
+ // run timing data
+ double m_runStartTime;
+ double m_runEndTime;
+
+ bool m_InFrame;
+};
+
+void CEngineStats::BeginRun( void )
+{
+ m_totalNumFrames = 0;
+ // frame timing data
+ m_runStartTime = Sys_FloatTime();
+}
+
+void CEngineStats::EndRun( void )
+{
+ m_runEndTime = Sys_FloatTime();
+}
+
+void CEngineStats::BeginFrame( void )
+{
+ m_InFrame = true;
+ m_frameStartTime = Sys_FloatTime();
+}
+
+void CEngineStats::EndFrame( void )
+{
+ double deltaTime;
+
+ m_frameEndTime = Sys_FloatTime();
+ deltaTime = GetCurrentSystemFrameTime();
+
+ m_InFrame = false;
+}
+
+double CEngineStats::GetRunTime( void )
+{
+ return m_runEndTime - m_runStartTime;
+}
+
+double CEngineStats::GetCurrentSystemFrameTime( void )
+{
+ return m_frameEndTime - m_frameStartTime;
+}
+static CEngineStats g_EngineStats;
+
+
+//-----------------------------------------------------------------------------
+// Lighting
+//-----------------------------------------------------------------------------
+// If you change the number of lighting combinations, change LIGHTING_COMBINATION_COUNT
+static LightType_t g_LightCombinations[][MAX_LIGHTS] =
+{
+ { MATERIAL_LIGHT_DISABLE, MATERIAL_LIGHT_DISABLE }, // 0
+// { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_DISABLE },
+// { MATERIAL_LIGHT_POINT, MATERIAL_LIGHT_DISABLE },
+ { MATERIAL_LIGHT_DIRECTIONAL, MATERIAL_LIGHT_DISABLE },
+ { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_SPOT },
+
+// { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_POINT }, // 5
+// { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_DIRECTIONAL },
+// { MATERIAL_LIGHT_POINT, MATERIAL_LIGHT_POINT },
+ { MATERIAL_LIGHT_POINT, MATERIAL_LIGHT_DIRECTIONAL },
+ { MATERIAL_LIGHT_DIRECTIONAL, MATERIAL_LIGHT_DIRECTIONAL }, // 9
+};
+
+LightDesc_t g_TestLights[NUM_LIGHT_TYPES][MAX_LIGHTS];
+
+static void FixLight( LightDesc_t *pLight )
+{
+ pLight->m_Range = 0.0f;
+ pLight->m_Falloff = 1.0f;
+ pLight->m_ThetaDot = cos( pLight->m_Theta * 0.5f );
+ pLight->m_PhiDot = cos( pLight->m_Phi * 0.5f );
+ pLight->m_Flags = 0;
+ if( pLight->m_Attenuation0 != 0.0f )
+ {
+ pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0;
+ }
+ if( pLight->m_Attenuation1 != 0.0f )
+ {
+ pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1;
+ }
+ if( pLight->m_Attenuation2 != 0.0f )
+ {
+ pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2;
+ }
+ VectorNormalize( pLight->m_Direction );
+}
+
+
+static void InitTestLights( void )
+{
+ LightDesc_t *pLight;
+ int i;
+ for( i = 0; i < MAX_LIGHTS; i++ )
+ {
+ // MATERIAL_LIGHT_DISABLE
+ pLight = &g_TestLights[MATERIAL_LIGHT_DISABLE][i];
+ pLight->m_Type = MATERIAL_LIGHT_DISABLE;
+ }
+
+ // x - right
+ // y - up
+ // z - front of model
+ // MATERIAL_LIGHT_SPOT 0
+ pLight = &g_TestLights[MATERIAL_LIGHT_SPOT][0];
+ memset( pLight, 0, sizeof( LightDesc_t ) );
+ pLight->m_Type = MATERIAL_LIGHT_SPOT;
+ pLight->m_Color.Init( 5000.0f, 3500.0f, 3500.0f );
+ pLight->m_Position.Init( 0.0f, 0.0f, 50.0f );
+ pLight->m_Direction.Init( 0.0f, 0.5f, -1.0f );
+ pLight->m_Attenuation0 = 0.0f;
+ pLight->m_Attenuation1 = 0.0f;
+ pLight->m_Attenuation2 = 1.0f / 10;
+ pLight->m_Theta = DEG2RAD( 20.0f );
+ pLight->m_Phi = DEG2RAD( 30.0f );
+
+ // MATERIAL_LIGHT_SPOT 1
+ pLight = &g_TestLights[MATERIAL_LIGHT_SPOT][1];
+ memset( pLight, 0, sizeof( LightDesc_t ) );
+ pLight->m_Type = MATERIAL_LIGHT_SPOT;
+ pLight->m_Color.Init( 3500.0f, 5000.0f, 3500.0f );
+ pLight->m_Position.Init( 0.0f, 0.0f, 150.0f );
+ pLight->m_Direction.Init( 0.0f, 0.5f, -1.0f );
+ pLight->m_Attenuation0 = 0.0f;
+ pLight->m_Attenuation1 = 0.0f;
+ pLight->m_Attenuation2 = 1.0f / 10;
+ pLight->m_Theta = DEG2RAD( 20.0f );
+ pLight->m_Phi = DEG2RAD( 30.0f );
+
+ // MATERIAL_LIGHT_POINT 0
+ pLight = &g_TestLights[MATERIAL_LIGHT_POINT][0];
+ memset( pLight, 0, sizeof( LightDesc_t ) );
+ pLight->m_Type = MATERIAL_LIGHT_POINT;
+ pLight->m_Color.Init( 1500.0f, 750.0f, 750.0f );
+ pLight->m_Position.Init( 200.0f, 200.0f, 200.0f );
+ pLight->m_Attenuation0 = 0.0f;
+ pLight->m_Attenuation1 = 1.0f;
+ pLight->m_Attenuation2 = 0.0f;
+
+ // MATERIAL_LIGHT_POINT 1
+ pLight = &g_TestLights[MATERIAL_LIGHT_POINT][1];
+ memset( pLight, 0, sizeof( LightDesc_t ) );
+ pLight->m_Type = MATERIAL_LIGHT_POINT;
+ pLight->m_Color.Init( 750.0f, 750.0f, 1500.0f );
+ pLight->m_Position.Init( -200.0f, 200.0f, 200.0f );
+ pLight->m_Attenuation0 = 0.0f;
+ pLight->m_Attenuation1 = 1.0f;
+ pLight->m_Attenuation2 = 0.0f;
+
+ // MATERIAL_LIGHT_DIRECTIONAL 0
+ pLight = &g_TestLights[MATERIAL_LIGHT_DIRECTIONAL][0];
+ memset( pLight, 0, sizeof( LightDesc_t ) );
+ pLight->m_Type = MATERIAL_LIGHT_DIRECTIONAL;
+ pLight->m_Color.Init( 2.0f, 2.0f, 1.0f );
+ pLight->m_Direction.Init( -1.0f, 0.0f, 0.0f );
+ pLight->m_Attenuation0 = 1.0f;
+ pLight->m_Attenuation1 = 0.0f;
+ pLight->m_Attenuation2 = 0.0f;
+
+ // MATERIAL_LIGHT_DIRECTIONAL 1
+ pLight = &g_TestLights[MATERIAL_LIGHT_DIRECTIONAL][1];
+ memset( pLight, 0, sizeof( LightDesc_t ) );
+ pLight->m_Type = MATERIAL_LIGHT_DIRECTIONAL;
+ pLight->m_Color.Init( 1.0f, 1.0f, 2.0f );
+ pLight->m_Direction.Init( 1.0f, 0.0f, 0.0f );
+ pLight->m_Attenuation0 = 1.0f;
+ pLight->m_Attenuation1 = 0.0f;
+ pLight->m_Attenuation2 = 0.0f;
+
+ for( i = 0; i < MAX_LIGHTS; i++ )
+ {
+ int j;
+ for( j = 0; j < NUM_LIGHT_TYPES; j++ )
+ {
+ FixLight( &g_TestLights[j][i] );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Setup lighting
+//-----------------------------------------------------------------------------
+static void SetupLighting( int lightingCombination, Vector &lightOffset )
+{
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ if( lightingCombination == 0 )
+ {
+ g_pStudioRender->SetLocalLights( 0, NULL );
+ pRenderContext->SetAmbientLight( 1.0, 1.0, 1.0 );
+
+ static Vector white[6] =
+ {
+ Vector( 1.0, 1.0, 1.0 ),
+ Vector( 1.0, 1.0, 1.0 ),
+ Vector( 1.0, 1.0, 1.0 ),
+ Vector( 1.0, 1.0, 1.0 ),
+ Vector( 1.0, 1.0, 1.0 ),
+ Vector( 1.0, 1.0, 1.0 ),
+ };
+ g_pStudioRender->SetAmbientLightColors( white );
+ }
+ else
+ {
+ pRenderContext->SetAmbientLight( 0.0f, 0.0f, 0.0f );
+
+ static Vector black[6] =
+ {
+ Vector( 0.0, 0.0, 0.0 ),
+ Vector( 0.0, 0.0, 0.0 ),
+ Vector( 0.0, 0.0, 0.0 ),
+ Vector( 0.0, 0.0, 0.0 ),
+ Vector( 0.0, 0.0, 0.0 ),
+ Vector( 0.0, 0.0, 0.0 ),
+ };
+ g_pStudioRender->SetAmbientLightColors( black );
+
+ int lightID;
+ LightDesc_t lightDescs[MAX_LIGHTS];
+ for( lightID = 0; lightID < MAX_LIGHTS; lightID++ )
+ {
+ int lightType = g_LightCombinations[lightingCombination][lightID];
+ lightDescs[lightID] = g_TestLights[lightType][lightID];
+ lightDescs[lightID].m_Position += lightOffset;
+ }
+
+ // Feed disabled lights through?
+ if( g_LightCombinations[lightingCombination][1] == MATERIAL_LIGHT_DISABLE )
+ {
+ g_pStudioRender->SetLocalLights( 1, lightDescs );
+ }
+ else
+ {
+ g_pStudioRender->SetLocalLights( MAX_LIGHTS, lightDescs );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Models
+//-----------------------------------------------------------------------------
+static float s_PoseParameter[32];
+static float s_Cycle[9] = { 0.0f };
+
+virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const
+{
+ if ( numincludemodels == 0 )
+ return NULL;
+ return g_pMDLCache->GetVirtualModelFast( this, (MDLHandle_t)virtualModel );
+}
+
+byte *studiohdr_t::GetAnimBlock( int i ) const
+{
+ return g_pMDLCache->GetAnimBlock( (MDLHandle_t)virtualModel, i );
+}
+
+int studiohdr_t::GetAutoplayList( unsigned short **pOut ) const
+{
+ return g_pMDLCache->GetAutoplayList( (MDLHandle_t)virtualModel, pOut );
+}
+
+const studiohdr_t *virtualgroup_t::GetStudioHdr( void ) const
+{
+ return g_pMDLCache->GetStudioHdr( (MDLHandle_t)cache );
+}
+
+
+//-----------------------------------------------------------------------------
+// Set up the bones for a frame
+//-----------------------------------------------------------------------------
+matrix3x4_t* CIHVTestApp::SetUpBones( studiohdr_t *pStudioHdr, const matrix3x4_t &shapeToWorld, int iRun, int model, int boneMask )
+{
+ CStudioHdr studioHdr( pStudioHdr, g_pMDLCache );
+
+ // Default to middle of the pose parameter range
+ float flPoseParameter[MAXSTUDIOPOSEPARAM];
+ Studio_CalcDefaultPoseParameters( &studioHdr, flPoseParameter, MAXSTUDIOPOSEPARAM );
+
+ int nFrameCount = Studio_MaxFrame( &studioHdr, g_BenchRuns[iRun].sequence1[model], flPoseParameter );
+ if ( nFrameCount == 0 )
+ {
+ nFrameCount = 1;
+ }
+
+ Vector pos[MAXSTUDIOBONES];
+ Quaternion q[MAXSTUDIOBONES];
+
+ IBoneSetup boneSetup( &studioHdr, boneMask, flPoseParameter );
+ boneSetup.InitPose( pos, q );
+ boneSetup.AccumulatePose( pos, q, g_BenchRuns[iRun].sequence1[model], s_Cycle[model], 1.0f, 0.0, NULL );
+
+ // FIXME: Try enabling this?
+// CalcAutoplaySequences( pStudioHdr, NULL, pos, q, flPoseParameter, BoneMask( ), flTime );
+
+ // Root transform
+ matrix3x4_t rootToWorld, temp;
+
+ MatrixCopy( shapeToWorld, rootToWorld );
+
+ matrix3x4_t *pBoneToWorld = g_pStudioRender->LockBoneMatrices( studioHdr.numbones() );
+ for ( int i = 0; i < studioHdr.numbones(); i++ )
+ {
+ // If it's not being used, fill with NAN for errors
+ if ( !(studioHdr.pBone( i )->flags & boneMask) )
+ {
+ int j, k;
+ for (j = 0; j < 3; j++)
+ {
+ for (k = 0; k < 4; k++)
+ {
+ pBoneToWorld[i][j][k] = VEC_T_NAN;
+ }
+ }
+ continue;
+ }
+
+ matrix3x4_t boneMatrix;
+ QuaternionMatrix( q[i], boneMatrix );
+ MatrixSetColumn( pos[i], 3, boneMatrix );
+
+ if (studioHdr.pBone(i)->parent == -1)
+ {
+ ConcatTransforms (rootToWorld, boneMatrix, pBoneToWorld[i]);
+ }
+ else
+ {
+ ConcatTransforms (pBoneToWorld[ studioHdr.pBone(i)->parent ], boneMatrix, pBoneToWorld[i] );
+ }
+ }
+ g_pStudioRender->UnlockBoneMatrices();
+ return pBoneToWorld;
+}
+
+
+//-----------------------------------------------------------------------------
+// Use mdlcache to load a model
+//-----------------------------------------------------------------------------
+bool CIHVTestApp::LoadModel( const char* pModelName, IHVTestModel *pModel )
+{
+ pModel->hMdl = g_pMDLCache->FindMDL( pModelName );
+
+ pModel->pStudioHdr = g_pMDLCache->GetStudioHdr( pModel->hMdl );
+
+ g_pMDLCache->GetVertexData( pModel->hMdl );
+ g_pMDLCache->FinishPendingLoads();
+
+ g_pMDLCache->GetHardwareData( pModel->hMdl );
+ g_pMDLCache->FinishPendingLoads();
+
+ pModel->pHardwareData = g_pMDLCache->GetHardwareData( pModel->hMdl );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Loads all models
+//-----------------------------------------------------------------------------
+bool CIHVTestApp::LoadModels( void )
+{
+ const char *pArgVal;
+ if( CommandLine()->CheckParm( "-rowcol", &pArgVal ) )
+ {
+ g_NumRows = g_NumCols = atoi( pArgVal );
+ }
+
+ /* figure out which LOD we are going to render */
+ if( CommandLine()->CheckParm( "-lod", &pArgVal ) )
+ {
+ g_LOD = atoi( pArgVal );
+ }
+
+ if( CommandLine()->CheckParm( "-body", &pArgVal ) )
+ {
+ g_BodyGroup = atoi( pArgVal );
+ }
+
+ // figure out g_RefreshRate
+ if( CommandLine()->CheckParm( "-refresh", &pArgVal ) )
+ {
+ g_RefreshRate = atoi( pArgVal );
+ }
+
+ if( CommandLine()->CheckParm( "-light", &pArgVal ) )
+ {
+ g_LightingCombination = atoi( pArgVal );
+ if( g_LightingCombination < 0 )
+ {
+ g_LightingCombination = 0;
+ }
+ if( g_LightingCombination >= LIGHTING_COMBINATION_COUNT )
+ {
+ g_LightingCombination = LIGHTING_COMBINATION_COUNT - 1;
+ }
+ }
+
+ g_pForceMaterial = g_pMaterialSystem->FindMaterial( "models/alyx/thigh", TEXTURE_GROUP_OTHER );
+#ifdef MATERIAL_OVERRIDE
+ g_pStudioRender->ForcedMaterialOverride( g_pForceMaterial );
+#endif
+
+ InitTestLights();
+
+ if( g_BenchMode )
+ {
+ int i;
+ for( i = 0; i < NUM_BENCH_RUNS; i++ )
+ {
+ // Load each of the potentially alternating models:
+ int k;
+ for( k = 0; k < g_nMaxModels; k++ )
+ {
+ if( g_BenchRuns[i].pModelName[k] )
+ {
+ if( !LoadModel( g_BenchRuns[i].pModelName[k], &g_BenchModels[i][k] ) )
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ CommandLine()->CheckParm( "-i", &pArgVal );
+ if( !LoadModel( pArgVal, m_pIHVTestModel ) )
+ {
+ return false;
+ }
+ }
+ g_pMaterialSystem->CacheUsedMaterials();
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// App window proc
+//-----------------------------------------------------------------------------
+LONG CIHVTestApp::WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch( msg )
+ {
+ // abort when ESC is hit
+ case WM_CHAR:
+ switch(wParam)
+ {
+ case VK_ESCAPE:
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ m_bExitMainLoop = true;
+ return 0;
+ }
+
+ return DefWindowProc( hWnd, msg, wParam, lParam );
+}
+
+
+//-----------------------------------------------------------------------------
+// Static registered window proc
+//-----------------------------------------------------------------------------
+LONG WINAPI CIHVTestApp::WinAppWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ return s_IHVTestApp.WindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+//-----------------------------------------------------------------------------
+// Pump messages
+//-----------------------------------------------------------------------------
+void CIHVTestApp::AppPumpMessages()
+{
+ MSG msg;
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Advance the frame
+//-----------------------------------------------------------------------------
+void AdvanceFrame( CStudioHdr *pStudioHdr, int iRun, int model, float dt )
+{
+ if (dt > 0.1)
+ dt = 0.1f;
+
+ float t = Studio_Duration( pStudioHdr, g_BenchRuns[iRun].sequence1[model], s_PoseParameter );
+
+ if (t > 0)
+ {
+ s_Cycle[model] += dt / t;
+
+ // wrap
+ s_Cycle[model] -= (int)(s_Cycle[model]);
+ }
+ else
+ {
+ s_Cycle[model] = 0;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Render a frame
+//-----------------------------------------------------------------------------
+void CIHVTestApp::RenderFrame( void )
+{
+ VPROF( "RenderFrame" );
+ IHVTestModel *pModel = NULL;
+ static int currentRun = 0;
+ static int currentFrame = 0;
+ static int currentLightCombo = 0;
+ int modelAlternator = 0;
+
+ if (g_bInError)
+ {
+ // error context is active
+ // error may be renderer based, avoid re-entrant render to fatal crash
+ return;
+ }
+
+ if( g_BenchMode )
+ {
+ if( currentFrame > g_BenchRuns[currentRun].numFrames )
+ {
+ currentLightCombo++;
+ if( currentLightCombo >= LIGHTING_COMBINATION_COUNT )
+ {
+ currentRun++;
+ currentLightCombo = 0;
+ if( currentRun >= NUM_BENCH_RUNS )
+ {
+ g_BenchFinished = true;
+ return;
+ }
+ }
+ currentFrame = 0;
+ }
+ }
+ if( g_BenchMode )
+ {
+ pModel = &g_BenchModels[currentRun][0];
+ g_NumCols = g_BenchRuns[currentRun].cols;
+ g_NumRows = g_BenchRuns[currentRun].rows;
+ }
+ else
+ {
+ pModel = m_pIHVTestModel;
+ }
+ Assert( pModel );
+
+ g_EngineStats.BeginFrame();
+
+ g_pMaterialSystem->BeginFrame( 0 );
+ g_pStudioRender->BeginFrame();
+
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+
+ pRenderContext->ClearColor3ub( 0, 0, 0 );
+ pRenderContext->ClearBuffers( true, true );
+
+ pRenderContext->Viewport( 0, 0, g_RenderWidth, g_RenderHeight );
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->LoadIdentity();
+ pRenderContext->PerspectiveX( 90.0f, ( g_RenderWidth / g_RenderHeight), 1.0f, 500000.0f );
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->LoadIdentity();
+ if( g_BenchMode )
+ {
+ pRenderContext->Translate( 0.0f, 0.0f, ( float )-( g_NumCols * g_BenchRuns[currentRun].modelSize * 0.6f ) );
+ }
+ else
+ {
+ pRenderContext->Translate( 0.0f, 0.0f, ( float )-( g_NumCols * 80.0f * 0.5f ) );
+ }
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->LoadIdentity();
+
+ QAngle angles;
+ angles[YAW] = -90.0f;
+ angles[PITCH] = -90.0f;
+ angles[ROLL] = 0.0f;
+
+ matrix3x4_t cameraMatrix;
+ AngleMatrix( angles, cameraMatrix );
+
+ int r, c;
+ int trisRendered = 0;
+ float boneSetupTime = 0.0f;
+ for( r = 0; r < g_NumRows; r++ )
+ {
+ for( c = 0; c < g_NumCols; c++ )
+ {
+ // If we are alternating models, select the next valid model.
+ if( g_BenchMode )
+ {
+ do
+ {
+ // If I pass my maximum number of models, wrap around to model 0, which must always be valid.
+ if( ++modelAlternator >= g_nMaxModels )
+ {
+ modelAlternator = 0;
+ break;
+ }
+ }
+ while( !g_BenchRuns[currentRun].pModelName[modelAlternator] );
+
+ pModel = &g_BenchModels[currentRun][modelAlternator];
+ Assert( pModel );
+ }
+
+ if( g_BenchMode )
+ {
+ cameraMatrix[0][3] = ( ( c + 0.5f ) - ( g_NumCols * .5f ) ) * g_BenchRuns[currentRun].modelSize;
+ cameraMatrix[1][3] = ( ( float )r - ( g_NumCols * .5f ) ) * g_BenchRuns[currentRun].modelSize;
+ }
+ else
+ {
+ cameraMatrix[0][3] = ( ( c + 0.5f ) - ( g_NumCols * .5f ) ) * 75.0f;
+ cameraMatrix[1][3] = ( ( float )r - ( g_NumCols * .5f ) ) * 75.0f;
+ }
+
+ Vector modelOrigin( cameraMatrix[0][3], cameraMatrix[1][3], 0.0f );
+ Vector lightOffset( cameraMatrix[0][3], cameraMatrix[1][3], 0.0f );
+
+ if (g_LightingCombination < 0)
+ {
+ SetupLighting( g_BenchMode ? currentLightCombo : 0, lightOffset );
+ }
+ else
+ {
+ SetupLighting( g_LightingCombination, lightOffset );
+ }
+
+ float startBoneSetupTime = Sys_FloatTime();
+ int lod = g_LOD;
+ lod = clamp( lod, pModel->pHardwareData->m_RootLOD, pModel->pHardwareData->m_NumLODs-1 );
+
+ int boneMask = BONE_USED_BY_VERTEX_AT_LOD( lod );
+ matrix3x4_t *pBoneToWorld = SetUpBones( pModel->pStudioHdr, cameraMatrix, currentRun, modelAlternator, boneMask );
+ boneSetupTime += Sys_FloatTime() - startBoneSetupTime;
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PushMatrix();
+
+ DrawModelInfo_t modelInfo;
+ memset( &modelInfo, 0, sizeof( modelInfo ) );
+ modelInfo.m_pStudioHdr = pModel->pStudioHdr;
+ modelInfo.m_pHardwareData = pModel->pHardwareData;
+ modelInfo.m_Decals = STUDIORENDER_DECAL_INVALID;
+ modelInfo.m_Skin = 0;
+ modelInfo.m_Body = g_BodyGroup;
+ modelInfo.m_HitboxSet = 0;
+ modelInfo.m_pClientEntity = NULL;
+ modelInfo.m_Lod = lod;
+ modelInfo.m_pColorMeshes = NULL;
+ g_pStudioRender->DrawModel( NULL, modelInfo, pBoneToWorld, NULL, NULL, modelOrigin );
+
+ DrawModelResults_t results;
+ g_pStudioRender->GetPerfStats( &results, modelInfo, NULL );
+ trisRendered += results.m_ActualTriCount;
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PopMatrix();
+ }
+ }
+
+ pRenderContext->Flush( true );
+ g_EngineStats.EndFrame();
+
+ g_pStudioRender->EndFrame();
+ g_pMaterialSystem->EndFrame();
+
+ // hack - don't count the first frame in case there are any state
+ // transitions computed on that frame.
+ if( currentFrame != 0 )
+ {
+ g_BenchResults[currentRun][currentLightCombo].totalTime += g_EngineStats.GetCurrentSystemFrameTime();
+ g_BenchResults[currentRun][currentLightCombo].totalTris += trisRendered;
+ }
+
+ for ( int model = 0; model < g_nMaxModels; ++model )
+ {
+ CStudioHdr studioHdr( g_BenchModels[currentRun][model].pStudioHdr, g_pMDLCache );
+ AdvanceFrame( &studioHdr, currentRun, model, g_EngineStats.GetCurrentSystemFrameTime() );
+ }
+
+ g_pMaterialSystem->SwapBuffers();
+
+#ifdef USE_VPROF
+ g_VProfCurrentProfile.MarkFrame();
+ static bool bBeenHere = false;
+ if( !bBeenHere )
+ {
+ bBeenHere = true;
+ g_VProfCurrentProfile.Reset();
+ }
+#endif
+ currentFrame++;
+}
+
+
+//-----------------------------------------------------------------------------
+// Create the application object
+//-----------------------------------------------------------------------------
+bool CIHVTestApp::Create()
+{
+ AppSystemInfo_t appSystems[] =
+ {
+ { "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
+ { "datacache.dll", DATACACHE_INTERFACE_VERSION },
+ { "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
+ { "datacache.dll", MDLCACHE_INTERFACE_VERSION },
+ { "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
+ { "", "" } // Required to terminate the list
+ };
+
+ MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
+
+ if ( !AddSystems( appSystems ) )
+ return false;
+
+ g_pFileSystem = ( IFileSystem * )FindSystem( FILESYSTEM_INTERFACE_VERSION );
+ g_pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
+ g_pStudioRender = (IStudioRender*)FindSystem( STUDIO_RENDER_INTERFACE_VERSION );
+ g_pMDLCache = (IMDLCache*)FindSystem( MDLCACHE_INTERFACE_VERSION );
+
+ if ( !g_pFileSystem || !g_pMaterialSystem || !g_pStudioRender || !g_pMDLCache )
+ {
+ DisplayError( "Unable to load required library interfaces!" );
+ return false;
+ }
+
+#if defined( _X360 )
+ // vxconsole - true will block (legacy behavior)
+ XBX_InitConsoleMonitor( false );
+#endif
+
+ const char* pDLLName;
+ if ( CommandLine()->CheckParm( "-null" ) )
+ {
+ g_bUseEmptyShader = true;
+ pDLLName = "shaderapiempty.dll";
+ }
+ else
+ {
+ pDLLName = "shaderapidx9.dll";
+ }
+
+#if defined( _X360 )
+ g_pFileSystem->LoadModule( pDLLName );
+#endif
+ g_pMaterialSystem->SetShaderAPI( pDLLName );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// StudioRender...
+//-----------------------------------------------------------------------------
+bool CIHVTestApp::SetupStudioRender( void )
+{
+ StudioRenderConfig_t config;
+ memset( &config, 0, sizeof(config) );
+
+ config.bEyeMove = true;
+ config.bTeeth = true;
+ config.bEyes = true;
+ config.bFlex = true;
+
+ config.fEyeShiftX = 0.0f;
+ config.fEyeShiftY = 0.0f;
+ config.fEyeShiftZ = 0.0f;
+ config.fEyeSize = 0.0f;
+
+ config.bNoHardware = false;
+ config.bNoSoftware = false;
+
+ config.bSoftwareSkin = false;
+ config.bSoftwareLighting = false;
+
+ config.drawEntities = true;
+ config.bWireframe = false;
+ config.bDrawNormals = false;
+ config.bDrawTangentFrame = false;
+ config.skin = 0;
+
+ config.fullbright = 0;
+
+ config.bShowEnvCubemapOnly = false;
+
+ g_pStudioRender->UpdateConfig( config );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Material system
+//-----------------------------------------------------------------------------
+bool InitMaterialSystem( HWND mainWindow )
+{
+ MaterialSystem_Config_t config;
+ if( g_WindowMode )
+ {
+ config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
+ }
+ config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, IsX360() ? 0 : true );
+
+ config.m_VideoMode.m_Width = 0;
+ config.m_VideoMode.m_Height = 0;
+ config.m_VideoMode.m_Format = IMAGE_FORMAT_BGRX8888;
+ config.m_VideoMode.m_RefreshRate = g_RefreshRate;
+ config.dxSupportLevel = IsX360() ? 98 : 0;
+
+ bool modeSet = g_pMaterialSystem->SetMode( (void*)mainWindow, config );
+ if (!modeSet)
+ {
+ DisplayError( "Unable to set mode\n" );
+ return false;
+ }
+
+ g_pMaterialSystem->OverrideConfig( config, false );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// PreInit
+//-----------------------------------------------------------------------------
+bool CIHVTestApp::PreInit( void )
+{
+ CreateInterfaceFn factory = GetFactory();
+ ConnectTier1Libraries( &factory, 1 );
+
+ // Add paths...
+ if ( !SetupSearchPaths( NULL, false, true ) )
+ {
+ Error( "Failed to setup search paths\n" );
+ return false;
+ }
+
+ const char *pArgVal;
+ if ( CommandLine()->CheckParm( "-bench" ) )
+ {
+ g_BenchMode = true;
+ }
+
+ if( !g_BenchMode && !CommandLine()->CheckParm( "-i" ) )
+ {
+ // Set some default parameters for running as a unittest
+ g_BenchMode = true;
+ g_WindowMode = IsPC() ? true : false;
+ }
+
+ if( g_BenchMode )
+ {
+ if ( CommandLine()->CheckParm( "-i", &pArgVal ) )
+ {
+ g_BenchRuns[0].pModelName[0] = pArgVal;
+ }
+ }
+
+ if( CommandLine()->CheckParm( "-softwaretl" ) )
+ {
+ g_SoftwareTL = true;
+ }
+
+ // Explicitly in window/fullscreen mode?
+ if ( CommandLine()->CheckParm( "-window") )
+ {
+ g_WindowMode = true;
+ }
+ else if ( CommandLine()->CheckParm( "-fullscreen" ) )
+ {
+ g_WindowMode = false;
+ }
+
+ /* figure out g_Renderwidth and g_RenderHeight */
+ g_RenderWidth = -1;
+ g_RenderHeight = -1;
+
+ if( CommandLine()->CheckParm( "-width", &pArgVal ) )
+ {
+ g_RenderWidth = atoi( pArgVal );
+ }
+ if( CommandLine()->CheckParm( "-height", &pArgVal ) )
+ {
+ g_RenderHeight = atoi( pArgVal );
+ }
+
+ if( g_RenderWidth == -1 && g_RenderHeight == -1 )
+ {
+ g_RenderWidth = 640;
+ g_RenderHeight = 480;
+ }
+ else if( g_RenderWidth != -1 && g_RenderHeight == -1 )
+ {
+ switch( g_RenderWidth )
+ {
+ case 320:
+ g_RenderHeight = 240;
+ break;
+ case 512:
+ g_RenderHeight = 384;
+ break;
+ case 640:
+ g_RenderHeight = 480;
+ break;
+ case 800:
+ g_RenderHeight = 600;
+ break;
+ case 1024:
+ g_RenderHeight = 768;
+ break;
+ case 1280:
+ g_RenderHeight = 1024;
+ break;
+ case 1600:
+ g_RenderHeight = 1200;
+ break;
+ default:
+ DisplayError( "Can't figure out window dimensions!!" );
+ exit( -1 );
+ break;
+ }
+ }
+
+ if( g_RenderWidth == -1 || g_RenderHeight == -1 )
+ {
+ DisplayError( "Can't figure out window dimensions!!" );
+ exit( -1 );
+ }
+
+ int windowWidth, windowHeight;
+ CalcWindowSize( g_RenderWidth, g_RenderHeight, &windowWidth, &windowHeight );
+
+ if( !CreateAppWindow( "ihvtest1", windowWidth, windowHeight ) )
+ {
+ return false;
+ }
+ return true;
+}
+
+void CIHVTestApp::PostShutdown()
+{
+ DisconnectTier1Libraries();
+}
+
+
+//-----------------------------------------------------------------------------
+// The application main loop
+//-----------------------------------------------------------------------------
+int CIHVTestApp::Main()
+{
+ SpewOutputFunc( IHVTestSpewFunc );
+
+ if ( !SetupStudioRender() )
+ {
+ return 0;
+ }
+
+ if ( !InitMaterialSystem( m_hWnd ) )
+ {
+ return 0;
+ }
+
+#if !defined( _X360 ) // X360TBD:
+extern void Sys_InitFloatTime( void ); //garymcthack
+ Sys_InitFloatTime();
+#endif
+
+ LoadModels();
+
+#if USE_VTUNE
+ VTResume();
+#endif
+#ifdef USE_VPROF
+ g_VProfCurrentProfile.Start();
+#endif
+
+ bool m_bExitMainLoop = false;
+ while (!m_bExitMainLoop && !g_BenchFinished)
+ {
+ AppPumpMessages();
+ RenderFrame();
+ }
+
+#ifdef USE_VPROF
+ g_VProfCurrentProfile.Stop();
+#endif
+ g_IHVTestFP = fopen( "ihvtest_vprof.txt", "w" );
+#ifdef USE_VPROF
+ SpewOutputFunc( IHVTestVProfSpewFunc );
+ g_VProfCurrentProfile.OutputReport( VPRT_SUMMARY );
+ g_VProfCurrentProfile.OutputReport( VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY );
+ fclose( g_IHVTestFP );
+ SpewOutputFunc( IHVTestSpewFunc );
+#endif
+#if USE_VTUNE
+ VTPause();
+#endif
+
+ return 0;
+}
+