Counter Strike : Global Offensive Source Code
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.

1879 lines
61 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "shadersystem.h"
  7. #include <stdlib.h>
  8. #include "materialsystem_global.h"
  9. #include "filesystem.h"
  10. #include "tier1/utldict.h"
  11. #include "shaderlib/ShaderDLL.h"
  12. #include "texturemanager.h"
  13. #include "itextureinternal.h"
  14. #include "IHardwareConfigInternal.h"
  15. #include "tier1/utlstack.h"
  16. #include "tier1/utlbuffer.h"
  17. #include "mathlib/vmatrix.h"
  18. #include "imaterialinternal.h"
  19. #include "tier1/strtools.h"
  20. #include "tier0/icommandline.h"
  21. #include "shaderlib/cshader.h"
  22. #include "tier1/convar.h"
  23. #include "tier1/keyvalues.h"
  24. #include "shader_dll_verify.h"
  25. #include "tier0/vprof.h"
  26. #include "tier1/tier1_logging.h"
  27. // NOTE: This must be the last file included!
  28. #include "tier0/memdbgon.h"
  29. #if defined( _PS3 ) || defined( _OSX )
  30. #define g_pShaderAPI ShaderAPI()
  31. #define ShaderApiParam( x ) g_pShaderAPIDX8
  32. #else
  33. #define ShaderApiParam( x ) x
  34. #endif
  35. //#define DEBUG_DEPTH 1
  36. //-----------------------------------------------------------------------------
  37. // Lovely convars
  38. //-----------------------------------------------------------------------------
  39. static ConVar mat_showenvmapmask( "mat_showenvmapmask", "0" );
  40. static ConVar mat_debugdepth( "mat_debugdepth", "0" );
  41. extern ConVar mat_supportflashlight;
  42. //-----------------------------------------------------------------------------
  43. // Implementation of the shader system
  44. //-----------------------------------------------------------------------------
  45. class CShaderSystem : public IShaderSystemInternal
  46. {
  47. public:
  48. CShaderSystem();
  49. // Methods of IShaderSystem
  50. virtual ShaderAPITextureHandle_t GetShaderAPITextureBindHandle( ITexture *pTexture, int nFrameVar, int nTextureChannel = 0 );
  51. virtual void BindTexture( Sampler_t sampler1, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame = 0 );
  52. virtual void BindTexture( Sampler_t sampler1, Sampler_t sampler2, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame = 0 );
  53. virtual void BindVertexTexture( VertexTextureSampler_t vtSampler, ITexture *pTexture, int nFrame = 0 );
  54. virtual void TakeSnapshot( );
  55. virtual void DrawSnapshot( const unsigned char *pInstanceCommandBuffer, bool bMakeActualDrawCall = true );
  56. virtual bool IsUsingGraphics() const;
  57. // Methods of IShaderSystemInternal
  58. virtual void Init();
  59. virtual void Shutdown();
  60. virtual void ModInit();
  61. virtual void ModShutdown();
  62. virtual bool LoadShaderDLL( const char *pFullPath );
  63. virtual bool LoadShaderDLL( const char *pFullPath, const char *pPathID, bool bModShaderDLL );
  64. virtual void UnloadShaderDLL( const char *pFullPath );
  65. virtual IShader* FindShader( char const* pShaderName );
  66. virtual void CreateDebugMaterials();
  67. virtual void CleanUpDebugMaterials();
  68. virtual char const* ShaderStateString( int i ) const;
  69. virtual int ShaderStateCount( ) const;
  70. virtual void InitShaderParameters( IShader *pShader, IMaterialVar **params, const char *pMaterialName );
  71. virtual void InitShaderInstance( IShader *pShader, IMaterialVar **params, const char *pMaterialName, const char *pTextureGroupName );
  72. virtual bool InitRenderState( IShader *pShader, int numParams, IMaterialVar **params, ShaderRenderState_t* pRenderState, char const* pMaterialName );
  73. virtual void CleanupRenderState( ShaderRenderState_t* pRenderState );
  74. virtual void DrawElements( IShader *pShader, IMaterialVar **params, ShaderRenderState_t* pShaderState, VertexCompressionType_t vertexCompression, uint32 nVarChangeID, uint32 nModulationFlags, bool bRenderingPreTessPatchMesh );
  75. // Used to iterate over all shaders for editing purposes
  76. virtual int ShaderCount() const;
  77. virtual int GetShaders( int nFirstShader, int nMaxCount, IShader **ppShaderList ) const;
  78. // Methods of IShaderInit
  79. virtual void LoadTexture( IMaterialVar *pTextureVar, const char *pTextureGroupName, int nAdditionalCreationFlags = 0 );
  80. virtual void LoadBumpMap( IMaterialVar *pTextureVar, const char *pTextureGroupName, int nAdditionalCreationFlags = 0 );
  81. virtual void LoadCubeMap( IMaterialVar **ppParams, IMaterialVar *pTextureVar, int nAdditionalCreationFlags = 0 );
  82. bool CanUseEditorMaterials() const;
  83. virtual void AddShaderComboInformation( const ShaderComboSemantics_t *pSemantics );
  84. private:
  85. struct ShaderDLLInfo_t
  86. {
  87. char *m_pFileName;
  88. CSysModule *m_hInstance;
  89. IShaderDLLInternal *m_pShaderDLL;
  90. ShaderDLL_t m_hShaderDLL;
  91. // True if this is a mod's shader DLL, in which case it's not allowed to
  92. // override any existing shader names.
  93. bool m_bModShaderDLL;
  94. CUtlDict< IShader *, unsigned short > m_ShaderDict;
  95. };
  96. private:
  97. // Load up the shader DLLs...
  98. void LoadAllShaderDLLs();
  99. // Load the "mshader_" DLLs.
  100. void LoadModShaderDLLs( int dxSupportLevel );
  101. // Unload all the shader DLLs...
  102. void UnloadAllShaderDLLs();
  103. // Sets up the shader dictionary.
  104. void SetupShaderDictionary( int nShaderDLLIndex );
  105. // Cleans up the shader dictionary.
  106. void CleanupShaderDictionary( int nShaderDLLIndex );
  107. // Finds an already loaded shader DLL
  108. int FindShaderDLL( const char *pFullPath );
  109. // Unloads a particular shader DLL
  110. void UnloadShaderDLL( int nShaderDLLIndex );
  111. // Sets up the current ShaderState_t for rendering
  112. void PrepForShaderDraw( IShader *pShader, IMaterialVar** ppParams,
  113. ShaderRenderState_t* pRenderState, int modulation );
  114. void DoneWithShaderDraw();
  115. // Initializes state snapshots
  116. void InitStateSnapshots( IShader *pShader, IMaterialVar **params, ShaderRenderState_t* pRenderState );
  117. // Compute snapshots for all combinations of alpha + color modulation
  118. void InitRenderStateFlags( ShaderRenderState_t* pRenderState, int numParams, IMaterialVar **params );
  119. // Computes flags from a particular snapshot
  120. void ComputeRenderStateFlagsFromSnapshot( ShaderRenderState_t* pRenderState );
  121. // Computes vertex format + usage from a particular snapshot
  122. bool ComputeVertexFormatFromSnapshot( IMaterialVar **params, ShaderRenderState_t* pRenderState );
  123. // Gets at the current snapshot
  124. StateSnapshot_t CurrentStateSnapshot();
  125. // Draws using a particular material..
  126. void DrawUsingMaterial( IMaterialInternal *pMaterial, VertexCompressionType_t vertexCompression );
  127. // Copies material vars
  128. void CopyMaterialVarToDebugShader( IMaterialInternal *pDebugMaterial, IShader *pShader, IMaterialVar **ppParams, const char *pSrcVarName, const char *pDstVarName = NULL );
  129. // Debugging draw methods...
  130. void DrawMeasureFillRate( ShaderRenderState_t* pRenderState, int mod, VertexCompressionType_t vertexCompression );
  131. void DrawNormalMap( IShader *pShader, IMaterialVar **ppParams, VertexCompressionType_t vertexCompression );
  132. bool DrawEnvmapMask( IShader *pShader, IMaterialVar **ppParams, ShaderRenderState_t* pRenderState, VertexCompressionType_t vertexCompression );
  133. int GetModulationSnapshotCount( IMaterialVar **params );
  134. private:
  135. // List of all DLLs containing shaders
  136. CUtlVector< ShaderDLLInfo_t > m_ShaderDLLs;
  137. // Used to prevent re-entrant rendering from warning messages.
  138. CBufferedLoggingListener m_BufferedLoggingListener;
  139. // Causes Log_Error() to break into debugger instead of exiting.
  140. CNonFatalLoggingResponsePolicy m_NonFatalLoggingResponsePolicy;
  141. // Render state we're drawing with
  142. ShaderRenderState_t* m_pRenderState;
  143. unsigned short m_hShaderDLL;
  144. unsigned char m_nModulation;
  145. unsigned char m_nRenderPass;
  146. // Debugging materials
  147. // If you add to this, add to the list of debug shader names (s_pDebugShaderName) below
  148. enum
  149. {
  150. MATERIAL_FILL_RATE = 0,
  151. MATERIAL_DEBUG_NORMALMAP,
  152. MATERIAL_DEBUG_ENVMAPMASK,
  153. MATERIAL_DEBUG_DEPTH,
  154. MATERIAL_DEBUG_DEPTH_DECAL,
  155. MATERIAL_DEBUG_WIREFRAME,
  156. MATERIAL_DEBUG_COUNT,
  157. };
  158. IMaterialInternal* m_pDebugMaterials[MATERIAL_DEBUG_COUNT];
  159. static const char *s_pDebugShaderName[MATERIAL_DEBUG_COUNT];
  160. bool m_bForceUsingGraphicsReturnTrue;
  161. };
  162. //-----------------------------------------------------------------------------
  163. // Singleton
  164. //-----------------------------------------------------------------------------
  165. static CShaderSystem s_ShaderSystem;
  166. IShaderSystemInternal *g_pShaderSystem = &s_ShaderSystem;
  167. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderSystem, IShaderSystem,
  168. SHADERSYSTEM_INTERFACE_VERSION, s_ShaderSystem );
  169. //-----------------------------------------------------------------------------
  170. // Debugging shader names
  171. //-----------------------------------------------------------------------------
  172. const char *CShaderSystem::s_pDebugShaderName[MATERIAL_DEBUG_COUNT] =
  173. {
  174. "FillRate",
  175. "DebugNormalMap",
  176. "DebugDrawEnvmapMask",
  177. "DebugDepth",
  178. "DebugDepth",
  179. "Wireframe_DX9"
  180. };
  181. //-----------------------------------------------------------------------------
  182. // Constructor
  183. //-----------------------------------------------------------------------------
  184. CShaderSystem::CShaderSystem() : m_bForceUsingGraphicsReturnTrue( false )
  185. {
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Initialization, shutdown
  189. //-----------------------------------------------------------------------------
  190. void CShaderSystem::Init()
  191. {
  192. m_bForceUsingGraphicsReturnTrue = false;
  193. if ( CommandLine()->FindParm( "-noshaderapi" ) ||
  194. CommandLine()->FindParm( "-makereslists" ) )
  195. {
  196. m_bForceUsingGraphicsReturnTrue = true;
  197. }
  198. for ( int i = 0; i < MATERIAL_DEBUG_COUNT; ++i )
  199. {
  200. m_pDebugMaterials[i] = NULL;
  201. }
  202. LoadAllShaderDLLs();
  203. }
  204. void CShaderSystem::Shutdown()
  205. {
  206. UnloadAllShaderDLLs();
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Load/unload mod-specific shader DLLs
  210. //-----------------------------------------------------------------------------
  211. void CShaderSystem::ModInit()
  212. {
  213. // Load up standard shader DLLs...
  214. int dxSupportLevel = HardwareConfig()->GetMaxDXSupportLevel();
  215. Assert( dxSupportLevel >= 60 );
  216. dxSupportLevel /= 10;
  217. LoadModShaderDLLs( dxSupportLevel );
  218. }
  219. void CShaderSystem::ModShutdown()
  220. {
  221. // Unload only MOD dlls
  222. for ( int i = m_ShaderDLLs.Count(); --i >= 0; )
  223. {
  224. if ( m_ShaderDLLs[i].m_bModShaderDLL )
  225. {
  226. UnloadShaderDLL(i);
  227. delete[] m_ShaderDLLs[i].m_pFileName;
  228. m_ShaderDLLs.Remove( i );
  229. }
  230. }
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Load up the shader DLLs...
  234. //-----------------------------------------------------------------------------
  235. void CShaderSystem::LoadAllShaderDLLs( )
  236. {
  237. UnloadAllShaderDLLs();
  238. GetShaderDLLInternal()->Connect( Sys_GetFactoryThis(), true );
  239. // Loads local defined or statically linked shaders
  240. int i = m_ShaderDLLs.AddToHead();
  241. m_ShaderDLLs[i].m_pFileName = new char[1];
  242. m_ShaderDLLs[i].m_pFileName[0] = 0;
  243. m_ShaderDLLs[i].m_hInstance = NULL;
  244. m_ShaderDLLs[i].m_pShaderDLL = GetShaderDLLInternal();
  245. m_ShaderDLLs[i].m_bModShaderDLL = false;
  246. // Add the shaders to the dictionary of shaders...
  247. SetupShaderDictionary( i );
  248. #if defined( _PS3 ) || defined( _OSX )
  249. LoadShaderDLL( "stdshader_dx9" DLL_EXT_STRING );
  250. #else // _PS3 || _OSX
  251. // 360 has the the debug shaders in its dx9 dll
  252. if ( IsPC() || !IsX360() )
  253. {
  254. // Always need the debug shaders
  255. LoadShaderDLL( "stdshader_dbg" );
  256. }
  257. // Load up standard shader DLLs...
  258. int dxSupportLevel = HardwareConfig()->GetMaxDXSupportLevel();
  259. Assert( dxSupportLevel >= 60 );
  260. dxSupportLevel /= 10;
  261. // 360 only supports its dx9 dll
  262. int dxStart = 9;
  263. char buf[32];
  264. for ( i = dxStart; i <= dxSupportLevel; ++i )
  265. {
  266. Q_snprintf( buf, sizeof( buf ), "stdshader_dx%d", i );
  267. LoadShaderDLL( buf );
  268. }
  269. const char *pShaderName = NULL;
  270. #ifdef _DEBUG
  271. pShaderName = CommandLine()->ParmValue( "-shader" );
  272. #endif
  273. if ( !pShaderName )
  274. {
  275. pShaderName = HardwareConfig()->GetHWSpecificShaderDLLName();
  276. }
  277. if ( pShaderName )
  278. {
  279. LoadShaderDLL( pShaderName );
  280. }
  281. #ifdef _DEBUG
  282. // For fast-iteration debugging
  283. if ( CommandLine()->FindParm( "-testshaders" ) )
  284. {
  285. LoadShaderDLL( "shader_test" );
  286. }
  287. #endif
  288. #endif // !_PS3
  289. }
  290. void CShaderSystem::LoadModShaderDLLs( int dxSupportLevel )
  291. {
  292. // @wge: Not so sure about this OSX addition, may break modding support!
  293. return; // no more support for custom game shaders to control which DLLs we allow loading
  294. const char *pModShaderPathID = "GAMEBIN";
  295. // First load the ones with dx_ prefix.
  296. char buf[256];
  297. int dxStart = 6;
  298. for ( int i = dxStart; i <= dxSupportLevel; ++i )
  299. {
  300. Q_snprintf( buf, sizeof( buf ), "game_shader_dx%d", i );
  301. LoadShaderDLL( buf, pModShaderPathID, true );
  302. }
  303. // Now load the ones with any dx_ prefix.
  304. FileFindHandle_t findHandle;
  305. const char *pFilename = g_pFullFileSystem->FindFirstEx( "game_shader_generic*", pModShaderPathID, &findHandle );
  306. while ( pFilename )
  307. {
  308. Q_snprintf( buf, sizeof( buf ), "%s", pFilename );
  309. LoadShaderDLL( buf, pModShaderPathID, true );
  310. pFilename = g_pFullFileSystem->FindNext( findHandle );
  311. }
  312. }
  313. //-----------------------------------------------------------------------------
  314. // Unload all the shader DLLs...
  315. //-----------------------------------------------------------------------------
  316. void CShaderSystem::UnloadAllShaderDLLs()
  317. {
  318. if ( m_ShaderDLLs.Count() == 0 )
  319. return;
  320. for ( int i = m_ShaderDLLs.Count(); --i >= 0; )
  321. {
  322. UnloadShaderDLL(i);
  323. delete[] m_ShaderDLLs[i].m_pFileName;
  324. }
  325. m_ShaderDLLs.RemoveAll();
  326. }
  327. bool CShaderSystem::LoadShaderDLL( const char *pFullPath )
  328. {
  329. return LoadShaderDLL( pFullPath, NULL, false );
  330. }
  331. //-----------------------------------------------------------------------------
  332. // Methods related to reading in shader DLLs
  333. //-----------------------------------------------------------------------------
  334. bool CShaderSystem::LoadShaderDLL( const char *pFullPath, const char *pPathID, bool bModShaderDLL )
  335. {
  336. #if !defined( _PS3 ) && !defined( _OSX )
  337. if ( !pFullPath && !pFullPath[0] )
  338. return true;
  339. // Load the new shader
  340. bool bValidatedDllOnly = true;
  341. if ( bModShaderDLL )
  342. bValidatedDllOnly = false;
  343. CSysModule *hInstance = g_pFullFileSystem->LoadModule( pFullPath, pPathID, bValidatedDllOnly );
  344. if ( !hInstance )
  345. return false;
  346. // Get at the shader DLL interface
  347. CreateInterfaceFn factory = Sys_GetFactory( hInstance );
  348. if (!factory)
  349. {
  350. g_pFullFileSystem->UnloadModule( hInstance );
  351. return false;
  352. }
  353. IShaderDLLInternal *pShaderDLL = (IShaderDLLInternal*)factory( SHADER_DLL_INTERFACE_VERSION, NULL );
  354. if ( !pShaderDLL )
  355. {
  356. g_pFullFileSystem->UnloadModule( hInstance );
  357. return false;
  358. }
  359. // Allow the DLL to try to connect to interfaces it needs
  360. if ( !pShaderDLL->Connect( Sys_GetFactoryThis(), false ) )
  361. {
  362. g_pFullFileSystem->UnloadModule( hInstance );
  363. return false;
  364. }
  365. #else
  366. CSysModule *hInstance = NULL;
  367. IShaderDLLInternal *pShaderDLL = GetShaderDLLInternal();
  368. pShaderDLL->Connect( Sys_GetFactoryThis(), false );
  369. #endif // !_PS3 && !_OSX
  370. // FIXME: We need to do some sort of shader validation here for anticheat.
  371. // Now replace any existing shader
  372. int nShaderDLLIndex = FindShaderDLL( pFullPath );
  373. if ( nShaderDLLIndex >= 0 )
  374. {
  375. UnloadShaderDLL( nShaderDLLIndex );
  376. }
  377. else
  378. {
  379. nShaderDLLIndex = m_ShaderDLLs.AddToTail();
  380. int nLen = Q_strlen(pFullPath) + 1;
  381. m_ShaderDLLs[nShaderDLLIndex].m_pFileName = new char[ nLen ];
  382. Q_strncpy( m_ShaderDLLs[nShaderDLLIndex].m_pFileName, pFullPath, nLen );
  383. }
  384. // Ok, the shader DLL's good!
  385. m_ShaderDLLs[nShaderDLLIndex].m_hInstance = hInstance;
  386. m_ShaderDLLs[nShaderDLLIndex].m_pShaderDLL = pShaderDLL;
  387. m_ShaderDLLs[nShaderDLLIndex].m_bModShaderDLL = bModShaderDLL;
  388. // Add the shaders to the dictionary of shaders...
  389. SetupShaderDictionary( nShaderDLLIndex );
  390. // FIXME: Fix up existing materials that were using shaders that have
  391. // been reloaded?
  392. return true;
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Finds an already loaded shader DLL
  396. //-----------------------------------------------------------------------------
  397. int CShaderSystem::FindShaderDLL( const char *pFullPath )
  398. {
  399. for ( int i = m_ShaderDLLs.Count(); --i >= 0; )
  400. {
  401. if ( !Q_stricmp( pFullPath, m_ShaderDLLs[i].m_pFileName ) )
  402. return i;
  403. }
  404. return -1;
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Unloads a particular shader DLL
  408. //-----------------------------------------------------------------------------
  409. void CShaderSystem::UnloadShaderDLL( int nShaderDLLIndex )
  410. {
  411. if ( nShaderDLLIndex < 0 )
  412. return;
  413. // FIXME: Do some sort of fixup of materials to determine which
  414. // materials are referencing shaders in this DLL?
  415. CleanupShaderDictionary( nShaderDLLIndex );
  416. IShaderDLLInternal *pShaderDLL = m_ShaderDLLs[nShaderDLLIndex].m_pShaderDLL;
  417. pShaderDLL->Disconnect( pShaderDLL == GetShaderDLLInternal() );
  418. if ( m_ShaderDLLs[nShaderDLLIndex].m_hInstance )
  419. {
  420. g_pFullFileSystem->UnloadModule( m_ShaderDLLs[nShaderDLLIndex].m_hInstance );
  421. }
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Unloads a particular shader DLL
  425. //-----------------------------------------------------------------------------
  426. void CShaderSystem::UnloadShaderDLL( const char *pFullPath )
  427. {
  428. int nShaderDLLIndex = FindShaderDLL( pFullPath );
  429. if ( nShaderDLLIndex >= 0 )
  430. {
  431. UnloadShaderDLL( nShaderDLLIndex );
  432. delete[] m_ShaderDLLs[nShaderDLLIndex].m_pFileName;
  433. m_ShaderDLLs.Remove( nShaderDLLIndex );
  434. }
  435. }
  436. //-----------------------------------------------------------------------------
  437. // Make sure these match the bits in imaterial.h
  438. //-----------------------------------------------------------------------------
  439. static char* s_pShaderStateString[] =
  440. {
  441. "$debug",
  442. "$no_fullbright",
  443. "$no_draw",
  444. "$use_in_fillrate_mode",
  445. "$vertexcolor",
  446. "$vertexalpha",
  447. "$selfillum",
  448. "$additive",
  449. "$alphatest",
  450. "$pseudotranslucent",
  451. "$znearer",
  452. "$model",
  453. "$flat",
  454. "$nocull",
  455. "$nofog",
  456. "$ignorez",
  457. "$decal",
  458. "$envmapsphere",
  459. "$xxxxxxunusedxxxxx",
  460. "$envmapcameraspace",
  461. "$basealphaenvmapmask",
  462. "$translucent",
  463. "$normalmapalphaenvmapmask",
  464. "$softwareskin",
  465. "$opaquetexture",
  466. "$multiply",
  467. "$nodecal",
  468. "$halflambert",
  469. "$wireframe",
  470. "$allowalphatocoverage",
  471. "$alphamodifiedbyproxy_DO_NOT_SET_IN_VMT", // This one is only used as a flag from code externally. Isnt' to be st in vmt files.
  472. "$vertexfog",
  473. "" // last one must be null
  474. };
  475. //-----------------------------------------------------------------------------
  476. // returns strings associated with the shader state flags...
  477. // If you modify this, make sure and modify MaterialVarFlags_t in imaterial.h
  478. //-----------------------------------------------------------------------------
  479. int CShaderSystem::ShaderStateCount( ) const
  480. {
  481. return sizeof( s_pShaderStateString ) / sizeof( char* ) - 1;
  482. }
  483. //-----------------------------------------------------------------------------
  484. // returns strings associated with the shader state flags...
  485. // If you modify this, make sure and modify MaterialVarFlags_t in imaterial.h
  486. //-----------------------------------------------------------------------------
  487. char const* CShaderSystem::ShaderStateString( int i ) const
  488. {
  489. return s_pShaderStateString[i];
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Sets up the shader dictionary.
  493. //-----------------------------------------------------------------------------
  494. void CShaderSystem::SetupShaderDictionary( int nShaderDLLIndex )
  495. {
  496. // We could have put the shader dictionary into each shader DLL
  497. // I'm not sure if that makes this system any less secure than it already is
  498. ShaderDLLInfo_t &info = m_ShaderDLLs[nShaderDLLIndex];
  499. for ( int i = 0; i < info.m_pShaderDLL->ShaderComboSemanticsCount(); i++ )
  500. {
  501. const ShaderComboSemantics_t *pSemantics = info.m_pShaderDLL->GetComboSemantics( i );
  502. g_pShaderAPI->AddShaderComboInformation( pSemantics );
  503. }
  504. int nCount = info.m_pShaderDLL->ShaderCount();
  505. for ( int i = 0; i < nCount; ++i )
  506. {
  507. IShader *pShader = info.m_pShaderDLL->GetShader( i );
  508. const char *pShaderName = pShader->GetName();
  509. #ifdef POSIX
  510. //if (CommandLine()->FindParm("-glmspew"))
  511. // printf("CShaderSystem::SetupShaderDictionary: %s", pShaderName );
  512. #endif
  513. // Make sure it doesn't try to override another shader DLL's names.
  514. if ( info.m_bModShaderDLL )
  515. {
  516. for ( int iTestDLL=0; iTestDLL < m_ShaderDLLs.Count(); iTestDLL++ )
  517. {
  518. ShaderDLLInfo_t *pTestDLL = &m_ShaderDLLs[iTestDLL];
  519. if ( !pTestDLL->m_bModShaderDLL )
  520. {
  521. if ( pTestDLL->m_ShaderDict.Find( pShaderName ) != pTestDLL->m_ShaderDict.InvalidIndex() )
  522. {
  523. Error( "Game shader '%s' trying to override a base shader '%s'.", info.m_pFileName, pShaderName );
  524. }
  525. }
  526. }
  527. }
  528. info.m_ShaderDict.Insert( pShaderName, pShader );
  529. }
  530. }
  531. //-----------------------------------------------------------------------------
  532. // Cleans up the shader dictionary.
  533. //-----------------------------------------------------------------------------
  534. void CShaderSystem::CleanupShaderDictionary( int nShaderDLLIndex )
  535. {
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Finds a shader in the shader dictionary
  539. //-----------------------------------------------------------------------------
  540. IShader* CShaderSystem::FindShader( char const* pShaderName )
  541. {
  542. // FIXME: What kind of search order should we use here?
  543. // I'm currently assuming last added, first searched.
  544. for (int i = m_ShaderDLLs.Count(); --i >= 0; )
  545. {
  546. ShaderDLLInfo_t &info = m_ShaderDLLs[i];
  547. unsigned short idx = info.m_ShaderDict.Find( pShaderName );
  548. if ( idx != info.m_ShaderDict.InvalidIndex() )
  549. {
  550. return info.m_ShaderDict[idx];
  551. }
  552. }
  553. return NULL;
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Used to iterate over all shaders for editing purposes
  557. //-----------------------------------------------------------------------------
  558. int CShaderSystem::ShaderCount() const
  559. {
  560. return GetShaders( 0, 65536, NULL );
  561. }
  562. int CShaderSystem::GetShaders( int nFirstShader, int nMaxCount, IShader **ppShaderList ) const
  563. {
  564. CUtlSymbolTable uniqueNames( 0, 512, true );
  565. int nCount = 0;
  566. int nActualCount = 0;
  567. for ( int i = m_ShaderDLLs.Count(); --i >= 0; )
  568. {
  569. const ShaderDLLInfo_t &info = m_ShaderDLLs[i];
  570. for ( unsigned short j = info.m_ShaderDict.First();
  571. j != info.m_ShaderDict.InvalidIndex();
  572. j = info.m_ShaderDict.Next( j ) )
  573. {
  574. // Don't add shaders twice
  575. const char *pShaderName = info.m_ShaderDict.GetElementName( j );
  576. if ( uniqueNames.Find( pShaderName ) != UTL_INVAL_SYMBOL )
  577. continue;
  578. // Indicate we've seen this shader
  579. uniqueNames.AddString( pShaderName );
  580. ++nActualCount;
  581. if ( nActualCount > nFirstShader )
  582. {
  583. if ( ppShaderList )
  584. {
  585. ppShaderList[ nCount ] = info.m_ShaderDict[j];
  586. }
  587. ++nCount;
  588. if ( nCount >= nMaxCount )
  589. return nCount;
  590. }
  591. }
  592. }
  593. return nCount;
  594. }
  595. //-----------------------------------------------------------------------------
  596. //
  597. // Methods of IShaderInit lie below
  598. //
  599. //-----------------------------------------------------------------------------
  600. //-----------------------------------------------------------------------------
  601. // Gets at the render pass info for this pass...
  602. //-----------------------------------------------------------------------------
  603. inline StateSnapshot_t CShaderSystem::CurrentStateSnapshot()
  604. {
  605. Assert( m_pRenderState );
  606. Assert( m_nRenderPass < MAX_RENDER_PASSES );
  607. Assert( m_nRenderPass < m_pRenderState->m_pSnapshots[m_nModulation].m_nPassCount );
  608. return m_pRenderState->m_pSnapshots[m_nModulation].m_Snapshot[m_nRenderPass];
  609. }
  610. //-----------------------------------------------------------------------------
  611. // Create debugging materials
  612. //-----------------------------------------------------------------------------
  613. void CShaderSystem::CreateDebugMaterials()
  614. {
  615. if (m_pDebugMaterials[0])
  616. return;
  617. KeyValues *pVMTKeyValues[MATERIAL_DEBUG_COUNT];
  618. int i;
  619. for ( i = 0; i < MATERIAL_DEBUG_COUNT; ++i )
  620. {
  621. pVMTKeyValues[i] = new KeyValues( s_pDebugShaderName[i] );
  622. }
  623. pVMTKeyValues[MATERIAL_DEBUG_DEPTH_DECAL]->SetInt( "$decal", 1 );
  624. for ( i = 0; i < MATERIAL_DEBUG_COUNT; ++i )
  625. {
  626. char shaderName[64];
  627. Q_snprintf( shaderName, sizeof( shaderName ), "___%s_%d.vmt", s_pDebugShaderName[i], i );
  628. m_pDebugMaterials[i] = static_cast<IMaterialInternal*>(MaterialSystem()->CreateMaterial( shaderName, pVMTKeyValues[i] ));
  629. if( m_pDebugMaterials[i] )
  630. m_pDebugMaterials[i] = m_pDebugMaterials[i]->GetRealTimeVersion();
  631. }
  632. }
  633. //-----------------------------------------------------------------------------
  634. // Cleans up the debugging materials
  635. //-----------------------------------------------------------------------------
  636. void CShaderSystem::CleanUpDebugMaterials()
  637. {
  638. if (m_pDebugMaterials[0])
  639. {
  640. for ( int i = 0; i < MATERIAL_DEBUG_COUNT; ++i )
  641. {
  642. m_pDebugMaterials[i]->DecrementReferenceCount();
  643. if ( m_pDebugMaterials[i]->InMaterialPage() )
  644. {
  645. MaterialSystem()->RemoveMaterialSubRect( m_pDebugMaterials[i] );
  646. }
  647. else
  648. {
  649. MaterialSystem()->RemoveMaterial( m_pDebugMaterials[i] );
  650. }
  651. m_pDebugMaterials[i] = NULL;
  652. }
  653. }
  654. }
  655. //-----------------------------------------------------------------------------
  656. // Deals with shader draw
  657. //-----------------------------------------------------------------------------
  658. void CShaderSystem::PrepForShaderDraw( IShader *pShader,
  659. IMaterialVar** ppParams, ShaderRenderState_t* pRenderState, int nModulation )
  660. {
  661. Assert( !m_pRenderState );
  662. // 360 runs the console remotely, spew cannot cause the matsys to be reentrant
  663. // 360 sidesteps the other negative affect that *all* buffered spew redirects as warning text
  664. if ( IsPC() || ( !IsX360() && !IsPS3() ) )
  665. {
  666. LoggingSystem_PushLoggingState( true );
  667. LoggingSystem_RegisterLoggingListener( &m_BufferedLoggingListener );
  668. LoggingSystem_SetLoggingResponsePolicy( &m_NonFatalLoggingResponsePolicy );
  669. }
  670. m_pRenderState = pRenderState;
  671. m_nModulation = nModulation;
  672. m_nRenderPass = 0;
  673. }
  674. void CShaderSystem::DoneWithShaderDraw()
  675. {
  676. if ( IsPC() || ( !IsX360() && !IsPS3() ) )
  677. {
  678. LoggingSystem_PopLoggingState( true );
  679. m_BufferedLoggingListener.EmitBufferedSpew();
  680. }
  681. m_pRenderState = NULL;
  682. }
  683. #ifdef _DEBUG
  684. #pragma warning (disable:4189)
  685. #endif
  686. //-----------------------------------------------------------------------------
  687. // Call the SHADER_PARAM_INIT block of the shaders
  688. //-----------------------------------------------------------------------------
  689. void CShaderSystem::InitShaderParameters( IShader *pShader, IMaterialVar **params, const char *pMaterialName )
  690. {
  691. #ifdef _DEBUG
  692. if ( IsFlagSet( params, MATERIAL_VAR_DEBUG ) )
  693. {
  694. // Putcher breakpoint here to catch the rendering of a material
  695. // marked for debugging ($debug = 1 in a .vmt file) init params version
  696. int x = 0;
  697. }
  698. #endif
  699. // Let the derived class do its thing
  700. PrepForShaderDraw( pShader, params, 0, 0 );
  701. pShader->InitShaderParams( params, pMaterialName );
  702. DoneWithShaderDraw();
  703. // Set up color + alpha defaults
  704. if (!params[COLOR]->IsDefined())
  705. {
  706. params[COLOR]->SetVecValue( 1.0f, 1.0f, 1.0f );
  707. }
  708. if (!params[ALPHA]->IsDefined())
  709. {
  710. params[ALPHA]->SetFloatValue( 1.0f );
  711. }
  712. // Initialize all shader params based on their type...
  713. int i;
  714. for ( i = pShader->GetParamCount(); --i >= 0; )
  715. {
  716. // Don't initialize parameters that are already set up
  717. if (params[i]->IsDefined())
  718. continue;
  719. int type = pShader->GetParamInfo( i ).m_Type;
  720. switch( type )
  721. {
  722. case SHADER_PARAM_TYPE_TEXTURE:
  723. // Do nothing; we'll be loading in a string later
  724. break;
  725. case SHADER_PARAM_TYPE_STRING:
  726. // Do nothing; we'll be loading in a string later
  727. break;
  728. case SHADER_PARAM_TYPE_MATERIAL:
  729. params[i]->SetMaterialValue( NULL );
  730. break;
  731. case SHADER_PARAM_TYPE_BOOL:
  732. case SHADER_PARAM_TYPE_INTEGER:
  733. params[i]->SetIntValue( 0 );
  734. break;
  735. case SHADER_PARAM_TYPE_COLOR:
  736. params[i]->SetVecValue( 1.0f, 1.0f, 1.0f );
  737. break;
  738. case SHADER_PARAM_TYPE_VEC2:
  739. params[i]->SetVecValue( 0.0f, 0.0f );
  740. break;
  741. case SHADER_PARAM_TYPE_VEC3:
  742. params[i]->SetVecValue( 0.0f, 0.0f, 0.0f );
  743. break;
  744. case SHADER_PARAM_TYPE_VEC4:
  745. params[i]->SetVecValue( 0.0f, 0.0f, 0.0f, 0.0f );
  746. break;
  747. case SHADER_PARAM_TYPE_FLOAT:
  748. params[i]->SetFloatValue( 0 );
  749. break;
  750. case SHADER_PARAM_TYPE_FOURCC:
  751. params[i]->SetFourCCValue( 0, 0 );
  752. break;
  753. case SHADER_PARAM_TYPE_MATRIX:
  754. {
  755. VMatrix identity;
  756. MatrixSetIdentity( identity );
  757. params[i]->SetMatrixValue( identity );
  758. }
  759. break;
  760. default:
  761. Assert(0);
  762. }
  763. }
  764. }
  765. #ifdef _DEBUG
  766. #pragma warning (default:4189)
  767. #endif
  768. //-----------------------------------------------------------------------------
  769. // Call the SHADER_INIT block of the shaders
  770. //-----------------------------------------------------------------------------
  771. void CShaderSystem::InitShaderInstance( IShader *pShader, IMaterialVar **params, const char *pMaterialName, const char *pTextureGroupName )
  772. {
  773. // Let the derived class do its thing
  774. PrepForShaderDraw( pShader, params, 0, 0 );
  775. pShader->InitShaderInstance( params, ShaderSystem(), pMaterialName, pTextureGroupName );
  776. DoneWithShaderDraw();
  777. }
  778. //-----------------------------------------------------------------------------
  779. // Compute snapshots for all combinations of alpha + color modulation
  780. //-----------------------------------------------------------------------------
  781. void CShaderSystem::InitRenderStateFlags( ShaderRenderState_t* pRenderState, int numParams, IMaterialVar **params )
  782. {
  783. // Compute vertex format and flags
  784. pRenderState->m_Flags = 0;
  785. // Make sure the shader don't force these flags. . they are automatically computed.
  786. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_TRANSLUCENT ) );
  787. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_ALPHATEST ) );
  788. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_OPAQUE ) );
  789. // If we are in release mode, just go ahead and clear in case the above is screwed up.
  790. pRenderState->m_Flags &= ~SHADER_OPACITY_MASK;
  791. /*
  792. // HACK: Also kind of gross; turn off bump lightmapping for low-end
  793. if (g_config.bUseGraphics && !HardwareConfig()->SupportsVertexAndPixelShaders())
  794. {
  795. pRenderState->m_Flags &= ~SHADER_NEEDS_BUMPED_LIGHTMAPS;
  796. }
  797. */
  798. /*
  799. // HACK: more grossness!!! turn off bump lightmapping if we don't have a bumpmap
  800. // Shaders should specify SHADER_NEEDS_BUMPED_LIGHTMAPS if they might need a bumpmap,
  801. // and this'll take care of getting rid of it if it isn't there.
  802. if( pRenderState->m_Flags & SHADER_NEEDS_BUMPED_LIGHTMAPS )
  803. {
  804. pRenderState->m_Flags &= ~SHADER_NEEDS_BUMPED_LIGHTMAPS;
  805. for( int i = 0; i < numParams; i++ )
  806. {
  807. if( stricmp( params[i]->GetName(), "$bumpmap" ) == 0 )
  808. {
  809. if( params[i]->IsDefined() )
  810. {
  811. const char *blah = params[i]->GetStringValue();
  812. pRenderState->m_Flags |= SHADER_NEEDS_BUMPED_LIGHTMAPS;
  813. break;
  814. }
  815. }
  816. }
  817. }
  818. */
  819. }
  820. //-----------------------------------------------------------------------------
  821. // Computes flags from a particular snapshot
  822. //-----------------------------------------------------------------------------
  823. void CShaderSystem::ComputeRenderStateFlagsFromSnapshot( ShaderRenderState_t* pRenderState )
  824. {
  825. // When computing the flags, use the snapshot that has no alpha or color
  826. // modulation. When asking for translucency, we'll have to check for
  827. // alpha modulation in addition to checking the TRANSLUCENT flag.
  828. // I have to do it this way because I'm really wanting to treat alpha
  829. // modulation as a dynamic state, even though it's being used to compute
  830. // shadow state. I still want to use it to compute shadow state though
  831. // because it's somewhat complicated code that I'd rather precache.
  832. StateSnapshot_t snapshot = pRenderState->m_pSnapshots[0].m_Snapshot[0];
  833. // Automatically compute if the snapshot is transparent or not
  834. if ( g_pShaderAPI->IsTranslucent( snapshot ) )
  835. {
  836. pRenderState->m_Flags |= SHADER_OPACITY_TRANSLUCENT;
  837. }
  838. else
  839. {
  840. if ( g_pShaderAPI->IsAlphaTested( snapshot ) )
  841. {
  842. pRenderState->m_Flags |= SHADER_OPACITY_ALPHATEST;
  843. }
  844. else
  845. {
  846. pRenderState->m_Flags |= SHADER_OPACITY_OPAQUE;
  847. }
  848. }
  849. #ifdef _DEBUG
  850. if( pRenderState->m_Flags & SHADER_OPACITY_TRANSLUCENT )
  851. {
  852. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_ALPHATEST ) );
  853. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_OPAQUE ) );
  854. }
  855. if( pRenderState->m_Flags & SHADER_OPACITY_ALPHATEST )
  856. {
  857. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_TRANSLUCENT ) );
  858. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_OPAQUE ) );
  859. }
  860. if( pRenderState->m_Flags & SHADER_OPACITY_OPAQUE )
  861. {
  862. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_ALPHATEST ) );
  863. Assert( !( pRenderState->m_Flags & SHADER_OPACITY_TRANSLUCENT ) );
  864. }
  865. #endif
  866. }
  867. //-----------------------------------------------------------------------------
  868. // Initializes state snapshots
  869. //-----------------------------------------------------------------------------
  870. #ifdef _DEBUG
  871. #pragma warning (disable:4189)
  872. #endif
  873. int CShaderSystem::GetModulationSnapshotCount( IMaterialVar **params )
  874. {
  875. int nSnapshotCount = SnapshotTypeCount();
  876. return nSnapshotCount;
  877. }
  878. #define SET_FLAGS2B( nFlag, bState ) \
  879. if ( bState ) \
  880. SET_FLAGS2( nFlag ); \
  881. else \
  882. CLEAR_FLAGS2( nFlag );
  883. void CShaderSystem::InitStateSnapshots( IShader *pShader, IMaterialVar **params, ShaderRenderState_t* pRenderState )
  884. {
  885. #ifdef _DEBUG
  886. if ( IsFlagSet( params, MATERIAL_VAR_DEBUG ) )
  887. {
  888. // Putcher breakpoint here to catch the rendering of a material
  889. // marked for debugging ($debug = 1 in a .vmt file) shadow state version
  890. int x = 0;
  891. }
  892. #endif
  893. // Store off the current settings
  894. bool bPaint = IsFlag2Set( params, MATERIAL_VAR2_USE_PAINT );
  895. bool bFlashlight = IsFlag2Set( params, MATERIAL_VAR2_USE_FLASHLIGHT );
  896. bool bEditor = IsFlag2Set( params, MATERIAL_VAR2_USE_EDITOR );
  897. bool bGBuffer0 = IsFlag2Set( params, MATERIAL_VAR2_USE_GBUFFER0 );
  898. bool bGBuffer1 = IsFlag2Set( params, MATERIAL_VAR2_USE_GBUFFER1 );
  899. int nSnapshotCount = GetModulationSnapshotCount( params );
  900. // If the current mod does not use the flashlight, skip all flashlight snapshots (saves a ton of memory)
  901. bool bModUsesFlashlight = ( mat_supportflashlight.GetInt() != 0 );
  902. bool bCanSupportGBuffer = ( MaterialSystem()->GetConfigurationFlags() & MATCONFIG_FLAGS_SUPPORT_GBUFFER ) != 0;
  903. bool bCanSupportPaint = true; //FIXME g_pConfig->m_bPaintInGame;
  904. for ( int i = 0; i < nSnapshotCount; ++i )
  905. {
  906. // skipping this snapshot?
  907. if (
  908. ( ( i & SHADER_USING_PAINT ) && !bCanSupportPaint ) || // skipping paint for mods that don't use it
  909. ( ( i & SHADER_USING_FLASHLIGHT ) && !bModUsesFlashlight ) || // skipping flashlight for mods that don't use it
  910. ( ( i & SHADER_USING_FLASHLIGHT ) && ( i & ( SHADER_USING_GBUFFER0 | SHADER_USING_GBUFFER1 ) ) ) || // skipping flashlight with gbuffer
  911. ( ( i & SHADER_USING_EDITOR ) && ( !CanUseEditorMaterials() ) ) || // skipping editor
  912. ( ( i & ( SHADER_USING_GBUFFER0 | SHADER_USING_GBUFFER1 ) ) && !bCanSupportGBuffer ) // skipping gbuffer if not supported
  913. )
  914. {
  915. pRenderState->m_pSnapshots[i].m_nPassCount = 0;
  916. continue;
  917. }
  918. SET_FLAGS2B( MATERIAL_VAR2_USE_FLASHLIGHT, ( i & SHADER_USING_FLASHLIGHT ) );
  919. SET_FLAGS2B( MATERIAL_VAR2_USE_EDITOR, ( i & SHADER_USING_EDITOR ) );
  920. SET_FLAGS2B( MATERIAL_VAR2_USE_PAINT, ( i & SHADER_USING_PAINT ) );
  921. SET_FLAGS2B( MATERIAL_VAR2_USE_GBUFFER0, ( i & SHADER_USING_GBUFFER0 ) );
  922. SET_FLAGS2B( MATERIAL_VAR2_USE_GBUFFER1, ( i & SHADER_USING_GBUFFER1 ) );
  923. PrepForShaderDraw( pShader, params, pRenderState, i );
  924. // Now snapshot how we're going to draw
  925. // NOTE: We're in a half-way point here; modulation flags should be entirely computed here
  926. // but I want to minimize code change while fixing the alpha-modulation related
  927. // problem that the modulation flag isn't bring driven by the per-instance modulation alpha state
  928. pRenderState->m_pSnapshots[i].m_nPassCount = 0;
  929. pShader->DrawElements( params, i, g_pShaderShadow, 0, VERTEX_COMPRESSION_NONE, &(pRenderState->m_pSnapshots[i].m_pContextData[0] ), &(pRenderState->m_pSnapshots[i].m_pInstanceData[0] ) );
  930. DoneWithShaderDraw();
  931. }
  932. // restore flags
  933. SET_FLAGS2B( MATERIAL_VAR2_USE_PAINT, bPaint );
  934. SET_FLAGS2B( MATERIAL_VAR2_USE_EDITOR, bEditor );
  935. SET_FLAGS2B( MATERIAL_VAR2_USE_FLASHLIGHT, bFlashlight );
  936. SET_FLAGS2B( MATERIAL_VAR2_USE_GBUFFER0, bGBuffer0 );
  937. SET_FLAGS2B( MATERIAL_VAR2_USE_GBUFFER1, bGBuffer1 );
  938. }
  939. #ifdef _DEBUG
  940. #pragma warning (default:4189)
  941. #endif
  942. //-----------------------------------------------------------------------------
  943. // Helper to count texture coordinates
  944. //-----------------------------------------------------------------------------
  945. static int NumTextureCoordinates( VertexFormat_t vertexFormat )
  946. {
  947. // FIXME: this is a duplicate of the function in meshdx8.cpp
  948. int nTexCoordCount = 0;
  949. for ( int i = 0; i < VERTEX_MAX_TEXTURE_COORDINATES; ++i )
  950. {
  951. if ( TexCoordSize( i, vertexFormat ) == 0 )
  952. continue;
  953. ++nTexCoordCount;
  954. }
  955. return nTexCoordCount;
  956. }
  957. //-----------------------------------------------------------------------------
  958. // Displays the vertex format
  959. //-----------------------------------------------------------------------------
  960. static void OutputVertexFormat( VertexFormat_t format )
  961. {
  962. // FIXME: this is a duplicate of the function in meshdx8.cpp
  963. VertexCompressionType_t compressionType = CompressionType( format );
  964. if( format & VERTEX_POSITION )
  965. {
  966. Warning( "VERTEX_POSITION|" );
  967. }
  968. if( format & VERTEX_NORMAL )
  969. {
  970. if ( compressionType == VERTEX_COMPRESSION_ON )
  971. Warning( "VERTEX_NORMAL[COMPRESSED]|" );
  972. else
  973. Warning( "VERTEX_NORMAL|" );
  974. }
  975. if( format & VERTEX_COLOR )
  976. {
  977. Warning( "VERTEX_COLOR|" );
  978. }
  979. if( format & VERTEX_SPECULAR )
  980. {
  981. Warning( "VERTEX_SPECULAR|" );
  982. }
  983. if( format & VERTEX_TANGENT_S )
  984. {
  985. Warning( "VERTEX_TANGENT_S|" );
  986. }
  987. if( format & VERTEX_TANGENT_T )
  988. {
  989. Warning( "VERTEX_TANGENT_T|" );
  990. }
  991. if( format & VERTEX_BONE_INDEX )
  992. {
  993. Warning( "VERTEX_BONE_INDEX|" );
  994. }
  995. Warning( "\nBone weights: %d\n", NumBoneWeights( format ) );
  996. Warning( "user data size: %d (%s)\n", UserDataSize( format ),
  997. ( CompressionType( format ) == VERTEX_COMPRESSION_ON ? "compressed" : "uncompressed" ) );
  998. Warning( "num tex coords: %d\n", NumTextureCoordinates( format ) );
  999. // NOTE: This doesn't print texcoord sizes.
  1000. }
  1001. #ifdef _DEBUG
  1002. static bool IsVertexFormatSubsetOfVertexformat( VertexFormat_t subset, VertexFormat_t superset )
  1003. {
  1004. subset &= ~VERTEX_FORMAT_USE_EXACT_FORMAT;
  1005. superset &= ~VERTEX_FORMAT_USE_EXACT_FORMAT;
  1006. // Test the flags
  1007. if( VertexFlags( subset ) & VertexFlags( ~superset ) )
  1008. return false;
  1009. // Test bone weights
  1010. if( NumBoneWeights( subset ) > NumBoneWeights( superset ) )
  1011. return false;
  1012. // Test user data size
  1013. if( UserDataSize( subset ) > UserDataSize( superset ) )
  1014. return false;
  1015. // Test the texcoord dimensions
  1016. for( int i = 0; i < VERTEX_MAX_TEXTURE_COORDINATES; i++ )
  1017. {
  1018. if( TexCoordSize( i, subset ) > TexCoordSize( i, superset ) )
  1019. return false;
  1020. }
  1021. return true;
  1022. }
  1023. #endif
  1024. //-----------------------------------------------------------------------------
  1025. // Adds state snapshots to the render list
  1026. //-----------------------------------------------------------------------------
  1027. static void AddSnapshotsToList( RenderPassList_t *pPassList, int &nSnapshotID, StateSnapshot_t *pSnapshots )
  1028. {
  1029. int nNumPassSnapshots = pPassList->m_nPassCount;
  1030. for( int i = 0; i < nNumPassSnapshots; ++i )
  1031. {
  1032. pSnapshots[nSnapshotID] = pPassList->m_Snapshot[i];
  1033. nSnapshotID++;
  1034. }
  1035. }
  1036. //-----------------------------------------------------------------------------
  1037. // Computes vertex format + usage from a particular snapshot
  1038. //-----------------------------------------------------------------------------
  1039. bool CShaderSystem::ComputeVertexFormatFromSnapshot( IMaterialVar **params, ShaderRenderState_t* pRenderState )
  1040. {
  1041. // When computing the usage, use the snapshot that has no alpha or color
  1042. // modulation. We need the usage + format to be the same for all
  1043. // combinations of alpha + color modulation, though, or we are asking for
  1044. // trouble.
  1045. int nModulationSnapshotCount = GetModulationSnapshotCount( params );
  1046. int numSnapshots = pRenderState->m_pSnapshots[0].m_nPassCount;
  1047. if (nModulationSnapshotCount >= SHADER_USING_FLASHLIGHT)
  1048. {
  1049. numSnapshots += pRenderState->m_pSnapshots[SHADER_USING_FLASHLIGHT].m_nPassCount;
  1050. }
  1051. if (nModulationSnapshotCount >= SHADER_USING_PAINT)
  1052. {
  1053. numSnapshots += pRenderState->m_pSnapshots[SHADER_USING_PAINT].m_nPassCount;
  1054. }
  1055. if ( CanUseEditorMaterials() )
  1056. {
  1057. numSnapshots += pRenderState->m_pSnapshots[SHADER_USING_EDITOR].m_nPassCount;
  1058. }
  1059. StateSnapshot_t* pSnapshots = (StateSnapshot_t*)stackalloc(
  1060. numSnapshots * sizeof(StateSnapshot_t) );
  1061. int snapshotID = 0;
  1062. AddSnapshotsToList( &pRenderState->m_pSnapshots[0], snapshotID, pSnapshots );
  1063. if (nModulationSnapshotCount >= SHADER_USING_FLASHLIGHT)
  1064. {
  1065. AddSnapshotsToList( &pRenderState->m_pSnapshots[SHADER_USING_FLASHLIGHT], snapshotID, pSnapshots );
  1066. }
  1067. if (nModulationSnapshotCount >= SHADER_USING_PAINT)
  1068. {
  1069. AddSnapshotsToList( &pRenderState->m_pSnapshots[SHADER_USING_PAINT], snapshotID, pSnapshots );
  1070. }
  1071. if ( CanUseEditorMaterials() )
  1072. {
  1073. AddSnapshotsToList( &pRenderState->m_pSnapshots[SHADER_USING_EDITOR], snapshotID, pSnapshots );
  1074. }
  1075. Assert( snapshotID == numSnapshots );
  1076. pRenderState->m_VertexUsage = g_pShaderAPI->ComputeVertexUsage( numSnapshots, pSnapshots );
  1077. #ifdef _DEBUG
  1078. // Make sure all modulation combinations match vertex usage
  1079. for ( int mod = 1; mod < nModulationSnapshotCount; ++mod )
  1080. {
  1081. int numSnapshotsTest = pRenderState->m_pSnapshots[mod].m_nPassCount;
  1082. StateSnapshot_t* pSnapshotsTest = (StateSnapshot_t*)stackalloc(
  1083. numSnapshotsTest * sizeof(StateSnapshot_t) );
  1084. for (int i = 0; i < numSnapshotsTest; ++i)
  1085. {
  1086. pSnapshotsTest[i] = pRenderState->m_pSnapshots[mod].m_Snapshot[i];
  1087. }
  1088. VertexFormat_t usageTest = g_pShaderAPI->ComputeVertexUsage( numSnapshotsTest, pSnapshotsTest );
  1089. Assert( IsVertexFormatSubsetOfVertexformat( usageTest, pRenderState->m_VertexUsage ) );
  1090. }
  1091. #endif
  1092. if ( IsPC() )
  1093. {
  1094. pRenderState->m_VertexFormat = g_pShaderAPI->ComputeVertexFormat( numSnapshots, pSnapshots );
  1095. }
  1096. else
  1097. {
  1098. pRenderState->m_VertexFormat = pRenderState->m_VertexUsage;
  1099. }
  1100. return true;
  1101. }
  1102. //-----------------------------------------------------------------------------
  1103. // go through each param and make sure it is the right type, load textures,
  1104. // compute state snapshots and vertex types, etc.
  1105. //-----------------------------------------------------------------------------
  1106. bool CShaderSystem::InitRenderState( IShader *pShader, int numParams, IMaterialVar **params, ShaderRenderState_t* pRenderState, char const* pMaterialName )
  1107. {
  1108. Assert( !m_pRenderState );
  1109. // Initialize render state flags
  1110. InitRenderStateFlags( pRenderState, numParams, params );
  1111. // Compute state snapshots for each combination of alpha + color
  1112. InitStateSnapshots( pShader, params, pRenderState );
  1113. // Compute other infomation for the render state based on snapshots
  1114. if (pRenderState->m_pSnapshots[0].m_nPassCount == 0)
  1115. {
  1116. Warning( "Material \"%s\":\n No render states in shader \"%s\"\n", pMaterialName, pShader->GetName() );
  1117. return false;
  1118. }
  1119. // Set a couple additional flags based on the render state
  1120. ComputeRenderStateFlagsFromSnapshot( pRenderState );
  1121. // Compute the vertex format + usage from the snapshot
  1122. if ( !ComputeVertexFormatFromSnapshot( params, pRenderState ) )
  1123. {
  1124. // warn.. return a null render state...
  1125. Warning("Material \"%s\":\n Shader \"%s\" can't be used with models!\n", pMaterialName, pShader->GetName() );
  1126. CleanupRenderState( pRenderState );
  1127. return false;
  1128. }
  1129. return true;
  1130. }
  1131. // When you're done with the shader, be sure to call this to clean up
  1132. void CShaderSystem::CleanupRenderState( ShaderRenderState_t* pRenderState )
  1133. {
  1134. if (pRenderState)
  1135. {
  1136. int nSnapshotCount = SnapshotTypeCount();
  1137. // kill context data
  1138. // Indicate no passes for any of the snapshot lists
  1139. RenderPassList_t *pTemp = pRenderState->m_pSnapshots;
  1140. for(int i = 0; i < nSnapshotCount; i++ )
  1141. {
  1142. for(int j = 0 ; j < pRenderState->m_pSnapshots[i].m_nPassCount; j++ )
  1143. {
  1144. if ( pTemp[i].m_pContextData[j] )
  1145. {
  1146. delete pTemp[i].m_pContextData[j];
  1147. pTemp[i].m_pContextData[j] = NULL;
  1148. }
  1149. if ( pTemp[i].m_pInstanceData[j] )
  1150. {
  1151. delete pTemp[i].m_pInstanceData[j];
  1152. pTemp[i].m_pInstanceData[j] = NULL;
  1153. }
  1154. }
  1155. pRenderState->m_pSnapshots[i].m_nPassCount = 0;
  1156. }
  1157. }
  1158. }
  1159. //-----------------------------------------------------------------------------
  1160. // Does the rendering!
  1161. //-----------------------------------------------------------------------------
  1162. void CShaderSystem::DrawElements( IShader *pShader, IMaterialVar **params,
  1163. ShaderRenderState_t* pRenderState,
  1164. VertexCompressionType_t vertexCompression,
  1165. uint32 nMaterialVarChangeTimeStamp,
  1166. uint32 nModulationFlags,
  1167. bool bRenderingPreTessPatchMesh )
  1168. {
  1169. VPROF("CShaderSystem::DrawElements");
  1170. g_pShaderAPI->InvalidateDelayedShaderConstants();
  1171. // Compute modulation...
  1172. int mod = pShader->ComputeModulationFlags( params, ShaderApiParam( g_pShaderAPI ) );
  1173. mod |= nModulationFlags;
  1174. // No snapshots? do nothing.
  1175. if ( pRenderState->m_pSnapshots[mod].m_nPassCount == 0 )
  1176. return;
  1177. int materialVarFlags = params[FLAGS]->GetIntValue();
  1178. // FIXME: need one conditional that we calculate once a frame for debug or not with everything debug under that.
  1179. if ( !IsOSXOpenGL() &&
  1180. ( ( g_config.bMeasureFillRate || g_config.bVisualizeFillRate ) &&
  1181. ( ( materialVarFlags & MATERIAL_VAR_USE_IN_FILLRATE_MODE ) == 0 ) ) )
  1182. {
  1183. DrawMeasureFillRate( pRenderState, mod, vertexCompression );
  1184. }
  1185. else if( ( g_config.bShowNormalMap || g_config.nShowMipLevels == 2 ) &&
  1186. ( IsFlag2Set( params, MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ) ||
  1187. IsFlag2Set( params, MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL ) ) )
  1188. {
  1189. DrawNormalMap( pShader, params, vertexCompression );
  1190. }
  1191. #if defined(DEBUG_DEPTH)
  1192. else if ( mat_debugdepth.GetInt() && ((materialVarFlags & MATERIAL_VAR_NO_DEBUG_OVERRIDE) == 0) )
  1193. {
  1194. int nIndex = 0;
  1195. if ( IsFlagSet( params, MATERIAL_VAR_DECAL ) )
  1196. {
  1197. nIndex |= 0x1;
  1198. }
  1199. IMaterialInternal *pDebugMaterial = m_pDebugMaterials[ MATERIAL_DEBUG_DEPTH + nIndex ];
  1200. if ( !g_pShaderAPI->IsDepthWriteEnabled( pRenderState->m_Snapshots[mod].m_Snapshot[0] ) )
  1201. {
  1202. pDebugMaterial = m_pDebugMaterials[MATERIAL_DEBUG_WIREFRAME];
  1203. }
  1204. DrawUsingMaterial( pDebugMaterial, vertexCompression );
  1205. }
  1206. #endif
  1207. else if( bRenderingPreTessPatchMesh && !IsFlag2Set( params, MATERIAL_VAR2_SUPPORTS_TESSELLATION ) )
  1208. {
  1209. Warning( "Warning error: CShaderSystem::DrawElements: Mesh supports tessellation, but material does not.\n" );
  1210. DrawUsingMaterial( g_pErrorMaterial, vertexCompression );
  1211. }
  1212. else
  1213. {
  1214. g_pShaderAPI->SetDefaultState();
  1215. // If we're rendering flat, turn on flat mode...
  1216. if (materialVarFlags & MATERIAL_VAR_FLAT)
  1217. {
  1218. g_pShaderAPI->ShadeMode( SHADER_FLAT );
  1219. }
  1220. PrepForShaderDraw( pShader, params, pRenderState, mod );
  1221. g_pShaderAPI->BeginPass( CurrentStateSnapshot() );
  1222. CBasePerMaterialContextData ** pContextDataPtr =
  1223. &( m_pRenderState->m_pSnapshots[m_nModulation].m_pContextData[0] );
  1224. if ( *pContextDataPtr && ( (*pContextDataPtr)->m_nVarChangeID != nMaterialVarChangeTimeStamp ) )
  1225. {
  1226. (*pContextDataPtr)->m_bMaterialVarsChanged = true;
  1227. (*pContextDataPtr)->m_nVarChangeID = nMaterialVarChangeTimeStamp;
  1228. }
  1229. pShader->DrawElements(
  1230. params, mod, 0, ShaderApiParam( g_pShaderAPI ), vertexCompression, pContextDataPtr,
  1231. &( m_pRenderState->m_pSnapshots[m_nModulation].m_pInstanceData[0] ) );
  1232. DoneWithShaderDraw();
  1233. }
  1234. MaterialSystem()->ForceDepthFuncEquals( false );
  1235. }
  1236. //-----------------------------------------------------------------------------
  1237. // Are we using graphics?
  1238. //-----------------------------------------------------------------------------
  1239. bool CShaderSystem::IsUsingGraphics() const
  1240. {
  1241. // YWB Hack if running with -noshaderapi/-makereslists this forces materials to "precache" which means they will resolve their .vtf files for
  1242. // things like normal/height/dudv maps...
  1243. if ( m_bForceUsingGraphicsReturnTrue )
  1244. return true;
  1245. return g_pShaderDevice->IsUsingGraphics();
  1246. }
  1247. //-----------------------------------------------------------------------------
  1248. // Are we using the editor materials?
  1249. //-----------------------------------------------------------------------------
  1250. bool CShaderSystem::CanUseEditorMaterials() const
  1251. {
  1252. return MaterialSystem()->GetConfigurationFlags() & MATCONFIG_FLAGS_SUPPORT_EDITOR;
  1253. }
  1254. //-----------------------------------------------------------------------------
  1255. // Takes a snapshot
  1256. //-----------------------------------------------------------------------------
  1257. void CShaderSystem::TakeSnapshot( )
  1258. {
  1259. Assert( m_pRenderState );
  1260. Assert( m_nModulation < SnapshotTypeCount() );
  1261. if ( g_pHardwareConfig->GetDXSupportLevel() >= 92 )
  1262. {
  1263. //enable linear->gamma srgb conversion lookup texture
  1264. g_pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
  1265. g_pShaderShadow->EnableSRGBRead( SHADER_SAMPLER15, true );
  1266. }
  1267. RenderPassList_t& snapshotList = m_pRenderState->m_pSnapshots[m_nModulation];
  1268. // Take a snapshot...
  1269. snapshotList.m_Snapshot[snapshotList.m_nPassCount] = g_pShaderAPI->TakeSnapshot();
  1270. ++snapshotList.m_nPassCount;
  1271. Assert( snapshotList.m_nPassCount <= MAX_RENDER_PASSES );
  1272. }
  1273. //-----------------------------------------------------------------------------
  1274. // Draws a snapshot
  1275. //-----------------------------------------------------------------------------
  1276. void CShaderSystem::DrawSnapshot( const unsigned char *pInstanceCommandBuffer, bool bMakeActualDrawCall )
  1277. {
  1278. Assert( m_pRenderState );
  1279. RenderPassList_t& snapshotList = m_pRenderState->m_pSnapshots[m_nModulation];
  1280. int nPassCount = snapshotList.m_nPassCount;
  1281. Assert( m_nRenderPass < nPassCount );
  1282. if ( bMakeActualDrawCall )
  1283. {
  1284. g_pShaderAPI->RenderPass( pInstanceCommandBuffer, m_nRenderPass, nPassCount );
  1285. }
  1286. g_pShaderAPI->InvalidateDelayedShaderConstants();
  1287. if (++m_nRenderPass < nPassCount)
  1288. {
  1289. g_pShaderAPI->BeginPass( CurrentStateSnapshot() );
  1290. }
  1291. }
  1292. //-----------------------------------------------------------------------------
  1293. //
  1294. // Debugging material methods below
  1295. //
  1296. //-----------------------------------------------------------------------------
  1297. //-----------------------------------------------------------------------------
  1298. // Draws a using a particular material..
  1299. //-----------------------------------------------------------------------------
  1300. void CShaderSystem::DrawUsingMaterial( IMaterialInternal *pMaterial, VertexCompressionType_t vertexCompression )
  1301. {
  1302. ShaderRenderState_t *pRenderState = pMaterial->GetRenderState();
  1303. g_pShaderAPI->SetDefaultState( );
  1304. IShader *pShader = pMaterial->GetShader();
  1305. int nMod = pShader->ComputeModulationFlags( pMaterial->GetShaderParams(), ShaderApiParam( g_pShaderAPI ) );
  1306. PrepForShaderDraw( pShader, pMaterial->GetShaderParams(), pRenderState, nMod );
  1307. g_pShaderAPI->BeginPass( pRenderState->m_pSnapshots[nMod].m_Snapshot[0] );
  1308. pShader->DrawElements( pMaterial->GetShaderParams(), nMod, 0, ShaderApiParam( g_pShaderAPI ), vertexCompression,
  1309. &( pRenderState->m_pSnapshots[nMod].m_pContextData[0] ),
  1310. &( pRenderState->m_pSnapshots[nMod].m_pInstanceData[0] ));
  1311. DoneWithShaderDraw( );
  1312. }
  1313. //-----------------------------------------------------------------------------
  1314. // Copies material vars
  1315. //-----------------------------------------------------------------------------
  1316. void CShaderSystem::CopyMaterialVarToDebugShader( IMaterialInternal *pDebugMaterial, IShader *pShader, IMaterialVar **ppParams, const char *pSrcVarName, const char *pDstVarName )
  1317. {
  1318. bool bFound;
  1319. IMaterialVar *pMaterialVar = pDebugMaterial->FindVar( pDstVarName ? pDstVarName : pSrcVarName, &bFound );
  1320. Assert( bFound );
  1321. for( int i = pShader->GetParamCount(); --i >= 0; )
  1322. {
  1323. if( !Q_stricmp( ppParams[i]->GetName( ), pSrcVarName ) )
  1324. {
  1325. pMaterialVar->CopyFrom( ppParams[i] );
  1326. return;
  1327. }
  1328. }
  1329. pMaterialVar->SetUndefined();
  1330. }
  1331. //-----------------------------------------------------------------------------
  1332. // Draws the puppy in fill rate mode...
  1333. //-----------------------------------------------------------------------------
  1334. void CShaderSystem::DrawMeasureFillRate( ShaderRenderState_t* pRenderState, int mod, VertexCompressionType_t vertexCompression )
  1335. {
  1336. int nPassCount = pRenderState->m_pSnapshots[mod].m_nPassCount;
  1337. IMaterialInternal *pMaterial = m_pDebugMaterials[ MATERIAL_FILL_RATE ];
  1338. bool bFound;
  1339. IMaterialVar *pMaterialVar = pMaterial->FindVar( "$passcount", &bFound );
  1340. pMaterialVar->SetIntValue( nPassCount );
  1341. DrawUsingMaterial( pMaterial, vertexCompression );
  1342. }
  1343. //-----------------------------------------------------------------------------
  1344. // Draws normalmaps
  1345. //-----------------------------------------------------------------------------
  1346. void CShaderSystem::DrawNormalMap( IShader *pShader, IMaterialVar **ppParams, VertexCompressionType_t vertexCompression )
  1347. {
  1348. IMaterialInternal *pDebugMaterial = m_pDebugMaterials[MATERIAL_DEBUG_NORMALMAP];
  1349. if( !g_config.m_bFastNoBump )
  1350. {
  1351. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$bumpmap" );
  1352. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$bumpframe" );
  1353. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$bumptransform" );
  1354. }
  1355. else
  1356. {
  1357. bool bFound;
  1358. IMaterialVar *pMaterialVar = pDebugMaterial->FindVar( "$bumpmap", &bFound );
  1359. Assert( bFound );
  1360. pMaterialVar->SetUndefined();
  1361. }
  1362. DrawUsingMaterial( pDebugMaterial, vertexCompression );
  1363. }
  1364. //-----------------------------------------------------------------------------
  1365. // Draws envmapmask
  1366. //-----------------------------------------------------------------------------
  1367. bool CShaderSystem::DrawEnvmapMask( IShader *pShader, IMaterialVar **ppParams,
  1368. ShaderRenderState_t* pRenderState, VertexCompressionType_t vertexCompression )
  1369. {
  1370. // FIXME! Make this work with fixed function.
  1371. IMaterialInternal *pDebugMaterial = m_pDebugMaterials[ MATERIAL_DEBUG_ENVMAPMASK ];
  1372. bool bFound;
  1373. IMaterialVar *pMaterialVar = pDebugMaterial->FindVar( "$showalpha", &bFound );
  1374. Assert( bFound );
  1375. if( IsFlagSet( ppParams, MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK ) )
  1376. {
  1377. // $bumpmap
  1378. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$bumpmap", "$basetexture" );
  1379. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$bumpframe", "$frame" );
  1380. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$bumptransform", "$basetexturetransform" );
  1381. pMaterialVar->SetIntValue( 1 );
  1382. }
  1383. else if( IsFlagSet( ppParams, MATERIAL_VAR_BASEALPHAENVMAPMASK ) )
  1384. {
  1385. // $basealphaenvmapmask
  1386. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$basetexture" );
  1387. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$frame" );
  1388. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$basetexturetransform" );
  1389. pMaterialVar->SetIntValue( 1 );
  1390. }
  1391. else
  1392. {
  1393. // $envmapmask
  1394. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$envmapmask", "$basetexture" );
  1395. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$envmapmaskframe", "$frame" );
  1396. CopyMaterialVarToDebugShader( pDebugMaterial, pShader, ppParams, "$envmapmasktransform", "$basetexturetransform" );
  1397. pMaterialVar->SetIntValue( 0 );
  1398. }
  1399. if( pDebugMaterial->FindVar( "$basetexture", NULL )->IsTexture() )
  1400. {
  1401. DrawUsingMaterial( pDebugMaterial, vertexCompression );
  1402. return true;
  1403. }
  1404. else
  1405. {
  1406. return false;
  1407. }
  1408. }
  1409. //-----------------------------------------------------------------------------
  1410. //
  1411. // Methods of IShaderSystem lie below
  1412. //
  1413. //-----------------------------------------------------------------------------
  1414. ShaderAPITextureHandle_t CShaderSystem::GetShaderAPITextureBindHandle( ITexture *pTexture, int nFrame, int nTextureChannel )
  1415. {
  1416. Assert( !IsTextureInternalEnvCubemap( static_cast<ITextureInternal*>(pTexture) ) );
  1417. // Bind away baby
  1418. if( pTexture )
  1419. {
  1420. return static_cast<ITextureInternal*>(pTexture)->GetTextureHandle( nFrame, nTextureChannel );
  1421. }
  1422. else
  1423. return INVALID_SHADERAPI_TEXTURE_HANDLE;
  1424. }
  1425. //-----------------------------------------------------------------------------
  1426. // Binds a texture
  1427. //-----------------------------------------------------------------------------
  1428. void CShaderSystem::BindTexture( Sampler_t sampler1, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame /* = 0 */ )
  1429. {
  1430. // The call to IMaterialVar::GetTextureValue should have converted this to a real thing
  1431. Assert( !IsTextureInternalEnvCubemap( static_cast<ITextureInternal*>(pTexture) ) );
  1432. // Bind away baby
  1433. if( pTexture )
  1434. {
  1435. static_cast<ITextureInternal*>(pTexture)->Bind( sampler1, nBindFlags, nFrame );
  1436. }
  1437. }
  1438. void CShaderSystem::BindTexture( Sampler_t sampler1, Sampler_t sampler2, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame /* = 0 */ )
  1439. {
  1440. // The call to IMaterialVar::GetTextureValue should have converted this to a real thing
  1441. Assert( !IsTextureInternalEnvCubemap( static_cast<ITextureInternal*>(pTexture) ) );
  1442. // Bind away baby
  1443. if( pTexture )
  1444. {
  1445. if ( sampler2 == -1 )
  1446. {
  1447. static_cast<ITextureInternal*>(pTexture)->Bind( sampler1, nBindFlags, nFrame );
  1448. }
  1449. else
  1450. {
  1451. static_cast<ITextureInternal*>(pTexture)->Bind( sampler1, nBindFlags, nFrame, sampler2 );
  1452. }
  1453. }
  1454. }
  1455. void CShaderSystem::BindVertexTexture( VertexTextureSampler_t vtSampler, ITexture *pTexture, int nFrame /* = 0 */ )
  1456. {
  1457. if( pTexture )
  1458. {
  1459. static_cast<ITextureInternal*>(pTexture)->BindVertexTexture( vtSampler, nFrame );
  1460. }
  1461. }
  1462. //-----------------------------------------------------------------------------
  1463. //
  1464. // Methods of IShaderInit lie below
  1465. //
  1466. //-----------------------------------------------------------------------------
  1467. //-----------------------------------------------------------------------------
  1468. // Loads a texture
  1469. //-----------------------------------------------------------------------------
  1470. void CShaderSystem::LoadTexture( IMaterialVar *pTextureVar, const char *pTextureGroupName, int nAdditionalCreationFlags /* = 0 */ )
  1471. {
  1472. if (pTextureVar->GetType() != MATERIAL_VAR_TYPE_STRING)
  1473. {
  1474. // This here will cause 'UNDEFINED' material vars
  1475. if (pTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE)
  1476. {
  1477. pTextureVar->SetTextureValue( TextureManager()->ErrorTexture() );
  1478. }
  1479. return;
  1480. }
  1481. // In this case, we have to convert the string into a texture value
  1482. const char *pName = pTextureVar->GetStringValue();
  1483. // Fix cases where people stupidly put a slash at the front of the vtf filename in a vmt. Causes trouble elsewhere.
  1484. if ( pName[0] == CORRECT_PATH_SEPARATOR || pName[1] == CORRECT_PATH_SEPARATOR )
  1485. ++pName;
  1486. ITextureInternal *pTexture;
  1487. // Force local cubemaps when using the editor
  1488. if ( CanUseEditorMaterials() && ( stricmp( pName, "env_cubemap" ) == 0 ) )
  1489. {
  1490. pTexture = (ITextureInternal*)-1;
  1491. }
  1492. else
  1493. {
  1494. pTexture = TextureManager()->FindOrLoadTexture( pName, pTextureGroupName, nAdditionalCreationFlags );
  1495. }
  1496. if( !pTexture )
  1497. {
  1498. if( !g_pShaderDevice->IsUsingGraphics() && ( stricmp( pName, "env_cubemap" ) != 0 ) )
  1499. {
  1500. Warning( "Shader_t::LoadTexture: texture \"%s.vtf\" doesn't exist\n", pName );
  1501. }
  1502. pTexture = TextureManager()->ErrorTexture();
  1503. }
  1504. pTextureVar->SetTextureValue( pTexture );
  1505. }
  1506. //-----------------------------------------------------------------------------
  1507. // Loads a bumpmap
  1508. //-----------------------------------------------------------------------------
  1509. void CShaderSystem::LoadBumpMap( IMaterialVar *pTextureVar, const char *pTextureGroupName, int nAdditionalCreationFlags )
  1510. {
  1511. Assert( pTextureVar );
  1512. if (pTextureVar->GetType() != MATERIAL_VAR_TYPE_STRING)
  1513. {
  1514. // This here will cause 'UNDEFINED' material vars
  1515. if (pTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE)
  1516. {
  1517. pTextureVar->SetTextureValue( TextureManager()->ErrorTexture() );
  1518. }
  1519. return;
  1520. }
  1521. // Convert a string to the actual texture
  1522. ITextureInternal *pTexture;
  1523. pTexture = TextureManager()->FindOrLoadTexture( pTextureVar->GetStringValue(), pTextureGroupName, nAdditionalCreationFlags );
  1524. // FIXME: Make a bumpmap error texture
  1525. if (!pTexture)
  1526. {
  1527. pTexture = TextureManager()->ErrorTexture();
  1528. }
  1529. pTextureVar->SetTextureValue( pTexture );
  1530. }
  1531. //-----------------------------------------------------------------------------
  1532. // Loads a cubemap
  1533. //-----------------------------------------------------------------------------
  1534. void CShaderSystem::LoadCubeMap( IMaterialVar **ppParams, IMaterialVar *pTextureVar, int nAdditionalCreationFlags /* = 0 */ )
  1535. {
  1536. if ( pTextureVar->GetType() != MATERIAL_VAR_TYPE_STRING )
  1537. {
  1538. // This here will cause 'UNDEFINED' material vars
  1539. if (pTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE)
  1540. {
  1541. pTextureVar->SetTextureValue( TextureManager()->ErrorTexture() );
  1542. }
  1543. return;
  1544. }
  1545. if ( stricmp( pTextureVar->GetStringValue(), "env_cubemap" ) == 0 )
  1546. {
  1547. // garymcthack
  1548. // don't have to load anything here. . just set the texture value to something
  1549. // special that says to use the cubemap entity.
  1550. pTextureVar->SetTextureValue( ( ITexture * )-1 );
  1551. SetFlags2( ppParams, MATERIAL_VAR2_USES_ENV_CUBEMAP );
  1552. }
  1553. else
  1554. {
  1555. ITextureInternal *pTexture;
  1556. char textureName[MAX_PATH];
  1557. Q_strncpy( textureName, pTextureVar->GetStringValue(), MAX_PATH );
  1558. if ( HardwareConfig()->GetHDRType() != HDR_TYPE_NONE )
  1559. {
  1560. // Overload the texture name to ".hdr.vtf" (instead of .vtf) if we are running with
  1561. // HDR enabled.
  1562. Q_strncat( textureName, ".hdr", MAX_PATH, COPY_ALL_CHARACTERS );
  1563. }
  1564. pTexture = TextureManager()->FindOrLoadTexture( textureName, TEXTURE_GROUP_CUBE_MAP, nAdditionalCreationFlags );
  1565. // FIXME: Make a cubemap error texture
  1566. if ( !pTexture )
  1567. {
  1568. pTexture = TextureManager()->ErrorTexture();
  1569. }
  1570. pTextureVar->SetTextureValue( pTexture );
  1571. }
  1572. }
  1573. void CShaderSystem::AddShaderComboInformation( const ShaderComboSemantics_t *pSemantics )
  1574. {
  1575. g_pShaderAPI->AddShaderComboInformation( pSemantics );
  1576. }
  1577. #ifdef _PS3
  1578. #include "shadersystem_ps3nonvirt.inl"
  1579. #endif