Team Fortress 2 Source Code as on 22/4/2020
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.

146 lines
5.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: CGPUBufferAllocator manages allocation of VBs/IBs from shared memory pools.
  4. // Avoids 4KB physical alloc alignment overhead per VB/IB.
  5. //
  6. // $NoKeywords: $
  7. //
  8. //===========================================================================//
  9. #ifndef GPUBUFFERALLOCATOR_H
  10. #define GPUBUFFERALLOCATOR_H
  11. #ifdef _WIN32
  12. #pragma once
  13. #endif
  14. #ifdef _X360
  15. #include "tier1/utlvector.h"
  16. #include "tier1/convar.h"
  17. class CVertexBuffer;
  18. class CIndexBuffer;
  19. // Only active on X360 atm
  20. #define USE_GPU_BUFFER_ALLOCATOR ( IsX360() )
  21. //-----------------------------------------------------------------------------
  22. // A handle to a buffer pool allocation, held by the allocated VB/IB
  23. //-----------------------------------------------------------------------------
  24. struct GPUBufferHandle_t
  25. {
  26. GPUBufferHandle_t( void ) : nPoolNum( -1 ), pMemory( NULL ), nPoolEntry( -1 ) {}
  27. bool IsValid( void ) { return ( pMemory != NULL ); }
  28. byte * pMemory; // Physical address of the allocation
  29. int nPoolNum; // Identifies the pool
  30. int nPoolEntry; // Identifies this allocation within the pool
  31. };
  32. //-----------------------------------------------------------------------------
  33. // Describes an entry in a CGPUBufferPool
  34. //-----------------------------------------------------------------------------
  35. struct GPUBufferPoolEntry_t
  36. {
  37. int nOffset;
  38. int nSize;
  39. bool bIsVertexBuffer;
  40. union
  41. {
  42. // These are set to NULL by CGPUBufferPool::Free() (called when the VB/IB is destroyed)
  43. CVertexBuffer *pVertexBuffer;
  44. CIndexBuffer *pIndexBuffer;
  45. };
  46. };
  47. //-----------------------------------------------------------------------------
  48. // A single memory block out of which individual VBs/IBs are allocated
  49. //-----------------------------------------------------------------------------
  50. class CGPUBufferPool
  51. {
  52. public:
  53. CGPUBufferPool( int nSize );
  54. virtual ~CGPUBufferPool( void );
  55. // Returns the index (-1 on failure) of a new allocation in the pool, for a buffer of the given size.
  56. int Allocate( int nSize, bool bIsVertexBuffer, void *pObject );
  57. // Frees a given entry (just marks it as freed, the memory will not be reused by Allocate() until CGPUBufferAllocator::Defrag() is called )
  58. void Deallocate( const GPUBufferHandle_t *pHandle );
  59. private:
  60. // NOTE: these values are specialized for X360 and should be #ifdef'd for other target platforms
  61. static const int POOL_ENTRIES_INIT_SIZE = 256;
  62. static const int POOL_ENTRIES_GROW_SIZE = 256;
  63. static const int POOL_ENTRY_ALIGNMENT = 4; // 4-byte alignment required for VB/IB data on XBox360
  64. byte * m_pMemory; // Pointer to the (physical) address of the pool's memory
  65. int m_nSize; // Total size of the pool
  66. int m_nBytesUsed; // High watermark of used memory in the pool
  67. CUtlVector<GPUBufferPoolEntry_t>m_PoolEntries; // Memory-order array of items allocated in the pool
  68. // CGPUBufferAllocator is a friend so that CGPUBufferAllocator::Defrag() can shuffle allocations around
  69. friend class CGPUBufferAllocator;
  70. };
  71. //-----------------------------------------------------------------------------
  72. // Manages a set of memory blocks out of which individual VBs/IBs are allocated
  73. //-----------------------------------------------------------------------------
  74. class CGPUBufferAllocator
  75. {
  76. public:
  77. CGPUBufferAllocator( void );
  78. virtual ~CGPUBufferAllocator( void );
  79. // (De)Allocates memory for a vertex/index buffer:
  80. bool AllocateVertexBuffer( CVertexBuffer *pVertexBuffer, int nBufferSize );
  81. bool AllocateIndexBuffer( CIndexBuffer *pIndexBuffer, int nBufferSize );
  82. void DeallocateVertexBuffer( CVertexBuffer *pVertexBuffer );
  83. void DeallocateIndexBuffer( CIndexBuffer *pIndexBuffer );
  84. // Compact memory to account for freed buffers
  85. // NOTE: this must only be called during map transitions, no rendering must be in flight and everything must be single-threaded!
  86. void Compact();
  87. // Spew statistics about pooled buffer allocations
  88. void SpewStats( bool bBrief = false );
  89. private:
  90. // NOTE: these values are specialized for X360 and should be #ifdef'd for other target platforms
  91. static const int INITIAL_POOL_SIZE = 57*1024*1024 + 256*1024;
  92. static const int ADDITIONAL_POOL_SIZE = 2*1024*1024;
  93. static const int MAX_POOLS = 8;
  94. static const int MAX_BUFFER_SIZE = ADDITIONAL_POOL_SIZE; // 256*1024;
  95. // Allocate a new CGPUBufferPool
  96. bool AllocatePool( int nPoolSize );
  97. // Allocate/deallocate a buffer (type-agnostic)
  98. bool AllocateBuffer( GPUBufferHandle_t *pHandle, int nBufferSize, void *pObject, bool bIsVertexBuffer );
  99. void DeallocateBuffer( const GPUBufferHandle_t *pHandle );
  100. // Make a handle for a given allocation
  101. GPUBufferHandle_t MakeGPUBufferHandle( int nPoolNum, int nPoolEntry );
  102. // Helper for Compact
  103. void MoveBufferMemory( int nDstPool, int *pnDstEntry, int *pnDstOffset, CGPUBufferPool &srcPool, GPUBufferPoolEntry_t &srcEntry );
  104. CGPUBufferPool *m_BufferPools[ MAX_POOLS ];
  105. int m_nBufferPools;
  106. bool m_bEnabled;
  107. CThreadFastMutex m_mutex;
  108. };
  109. // Track non-pooled physallocs, to help tune CGPUBufferAllocator usage:
  110. extern CInterlockedInt g_NumIndividualIBPhysAllocs;
  111. extern CInterlockedInt g_SizeIndividualIBPhysAllocs;
  112. extern CInterlockedInt g_NumIndividualVBPhysAllocs;
  113. extern CInterlockedInt g_SizeIndividualVBPhysAllocs;
  114. #endif // _X360
  115. #endif // GPUBUFFERALLOCATOR_H