3DEngineMemory.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. // Original file Copyright Crytek GMBH or its affiliates, used under license.
  13. #ifndef CRYINCLUDE_CRY3DENGINE_3DENGINEMEMORY_H
  14. #define CRYINCLUDE_CRY3DENGINE_3DENGINEMEMORY_H
  15. #pragma once
  16. // The type of pool responsible for temporary allocations within the 3dengine
  17. //
  18. // Note: The header is included here for reasons of devirtualization. If
  19. // included directly from the precompiled header in 3dEngine, the gamedll will
  20. // fail to compile!
  21. #include <CryPool/PoolAlloc.h>
  22. #include <InplaceFactory.h>
  23. using NCryPoolAlloc::CFirstFit; // speed of allocations are crucial, so simply use the first fitting free allocation
  24. using NCryPoolAlloc::CInPlace; //
  25. using NCryPoolAlloc::CMemoryDynamic; // the pool itself will be dynamically allocated
  26. using NCryPoolAlloc::CListItemInPlace; // use inplace items
  27. // Tempororary Pool Holder
  28. class CTemporaryPool
  29. {
  30. private:
  31. // Access granted for 3dEngine to create, destroy and maintain the temporary
  32. // pool for the 3d engine
  33. friend class C3DEngine;
  34. // The static pool instance - one pool to rule them all (temp allocations at least)
  35. static CTemporaryPool* s_Instance;
  36. // The type of the backing temporary pool
  37. typedef CFirstFit<CInPlace<CMemoryDynamic>, CListItemInPlace> TTemporaryPool;
  38. TTemporaryPool Pool;
  39. // A non-recursive critical section guards the pool against concurrent access
  40. typedef CryCriticalSectionNonRecursive TTemporaryPoolLock;
  41. TTemporaryPoolLock Lock;
  42. // Initialize the pool manager.
  43. //
  44. // Allocates the backing storage and initializes the temporary pool
  45. // itself. The backing storage is aligned to 16 bytes to reduce the amount of
  46. // cachelines crossed by the temporary pool
  47. static bool Initialize(size_t poolSize)
  48. {
  49. // Create the object instance
  50. s_Instance = new CTemporaryPool();
  51. if (!s_Instance)
  52. {
  53. CryFatalError("CTemporaryPool::Init(): could not create an instance of CTemporaryPool");
  54. return false;
  55. }
  56. // Allocate the backing storage
  57. uint8* tempPool = reinterpret_cast<uint8*>(CryModuleMemalign(poolSize, 16));
  58. if (!tempPool)
  59. {
  60. CryFatalError("CTemporaryPool::Init(): could not allocate %" PRISIZE_T " bytes for temportary pool", poolSize);
  61. return false;
  62. }
  63. // Initialize the actual pool
  64. s_Instance->Pool.InitMem(poolSize, tempPool);
  65. return true;
  66. }
  67. // Shutdown the temporary pool manager.
  68. //
  69. // Frees the temporary pool
  70. static bool Shutdown()
  71. {
  72. if (s_Instance == NULL)
  73. {
  74. CryFatalError("CTemporaryPool::Shutdown(): no temporary pool instance present");
  75. return false;
  76. }
  77. bool error = false;
  78. CTemporaryPool& instance = *s_Instance;
  79. if (instance.Pool.Data())
  80. {
  81. CryModuleMemalignFree(instance.Pool.Data());
  82. }
  83. else
  84. {
  85. error = true;
  86. }
  87. delete s_Instance;
  88. s_Instance = NULL;
  89. return !error;
  90. }
  91. // Templated construct helper member function using an inplace factory
  92. //
  93. // Called from the templated New<T, Expr> function below. Returns a typed
  94. // pointer to the inplace constructed object.
  95. template<typename T, typename InPlaceFactory>
  96. T* Construct(const InPlaceFactory& factory, void* storage)
  97. {
  98. return reinterpret_cast<T*>(factory.template apply<T>(storage));
  99. }
  100. // Templated destruct helper member function.
  101. //
  102. // Calls the object's destructor and returns a void pointer to the storage
  103. template<typename T>
  104. void* Destruct(T* obj)
  105. {
  106. obj->~T();
  107. return reinterpret_cast<void*>(obj);
  108. }
  109. // Empty private constructor/destructors to prevent clients from creating and
  110. // destroying instances of CTemporaryPool (there should only be one instance
  111. // in the 3DEngine).
  112. CTemporaryPool() {};
  113. ~CTemporaryPool() {};
  114. public:
  115. // Allocate a block of memory with the given size and alignment
  116. void* Allocate(size_t size, size_t align)
  117. {
  118. AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
  119. void* pData = Pool.Allocate<void*>(size, align);
  120. if (pData == NULL)
  121. {
  122. CryFatalError("**** could not allocate %" PRISIZE_T " bytes from temporary pool", size);
  123. }
  124. return Pool.Resolve<void*>(pData);
  125. };
  126. // Allocates memory and constructs object of type 'T'
  127. //
  128. // Note: This method is respects the alignment of 'T' via C99 alignof()
  129. template<typename T, typename Expr>
  130. T* New(const Expr& expr)
  131. {
  132. AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
  133. void* pObjStorage = Pool.Allocate<void*>(sizeof(T), alignof(T));
  134. if (pObjStorage == NULL)
  135. {
  136. CryFatalError("**** could not allocate %d bytes from temporary pool",
  137. (int)sizeof (T));
  138. }
  139. return Construct<T>(expr, pObjStorage);
  140. };
  141. // Allocates memory and constructs object of type 'T'
  142. //
  143. // Note: This method is respects the alignment of 'T' via C99 alignof()
  144. template<typename T>
  145. T* New()
  146. {
  147. AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
  148. void* pObjStorage = Pool.Allocate<void*>(sizeof(T), alignof(T));
  149. if (pObjStorage == NULL)
  150. {
  151. CryFatalError("**** could not allocate %d bytes from temporary pool",
  152. (int)sizeof (T));
  153. }
  154. return Construct<T>(InplaceFactory(), pObjStorage);
  155. };
  156. // Frees a block of memory from the temporary pool
  157. //
  158. void Free(void* ptr)
  159. {
  160. AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
  161. Pool.Free(ptr);
  162. }
  163. // Destroys an object of type 'T' and frees the underlying block of memory
  164. template<typename T>
  165. void Delete(T* ptr)
  166. {
  167. AUTO_LOCK_T(CryCriticalSectionNonRecursive, Lock);
  168. Pool.Free(Destruct<T>(ptr));
  169. }
  170. // Static function to retrieve the static instance of CTemporaryPool
  171. static CTemporaryPool* Get() { return s_Instance; };
  172. void GetMemoryUsage(ICrySizer* pSizer) const
  173. {
  174. pSizer->AddObject(Pool.Data(), Pool.MemSize());
  175. }
  176. };
  177. // A stl compliant scratch allocator that uses the given temporary pool.
  178. template <class Type>
  179. class scratch_allocator
  180. {
  181. public:
  182. typedef Type value_type;
  183. typedef value_type* pointer;
  184. typedef const value_type* const_pointer;
  185. typedef value_type& reference;
  186. typedef const value_type& const_reference;
  187. typedef size_t size_type;
  188. typedef ptrdiff_t difference_type;
  189. template <class value_type1>
  190. struct rebind
  191. {
  192. typedef scratch_allocator<value_type1> other;
  193. };
  194. scratch_allocator() {}
  195. template <class value_type1>
  196. scratch_allocator(const scratch_allocator<value_type1>&) {}
  197. scratch_allocator(const scratch_allocator<value_type>&) {}
  198. ~scratch_allocator() {}
  199. pointer address(reference x) const {return &x; }
  200. const_pointer address(const_reference x) const { return &x; }
  201. // Note: size can be zero - return value will be null in that case
  202. value_type* allocate(size_type n, const void* = 0)
  203. {
  204. if (n != 0)
  205. {
  206. size_type buf_size = n * sizeof(value_type);
  207. void* ret = CTemporaryPool::Get()->Allocate(
  208. buf_size,
  209. alignof(value_type));
  210. return reinterpret_cast<value_type*>(ret);
  211. }
  212. return 0;
  213. }
  214. // Note: size can be zero.
  215. void deallocate(pointer p, [[maybe_unused]] size_type n)
  216. {
  217. if (p != NULL)
  218. {
  219. CTemporaryPool::Get()->Free(p);
  220. }
  221. }
  222. size_type max_size() const { return size_t(-1) / sizeof(value_type); }
  223. void construct(pointer p, const_reference val)
  224. { new (reinterpret_cast<void*>(p))value_type(val); }
  225. void destroy(pointer p) { p->~value_type(); }
  226. void cleanup() {}
  227. size_t get_heap_size() { return 0; }
  228. size_t get_wasted_in_allocation() { return 0; }
  229. size_t get_wasted_in_blocks() { return 0; }
  230. };
  231. // A scratch vector type to use the stl vector
  232. template<typename Type>
  233. class scratch_vector
  234. : public std::vector<Type, scratch_allocator<Type> >
  235. {
  236. };
  237. namespace util
  238. {
  239. extern void* pool_allocate(size_t nSize);
  240. extern void pool_free(void* ptr);
  241. }
  242. #endif // CRYINCLUDE_CRY3DENGINE_3DENGINEMEMORY_H