AkMemoryMgr.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*******************************************************************************
  2. The content of this file includes portions of the AUDIOKINETIC Wwise Technology
  3. released in source code form as part of the SDK installer package.
  4. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. /// \file
  21. /// Memory Manager namespace.
  22. #ifndef _AKMEMORYMGR_H_
  23. #define _AKMEMORYMGR_H_
  24. #if !defined( AK_OPTIMIZED ) && !( defined AK_DISABLE_MEMDEBUG )
  25. #ifndef AK_MEMDEBUG
  26. #define AK_MEMDEBUG
  27. #endif
  28. #endif
  29. #include <AK/SoundEngine/Common/AkTypes.h>
  30. #include <AK/SoundEngine/Common/AkSoundEngineExport.h>
  31. struct AkMemSettings;
  32. /// Memory category IDs.
  33. enum AkMemID
  34. {
  35. AkMemID_Object, ///< Generic placeholder for allocations tied to the Wwise project.
  36. AkMemID_Event, ///< Events from the Wwise project.
  37. AkMemID_Structure, ///< Structures from the Wwise project.
  38. AkMemID_Media, ///< Media from the Wwise project.
  39. AkMemID_GameObject, ///< Game Objects and related.
  40. AkMemID_Processing, ///< Anything tied to instancing and processing of the DSP graph.
  41. AkMemID_ProcessingPlugin, ///< Plug-in allocations related to the DSP graph.
  42. AkMemID_Streaming, ///< Streaming Manager objects.
  43. AkMemID_StreamingIO, ///< Streaming Manager I/O memory.
  44. AkMemID_SpatialAudio, ///< Spatial audio.
  45. AkMemID_SpatialAudioGeometry, ///< Spatial audio geometry data.
  46. AkMemID_SpatialAudioPaths, ///< Spatial audio paths data.
  47. AkMemID_GameSim, ///< Game Simulator allocations.
  48. AkMemID_MonitorQueue, ///< Monitor Queue.
  49. AkMemID_Profiler, ///< Profiler.
  50. AkMemID_FilePackage, ///< File packager.
  51. AkMemID_SoundEngine, ///< Base sound engine allocations (managers, etc).
  52. AkMemID_Integration, ///< Game engine integration allocations.
  53. AkMemID_JobMgr, ///< Allocations for Sound Engine jobs and job dependencies.
  54. AkMemID_TempAudioRender, ///< Temporary allocations for audio render.
  55. AkMemID_NUM, ///< Category count.
  56. AkMemID_MASK = 0x1FFFFFFF, ///< Mask for category IDs.
  57. AkMemType_Media = 0x20000000, ///< Media memory type bit.
  58. AkMemType_Device = 0x40000000, ///< Device memory type bit.
  59. AkMemType_NoTrack = 0x80000000 ///< Do not track this allocation.
  60. };
  61. namespace AK
  62. {
  63. /// Memory Manager namespace.
  64. /// \remarks The functions in this namespace are thread-safe, unless stated otherwise.
  65. /// \sa
  66. /// - \ref memorymanager
  67. namespace MemoryMgr
  68. {
  69. /// Memory category statistics.
  70. /// \remarks These statistics are not collected in the Release configuration of
  71. /// the default memory manager implementation.
  72. /// \sa
  73. /// - AK::MemoryMgr::GetCategoryStats()
  74. /// - \ref memorymanager
  75. struct CategoryStats
  76. {
  77. // Current state
  78. AkUInt64 uUsed; ///< Used memory (in bytes)
  79. // Statistics
  80. AkUInt64 uPeakUsed; ///< Peak used memory (in bytes)
  81. AkUInt32 uAllocs; ///< Number of allocation calls since initialization
  82. AkUInt32 uFrees; ///< Number of free calls since initialization
  83. };
  84. /// Memory global statistics.
  85. /// \remarks These statistics are not collected in the Release configuration of
  86. /// the default memory manager implementation.
  87. /// \sa
  88. /// - AK::MemoryMgr::GetGlobalStats()
  89. /// - \ref memorymanager
  90. struct GlobalStats
  91. {
  92. AkUInt64 uUsed; ///< Total memory used including all categories (in bytes)
  93. AkUInt64 uDeviceUsed; ///< Total device memory used including all categories (in bytes)
  94. AkUInt64 uReserved; ///< Total reserved memory. (Used and unused). Will return 0 if the reserved memory is not traceable.
  95. AkUInt64 uMax; ///< Maximum total allocation size, specified in the initialization settings through uMemAllocationSizeLimit. Will be 0 if no limit was set.
  96. };
  97. ////////////////////////////////////////////////////////////////////////
  98. /// @name Initialization
  99. //@{
  100. /// Query whether the Memory Manager has been sucessfully initialized.
  101. /// \warning This function is not thread-safe. It should not be called at the same time as MemoryMgr::Init or MemoryMgr::Term.
  102. /// \return True if the Memory Manager is initialized, False otherwise
  103. /// \sa
  104. /// - AK::MemoryMgr::Init()
  105. /// - \ref memorymanager
  106. AK_EXTERNAPIFUNC( bool, IsInitialized )();
  107. /// Terminate the Memory Manager.
  108. /// \warning This function is not thread-safe. It is not valid to allocate memory or otherwise interact with the memory manager during or after this call.
  109. /// \sa
  110. /// - \ref memorymanager
  111. AK_EXTERNAPIFUNC( void, Term )();
  112. /// Performs whatever steps are required to initialize a thread for use with the memory manager.
  113. /// For example initializing thread local storage that the allocator requires to work.
  114. /// The default implementation of the memory manager performs thread initialization automatically and therefore this call is optional.
  115. /// For implementations where the cost of automatically initializing a thread for use with an allocator would be prohibitively expensive
  116. /// this call allows you to perform the initialization once during, for example, thread creation.
  117. /// \sa
  118. /// - AkMemInitForThread
  119. AK_EXTERNAPIFUNC( void, InitForThread )();
  120. /// Allows you to manually terminate a thread for use with the memory manager.
  121. /// The default implementation of the memory manager requires that all threads that interact with the memory manager call this function prior
  122. /// to either their termination or the termination of the memory manager. Threads not created by the sound engine itself will not have this
  123. /// function called for them automatically.
  124. /// Take care to call this function for any thread, not owned by wwise, that may have interacted with the memory manager. For example job system workers.
  125. /// \sa
  126. /// - AkMemTermForThread
  127. AK_EXTERNAPIFUNC( void, TermForThread )();
  128. /// Allows you to "trim" a thread being used with the memory manager.
  129. /// This is a function that will be called periodically by some Wwise-owned threads,
  130. /// so that any thread-local state can be cleaned up in order to return memory for other systems to use.
  131. /// For example, this can be used to return thread-local heaps to global stores or to finalize other deferred operations.
  132. /// This function is only required for optimization purposes and does not have to be defined.
  133. /// Therefore, unlike TermForThread, this is not expected to be called in all scenarios by Wwise.
  134. /// It is also recommended to be called by game engine integrations in any worker threads that run Wwise jobs.
  135. /// Refer to \ref eventmgrthread_jobmgr_best_practices for more information.
  136. /// \sa
  137. /// - AkMemTrimForThread
  138. AK_EXTERNAPIFUNC( void, TrimForThread )();
  139. //@}
  140. ////////////////////////////////////////////////////////////////////////
  141. /// @name Memory Allocation
  142. //@{
  143. #ifdef AK_MEMDEBUG
  144. /// Allocate memory: debug version.
  145. /// \return A pointer to the start of the allocated memory (NULL if the allocation could not be completed)
  146. /// \sa
  147. /// - \ref memorymanager
  148. AK_EXTERNAPIFUNC( void *, dMalloc )(
  149. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  150. size_t in_uSize, ///< Number of bytes to allocate
  151. const char *in_pszFile, ///< Debug file name
  152. AkUInt32 in_uLine ///< Debug line number
  153. );
  154. #endif // AK_MEMDEBUG
  155. /// Allocate memory.
  156. /// \return A pointer to the start of the allocated memory (NULL if the allocation could not be completed)
  157. /// \sa
  158. /// - \ref memorymanager
  159. AK_EXTERNAPIFUNC( void *, Malloc )(
  160. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  161. size_t in_uSize ///< Number of bytes to allocate
  162. );
  163. #ifdef AK_MEMDEBUG
  164. /// Reallocate memory: debug version.
  165. /// \return A pointer to the start of the reallocated memory (NULL if the allocation could not be completed)
  166. /// \sa
  167. /// - \ref memorymanager
  168. AK_EXTERNAPIFUNC( void*, dRealloc )(
  169. AkMemPoolId in_poolId,
  170. void *in_pAlloc,
  171. size_t in_uSize,
  172. const char *in_pszFile,
  173. AkUInt32 in_uLine
  174. );
  175. #endif // AK_MEMDEBUG
  176. /// Reallocate memory.
  177. /// \return A pointer to the start of the reallocated memory (NULL if the allocation could not be completed)
  178. /// \sa
  179. /// - \ref memorymanager
  180. AK_EXTERNAPIFUNC( void *, Realloc )(
  181. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  182. void * in_pAlloc, ///< Pointer to the start of the allocated memory
  183. size_t in_uSize ///< Number of bytes to allocate
  184. );
  185. #ifdef AK_MEMDEBUG
  186. /// Reallocate memory: debug version.
  187. /// \return A pointer to the start of the reallocated memory (NULL if the allocation could not be completed)
  188. /// \sa
  189. /// - \ref memorymanager
  190. AK_EXTERNAPIFUNC( void*, dReallocAligned )(
  191. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  192. void *in_pAlloc, ///< Pointer to the start of the allocated memory
  193. size_t in_uSize, ///< Number of bytes to allocate
  194. AkUInt32 in_uAlignment, ///< Alignment (in bytes)
  195. const char *in_pszFile, ///< Debug file name
  196. AkUInt32 in_uLine ///< Debug line number
  197. );
  198. #endif // AK_MEMDEBUG
  199. /// Reallocate memory.
  200. /// \return A pointer to the start of the reallocated memory (NULL if the allocation could not be completed)
  201. /// \sa
  202. /// - \ref memorymanager
  203. AK_EXTERNAPIFUNC( void *, ReallocAligned )(
  204. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  205. void * in_pAlloc, ///< Pointer to the start of the allocated memory
  206. size_t in_uSize, ///< Number of bytes to allocate
  207. AkUInt32 in_uAlignment ///< Alignment (in bytes)
  208. );
  209. /// Free memory allocated with the memory manager.
  210. /// \sa
  211. /// - \ref memorymanager
  212. AK_EXTERNAPIFUNC( void, Free )(
  213. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  214. void * in_pMemAddress ///< Pointer to the start of memory
  215. );
  216. #ifdef AK_MEMDEBUG
  217. /// Allocate memory with a specific alignment. debug version.
  218. /// \return A pointer to the start of the allocated memory (NULL if the allocation could not be completed)
  219. /// \sa
  220. /// - \ref memorymanager
  221. AK_EXTERNAPIFUNC( void *, dMalign )(
  222. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  223. size_t in_uSize, ///< Number of bytes to allocate
  224. AkUInt32 in_uAlignment, ///< Alignment (in bytes)
  225. const char* in_pszFile, ///< Debug file name
  226. AkUInt32 in_uLine ///< Debug line number
  227. );
  228. #endif // AK_MEMDEBUG
  229. /// Allocate memory with a specific alignment.
  230. /// \return A pointer to the start of the allocated memory (NULL if the allocation could not be completed)
  231. /// \sa
  232. /// - \ref memorymanager
  233. AK_EXTERNAPIFUNC( void *, Malign )(
  234. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  235. size_t in_uSize, ///< Number of bytes to allocate
  236. AkUInt32 in_uAlignment ///< Alignment (in bytes)
  237. );
  238. //@}
  239. ////////////////////////////////////////////////////////////////////////
  240. /// @name Memory Profiling
  241. //@{
  242. /// Get statistics for a given memory category.
  243. /// \note Be aware of the potentially incoherent nature of reporting such information during concurrent modification by multiple threads.
  244. AK_EXTERNAPIFUNC( void, GetCategoryStats )(
  245. AkMemPoolId in_poolId, ///< ID of the memory category (AkMemID)
  246. CategoryStats& out_poolStats ///< Returned statistics.
  247. );
  248. /// Get statistics for overall memory manager usage.
  249. /// \note Be aware of the potentially incoherent nature of reporting such information during concurrent modification by multiple threads.
  250. AK_EXTERNAPIFUNC( void, GetGlobalStats )(
  251. GlobalStats& out_stats ///< Returned statistics.
  252. );
  253. /// Called to start profiling memory usage for one thread (the calling thread).
  254. /// \note Not implementing this will result in the Soundbank tab of the Wwise Profiler to show 0 bytes for memory usage.
  255. AK_EXTERNAPIFUNC( void, StartProfileThreadUsage )(
  256. );
  257. /// Called to stop profiling memory usage for the current thread.
  258. /// \return The amount of memory allocated by this thread since StartProfileThreadUsage was called.
  259. /// \note Not implementing this will result in the Soundbank tab of the Wwise Profiler to show 0 bytes for memory usage.
  260. AK_EXTERNAPIFUNC( AkUInt64, StopProfileThreadUsage )(
  261. );
  262. /// Dumps the currently tracked allocations to a file
  263. /// \note AkMemSettings::uMemoryDebugLevel must be enabled and the build must define AK_MEMDEBUG for this to work
  264. AK_EXTERNAPIFUNC( void, DumpToFile )(
  265. const AkOSChar* pszFilename ///< Filename.
  266. );
  267. //@}
  268. }
  269. /// TempAlloc namespace.
  270. /// \remarks The functions in this namespace are thread-safe, unless stated otherwise.
  271. namespace TempAlloc
  272. {
  273. ////////////////////////////////////////////////////////////////////////
  274. /// @name TempAlloc systems
  275. //@{
  276. /// Temp-alloc memory statistics. Whenever these are fetched, they represent the last completed temp-alloc "tick".
  277. /// \remarks These statistics are not collected in the Release configuration of the memory mgr.
  278. struct Stats
  279. {
  280. AkUInt32 uMemUsed; ///< Used memory (in bytes).
  281. AkUInt32 uMemAllocated; ///< Allocated memory (in bytes).
  282. AkUInt32 uBlocksUsed; ///< Number of individual blocks used.
  283. AkUInt32 uPeakMemUsed; ///< The peak value for uMemUsed since initialization.
  284. AkUInt32 uPeakMemAllocated; ///< The peak value for uMemAllocated since initialization.
  285. AkUInt32 uPeakBlocksUsed; ///< The peak value for uBlocksUsed since initialization.
  286. AkUInt32 uPeakBlockUsed; ///< The peak amount of used memory in any single block since initialization.
  287. };
  288. /// IDs of temporary memory pools used by the sound engine.
  289. enum Type
  290. {
  291. Type_AudioRender,
  292. Type_NUM, // end of the enum list
  293. };
  294. /// Initialization settings for temporary-memory pools. Separate settings are specified for each temporary-memory pool.
  295. struct InitSettings
  296. {
  297. AkUInt32 uMinimumBlockCount; ///< The number of blocks of memory the system is initialized with and is the minimum kept around forever. Defaults to 1. Higher values increase upfront memory use, but can reduce, or eliminate, the creation and destruction of memory blocks over time.
  298. AkUInt32 uMinimumBlockSize; ///< The minimum size of each block. If a new allocation requests a new block of memory, then the new block is the size of the requested allocation times four, and then rounded up to the next multiple of this value. Defaults to 2MiB.
  299. AkUInt32 uMaximumUnusedBlocks; ///< The maximum number of blocks that the system keeps in an unused state, and avoids freeing. Defaults to 1. Higher values do not increase the peak memory use, but do prevent unused memory from being freed, in order to reduce creation and destruction of memory blocks.
  300. // Various debug options for monitoring and analyzing potential issues in usage of the TempAlloc system. All of these are ignored (treated as disabled) in Release configurations.
  301. bool bDebugDetailedStats; ///< Enable to track detailed stats and include them in the detailed stat dump. Detailed stats include the size and quantity of each type of allocation from the system. Disabled by default.
  302. bool bDebugClearMemory; ///< Enable to clear any allocation to a deterministic garbage value. Useful to make sure memory is initialized properly. Disabled by default.
  303. bool bDebugEnableSentinels; ///< Enable to write out sentinels between most allocations to help detect memory overwrites, verified at the end of a tick. Enabled by default. Increases memory usage of blocks slightly.
  304. bool bDebugFlushBlocks; ///< Enable to forcefully release all blocks at the end of a tick and recreate them from scratch every tick. Useful to ensure stale memory is not being accessed. Disabled by default. This might interfere with some stats reporting due to blocks being released between ticks.
  305. bool bDebugStandaloneAllocs; ///< Enable to force the block size to be as small as possible for each allocation (smaller than can be achieved by just setting uMinimumBlockSize to very low values). Useful to investigate memory overruns in-depth, especially in conjunction with other options like bDebugFlushBlocks and the MemoryMgr's stomp allocator. If enabled, bDebugDetailedStats and bDebugEnableSentinels will be disabled. Greatly increases CPU and memory usage.
  306. };
  307. /// Get simple statistics for a given temporary-memory pool
  308. AK_EXTERNAPIFUNC(void, GetStats)(
  309. Type in_eType, ///< Temporary-memory pool type.
  310. Stats& out_stats ///< Returned statistics.
  311. );
  312. /// Get a detailed listing of the allocations into the temp-alloc pool, and output them to a file.
  313. /// \note TempAllocInitSettings::bTrackDetailedStats must be enabled for the specified type to get detailed information about the underlying allocs. Otherwise, only the simple stats are listed.
  314. AK_EXTERNAPIFUNC(void, DumpTempAllocsToFile)(
  315. Type in_eType, ///< Temporary-memory pool type.
  316. const AkOSChar* pszFilename ///< Filename.
  317. );
  318. }
  319. }
  320. #endif // _AKMEMORYMGR_H_