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