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.

467 lines
16 KiB

  1. //=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
  2. //
  3. // The copyright to the contents herein is the property of Valve, L.L.C.
  4. // The contents may be used and/or copied only with the written permission of
  5. // Valve, L.L.C., or in accordance with the terms and conditions stipulated in
  6. // the agreement/contract under which the contents have been supplied.
  7. //
  8. // $Header: $
  9. // $NoKeywords: $
  10. //
  11. // model loading and caching
  12. //
  13. //=============================================================================
  14. #ifndef IMDLCACHE_H
  15. #define IMDLCACHE_H
  16. #ifdef _WIN32
  17. #pragma once
  18. #endif
  19. #include "tier0/platform.h"
  20. #include "appframework/iappsystem.h"
  21. #include "filesystem.h"
  22. #include "string_t.h"
  23. //-----------------------------------------------------------------------------
  24. // Forward declarations
  25. //-----------------------------------------------------------------------------
  26. struct studiohdr_t;
  27. struct studiohwdata_t;
  28. struct vcollide_t;
  29. struct virtualmodel_t;
  30. struct vertexFileHeader_t;
  31. class KeyValues;
  32. class IDataCacheSection;
  33. class IVTFTexture;
  34. namespace OptimizedModel
  35. {
  36. struct FileHeader_t;
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Reference to a loaded studiomdl
  40. //-----------------------------------------------------------------------------
  41. typedef unsigned short MDLHandle_t;
  42. inline MDLHandle_t VoidPtrToMDLHandle( void *ptr )
  43. {
  44. return ( MDLHandle_t ) ( int ) ( intp ) ptr;
  45. }
  46. inline void* MDLHandleToVirtual( MDLHandle_t hndl )
  47. {
  48. return (void*)(uintp)hndl;
  49. }
  50. enum
  51. {
  52. MDLHANDLE_INVALID = (MDLHandle_t)~0
  53. };
  54. //-----------------------------------------------------------------------------
  55. // Cache data types
  56. //-----------------------------------------------------------------------------
  57. enum MDLCacheDataType_t
  58. {
  59. MDLCACHE_NONE = -1,
  60. // Callbacks to get called when data is loaded or unloaded for these:
  61. MDLCACHE_STUDIOHDR = 0,
  62. MDLCACHE_STUDIOHWDATA,
  63. MDLCACHE_VCOLLIDE,
  64. // Callbacks NOT called when data is loaded or unloaded for these:
  65. MDLCACHE_ANIMBLOCK,
  66. MDLCACHE_VIRTUALMODEL,
  67. MDLCACHE_VERTEXES,
  68. MDLCACHE_DECODEDANIMBLOCK
  69. };
  70. abstract_class IMDLCacheNotify
  71. {
  72. public:
  73. virtual ~IMDLCacheNotify() { };
  74. // Called right after the data is loaded
  75. virtual void OnDataLoaded( MDLCacheDataType_t type, MDLHandle_t handle ) = 0;
  76. // Called right before combiner process data into cache
  77. virtual void OnCombinerPreCache( MDLHandle_t OldHandle, MDLHandle_t NewHandle ) = 0;
  78. // Called right before the data is unloaded
  79. virtual void OnDataUnloaded( MDLCacheDataType_t type, MDLHandle_t handle ) = 0;
  80. virtual bool ShouldSupressLoadWarning( MDLHandle_t handle ) = 0;
  81. };
  82. //-----------------------------------------------------------------------------
  83. // Flags for flushing
  84. //-----------------------------------------------------------------------------
  85. enum MDLCacheFlush_t
  86. {
  87. MDLCACHE_FLUSH_STUDIOHDR = 0x01,
  88. MDLCACHE_FLUSH_STUDIOHWDATA = 0x02,
  89. MDLCACHE_FLUSH_VCOLLIDE = 0x04,
  90. MDLCACHE_FLUSH_ANIMBLOCK = 0x08,
  91. MDLCACHE_FLUSH_VIRTUALMODEL = 0x10,
  92. MDLCACHE_FLUSH_AUTOPLAY = 0x20,
  93. MDLCACHE_FLUSH_VERTEXES = 0x40,
  94. MDLCACHE_FLUSH_COMBINED_DATA = 0x80,
  95. MDLCACHE_FLUSH_IGNORELOCK = 0x80000000,
  96. MDLCACHE_FLUSH_ALL = 0xFFFFFFFF
  97. };
  98. //-----------------------------------------------------------------------------
  99. // Combiner
  100. //-----------------------------------------------------------------------------
  101. #define COMBINER_MAX_MODELS 15
  102. #define COMBINER_MAX_LODS 8
  103. #define COMBINER_MAX_TEXTURES_PER_MATERIAL 5
  104. #define COMBINER_MAX_ATLAS_GROUPS 5
  105. #define COMBINER_MAX_MATERIALS_PER_INPUT_MODEL 4
  106. enum ECombinedResult
  107. {
  108. COMBINE_RESULT_FLAG_OK = 0,
  109. COMBINE_RESULT_FLAG_TOO_MANY_STRINGS,
  110. COMBINE_RESULT_FLAG_OUT_OF_MEMORY,
  111. COMBINE_RESULT_FLAG_TOO_MANY_BONES,
  112. COMBINE_RESULT_FLAG_UNSUPPORTED_FEATURE, // Major feature of the formats that isn't supported. You'll need to debug the specific cause of this.
  113. COMBINE_RESULT_FLAG_UNHANDLED_ISSUE, // Minor section of the formats that wasn't expected. You'll need to debug the specific cause of this.
  114. COMBINE_RESULT_FLAG_MISSING_ASSET_FILE,
  115. COMBINE_RESULT_FLAG_UNSUPPORTED_SHADER,
  116. COMBINE_RESULT_FLAG_FAILED_GOOD_PRACTICE, // Not necessarily an error, but sanity checks to make sure we are doing good practices
  117. COMBINE_RESULT_FLAG_KEY_VALUE_FAILURE,
  118. };
  119. enum EDetailedError
  120. {
  121. COMBINED_DETAIL_ERROR_NOT_SPECIFIED = 0,
  122. COMBINED_DETAIL_ERROR_TEXTURE_PACKER_NO_SPACE,
  123. COMBINED_DETAIL_ERROR_MODEL_PACKER_TOO_MANY_MATERIALS,
  124. COMBINED_DETAIL_ERROR_TEXTURE_COORDINATES_WRAP,
  125. COMBINED_DETAIL_ERROR_MODEL_LOWER_LOD_HIGHER_TRI_COUNT,
  126. };
  127. typedef struct SCombinedResults
  128. {
  129. // individual model info
  130. int m_nNumVerts[ COMBINER_MAX_MODELS ][ COMBINER_MAX_LODS ];
  131. int m_nNumIndexes[ COMBINER_MAX_MODELS ][ COMBINER_MAX_LODS ];
  132. int m_nBatches[ COMBINER_MAX_MODELS ][ COMBINER_MAX_LODS ];
  133. int m_nNumLODs[ COMBINER_MAX_MODELS ];
  134. // cumulative combined info
  135. int m_nCombinedNumVerts[ COMBINER_MAX_LODS ];
  136. int m_nCombinedNumIndexes[ COMBINER_MAX_LODS ];
  137. int m_nCombinedBatches[ COMBINER_MAX_LODS ];
  138. int m_nCombinedNumLODs;
  139. int m_nNumTexturePackIterations;
  140. unsigned int m_nCombinedResults;
  141. char m_szErrorMessage[ 256 ];
  142. char m_szErrorDetails[ 4096 ];
  143. unsigned int m_nDetailedError;
  144. float m_flModelLoadDuration;
  145. float m_flModelCombineDuration;
  146. float m_flTextureLoadDuration;
  147. float m_flTextureCombineDuration;
  148. float m_flEngineProcessingDuration;
  149. } TCombinedResults;
  150. enum ECombinedAsset
  151. {
  152. COMBINED_ASSET_MATERIAL = 0,
  153. COMBINED_ASSET_TEXTURE,
  154. COMBINED_ASSET_MAX
  155. };
  156. enum ECombinerFlags
  157. {
  158. COMBINER_FLAG_THREADING = 0x00000001,
  159. COMBINER_FLAG_NO_DATA_PROCESSING = 0x00000002,
  160. };
  161. struct STextureSubstitute_t
  162. {
  163. STextureSubstitute_t()
  164. : m_iszMaterialParam( NULL_STRING )
  165. , m_pVTFTexture( NULL )
  166. {
  167. }
  168. string_t m_iszMaterialParam;
  169. IVTFTexture *m_pVTFTexture;
  170. };
  171. struct SCombinerModelInput_t
  172. {
  173. SCombinerModelInput_t()
  174. : m_iszModelName( NULL_STRING )
  175. , m_nSkinFamily( 0 )
  176. , m_nBodyGroupSubModelSelection ( -1 )
  177. {
  178. }
  179. SCombinerModelInput_t( string_t iszModelName, int nSkinFamily = 0, int nBodyGroupSubModelSelection = -1 )
  180. : m_iszModelName( iszModelName )
  181. , m_nSkinFamily( nSkinFamily )
  182. , m_nBodyGroupSubModelSelection( nBodyGroupSubModelSelection )
  183. {
  184. }
  185. string_t m_iszModelName;
  186. int m_nSkinFamily;
  187. int m_nBodyGroupSubModelSelection; // -1 means no selection, include all body part sub models
  188. STextureSubstitute_t m_textureSubstitutes[ COMBINER_MAX_MATERIALS_PER_INPUT_MODEL ][ COMBINER_MAX_TEXTURES_PER_MATERIAL ]; // entries can have NULL contents, it means don't substitute (use the one the mdl says)
  189. };
  190. // Callback for the combining process
  191. // pUserData: the pointer you optionally specified in the FinishedCombinedModel() call
  192. // OldHandle: either the temporary model model returned by CreateCombinedModel() or MDLHANDLE_INVALID if reusing an existing handle
  193. // NewHandle: the combined model handle, which may be your reused model handle specified in CreateCombinedModel()
  194. // CombinedResults: various statistical and timing information about the model and combining process
  195. typedef void (*CombinedModelLoadedCallback)( void *pUserData, MDLHandle_t OldHandle, MDLHandle_t NewHandle, TCombinedResults &CombinedResults );
  196. //-----------------------------------------------------------------------------
  197. // The main MDL cacher
  198. //-----------------------------------------------------------------------------
  199. abstract_class IMDLCache : public IAppSystem
  200. {
  201. public:
  202. // Used to install callbacks for when data is loaded + unloaded
  203. // Returns the prior notify
  204. virtual void SetCacheNotify( IMDLCacheNotify *pNotify ) = 0;
  205. // NOTE: This assumes the "GAME" path if you don't use
  206. // the UNC method of specifying files. This will also increment
  207. // the reference count of the MDL
  208. virtual MDLHandle_t FindMDL( const char *pMDLRelativePath ) = 0;
  209. // Reference counting
  210. virtual int AddRef( MDLHandle_t handle ) = 0;
  211. virtual int Release( MDLHandle_t handle ) = 0;
  212. virtual int GetRef( MDLHandle_t handle ) = 0;
  213. // Gets at the various data associated with a MDL
  214. virtual studiohdr_t *GetStudioHdr( MDLHandle_t handle ) = 0;
  215. virtual studiohwdata_t *GetHardwareData( MDLHandle_t handle ) = 0;
  216. virtual vcollide_t *GetVCollide( MDLHandle_t handle ) = 0;
  217. virtual unsigned char *GetAnimBlock( MDLHandle_t handle, int nBlock, bool preloadIfMissing ) = 0;
  218. virtual bool HasAnimBlockBeenPreloaded( MDLHandle_t handle, int nBlock ) = 0;
  219. virtual virtualmodel_t *GetVirtualModel( MDLHandle_t handle ) = 0;
  220. virtual int GetAutoplayList( MDLHandle_t handle, unsigned short **pOut ) = 0;
  221. virtual vertexFileHeader_t *GetVertexData( MDLHandle_t handle ) = 0;
  222. // Brings all data associated with an MDL into memory
  223. virtual void TouchAllData( MDLHandle_t handle ) = 0;
  224. // Gets/sets user data associated with the MDL
  225. virtual void SetUserData( MDLHandle_t handle, void* pData ) = 0;
  226. virtual void *GetUserData( MDLHandle_t handle ) = 0;
  227. // Is this MDL using the error model?
  228. virtual bool IsErrorModel( MDLHandle_t handle ) = 0;
  229. virtual bool IsOverBudget( MDLHandle_t handle ) = 0;
  230. // Flushes the cache, force a full discard
  231. virtual void Flush( MDLCacheFlush_t nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0;
  232. // Flushes a particular model out of memory
  233. virtual void Flush( MDLHandle_t handle, int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0;
  234. // Returns the name of the model (its relative path)
  235. virtual const char *GetModelName( MDLHandle_t handle ) = 0;
  236. virtual IDataCacheSection *GetCacheSection( MDLCacheDataType_t type ) =0;
  237. // faster access when you already have the studiohdr
  238. virtual virtualmodel_t *GetVirtualModelFast( const studiohdr_t *pStudioHdr, MDLHandle_t handle ) = 0;
  239. // all cache entries that subsequently allocated or successfully checked
  240. // are considered "locked" and will not be freed when additional memory is needed
  241. virtual void BeginLock() = 0;
  242. // reset all protected blocks to normal
  243. virtual void EndLock() = 0;
  244. // returns a pointer to a counter that is incremented every time the cache has been out of the locked state (EVIL)
  245. virtual int *GetFrameUnlockCounterPtrOLD() = 0;
  246. // Finish all pending async operations
  247. virtual void FinishPendingLoads() = 0;
  248. virtual vcollide_t *GetVCollideEx( MDLHandle_t handle, bool synchronousLoad = true ) = 0;
  249. virtual bool GetVCollideSize( MDLHandle_t handle, int *pVCollideSize ) = 0;
  250. virtual bool GetAsyncLoad( MDLCacheDataType_t type ) = 0;
  251. virtual bool SetAsyncLoad( MDLCacheDataType_t type, bool bAsync ) = 0;
  252. virtual void BeginMapLoad() = 0;
  253. virtual void EndMapLoad() = 0;
  254. virtual void MarkAsLoaded( MDLHandle_t handle ) = 0;
  255. virtual void InitPreloadData( bool rebuild ) = 0;
  256. virtual void ShutdownPreloadData() = 0;
  257. virtual bool IsDataLoaded( MDLHandle_t handle, MDLCacheDataType_t type ) = 0;
  258. virtual int *GetFrameUnlockCounterPtr( MDLCacheDataType_t type ) = 0;
  259. virtual studiohdr_t *LockStudioHdr( MDLHandle_t handle ) = 0;
  260. virtual void UnlockStudioHdr( MDLHandle_t handle ) = 0;
  261. virtual bool PreloadModel( MDLHandle_t handle ) = 0;
  262. // Hammer uses this. If a model has an error loading in GetStudioHdr, then it is flagged
  263. // as an error model and any further attempts to load it will just get the error model.
  264. // That is, until you call this function. Then it will load the correct model.
  265. virtual void ResetErrorModelStatus( MDLHandle_t handle ) = 0;
  266. virtual void MarkFrame() = 0;
  267. // Locking for things that we can lock over longer intervals than
  268. // resources locked by BeginLock/EndLock
  269. virtual void BeginCoarseLock() = 0;
  270. virtual void EndCoarseLock() = 0;
  271. virtual void ReloadVCollide( MDLHandle_t handle ) = 0;
  272. virtual bool ReleaseAnimBlockAllocator() = 0;
  273. virtual bool RestoreHardwareData( MDLHandle_t handle, FSAsyncControl_t *pAsyncVTXControl, FSAsyncControl_t *pAsyncVVDControl ) = 0;
  274. virtual void DisableVCollideLoad() = 0;
  275. virtual void EnableVCollideLoad() = 0;
  276. virtual void DisableFileNotFoundWarnings() = 0;
  277. virtual void EnableFileNotFoundWarnings() = 0;
  278. virtual bool ProcessPendingHardwareRestore() = 0;
  279. virtual void UnloadQueuedHardwareData( ) = 0;
  280. virtual void DumpDictionaryState( ) = 0;
  281. // ========================
  282. // combined models
  283. // This will create a combined model by the name specified in pszModelName and return back a temporary model handle.
  284. // May return MDLHANDLE_INVALID if the name is a duplicate of an existing model
  285. virtual MDLHandle_t CreateCombinedModel( const char *pszModelName ) = 0;
  286. // This will create a combined model in replace of an existing model handle. The handle should be valid to use during the entire process.
  287. // Returns true if the handle is acceptable to use for the combining process.
  288. virtual bool CreateCombinedModel( MDLHandle_t handle ) = 0;
  289. // Sets the models for the combining process
  290. virtual bool SetCombineModels( MDLHandle_t handle, const CUtlVector< SCombinerModelInput_t > &vecModelsToCombine ) = 0;
  291. // Indicates that you are done with the setup of the combining process. You must specify a callback function and optionally
  292. // a user pointer that will be supplied to you in the callback
  293. virtual bool FinishCombinedModel( MDLHandle_t handle, CombinedModelLoadedCallback pFunc, void *pUserData = NULL ) = 0;
  294. // Lets you query a model handle to see if it is a placeholder returned by CreateCombinedModel()
  295. virtual bool IsCombinedPlaceholder( MDLHandle_t handle ) = 0;
  296. // Lets you query a model handle to see if it is a combined model
  297. virtual bool IsCombinedModel( MDLHandle_t handle ) = 0;
  298. // Returns the number of models contained in the combined model. Includes primary and all secondary models
  299. virtual int GetNumCombinedSubModels( MDLHandle_t handle ) = 0;
  300. // Gets the file name for a sub model
  301. virtual void GetCombinedSubModelFilename( MDLHandle_t handle, int nSubModelIndex, char *pszResult, int nResultSize ) = 0;
  302. // Returns the KV of the material set for the model. You are responsible for calling deleteThis() on the result.
  303. virtual KeyValues *GetCombinedMaterialKV( MDLHandle_t handle, int nAtlasGroup = 0 ) = 0;
  304. // Internal engine use function to help drive the combining process.
  305. virtual void UpdateCombiner( ) = 0; // should be called from main thread after rendering has completed
  306. // Internal engine function to help get access to specific combined assets
  307. virtual void *GetCombinedInternalAsset( ECombinedAsset AssetType, const char *pszAssetID = NULL, int *nSize = NULL ) = 0;
  308. // Set Combiner Flags
  309. virtual void SetCombinerFlags( unsigned nFlags ) = 0;
  310. // Clear Combiner Flags
  311. virtual void ClearCombinerFlags( unsigned nFlags ) = 0;
  312. // Dump out resident combiner info
  313. virtual void DebugCombinerInfo( ) = 0;
  314. };
  315. DECLARE_TIER3_INTERFACE( IMDLCache, g_pMDLCache );
  316. //-----------------------------------------------------------------------------
  317. // Critical section helper code
  318. //-----------------------------------------------------------------------------
  319. class CMDLCacheCriticalSection
  320. {
  321. public:
  322. CMDLCacheCriticalSection( IMDLCache *pCache ) : m_pCache( pCache )
  323. {
  324. m_pCache->BeginLock();
  325. }
  326. ~CMDLCacheCriticalSection()
  327. {
  328. m_pCache->EndLock();
  329. }
  330. private:
  331. IMDLCache *m_pCache;
  332. };
  333. class CMDLCacheCoarseCriticalSection
  334. {
  335. public:
  336. CMDLCacheCoarseCriticalSection( IMDLCache *pCache ) : m_pCache( pCache )
  337. {
  338. m_pCache->BeginCoarseLock();
  339. }
  340. ~CMDLCacheCoarseCriticalSection()
  341. {
  342. m_pCache->EndCoarseLock();
  343. }
  344. private:
  345. IMDLCache *m_pCache;
  346. };
  347. #define MDCACHE_FINE_GRAINED 1
  348. #if defined(MDCACHE_FINE_GRAINED)
  349. #define MDLCACHE_CRITICAL_SECTION_( pCache ) CMDLCacheCriticalSection cacheCriticalSection(pCache)
  350. #define MDLCACHE_COARSE_LOCK_( pCache ) CMDLCacheCoarseCriticalSection cacheCoarseCriticalSection(pCache)
  351. #elif defined(MDLCACHE_LEVEL_LOCKED)
  352. #define MDLCACHE_CRITICAL_SECTION_( pCache ) ((void)(0))
  353. #define MDLCACHE_COARSE_LOCK_( pCache ) ((void)(0))
  354. #else
  355. #define MDLCACHE_CRITICAL_SECTION_( pCache ) ((void)(0))
  356. #define MDLCACHE_COARSE_LOCK_( pCache ) CMDLCacheCriticalSection cacheCriticalSection(pCache); CMDLCacheCoarseCriticalSection cacheCoarseCriticalSection(pCache)
  357. #endif
  358. #define MDLCACHE_CRITICAL_SECTION() MDLCACHE_CRITICAL_SECTION_(mdlcache)
  359. #define MDLCACHE_COARSE_LOCK() MDLCACHE_COARSE_LOCK_(mdlcache)
  360. #endif // IMDLCACHE_H