VertexCache.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __VERTEXCACHE2_H__
  21. #define __VERTEXCACHE2_H__
  22. const int VERTCACHE_INDEX_MEMORY_PER_FRAME = 31 * 1024 * 1024;
  23. const int VERTCACHE_VERTEX_MEMORY_PER_FRAME = 31 * 1024 * 1024;
  24. const int VERTCACHE_JOINT_MEMORY_PER_FRAME = 256 * 1024;
  25. const int VERTCACHE_NUM_FRAMES = 2;
  26. // there are a lot more static indexes than vertexes, because interactions are just new
  27. // index lists that reference existing vertexes
  28. const int STATIC_INDEX_MEMORY = 31 * 1024 * 1024;
  29. const int STATIC_VERTEX_MEMORY = 31 * 1024 * 1024; // make sure it fits in VERTCACHE_OFFSET_MASK!
  30. // vertCacheHandle_t packs size, offset, and frame number into 64 bits
  31. typedef uint64 vertCacheHandle_t;
  32. const int VERTCACHE_STATIC = 1; // in the static set, not the per-frame set
  33. const int VERTCACHE_SIZE_SHIFT = 1;
  34. const int VERTCACHE_SIZE_MASK = 0x7fffff; // 8 megs
  35. const int VERTCACHE_OFFSET_SHIFT = 24;
  36. const int VERTCACHE_OFFSET_MASK = 0x1ffffff; // 32 megs
  37. const int VERTCACHE_FRAME_SHIFT = 49;
  38. const int VERTCACHE_FRAME_MASK = 0x7fff; // 15 bits = 32k frames to wrap around
  39. const int VERTEX_CACHE_ALIGN = 32;
  40. const int INDEX_CACHE_ALIGN = 16;
  41. const int JOINT_CACHE_ALIGN = 16;
  42. enum cacheType_t {
  43. CACHE_VERTEX,
  44. CACHE_INDEX,
  45. CACHE_JOINT
  46. };
  47. struct geoBufferSet_t {
  48. idIndexBuffer indexBuffer;
  49. idVertexBuffer vertexBuffer;
  50. idJointBuffer jointBuffer;
  51. byte * mappedVertexBase;
  52. byte * mappedIndexBase;
  53. byte * mappedJointBase;
  54. idSysInterlockedInteger indexMemUsed;
  55. idSysInterlockedInteger vertexMemUsed;
  56. idSysInterlockedInteger jointMemUsed;
  57. int allocations; // number of index and vertex allocations combined
  58. };
  59. class idVertexCache {
  60. public:
  61. void Init( bool restart = false );
  62. void Shutdown();
  63. void PurgeAll();
  64. // call on loading a new map
  65. void FreeStaticData();
  66. // this data is only valid for one frame of rendering
  67. vertCacheHandle_t AllocVertex( const void * data, int bytes ) {
  68. return ActuallyAlloc( frameData[listNum], data, bytes, CACHE_VERTEX );
  69. }
  70. vertCacheHandle_t AllocIndex( const void * data, int bytes ) {
  71. return ActuallyAlloc( frameData[listNum], data, bytes, CACHE_INDEX );
  72. }
  73. vertCacheHandle_t AllocJoint( const void * data, int bytes ) {
  74. return ActuallyAlloc( frameData[listNum], data, bytes, CACHE_JOINT );
  75. }
  76. // this data is valid until the next map load
  77. vertCacheHandle_t AllocStaticVertex( const void * data, int bytes ) {
  78. if ( staticData.vertexMemUsed.GetValue() + bytes > STATIC_VERTEX_MEMORY ) {
  79. idLib::FatalError( "AllocStaticVertex failed, increase STATIC_VERTEX_MEMORY" );
  80. }
  81. return ActuallyAlloc( staticData, data, bytes, CACHE_VERTEX );
  82. }
  83. vertCacheHandle_t AllocStaticIndex( const void * data, int bytes ) {
  84. if ( staticData.indexMemUsed.GetValue() + bytes > STATIC_INDEX_MEMORY ) {
  85. idLib::FatalError( "AllocStaticIndex failed, increase STATIC_INDEX_MEMORY" );
  86. }
  87. return ActuallyAlloc( staticData, data, bytes, CACHE_INDEX );
  88. }
  89. byte * MappedVertexBuffer( vertCacheHandle_t handle ) {
  90. release_assert( !CacheIsStatic( handle ) );
  91. const uint64 offset = (int)( handle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
  92. const uint64 frameNum = (int)( handle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  93. release_assert( frameNum == ( currentFrame & VERTCACHE_FRAME_MASK ) );
  94. return frameData[ listNum ].mappedVertexBase + offset;
  95. }
  96. byte * MappedIndexBuffer( vertCacheHandle_t handle ) {
  97. release_assert( !CacheIsStatic( handle ) );
  98. const uint64 offset = (int)( handle >> VERTCACHE_OFFSET_SHIFT ) & VERTCACHE_OFFSET_MASK;
  99. const uint64 frameNum = (int)( handle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  100. release_assert( frameNum == ( currentFrame & VERTCACHE_FRAME_MASK ) );
  101. return frameData[ listNum ].mappedIndexBase + offset;
  102. }
  103. // Returns false if it's been purged
  104. // This can only be called by the front end, the back end should only be looking at
  105. // vertCacheHandle_t that are already validated.
  106. bool CacheIsCurrent( const vertCacheHandle_t handle ) {
  107. const int isStatic = handle & VERTCACHE_STATIC;
  108. if ( isStatic ) {
  109. return true;
  110. }
  111. const uint64 frameNum = (int)( handle >> VERTCACHE_FRAME_SHIFT ) & VERTCACHE_FRAME_MASK;
  112. if ( frameNum != ( currentFrame & VERTCACHE_FRAME_MASK ) ) {
  113. return false;
  114. }
  115. return true;
  116. }
  117. static bool CacheIsStatic( const vertCacheHandle_t handle ) {
  118. return ( handle & VERTCACHE_STATIC ) != 0;
  119. }
  120. // vb/ib is a temporary reference -- don't store it
  121. bool GetVertexBuffer( vertCacheHandle_t handle, idVertexBuffer * vb );
  122. bool GetIndexBuffer( vertCacheHandle_t handle, idIndexBuffer * ib );
  123. bool GetJointBuffer( vertCacheHandle_t handle, idJointBuffer * jb );
  124. void BeginBackEnd();
  125. public:
  126. int currentFrame; // for determining the active buffers
  127. int listNum; // currentFrame % VERTCACHE_NUM_FRAMES
  128. int drawListNum; // (currentFrame-1) % VERTCACHE_NUM_FRAMES
  129. geoBufferSet_t staticData;
  130. geoBufferSet_t frameData[VERTCACHE_NUM_FRAMES];
  131. // High water marks for the per-frame buffers
  132. int mostUsedVertex;
  133. int mostUsedIndex;
  134. int mostUsedJoint;
  135. // Try to make room for <bytes> bytes
  136. vertCacheHandle_t ActuallyAlloc( geoBufferSet_t & vcs, const void * data, int bytes, cacheType_t type );
  137. };
  138. // platform specific code to memcpy into vertex buffers efficiently
  139. // 16 byte alignment is guaranteed
  140. void CopyBuffer( byte * dst, const byte * src, int numBytes );
  141. extern idVertexCache vertexCache;
  142. #endif // __VERTEXCACHE2_H__