DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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__