Team Fortress 2 Source Code as on 22/4/2020
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.

1508 lines
38 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // The copyright to the contents herein is the property of Valve, L.L.C.
  4. // The contents may be used and/or copied only with the written permission of
  5. // Valve, L.L.C., or in accordance with the terms and conditions stipulated in
  6. // the agreement/contract under which the contents have been supplied.
  7. //
  8. // $Header: $
  9. // $NoKeywords: $
  10. //
  11. //=============================================================================
  12. #define PROTECTED_THINGS_DISABLE
  13. #if !defined( _X360 )
  14. #define WIN32_LEAN_AND_MEAN
  15. #include <windows.h>
  16. #endif
  17. #include <time.h>
  18. #include "materialsystem/imaterialsystem.h"
  19. #include "materialsystem/IMaterialSystemHardwareConfig.h"
  20. #include "materialsystem/imaterialproxyfactory.h"
  21. #include "materialsystem/MaterialSystem_Config.h"
  22. #include "appframework/appframework.h"
  23. #include "datacache\idatacache.h"
  24. #include "datacache\imdlcache.h"
  25. #include "vphysics_interface.h"
  26. #include "filesystem.h"
  27. #include "IStudioRender.h"
  28. #include "studio.h"
  29. #include "clientstats.h"
  30. #include "bone_setup.h"
  31. #include "tier0/icommandline.h"
  32. #include "vstdlib/cvar.h"
  33. #include "tier0/vprof.h"
  34. #include "tier1/tier1.h"
  35. #include "optimize.h"
  36. #if defined( _X360 )
  37. #include "xbox\xbox_console.h"
  38. #include "xbox\xbox_win32stubs.h"
  39. #endif
  40. //-----------------------------------------------------------------------------
  41. // Main system interfaces
  42. //-----------------------------------------------------------------------------
  43. IMaterialSystem *g_pMaterialSystem = NULL;
  44. IStudioRender *g_pStudioRender = NULL;
  45. IFileSystem *g_pFileSystem = NULL;
  46. IMDLCache *g_pMDLCache = NULL;
  47. //-----------------------------------------------------------------------------
  48. // App control defines
  49. //-----------------------------------------------------------------------------
  50. //#define MATERIAL_OVERRIDE
  51. //#define USE_VTUNE
  52. //#define USE_VPROF
  53. #if USE_VTUNE
  54. #include "vtuneapi.h"
  55. #endif
  56. static bool g_WindowMode = false;
  57. static bool g_bUseEmptyShader = false;
  58. static bool g_BenchFinished = false;
  59. static bool g_BenchMode = false;
  60. static bool g_SoftwareTL = false;
  61. static int g_RenderWidth = 640;
  62. static int g_RenderHeight = 480;
  63. static int g_RefreshRate = 60;
  64. static int g_LOD = 0;
  65. static int g_BodyGroup = 0;
  66. static int g_NumRows = 10;
  67. static int g_NumCols = 10;
  68. static int g_dxLevel = 0;
  69. static int g_LightingCombination = -1;
  70. static FILE *g_IHVTestFP = NULL;
  71. static IMaterial *g_pForceMaterial = NULL;
  72. static bool g_bInError = false;
  73. #define MAX_LIGHTS 2
  74. #define NUM_LIGHT_TYPES 4
  75. #define LIGHTING_COMBINATION_COUNT 5
  76. static const char *g_LightCombinationNames[] =
  77. {
  78. "DISABLE ",
  79. // "SPOT ",
  80. "POINT ",
  81. "DIRECTIONAL ",
  82. "SPOT_SPOT ",
  83. // "SPOT_POINT ",
  84. // "SPOT_DIRECTIONAL ",
  85. // "POINT_POINT ",
  86. "POINT_DIRECTIONAL ",
  87. "DIRECTIONAL_DIRECTIONAL"
  88. };
  89. //-----------------------------------------------------------------------------
  90. // Test Model class
  91. //-----------------------------------------------------------------------------
  92. struct IHVTestModel
  93. {
  94. MDLHandle_t hMdl;
  95. studiohdr_t *pStudioHdr;
  96. studiohwdata_t *pHardwareData;
  97. };
  98. //-----------------------------------------------------------------------------
  99. // The application object
  100. //-----------------------------------------------------------------------------
  101. class CIHVTestApp : public CDefaultAppSystemGroup< CSteamAppSystemGroup >
  102. {
  103. public:
  104. // Methods of IApplication
  105. virtual bool Create();
  106. virtual bool PreInit();
  107. virtual int Main();
  108. virtual void PostShutdown();
  109. virtual void Destroy();
  110. private:
  111. bool CreateAppWindow( char const *pTitle, int w, int h );
  112. void AppPumpMessages( void );
  113. void RenderFrame( void );
  114. void RenderScene( void );
  115. bool SetupMaterialSystem();
  116. bool SetupStudioRender();
  117. bool LoadModels( void );
  118. bool LoadModel( const char *pModelName, IHVTestModel *pModel );
  119. bool CreateMainWindow( int width, int height, bool fullscreen );
  120. matrix3x4_t* SetUpBones( studiohdr_t *pStudioHdr, const matrix3x4_t &shapeToWorld, int iRun, int model, int boneMask );
  121. // Windproc
  122. static LONG WINAPI WinAppWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  123. LONG WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  124. HWND m_hWnd;
  125. bool m_bExitMainLoop;
  126. IHVTestModel *m_pIHVTestModel;
  127. };
  128. static CIHVTestApp s_IHVTestApp;
  129. DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT_GLOBALVAR( CIHVTestApp, s_IHVTestApp );
  130. //-----------------------------------------------------------------------------
  131. // Create the application window
  132. //-----------------------------------------------------------------------------
  133. bool CIHVTestApp::CreateAppWindow( const char* pAppName, int width, int height )
  134. {
  135. // Register the window class
  136. WNDCLASSEX wc;
  137. memset( &wc, 0, sizeof( wc ) );
  138. wc.cbSize = sizeof( wc );
  139. wc.style = CS_CLASSDC;
  140. wc.lpfnWndProc = WinAppWindowProc;
  141. wc.hInstance = (HINSTANCE)GetAppInstance();
  142. wc.lpszClassName = pAppName;
  143. wc.hIcon = NULL;
  144. wc.hIconSm = wc.hIcon;
  145. RegisterClassEx( &wc );
  146. // Create the application's window
  147. m_hWnd = CreateWindow( pAppName, pAppName,
  148. WS_OVERLAPPEDWINDOW,
  149. 0, 0, width, height,
  150. GetDesktopWindow(), NULL, wc.hInstance, NULL );
  151. ShowWindow (m_hWnd, SW_SHOWDEFAULT);
  152. return (m_hWnd != 0);
  153. }
  154. //#define TREES
  155. // The maximum number of distinctive models each test may specify.
  156. #ifdef TREES
  157. const int g_nMaxModels = 1;
  158. #else
  159. const int g_nMaxModels = 9;
  160. #endif
  161. //-----------------------------------------------------------------------------
  162. // Benchmarking
  163. //-----------------------------------------------------------------------------
  164. struct BenchRunInfo
  165. {
  166. const char *pModelName[g_nMaxModels];
  167. int numFrames;
  168. int rows;
  169. int cols;
  170. float modelSize;
  171. int sequence1[g_nMaxModels];
  172. int sequence2;
  173. };
  174. struct BenchResults
  175. {
  176. BenchResults() : totalTime( 0.0f ), totalTris( 0 ) {}
  177. float totalTime;
  178. int totalTris;
  179. };
  180. #define NUM_BENCH_RUNS 1
  181. static BenchResults g_BenchResults[NUM_BENCH_RUNS][LIGHTING_COMBINATION_COUNT];
  182. #ifdef TREES
  183. #define MODEL_ROWS 13
  184. #define MODEL_COLUMNS 13
  185. static BenchRunInfo g_BenchRuns[NUM_BENCH_RUNS] =
  186. {
  187. { { "models/props_foliage/tree_dead01.mdl"
  188. }, 100, MODEL_ROWS, MODEL_COLUMNS, 1000.0f, { 0 }, -1 },
  189. };
  190. #else
  191. #define MODEL_ROWS 3
  192. #define MODEL_COLUMNS 3
  193. static BenchRunInfo g_BenchRuns[NUM_BENCH_RUNS] =
  194. {
  195. { { "models/alyx.mdl",
  196. "models/alyx.mdl",
  197. "models/alyx.mdl",
  198. "models/alyx.mdl",
  199. "models/alyx.mdl",
  200. "models/alyx.mdl",
  201. "models/alyx.mdl",
  202. "models/alyx.mdl",
  203. "models/alyx.mdl",
  204. }, 100, MODEL_ROWS, MODEL_COLUMNS, 75.0f, { 1, 4, 20, 23, 25, 30, 34, 38, 1 }, -1 },
  205. };
  206. #endif
  207. // this is used in "-bench" mode
  208. static IHVTestModel g_BenchModels[NUM_BENCH_RUNS][g_nMaxModels];
  209. static void WriteBenchResults( void )
  210. {
  211. if( !g_BenchMode )
  212. {
  213. return;
  214. }
  215. FILE *fp = fopen( "ihvtest1.csv", "a+" );
  216. Assert( fp );
  217. if( !fp )
  218. {
  219. return;
  220. }
  221. fprintf( fp, "------------------------------------------------------------------\n" );
  222. time_t ltime;
  223. time( &ltime );
  224. fprintf( fp, "%s\n", GetCommandLine() );
  225. fprintf( fp, "Run at: %s", ctime( &ltime ) );
  226. int i;
  227. for( i = 0; i < NUM_BENCH_RUNS; i++ )
  228. {
  229. int j;
  230. fprintf( fp, "model,light combo,total tris,total time,tris/sec\n" );
  231. for( j = 0; j < LIGHTING_COMBINATION_COUNT; j++ )
  232. {
  233. int k;
  234. for( k = 0; k < g_nMaxModels; k++ )
  235. {
  236. if( g_BenchRuns[i].pModelName[k] )
  237. {
  238. fprintf( fp, "%s%s", k ? ", " : "", g_BenchRuns[i].pModelName[k] );
  239. }
  240. }
  241. fprintf( fp, "," );
  242. fprintf( fp, "%s,", g_LightCombinationNames[j] );
  243. fprintf( fp, "%d,", g_BenchResults[i][j].totalTris );
  244. fprintf( fp, "%0.5f,", ( float )g_BenchResults[i][j].totalTime );
  245. fprintf( fp, "%0.0lf\n", ( double )g_BenchResults[i][j].totalTris /
  246. ( double )g_BenchResults[i][j].totalTime );
  247. Warning( "%f %d\n", ( float )g_BenchResults[i][j].totalTime, g_BenchResults[i][j].totalTris );
  248. }
  249. }
  250. fclose( fp );
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Destroy app
  254. //-----------------------------------------------------------------------------
  255. void CIHVTestApp::Destroy()
  256. {
  257. // Close the window
  258. if (m_hWnd)
  259. DestroyWindow( m_hWnd );
  260. WriteBenchResults();
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Window size helper
  264. //-----------------------------------------------------------------------------
  265. static void CalcWindowSize( int desiredRenderingWidth, int desiredRenderingHeight,
  266. int *windowWidth, int *windowHeight )
  267. {
  268. int borderX, borderY;
  269. borderX = (GetSystemMetrics(SM_CXFIXEDFRAME) + 1) * 2;
  270. borderY = (GetSystemMetrics(SM_CYFIXEDFRAME) + 1) * 2 + GetSystemMetrics(SM_CYSIZE) + 1;
  271. *windowWidth = desiredRenderingWidth + borderX;
  272. *windowHeight = desiredRenderingHeight + borderY;
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Spew function!
  276. //-----------------------------------------------------------------------------
  277. SpewRetval_t IHVTestSpewFunc( SpewType_t spewType, char const *pMsg )
  278. {
  279. g_bInError = true;
  280. OutputDebugString( pMsg );
  281. switch( spewType )
  282. {
  283. case SPEW_MESSAGE:
  284. case SPEW_WARNING:
  285. case SPEW_LOG:
  286. OutputDebugString( pMsg );
  287. g_bInError = false;
  288. return SPEW_CONTINUE;
  289. case SPEW_ASSERT:
  290. case SPEW_ERROR:
  291. default:
  292. ::MessageBox( NULL, pMsg, "Error!", MB_OK );
  293. g_bInError = false;
  294. return SPEW_DEBUGGER;
  295. }
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Spew function to write to ihvtest_vprof.txt
  299. //-----------------------------------------------------------------------------
  300. SpewRetval_t IHVTestVProfSpewFunc( SpewType_t spewType, char const *pMsg )
  301. {
  302. g_bInError = true;
  303. switch( spewType )
  304. {
  305. case SPEW_MESSAGE:
  306. case SPEW_WARNING:
  307. case SPEW_LOG:
  308. fprintf( g_IHVTestFP, "%s", pMsg );
  309. g_bInError = false;
  310. return SPEW_CONTINUE;
  311. case SPEW_ASSERT:
  312. case SPEW_ERROR:
  313. default:
  314. ::MessageBox( NULL, pMsg, "Error!", MB_OK );
  315. g_bInError = false;
  316. return SPEW_DEBUGGER;
  317. }
  318. }
  319. //-----------------------------------------------------------------------------
  320. // Warnings and Errors...
  321. //-----------------------------------------------------------------------------
  322. #define MAXPRINTMSG 4096
  323. void DisplayError( const char* pError, ... )
  324. {
  325. va_list argptr;
  326. char msg[1024];
  327. g_bInError = true;
  328. va_start( argptr, pError );
  329. Q_vsnprintf( msg, sizeof( msg ), pError, argptr );
  330. va_end( argptr );
  331. MessageBox( 0, msg, 0, MB_OK );
  332. exit( -1 );
  333. }
  334. static void MaterialSystem_Warning( const char *fmt, ... )
  335. {
  336. va_list argptr;
  337. char msg[MAXPRINTMSG];
  338. va_start( argptr, fmt );
  339. Q_vsnprintf( msg, sizeof ( msg ), fmt, argptr );
  340. va_end( argptr );
  341. OutputDebugString( msg );
  342. }
  343. // garymcthack
  344. static void MaterialSystem_Warning( char *fmt, ... )
  345. {
  346. va_list argptr;
  347. char msg[MAXPRINTMSG];
  348. va_start( argptr, fmt );
  349. Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
  350. va_end( argptr );
  351. OutputDebugString( msg );
  352. }
  353. static void MaterialSystem_Error( char *fmt, ... )
  354. {
  355. va_list argptr;
  356. char msg[MAXPRINTMSG];
  357. g_bInError = true;
  358. va_start( argptr, fmt );
  359. Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
  360. va_end( argptr );
  361. MessageBox( NULL, (LPCTSTR)msg, "MaterialSystem Fatal Error", MB_OK | MB_ICONINFORMATION );
  362. #ifdef _DEBUG
  363. Assert( 0 );
  364. #endif
  365. exit( -1 );
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Engine Stats
  369. //-----------------------------------------------------------------------------
  370. // itty bitty interface for stat time
  371. class CStatTime : public IClientStatsTime
  372. {
  373. public:
  374. float GetTime()
  375. {
  376. return Sys_FloatTime();
  377. }
  378. };
  379. CStatTime g_StatTime;
  380. class CEngineStats
  381. {
  382. public:
  383. CEngineStats() : m_InFrame( false ) {};
  384. //
  385. // stats input
  386. //
  387. void BeginRun( void );
  388. void BeginFrame( void );
  389. void EndFrame( void );
  390. void EndRun( void );
  391. //
  392. // stats output
  393. // call these outside of a BeginFrame/EndFrame pair
  394. //
  395. // return the frame time in seconds for the whole system (not just graphics)
  396. double GetCurrentSystemFrameTime( void );
  397. double GetRunTime( void );
  398. private:
  399. // How many frames worth of data have we logged?
  400. int m_totalNumFrames;
  401. // frame timing data
  402. double m_frameStartTime;
  403. double m_frameEndTime;
  404. double m_minFrameTime;
  405. double m_maxFrameTime;
  406. // run timing data
  407. double m_runStartTime;
  408. double m_runEndTime;
  409. bool m_InFrame;
  410. };
  411. void CEngineStats::BeginRun( void )
  412. {
  413. m_totalNumFrames = 0;
  414. // frame timing data
  415. m_runStartTime = Sys_FloatTime();
  416. }
  417. void CEngineStats::EndRun( void )
  418. {
  419. m_runEndTime = Sys_FloatTime();
  420. }
  421. void CEngineStats::BeginFrame( void )
  422. {
  423. m_InFrame = true;
  424. m_frameStartTime = Sys_FloatTime();
  425. }
  426. void CEngineStats::EndFrame( void )
  427. {
  428. double deltaTime;
  429. m_frameEndTime = Sys_FloatTime();
  430. deltaTime = GetCurrentSystemFrameTime();
  431. m_InFrame = false;
  432. }
  433. double CEngineStats::GetRunTime( void )
  434. {
  435. return m_runEndTime - m_runStartTime;
  436. }
  437. double CEngineStats::GetCurrentSystemFrameTime( void )
  438. {
  439. return m_frameEndTime - m_frameStartTime;
  440. }
  441. static CEngineStats g_EngineStats;
  442. //-----------------------------------------------------------------------------
  443. // Lighting
  444. //-----------------------------------------------------------------------------
  445. // If you change the number of lighting combinations, change LIGHTING_COMBINATION_COUNT
  446. static LightType_t g_LightCombinations[][MAX_LIGHTS] =
  447. {
  448. { MATERIAL_LIGHT_DISABLE, MATERIAL_LIGHT_DISABLE }, // 0
  449. // { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_DISABLE },
  450. // { MATERIAL_LIGHT_POINT, MATERIAL_LIGHT_DISABLE },
  451. { MATERIAL_LIGHT_DIRECTIONAL, MATERIAL_LIGHT_DISABLE },
  452. { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_SPOT },
  453. // { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_POINT }, // 5
  454. // { MATERIAL_LIGHT_SPOT, MATERIAL_LIGHT_DIRECTIONAL },
  455. // { MATERIAL_LIGHT_POINT, MATERIAL_LIGHT_POINT },
  456. { MATERIAL_LIGHT_POINT, MATERIAL_LIGHT_DIRECTIONAL },
  457. { MATERIAL_LIGHT_DIRECTIONAL, MATERIAL_LIGHT_DIRECTIONAL }, // 9
  458. };
  459. LightDesc_t g_TestLights[NUM_LIGHT_TYPES][MAX_LIGHTS];
  460. static void FixLight( LightDesc_t *pLight )
  461. {
  462. pLight->m_Range = 0.0f;
  463. pLight->m_Falloff = 1.0f;
  464. pLight->m_ThetaDot = cos( pLight->m_Theta * 0.5f );
  465. pLight->m_PhiDot = cos( pLight->m_Phi * 0.5f );
  466. pLight->m_Flags = 0;
  467. if( pLight->m_Attenuation0 != 0.0f )
  468. {
  469. pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0;
  470. }
  471. if( pLight->m_Attenuation1 != 0.0f )
  472. {
  473. pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1;
  474. }
  475. if( pLight->m_Attenuation2 != 0.0f )
  476. {
  477. pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2;
  478. }
  479. VectorNormalize( pLight->m_Direction );
  480. }
  481. static void InitTestLights( void )
  482. {
  483. LightDesc_t *pLight;
  484. int i;
  485. for( i = 0; i < MAX_LIGHTS; i++ )
  486. {
  487. // MATERIAL_LIGHT_DISABLE
  488. pLight = &g_TestLights[MATERIAL_LIGHT_DISABLE][i];
  489. pLight->m_Type = MATERIAL_LIGHT_DISABLE;
  490. }
  491. // x - right
  492. // y - up
  493. // z - front of model
  494. // MATERIAL_LIGHT_SPOT 0
  495. pLight = &g_TestLights[MATERIAL_LIGHT_SPOT][0];
  496. memset( pLight, 0, sizeof( LightDesc_t ) );
  497. pLight->m_Type = MATERIAL_LIGHT_SPOT;
  498. pLight->m_Color.Init( 5000.0f, 3500.0f, 3500.0f );
  499. pLight->m_Position.Init( 0.0f, 0.0f, 50.0f );
  500. pLight->m_Direction.Init( 0.0f, 0.5f, -1.0f );
  501. pLight->m_Attenuation0 = 0.0f;
  502. pLight->m_Attenuation1 = 0.0f;
  503. pLight->m_Attenuation2 = 1.0f / 10;
  504. pLight->m_Theta = DEG2RAD( 20.0f );
  505. pLight->m_Phi = DEG2RAD( 30.0f );
  506. // MATERIAL_LIGHT_SPOT 1
  507. pLight = &g_TestLights[MATERIAL_LIGHT_SPOT][1];
  508. memset( pLight, 0, sizeof( LightDesc_t ) );
  509. pLight->m_Type = MATERIAL_LIGHT_SPOT;
  510. pLight->m_Color.Init( 3500.0f, 5000.0f, 3500.0f );
  511. pLight->m_Position.Init( 0.0f, 0.0f, 150.0f );
  512. pLight->m_Direction.Init( 0.0f, 0.5f, -1.0f );
  513. pLight->m_Attenuation0 = 0.0f;
  514. pLight->m_Attenuation1 = 0.0f;
  515. pLight->m_Attenuation2 = 1.0f / 10;
  516. pLight->m_Theta = DEG2RAD( 20.0f );
  517. pLight->m_Phi = DEG2RAD( 30.0f );
  518. // MATERIAL_LIGHT_POINT 0
  519. pLight = &g_TestLights[MATERIAL_LIGHT_POINT][0];
  520. memset( pLight, 0, sizeof( LightDesc_t ) );
  521. pLight->m_Type = MATERIAL_LIGHT_POINT;
  522. pLight->m_Color.Init( 1500.0f, 750.0f, 750.0f );
  523. pLight->m_Position.Init( 200.0f, 200.0f, 200.0f );
  524. pLight->m_Attenuation0 = 0.0f;
  525. pLight->m_Attenuation1 = 1.0f;
  526. pLight->m_Attenuation2 = 0.0f;
  527. // MATERIAL_LIGHT_POINT 1
  528. pLight = &g_TestLights[MATERIAL_LIGHT_POINT][1];
  529. memset( pLight, 0, sizeof( LightDesc_t ) );
  530. pLight->m_Type = MATERIAL_LIGHT_POINT;
  531. pLight->m_Color.Init( 750.0f, 750.0f, 1500.0f );
  532. pLight->m_Position.Init( -200.0f, 200.0f, 200.0f );
  533. pLight->m_Attenuation0 = 0.0f;
  534. pLight->m_Attenuation1 = 1.0f;
  535. pLight->m_Attenuation2 = 0.0f;
  536. // MATERIAL_LIGHT_DIRECTIONAL 0
  537. pLight = &g_TestLights[MATERIAL_LIGHT_DIRECTIONAL][0];
  538. memset( pLight, 0, sizeof( LightDesc_t ) );
  539. pLight->m_Type = MATERIAL_LIGHT_DIRECTIONAL;
  540. pLight->m_Color.Init( 2.0f, 2.0f, 1.0f );
  541. pLight->m_Direction.Init( -1.0f, 0.0f, 0.0f );
  542. pLight->m_Attenuation0 = 1.0f;
  543. pLight->m_Attenuation1 = 0.0f;
  544. pLight->m_Attenuation2 = 0.0f;
  545. // MATERIAL_LIGHT_DIRECTIONAL 1
  546. pLight = &g_TestLights[MATERIAL_LIGHT_DIRECTIONAL][1];
  547. memset( pLight, 0, sizeof( LightDesc_t ) );
  548. pLight->m_Type = MATERIAL_LIGHT_DIRECTIONAL;
  549. pLight->m_Color.Init( 1.0f, 1.0f, 2.0f );
  550. pLight->m_Direction.Init( 1.0f, 0.0f, 0.0f );
  551. pLight->m_Attenuation0 = 1.0f;
  552. pLight->m_Attenuation1 = 0.0f;
  553. pLight->m_Attenuation2 = 0.0f;
  554. for( i = 0; i < MAX_LIGHTS; i++ )
  555. {
  556. int j;
  557. for( j = 0; j < NUM_LIGHT_TYPES; j++ )
  558. {
  559. FixLight( &g_TestLights[j][i] );
  560. }
  561. }
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Setup lighting
  565. //-----------------------------------------------------------------------------
  566. static void SetupLighting( int lightingCombination, Vector &lightOffset )
  567. {
  568. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  569. if( lightingCombination == 0 )
  570. {
  571. g_pStudioRender->SetLocalLights( 0, NULL );
  572. pRenderContext->SetAmbientLight( 1.0, 1.0, 1.0 );
  573. static Vector white[6] =
  574. {
  575. Vector( 1.0, 1.0, 1.0 ),
  576. Vector( 1.0, 1.0, 1.0 ),
  577. Vector( 1.0, 1.0, 1.0 ),
  578. Vector( 1.0, 1.0, 1.0 ),
  579. Vector( 1.0, 1.0, 1.0 ),
  580. Vector( 1.0, 1.0, 1.0 ),
  581. };
  582. g_pStudioRender->SetAmbientLightColors( white );
  583. }
  584. else
  585. {
  586. pRenderContext->SetAmbientLight( 0.0f, 0.0f, 0.0f );
  587. static Vector black[6] =
  588. {
  589. Vector( 0.0, 0.0, 0.0 ),
  590. Vector( 0.0, 0.0, 0.0 ),
  591. Vector( 0.0, 0.0, 0.0 ),
  592. Vector( 0.0, 0.0, 0.0 ),
  593. Vector( 0.0, 0.0, 0.0 ),
  594. Vector( 0.0, 0.0, 0.0 ),
  595. };
  596. g_pStudioRender->SetAmbientLightColors( black );
  597. int lightID;
  598. LightDesc_t lightDescs[MAX_LIGHTS];
  599. for( lightID = 0; lightID < MAX_LIGHTS; lightID++ )
  600. {
  601. int lightType = g_LightCombinations[lightingCombination][lightID];
  602. lightDescs[lightID] = g_TestLights[lightType][lightID];
  603. lightDescs[lightID].m_Position += lightOffset;
  604. }
  605. // Feed disabled lights through?
  606. if( g_LightCombinations[lightingCombination][1] == MATERIAL_LIGHT_DISABLE )
  607. {
  608. g_pStudioRender->SetLocalLights( 1, lightDescs );
  609. }
  610. else
  611. {
  612. g_pStudioRender->SetLocalLights( MAX_LIGHTS, lightDescs );
  613. }
  614. }
  615. }
  616. //-----------------------------------------------------------------------------
  617. // Models
  618. //-----------------------------------------------------------------------------
  619. static float s_PoseParameter[32];
  620. static float s_Cycle[9] = { 0.0f };
  621. virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const
  622. {
  623. if ( numincludemodels == 0 )
  624. return NULL;
  625. return g_pMDLCache->GetVirtualModelFast( this, (MDLHandle_t)virtualModel );
  626. }
  627. byte *studiohdr_t::GetAnimBlock( int i ) const
  628. {
  629. return g_pMDLCache->GetAnimBlock( (MDLHandle_t)virtualModel, i );
  630. }
  631. int studiohdr_t::GetAutoplayList( unsigned short **pOut ) const
  632. {
  633. return g_pMDLCache->GetAutoplayList( (MDLHandle_t)virtualModel, pOut );
  634. }
  635. const studiohdr_t *virtualgroup_t::GetStudioHdr( void ) const
  636. {
  637. return g_pMDLCache->GetStudioHdr( (MDLHandle_t)cache );
  638. }
  639. //-----------------------------------------------------------------------------
  640. // Set up the bones for a frame
  641. //-----------------------------------------------------------------------------
  642. matrix3x4_t* CIHVTestApp::SetUpBones( studiohdr_t *pStudioHdr, const matrix3x4_t &shapeToWorld, int iRun, int model, int boneMask )
  643. {
  644. CStudioHdr studioHdr( pStudioHdr, g_pMDLCache );
  645. // Default to middle of the pose parameter range
  646. float flPoseParameter[MAXSTUDIOPOSEPARAM];
  647. Studio_CalcDefaultPoseParameters( &studioHdr, flPoseParameter, MAXSTUDIOPOSEPARAM );
  648. int nFrameCount = Studio_MaxFrame( &studioHdr, g_BenchRuns[iRun].sequence1[model], flPoseParameter );
  649. if ( nFrameCount == 0 )
  650. {
  651. nFrameCount = 1;
  652. }
  653. Vector pos[MAXSTUDIOBONES];
  654. Quaternion q[MAXSTUDIOBONES];
  655. IBoneSetup boneSetup( &studioHdr, boneMask, flPoseParameter );
  656. boneSetup.InitPose( pos, q );
  657. boneSetup.AccumulatePose( pos, q, g_BenchRuns[iRun].sequence1[model], s_Cycle[model], 1.0f, 0.0, NULL );
  658. // FIXME: Try enabling this?
  659. // CalcAutoplaySequences( pStudioHdr, NULL, pos, q, flPoseParameter, BoneMask( ), flTime );
  660. // Root transform
  661. matrix3x4_t rootToWorld, temp;
  662. MatrixCopy( shapeToWorld, rootToWorld );
  663. matrix3x4_t *pBoneToWorld = g_pStudioRender->LockBoneMatrices( studioHdr.numbones() );
  664. for ( int i = 0; i < studioHdr.numbones(); i++ )
  665. {
  666. // If it's not being used, fill with NAN for errors
  667. if ( !(studioHdr.pBone( i )->flags & boneMask) )
  668. {
  669. int j, k;
  670. for (j = 0; j < 3; j++)
  671. {
  672. for (k = 0; k < 4; k++)
  673. {
  674. pBoneToWorld[i][j][k] = VEC_T_NAN;
  675. }
  676. }
  677. continue;
  678. }
  679. matrix3x4_t boneMatrix;
  680. QuaternionMatrix( q[i], boneMatrix );
  681. MatrixSetColumn( pos[i], 3, boneMatrix );
  682. if (studioHdr.pBone(i)->parent == -1)
  683. {
  684. ConcatTransforms (rootToWorld, boneMatrix, pBoneToWorld[i]);
  685. }
  686. else
  687. {
  688. ConcatTransforms (pBoneToWorld[ studioHdr.pBone(i)->parent ], boneMatrix, pBoneToWorld[i] );
  689. }
  690. }
  691. g_pStudioRender->UnlockBoneMatrices();
  692. return pBoneToWorld;
  693. }
  694. //-----------------------------------------------------------------------------
  695. // Use mdlcache to load a model
  696. //-----------------------------------------------------------------------------
  697. bool CIHVTestApp::LoadModel( const char* pModelName, IHVTestModel *pModel )
  698. {
  699. pModel->hMdl = g_pMDLCache->FindMDL( pModelName );
  700. pModel->pStudioHdr = g_pMDLCache->GetStudioHdr( pModel->hMdl );
  701. g_pMDLCache->GetVertexData( pModel->hMdl );
  702. g_pMDLCache->FinishPendingLoads();
  703. g_pMDLCache->GetHardwareData( pModel->hMdl );
  704. g_pMDLCache->FinishPendingLoads();
  705. pModel->pHardwareData = g_pMDLCache->GetHardwareData( pModel->hMdl );
  706. return true;
  707. }
  708. //-----------------------------------------------------------------------------
  709. // Loads all models
  710. //-----------------------------------------------------------------------------
  711. bool CIHVTestApp::LoadModels( void )
  712. {
  713. const char *pArgVal;
  714. if( CommandLine()->CheckParm( "-rowcol", &pArgVal ) )
  715. {
  716. g_NumRows = g_NumCols = atoi( pArgVal );
  717. }
  718. /* figure out which LOD we are going to render */
  719. if( CommandLine()->CheckParm( "-lod", &pArgVal ) )
  720. {
  721. g_LOD = atoi( pArgVal );
  722. }
  723. if( CommandLine()->CheckParm( "-body", &pArgVal ) )
  724. {
  725. g_BodyGroup = atoi( pArgVal );
  726. }
  727. // figure out g_RefreshRate
  728. if( CommandLine()->CheckParm( "-refresh", &pArgVal ) )
  729. {
  730. g_RefreshRate = atoi( pArgVal );
  731. }
  732. if( CommandLine()->CheckParm( "-light", &pArgVal ) )
  733. {
  734. g_LightingCombination = atoi( pArgVal );
  735. if( g_LightingCombination < 0 )
  736. {
  737. g_LightingCombination = 0;
  738. }
  739. if( g_LightingCombination >= LIGHTING_COMBINATION_COUNT )
  740. {
  741. g_LightingCombination = LIGHTING_COMBINATION_COUNT - 1;
  742. }
  743. }
  744. g_pForceMaterial = g_pMaterialSystem->FindMaterial( "models/alyx/thigh", TEXTURE_GROUP_OTHER );
  745. #ifdef MATERIAL_OVERRIDE
  746. g_pStudioRender->ForcedMaterialOverride( g_pForceMaterial );
  747. #endif
  748. InitTestLights();
  749. if( g_BenchMode )
  750. {
  751. int i;
  752. for( i = 0; i < NUM_BENCH_RUNS; i++ )
  753. {
  754. // Load each of the potentially alternating models:
  755. int k;
  756. for( k = 0; k < g_nMaxModels; k++ )
  757. {
  758. if( g_BenchRuns[i].pModelName[k] )
  759. {
  760. if( !LoadModel( g_BenchRuns[i].pModelName[k], &g_BenchModels[i][k] ) )
  761. {
  762. return false;
  763. }
  764. }
  765. }
  766. }
  767. }
  768. else
  769. {
  770. CommandLine()->CheckParm( "-i", &pArgVal );
  771. if( !LoadModel( pArgVal, m_pIHVTestModel ) )
  772. {
  773. return false;
  774. }
  775. }
  776. g_pMaterialSystem->CacheUsedMaterials();
  777. return true;
  778. }
  779. //-----------------------------------------------------------------------------
  780. // App window proc
  781. //-----------------------------------------------------------------------------
  782. LONG CIHVTestApp::WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  783. {
  784. switch( msg )
  785. {
  786. // abort when ESC is hit
  787. case WM_CHAR:
  788. switch(wParam)
  789. {
  790. case VK_ESCAPE:
  791. SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
  792. break;
  793. }
  794. break;
  795. case WM_DESTROY:
  796. m_bExitMainLoop = true;
  797. return 0;
  798. }
  799. return DefWindowProc( hWnd, msg, wParam, lParam );
  800. }
  801. //-----------------------------------------------------------------------------
  802. // Static registered window proc
  803. //-----------------------------------------------------------------------------
  804. LONG WINAPI CIHVTestApp::WinAppWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  805. {
  806. return s_IHVTestApp.WindowProc( hWnd, uMsg, wParam, lParam );
  807. }
  808. //-----------------------------------------------------------------------------
  809. // Pump messages
  810. //-----------------------------------------------------------------------------
  811. void CIHVTestApp::AppPumpMessages()
  812. {
  813. MSG msg;
  814. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
  815. {
  816. TranslateMessage(&msg);
  817. DispatchMessage(&msg);
  818. }
  819. }
  820. //-----------------------------------------------------------------------------
  821. // Advance the frame
  822. //-----------------------------------------------------------------------------
  823. void AdvanceFrame( CStudioHdr *pStudioHdr, int iRun, int model, float dt )
  824. {
  825. if (dt > 0.1)
  826. dt = 0.1f;
  827. float t = Studio_Duration( pStudioHdr, g_BenchRuns[iRun].sequence1[model], s_PoseParameter );
  828. if (t > 0)
  829. {
  830. s_Cycle[model] += dt / t;
  831. // wrap
  832. s_Cycle[model] -= (int)(s_Cycle[model]);
  833. }
  834. else
  835. {
  836. s_Cycle[model] = 0;
  837. }
  838. }
  839. //-----------------------------------------------------------------------------
  840. // Render a frame
  841. //-----------------------------------------------------------------------------
  842. void CIHVTestApp::RenderFrame( void )
  843. {
  844. VPROF( "RenderFrame" );
  845. IHVTestModel *pModel = NULL;
  846. static int currentRun = 0;
  847. static int currentFrame = 0;
  848. static int currentLightCombo = 0;
  849. int modelAlternator = 0;
  850. if (g_bInError)
  851. {
  852. // error context is active
  853. // error may be renderer based, avoid re-entrant render to fatal crash
  854. return;
  855. }
  856. if( g_BenchMode )
  857. {
  858. if( currentFrame > g_BenchRuns[currentRun].numFrames )
  859. {
  860. currentLightCombo++;
  861. if( currentLightCombo >= LIGHTING_COMBINATION_COUNT )
  862. {
  863. currentRun++;
  864. currentLightCombo = 0;
  865. if( currentRun >= NUM_BENCH_RUNS )
  866. {
  867. g_BenchFinished = true;
  868. return;
  869. }
  870. }
  871. currentFrame = 0;
  872. }
  873. }
  874. if( g_BenchMode )
  875. {
  876. pModel = &g_BenchModels[currentRun][0];
  877. g_NumCols = g_BenchRuns[currentRun].cols;
  878. g_NumRows = g_BenchRuns[currentRun].rows;
  879. }
  880. else
  881. {
  882. pModel = m_pIHVTestModel;
  883. }
  884. Assert( pModel );
  885. g_EngineStats.BeginFrame();
  886. g_pMaterialSystem->BeginFrame( 0 );
  887. g_pStudioRender->BeginFrame();
  888. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  889. pRenderContext->ClearColor3ub( 0, 0, 0 );
  890. pRenderContext->ClearBuffers( true, true );
  891. pRenderContext->Viewport( 0, 0, g_RenderWidth, g_RenderHeight );
  892. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  893. pRenderContext->LoadIdentity();
  894. pRenderContext->PerspectiveX( 90.0f, ( g_RenderWidth / g_RenderHeight), 1.0f, 500000.0f );
  895. pRenderContext->MatrixMode( MATERIAL_VIEW );
  896. pRenderContext->LoadIdentity();
  897. if( g_BenchMode )
  898. {
  899. pRenderContext->Translate( 0.0f, 0.0f, ( float )-( g_NumCols * g_BenchRuns[currentRun].modelSize * 0.6f ) );
  900. }
  901. else
  902. {
  903. pRenderContext->Translate( 0.0f, 0.0f, ( float )-( g_NumCols * 80.0f * 0.5f ) );
  904. }
  905. pRenderContext->MatrixMode( MATERIAL_MODEL );
  906. pRenderContext->LoadIdentity();
  907. QAngle angles;
  908. angles[YAW] = -90.0f;
  909. angles[PITCH] = -90.0f;
  910. angles[ROLL] = 0.0f;
  911. matrix3x4_t cameraMatrix;
  912. AngleMatrix( angles, cameraMatrix );
  913. int r, c;
  914. int trisRendered = 0;
  915. float boneSetupTime = 0.0f;
  916. for( r = 0; r < g_NumRows; r++ )
  917. {
  918. for( c = 0; c < g_NumCols; c++ )
  919. {
  920. // If we are alternating models, select the next valid model.
  921. if( g_BenchMode )
  922. {
  923. do
  924. {
  925. // If I pass my maximum number of models, wrap around to model 0, which must always be valid.
  926. if( ++modelAlternator >= g_nMaxModels )
  927. {
  928. modelAlternator = 0;
  929. break;
  930. }
  931. }
  932. while( !g_BenchRuns[currentRun].pModelName[modelAlternator] );
  933. pModel = &g_BenchModels[currentRun][modelAlternator];
  934. Assert( pModel );
  935. }
  936. if( g_BenchMode )
  937. {
  938. cameraMatrix[0][3] = ( ( c + 0.5f ) - ( g_NumCols * .5f ) ) * g_BenchRuns[currentRun].modelSize;
  939. cameraMatrix[1][3] = ( ( float )r - ( g_NumCols * .5f ) ) * g_BenchRuns[currentRun].modelSize;
  940. }
  941. else
  942. {
  943. cameraMatrix[0][3] = ( ( c + 0.5f ) - ( g_NumCols * .5f ) ) * 75.0f;
  944. cameraMatrix[1][3] = ( ( float )r - ( g_NumCols * .5f ) ) * 75.0f;
  945. }
  946. Vector modelOrigin( cameraMatrix[0][3], cameraMatrix[1][3], 0.0f );
  947. Vector lightOffset( cameraMatrix[0][3], cameraMatrix[1][3], 0.0f );
  948. if (g_LightingCombination < 0)
  949. {
  950. SetupLighting( g_BenchMode ? currentLightCombo : 0, lightOffset );
  951. }
  952. else
  953. {
  954. SetupLighting( g_LightingCombination, lightOffset );
  955. }
  956. float startBoneSetupTime = Sys_FloatTime();
  957. int lod = g_LOD;
  958. lod = clamp( lod, pModel->pHardwareData->m_RootLOD, pModel->pHardwareData->m_NumLODs-1 );
  959. int boneMask = BONE_USED_BY_VERTEX_AT_LOD( lod );
  960. matrix3x4_t *pBoneToWorld = SetUpBones( pModel->pStudioHdr, cameraMatrix, currentRun, modelAlternator, boneMask );
  961. boneSetupTime += Sys_FloatTime() - startBoneSetupTime;
  962. pRenderContext->MatrixMode( MATERIAL_MODEL );
  963. pRenderContext->PushMatrix();
  964. DrawModelInfo_t modelInfo;
  965. memset( &modelInfo, 0, sizeof( modelInfo ) );
  966. modelInfo.m_pStudioHdr = pModel->pStudioHdr;
  967. modelInfo.m_pHardwareData = pModel->pHardwareData;
  968. modelInfo.m_Decals = STUDIORENDER_DECAL_INVALID;
  969. modelInfo.m_Skin = 0;
  970. modelInfo.m_Body = g_BodyGroup;
  971. modelInfo.m_HitboxSet = 0;
  972. modelInfo.m_pClientEntity = NULL;
  973. modelInfo.m_Lod = lod;
  974. modelInfo.m_pColorMeshes = NULL;
  975. g_pStudioRender->DrawModel( NULL, modelInfo, pBoneToWorld, NULL, NULL, modelOrigin );
  976. DrawModelResults_t results;
  977. g_pStudioRender->GetPerfStats( &results, modelInfo, NULL );
  978. trisRendered += results.m_ActualTriCount;
  979. pRenderContext->MatrixMode( MATERIAL_MODEL );
  980. pRenderContext->PopMatrix();
  981. }
  982. }
  983. pRenderContext->Flush( true );
  984. g_EngineStats.EndFrame();
  985. g_pStudioRender->EndFrame();
  986. g_pMaterialSystem->EndFrame();
  987. // hack - don't count the first frame in case there are any state
  988. // transitions computed on that frame.
  989. if( currentFrame != 0 )
  990. {
  991. g_BenchResults[currentRun][currentLightCombo].totalTime += g_EngineStats.GetCurrentSystemFrameTime();
  992. g_BenchResults[currentRun][currentLightCombo].totalTris += trisRendered;
  993. }
  994. for ( int model = 0; model < g_nMaxModels; ++model )
  995. {
  996. CStudioHdr studioHdr( g_BenchModels[currentRun][model].pStudioHdr, g_pMDLCache );
  997. AdvanceFrame( &studioHdr, currentRun, model, g_EngineStats.GetCurrentSystemFrameTime() );
  998. }
  999. g_pMaterialSystem->SwapBuffers();
  1000. #ifdef USE_VPROF
  1001. g_VProfCurrentProfile.MarkFrame();
  1002. static bool bBeenHere = false;
  1003. if( !bBeenHere )
  1004. {
  1005. bBeenHere = true;
  1006. g_VProfCurrentProfile.Reset();
  1007. }
  1008. #endif
  1009. currentFrame++;
  1010. }
  1011. //-----------------------------------------------------------------------------
  1012. // Create the application object
  1013. //-----------------------------------------------------------------------------
  1014. bool CIHVTestApp::Create()
  1015. {
  1016. AppSystemInfo_t appSystems[] =
  1017. {
  1018. { "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
  1019. { "datacache.dll", DATACACHE_INTERFACE_VERSION },
  1020. { "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
  1021. { "datacache.dll", MDLCACHE_INTERFACE_VERSION },
  1022. { "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
  1023. { "", "" } // Required to terminate the list
  1024. };
  1025. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
  1026. if ( !AddSystems( appSystems ) )
  1027. return false;
  1028. g_pFileSystem = ( IFileSystem * )FindSystem( FILESYSTEM_INTERFACE_VERSION );
  1029. g_pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
  1030. g_pStudioRender = (IStudioRender*)FindSystem( STUDIO_RENDER_INTERFACE_VERSION );
  1031. g_pMDLCache = (IMDLCache*)FindSystem( MDLCACHE_INTERFACE_VERSION );
  1032. if ( !g_pFileSystem || !g_pMaterialSystem || !g_pStudioRender || !g_pMDLCache )
  1033. {
  1034. DisplayError( "Unable to load required library interfaces!" );
  1035. return false;
  1036. }
  1037. #if defined( _X360 )
  1038. // vxconsole - true will block (legacy behavior)
  1039. XBX_InitConsoleMonitor( false );
  1040. #endif
  1041. const char* pDLLName;
  1042. if ( CommandLine()->CheckParm( "-null" ) )
  1043. {
  1044. g_bUseEmptyShader = true;
  1045. pDLLName = "shaderapiempty.dll";
  1046. }
  1047. else
  1048. {
  1049. pDLLName = "shaderapidx9.dll";
  1050. }
  1051. #if defined( _X360 )
  1052. g_pFileSystem->LoadModule( pDLLName );
  1053. #endif
  1054. g_pMaterialSystem->SetShaderAPI( pDLLName );
  1055. return true;
  1056. }
  1057. //-----------------------------------------------------------------------------
  1058. // StudioRender...
  1059. //-----------------------------------------------------------------------------
  1060. bool CIHVTestApp::SetupStudioRender( void )
  1061. {
  1062. StudioRenderConfig_t config;
  1063. memset( &config, 0, sizeof(config) );
  1064. config.bEyeMove = true;
  1065. config.bTeeth = true;
  1066. config.bEyes = true;
  1067. config.bFlex = true;
  1068. config.fEyeShiftX = 0.0f;
  1069. config.fEyeShiftY = 0.0f;
  1070. config.fEyeShiftZ = 0.0f;
  1071. config.fEyeSize = 0.0f;
  1072. config.bNoHardware = false;
  1073. config.bNoSoftware = false;
  1074. config.bSoftwareSkin = false;
  1075. config.bSoftwareLighting = false;
  1076. config.drawEntities = true;
  1077. config.bWireframe = false;
  1078. config.bDrawNormals = false;
  1079. config.bDrawTangentFrame = false;
  1080. config.skin = 0;
  1081. config.fullbright = 0;
  1082. config.bShowEnvCubemapOnly = false;
  1083. g_pStudioRender->UpdateConfig( config );
  1084. return true;
  1085. }
  1086. //-----------------------------------------------------------------------------
  1087. // Material system
  1088. //-----------------------------------------------------------------------------
  1089. bool InitMaterialSystem( HWND mainWindow )
  1090. {
  1091. MaterialSystem_Config_t config;
  1092. if( g_WindowMode )
  1093. {
  1094. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  1095. }
  1096. config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, IsX360() ? 0 : true );
  1097. config.m_VideoMode.m_Width = 0;
  1098. config.m_VideoMode.m_Height = 0;
  1099. config.m_VideoMode.m_Format = IMAGE_FORMAT_BGRX8888;
  1100. config.m_VideoMode.m_RefreshRate = g_RefreshRate;
  1101. config.dxSupportLevel = IsX360() ? 98 : 0;
  1102. bool modeSet = g_pMaterialSystem->SetMode( (void*)mainWindow, config );
  1103. if (!modeSet)
  1104. {
  1105. DisplayError( "Unable to set mode\n" );
  1106. return false;
  1107. }
  1108. g_pMaterialSystem->OverrideConfig( config, false );
  1109. return true;
  1110. }
  1111. //-----------------------------------------------------------------------------
  1112. // PreInit
  1113. //-----------------------------------------------------------------------------
  1114. bool CIHVTestApp::PreInit( void )
  1115. {
  1116. CreateInterfaceFn factory = GetFactory();
  1117. ConnectTier1Libraries( &factory, 1 );
  1118. // Add paths...
  1119. if ( !SetupSearchPaths( NULL, false, true ) )
  1120. {
  1121. Error( "Failed to setup search paths\n" );
  1122. return false;
  1123. }
  1124. const char *pArgVal;
  1125. if ( CommandLine()->CheckParm( "-bench" ) )
  1126. {
  1127. g_BenchMode = true;
  1128. }
  1129. if( !g_BenchMode && !CommandLine()->CheckParm( "-i" ) )
  1130. {
  1131. // Set some default parameters for running as a unittest
  1132. g_BenchMode = true;
  1133. g_WindowMode = IsPC() ? true : false;
  1134. }
  1135. if( g_BenchMode )
  1136. {
  1137. if ( CommandLine()->CheckParm( "-i", &pArgVal ) )
  1138. {
  1139. g_BenchRuns[0].pModelName[0] = pArgVal;
  1140. }
  1141. }
  1142. if( CommandLine()->CheckParm( "-softwaretl" ) )
  1143. {
  1144. g_SoftwareTL = true;
  1145. }
  1146. // Explicitly in window/fullscreen mode?
  1147. if ( CommandLine()->CheckParm( "-window") )
  1148. {
  1149. g_WindowMode = true;
  1150. }
  1151. else if ( CommandLine()->CheckParm( "-fullscreen" ) )
  1152. {
  1153. g_WindowMode = false;
  1154. }
  1155. /* figure out g_Renderwidth and g_RenderHeight */
  1156. g_RenderWidth = -1;
  1157. g_RenderHeight = -1;
  1158. if( CommandLine()->CheckParm( "-width", &pArgVal ) )
  1159. {
  1160. g_RenderWidth = atoi( pArgVal );
  1161. }
  1162. if( CommandLine()->CheckParm( "-height", &pArgVal ) )
  1163. {
  1164. g_RenderHeight = atoi( pArgVal );
  1165. }
  1166. if( g_RenderWidth == -1 && g_RenderHeight == -1 )
  1167. {
  1168. g_RenderWidth = 640;
  1169. g_RenderHeight = 480;
  1170. }
  1171. else if( g_RenderWidth != -1 && g_RenderHeight == -1 )
  1172. {
  1173. switch( g_RenderWidth )
  1174. {
  1175. case 320:
  1176. g_RenderHeight = 240;
  1177. break;
  1178. case 512:
  1179. g_RenderHeight = 384;
  1180. break;
  1181. case 640:
  1182. g_RenderHeight = 480;
  1183. break;
  1184. case 800:
  1185. g_RenderHeight = 600;
  1186. break;
  1187. case 1024:
  1188. g_RenderHeight = 768;
  1189. break;
  1190. case 1280:
  1191. g_RenderHeight = 1024;
  1192. break;
  1193. case 1600:
  1194. g_RenderHeight = 1200;
  1195. break;
  1196. default:
  1197. DisplayError( "Can't figure out window dimensions!!" );
  1198. exit( -1 );
  1199. break;
  1200. }
  1201. }
  1202. if( g_RenderWidth == -1 || g_RenderHeight == -1 )
  1203. {
  1204. DisplayError( "Can't figure out window dimensions!!" );
  1205. exit( -1 );
  1206. }
  1207. int windowWidth, windowHeight;
  1208. CalcWindowSize( g_RenderWidth, g_RenderHeight, &windowWidth, &windowHeight );
  1209. if( !CreateAppWindow( "ihvtest1", windowWidth, windowHeight ) )
  1210. {
  1211. return false;
  1212. }
  1213. return true;
  1214. }
  1215. void CIHVTestApp::PostShutdown()
  1216. {
  1217. DisconnectTier1Libraries();
  1218. }
  1219. //-----------------------------------------------------------------------------
  1220. // The application main loop
  1221. //-----------------------------------------------------------------------------
  1222. int CIHVTestApp::Main()
  1223. {
  1224. SpewOutputFunc( IHVTestSpewFunc );
  1225. if ( !SetupStudioRender() )
  1226. {
  1227. return 0;
  1228. }
  1229. if ( !InitMaterialSystem( m_hWnd ) )
  1230. {
  1231. return 0;
  1232. }
  1233. #if !defined( _X360 ) // X360TBD:
  1234. extern void Sys_InitFloatTime( void ); //garymcthack
  1235. Sys_InitFloatTime();
  1236. #endif
  1237. LoadModels();
  1238. #if USE_VTUNE
  1239. VTResume();
  1240. #endif
  1241. #ifdef USE_VPROF
  1242. g_VProfCurrentProfile.Start();
  1243. #endif
  1244. bool m_bExitMainLoop = false;
  1245. while (!m_bExitMainLoop && !g_BenchFinished)
  1246. {
  1247. AppPumpMessages();
  1248. RenderFrame();
  1249. }
  1250. #ifdef USE_VPROF
  1251. g_VProfCurrentProfile.Stop();
  1252. #endif
  1253. g_IHVTestFP = fopen( "ihvtest_vprof.txt", "w" );
  1254. #ifdef USE_VPROF
  1255. SpewOutputFunc( IHVTestVProfSpewFunc );
  1256. g_VProfCurrentProfile.OutputReport( VPRT_SUMMARY );
  1257. g_VProfCurrentProfile.OutputReport( VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY );
  1258. fclose( g_IHVTestFP );
  1259. SpewOutputFunc( IHVTestSpewFunc );
  1260. #endif
  1261. #if USE_VTUNE
  1262. VTPause();
  1263. #endif
  1264. return 0;
  1265. }