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.

406 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. // traceperf.cpp : Defines the entry point for the console application.
  3. //
  4. #include "stdafx.h"
  5. #include "gametrace.h"
  6. #include "fmtstr.h"
  7. #include "appframework/appframework.h"
  8. #include "filesystem.h"
  9. #include "filesystem_init.h"
  10. #include "tier1/tier1.h"
  11. #include "tier2/tier2.h"
  12. #include "tier3/tier3.h"
  13. IPhysicsCollision *physcollision = NULL;
  14. #define NUM_COLLISION_TESTS 2500
  15. void ReadPHYFile(const char *name, vcollide_t &collide )
  16. {
  17. FileHandle_t fp = g_pFullFileSystem->Open(name, "rb");
  18. if (!fp)
  19. Error ("Couldn't open %s", name);
  20. phyheader_t header;
  21. g_pFullFileSystem->Read( &header, sizeof(header), fp );
  22. if ( header.size != sizeof(header) || header.solidCount <= 0 )
  23. return;
  24. int fileSize = g_pFullFileSystem->Size(fp);
  25. char *buf = (char *)_alloca( fileSize );
  26. g_pFullFileSystem->Read( buf, fileSize, fp );
  27. g_pFullFileSystem->Close( fp );
  28. physcollision->VCollideLoad( &collide, header.solidCount, (const char *)buf, fileSize );
  29. }
  30. struct testlist_t
  31. {
  32. Vector start;
  33. Vector end;
  34. Vector normal;
  35. bool hit;
  36. };
  37. struct benchresults_t
  38. {
  39. int collisionTests;
  40. int collisionHits;
  41. float totalTime;
  42. float rayTime;
  43. float boxTime;
  44. };
  45. testlist_t g_Traces[NUM_COLLISION_TESTS];
  46. void Benchmark_PHY( const CPhysCollide *pCollide, benchresults_t *pOut )
  47. {
  48. int i;
  49. Vector start = vec3_origin;
  50. static Vector *targets = NULL;
  51. static bool first = true;
  52. static float test[2] = {1,1};
  53. if ( first )
  54. {
  55. float radius = 0;
  56. float theta = 0;
  57. float phi = 0;
  58. for ( int i = 0; i < NUM_COLLISION_TESTS; i++ )
  59. {
  60. radius += NUM_COLLISION_TESTS * 123.123f;
  61. radius = fabs(fmod(radius, 128));
  62. theta += NUM_COLLISION_TESTS * 0.76f;
  63. theta = fabs(fmod(theta, DEG2RAD(360)));
  64. phi += NUM_COLLISION_TESTS * 0.16666666f;
  65. phi = fabs(fmod(phi, DEG2RAD(180)));
  66. float st, ct, sp, cp;
  67. SinCos( theta, &st, &ct );
  68. SinCos( phi, &sp, &cp );
  69. st = sin(theta);
  70. ct = cos(theta);
  71. sp = sin(phi);
  72. cp = cos(phi);
  73. g_Traces[i].start.x = radius * ct * sp;
  74. g_Traces[i].start.y = radius * st * sp;
  75. g_Traces[i].start.z = radius * cp;
  76. }
  77. first = false;
  78. }
  79. float duration = 0;
  80. Vector size[2];
  81. size[0].Init(0,0,0);
  82. size[1].Init(16,16,16);
  83. #if VPROF_LEVEL > 0
  84. g_VProfCurrentProfile.Reset();
  85. g_VProfCurrentProfile.ResetPeaks();
  86. g_VProfCurrentProfile.Start();
  87. #endif
  88. #if TEST_BBOX
  89. Vector mins, maxs;
  90. physcollision->CollideGetAABB( &mins, &maxs, pCollide, Vector(-500, 200, -100), vec3_angle );
  91. Vector extents = maxs - mins;
  92. Vector center = 0.5f * (maxs+mins);
  93. Msg("bbox: %.2f,%.2f, %.2f @ %.2f, %.2f, %.2f\n", extents.x, extents.y, extents.z, center.x, center.y, center.z );
  94. #endif
  95. unsigned int hitCount = 0;
  96. double startTime = Plat_FloatTime();
  97. trace_t tr;
  98. for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
  99. {
  100. physcollision->TraceBox( g_Traces[i].start, start, -size[0], size[0], pCollide, vec3_origin, vec3_angle, &tr );
  101. if ( tr.DidHit() )
  102. {
  103. g_Traces[i].end = tr.endpos;
  104. g_Traces[i].normal = tr.plane.normal;
  105. g_Traces[i].hit = true;
  106. hitCount++;
  107. }
  108. else
  109. {
  110. g_Traces[i].hit = false;
  111. }
  112. }
  113. for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
  114. {
  115. physcollision->TraceBox( g_Traces[i].start, start, -size[1], size[1], pCollide, vec3_origin, vec3_angle, &tr );
  116. }
  117. duration = Plat_FloatTime() - startTime;
  118. #if VPROF_LEVEL > 0
  119. g_VProfCurrentProfile.MarkFrame();
  120. g_VProfCurrentProfile.Stop();
  121. g_VProfCurrentProfile.Reset();
  122. g_VProfCurrentProfile.ResetPeaks();
  123. g_VProfCurrentProfile.Start();
  124. #endif
  125. hitCount = 0;
  126. startTime = Plat_FloatTime();
  127. for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
  128. {
  129. physcollision->TraceBox( g_Traces[i].start, start, -size[0], size[0], pCollide, vec3_origin, vec3_angle, &tr );
  130. if ( tr.DidHit() )
  131. {
  132. g_Traces[i].end = tr.endpos;
  133. g_Traces[i].normal = tr.plane.normal;
  134. g_Traces[i].hit = true;
  135. hitCount++;
  136. }
  137. else
  138. {
  139. g_Traces[i].hit = false;
  140. }
  141. #if VPROF_LEVEL > 0
  142. g_VProfCurrentProfile.MarkFrame();
  143. #endif
  144. }
  145. double midTime = Plat_FloatTime();
  146. for ( i = 0; i < NUM_COLLISION_TESTS; i++ )
  147. {
  148. physcollision->TraceBox( g_Traces[i].start, start, -size[1], size[1], pCollide, vec3_origin, vec3_angle, &tr );
  149. #if VPROF_LEVEL > 0
  150. g_VProfCurrentProfile.MarkFrame();
  151. #endif
  152. }
  153. double endTime = Plat_FloatTime();
  154. duration = endTime - startTime;
  155. pOut->collisionTests = NUM_COLLISION_TESTS;
  156. pOut->collisionHits = hitCount;
  157. pOut->totalTime = duration * 1000.0f;
  158. pOut->rayTime = (midTime - startTime) * 1000.0f;
  159. pOut->boxTime = (endTime - midTime)*1000.0f;
  160. #if VPROF_LEVEL > 0
  161. g_VProfCurrentProfile.Stop();
  162. g_VProfCurrentProfile.OutputReport( VPRT_FULL & ~VPRT_HIERARCHY, NULL );
  163. #endif
  164. }
  165. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  166. //
  167. // Purpose:
  168. //
  169. // $NoKeywords: $
  170. //
  171. //===========================================================================//
  172. //-----------------------------------------------------------------------------
  173. // The application object
  174. //-----------------------------------------------------------------------------
  175. class CBenchmarkApp : public CDefaultAppSystemGroup< CSteamAppSystemGroup >
  176. {
  177. typedef CDefaultAppSystemGroup< CSteamAppSystemGroup > BaseClass;
  178. public:
  179. // Methods of IApplication
  180. virtual bool Create();
  181. virtual bool PreInit( );
  182. virtual int Main();
  183. virtual void PostShutdown();
  184. bool SetupSearchPaths();
  185. private:
  186. bool ParseArguments();
  187. };
  188. DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( CBenchmarkApp );
  189. //-----------------------------------------------------------------------------
  190. // The application object
  191. //-----------------------------------------------------------------------------
  192. bool CBenchmarkApp::Create()
  193. {
  194. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
  195. // Add in the cvar factory
  196. //AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() );
  197. //AddSystem( cvarModule, VENGINE_CVAR_INTERFACE_VERSION );
  198. AppSystemInfo_t appSystems[] =
  199. {
  200. { "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
  201. { "", "" } // Required to terminate the list
  202. };
  203. bool bRet = AddSystems( appSystems );
  204. if ( bRet )
  205. {
  206. physcollision = (IPhysicsCollision*)FindSystem( VPHYSICS_COLLISION_INTERFACE_VERSION );
  207. if ( !physcollision )
  208. return false;
  209. }
  210. return bRet;
  211. }
  212. bool CBenchmarkApp::SetupSearchPaths()
  213. {
  214. CFSSteamSetupInfo steamInfo;
  215. steamInfo.m_pDirectoryName = NULL;
  216. steamInfo.m_bOnlyUseDirectoryName = false;
  217. steamInfo.m_bToolsMode = true;
  218. steamInfo.m_bSetSteamDLLPath = true;
  219. steamInfo.m_bSteam = g_pFullFileSystem->IsSteam();
  220. if ( FileSystem_SetupSteamEnvironment( steamInfo ) != FS_OK )
  221. return false;
  222. CFSMountContentInfo fsInfo;
  223. fsInfo.m_pFileSystem = g_pFullFileSystem;
  224. fsInfo.m_bToolsMode = true;
  225. fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath;
  226. if ( FileSystem_MountContent( fsInfo ) != FS_OK )
  227. return false;
  228. // Finally, load the search paths for the "GAME" path.
  229. CFSSearchPathsInit searchPathsInit;
  230. searchPathsInit.m_pDirectoryName = steamInfo.m_GameInfoPath;
  231. searchPathsInit.m_pFileSystem = g_pFullFileSystem;
  232. if ( FileSystem_LoadSearchPaths( searchPathsInit ) != FS_OK )
  233. return false;
  234. g_pFullFileSystem->AddSearchPath( steamInfo.m_GameInfoPath, "SKIN", PATH_ADD_TO_HEAD );
  235. FileSystem_AddSearchPath_Platform( g_pFullFileSystem, steamInfo.m_GameInfoPath );
  236. return true;
  237. }
  238. bool CBenchmarkApp::PreInit( )
  239. {
  240. CreateInterfaceFn factory = GetFactory();
  241. ConnectTier1Libraries( &factory, 1 );
  242. ConnectTier2Libraries( &factory, 1 );
  243. ConnectTier3Libraries( &factory, 1 );
  244. if ( !g_pFullFileSystem || !physcollision )
  245. {
  246. Warning( "benchmark is missing a required interface!\n" );
  247. return false;
  248. }
  249. return SetupSearchPaths();//( NULL, false, true );
  250. }
  251. void CBenchmarkApp::PostShutdown()
  252. {
  253. DisconnectTier3Libraries();
  254. DisconnectTier2Libraries();
  255. DisconnectTier1Libraries();
  256. }
  257. struct baseline_t
  258. {
  259. float total;
  260. float ray;
  261. float box;
  262. };
  263. // current baseline measured on Core2DuoE6600
  264. baseline_t g_Baselines[] =
  265. {
  266. { 40.56f, 10.64f, 29.92f}, // bench01a.phy
  267. { 38.13f, 10.76f, 27.37f }, // bicycle01a.phy
  268. { 25.46f, 8.34f, 17.13f }, // furnituretable001a.phy
  269. { 12.65f, 6.02f, 6.62f }, // gravestone003a.phy
  270. { 40.58f, 16.49f, 24.10f }, // combineinnerwall001a.phy
  271. };
  272. const float g_TotalBaseline = 157.38f;
  273. /*
  274. Benchmark models\props_c17\bench01a.phy!
  275. 33.90 ms [1.20 X] 2500/2500 hits
  276. 8.95 ms rays [1.19 X] 24.95 ms boxes [1.20 X]
  277. Benchmark models\props_junk\bicycle01a.phy!
  278. 30.55 ms [1.25 X] 803/2500 hits
  279. 8.96 ms rays [1.20 X] 21.59 ms boxes [1.27 X]
  280. Benchmark models\props_c17\furnituretable001a.phy!
  281. 20.61 ms [1.24 X] 755/2500 hits
  282. 6.88 ms rays [1.21 X] 13.73 ms boxes [1.25 X]
  283. Benchmark models\props_c17\gravestone003a.phy!
  284. 9.13 ms [1.39 X] 2500/2500 hits
  285. 4.34 ms rays [1.39 X] 4.79 ms boxes [1.38 X]
  286. Benchmark models\props_combine\combineinnerwall001a.phy!
  287. 33.04 ms [1.23 X] 985/2500 hits
  288. 13.37 ms rays [1.23 X] 19.67 ms boxes [1.23 X]
  289. 127.22s total [1.24 X]!
  290. */
  291. #define IMPROVEMENT_FACTOR(x,baseline) (baseline/(x))
  292. #define IMPROVEMENT_PERCENT(x,baseline) (((baseline-(x)) / baseline) * 100.0f)
  293. #include <windows.h>
  294. //-----------------------------------------------------------------------------
  295. // The application object
  296. //-----------------------------------------------------------------------------
  297. int CBenchmarkApp::Main()
  298. {
  299. const char *pFileNames[] =
  300. {
  301. "models\\props_c17\\bench01a.phy",
  302. "models\\props_junk\\bicycle01a.phy",
  303. "models\\props_c17\\furnituretable001a.phy",
  304. "models\\props_c17\\gravestone003a.phy",
  305. "models\\props_combine\\combineinnerwall001a.phy",
  306. };
  307. vcollide_t testModels[ARRAYSIZE(pFileNames)];
  308. for ( int i = 0; i < ARRAYSIZE(pFileNames); i++ )
  309. {
  310. ReadPHYFile( pFileNames[i], testModels[i] );
  311. }
  312. SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS );
  313. SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST );
  314. float totalTime = 0.0f;
  315. int loopCount = ARRAYSIZE(pFileNames);
  316. #if VPROF_LEVEL > 0
  317. // loopCount = 3;
  318. #endif
  319. for ( int i = 0; i < loopCount; i++ )
  320. {
  321. if ( testModels[i].solidCount < 1 )
  322. {
  323. Msg("Failed to load %s, skipping test!\n", pFileNames[i] );
  324. continue;
  325. }
  326. Msg("Benchmark %s!\n\n", pFileNames[i] );
  327. benchresults_t results;
  328. memset( &results, 0, sizeof(results));
  329. int numRepeats = 3;
  330. #if VPROF_LEVEL > 0
  331. numRepeats = 1;
  332. #endif
  333. for ( int j = 0; j < numRepeats; j++ )
  334. {
  335. Benchmark_PHY( testModels[i].solids[0], &results );
  336. }
  337. Msg("%.2f ms [%.2f X] %d/%d hits\n", results.totalTime, IMPROVEMENT_FACTOR(results.totalTime, g_Baselines[i].total), results.collisionHits, results.collisionTests);
  338. Msg("%.2f ms rays \t[%.2f X] \t%.2f ms boxes [%.2f X]\n",
  339. results.rayTime, IMPROVEMENT_FACTOR(results.rayTime, g_Baselines[i].ray),
  340. results.boxTime, IMPROVEMENT_FACTOR(results.boxTime, g_Baselines[i].box));
  341. totalTime += results.totalTime;
  342. }
  343. SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
  344. Msg("\n%.2fs total \t[%.2f X]!\n", totalTime, IMPROVEMENT_FACTOR(totalTime, g_TotalBaseline) );
  345. return 0;
  346. }