1509 lines
38 KiB
C++
1509 lines
38 KiB
C++
//========= 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( <ime );
|
|
|
|
fprintf( fp, "%s\n", GetCommandLine() );
|
|
fprintf( fp, "Run at: %s", ctime( <ime ) );
|
|
|
|
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;
|
|
}
|
|
|