AkPlatformFuncs.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. // AkPlatformFuncs.h
  21. /// \file
  22. /// Platform-dependent functions definition.
  23. #ifndef _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H
  24. #define _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H
  25. #include <AK/SoundEngine/Common/AkTypes.h>
  26. #include <AK/SoundEngine/Common/AkAtomic.h>
  27. // Uncomment the following to enable built-in platform profiler markers in the sound engine
  28. //#define AK_ENABLE_INSTRUMENT
  29. #if defined(AK_WIN)
  30. #include <AK/Tools/Win32/AkPlatformFuncs.h>
  31. #elif defined (AK_XBOX)
  32. #include <AK/Tools/XboxOne/AkPlatformFuncs.h>
  33. #elif defined (AK_APPLE)
  34. #include <AK/Tools/Mac/AkPlatformFuncs.h>
  35. #include <AK/Tools/POSIX/AkPlatformFuncs.h>
  36. #elif defined( AK_ANDROID ) || defined ( AK_LINUX_AOSP )
  37. #include <AK/Tools/Android/AkPlatformFuncs.h>
  38. #elif defined (AK_PS4)
  39. #include <AK/Tools/PS4/AkPlatformFuncs.h>
  40. #elif defined (AK_PS5)
  41. #include <AK/Tools/PS5/AkPlatformFuncs.h>
  42. #elif defined (AK_EMSCRIPTEN)
  43. #include <AK/Tools/Emscripten/AkPlatformFuncs.h>
  44. #elif defined (AK_LINUX)
  45. #ifdef AK_GGP
  46. #include <AK/Tools/GGP/AkPlatformFuncs.h>
  47. #endif
  48. #include <AK/Tools/Linux/AkPlatformFuncs.h>
  49. #include <AK/Tools/POSIX/AkPlatformFuncs.h>
  50. #elif defined (AK_QNX)
  51. #include <AK/Tools/QNX/AkPlatformFuncs.h>
  52. #include <AK/Tools/POSIX/AkPlatformFuncs.h>
  53. #elif defined (AK_NX)
  54. #include <AK/Tools/NX/AkPlatformFuncs.h>
  55. #else
  56. #error AkPlatformFuncs.h: Undefined platform
  57. #endif
  58. #ifndef AkPrefetchZero
  59. #define AkPrefetchZero(___Dest, ___Size)
  60. #endif
  61. #ifndef AkPrefetchZeroAligned
  62. #define AkPrefetchZeroAligned(___Dest, ___Size)
  63. #endif
  64. #ifndef AkZeroMemAligned
  65. #define AkZeroMemAligned(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
  66. #endif
  67. #ifndef AkZeroMemLarge
  68. #define AkZeroMemLarge(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
  69. #endif
  70. #ifndef AkZeroMemSmall
  71. #define AkZeroMemSmall(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
  72. #endif
  73. #ifndef AkAllocaSIMD
  74. #ifdef __clang__
  75. #if __has_builtin( __builtin_alloca_with_align )
  76. #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, 128 )
  77. #else
  78. // work around alloca alignment issues in versions of clang before 4.0
  79. #define AkAllocaSIMD( _size_ ) (void*)( ( ( uintptr_t )AkAlloca( _size_ + 16 ) + 0xF ) & ~0xF )
  80. #endif
  81. #else
  82. #define AkAllocaSIMD( _size_ ) AkAlloca( _size_ )
  83. #endif
  84. #endif
  85. #ifndef AK_THREAD_INIT_CODE
  86. #define AK_THREAD_INIT_CODE(_threadProperties)
  87. #endif
  88. /// Utility functions
  89. namespace AK
  90. {
  91. /// Count non-zero bits.
  92. /// \return Number of channels.
  93. AkForceInline AkUInt32 GetNumNonZeroBits( AkUInt32 in_uWord )
  94. {
  95. AkUInt32 num = 0;
  96. while( in_uWord ){ ++num; in_uWord &= in_uWord-1; }
  97. return num;
  98. }
  99. /// Computes the next power of two given a value.
  100. /// \return next power of two.
  101. AkForceInline AkUInt32 GetNextPowerOfTwo( AkUInt32 in_uValue )
  102. {
  103. in_uValue--;
  104. in_uValue |= in_uValue >> 1;
  105. in_uValue |= in_uValue >> 2;
  106. in_uValue |= in_uValue >> 4;
  107. in_uValue |= in_uValue >> 8;
  108. in_uValue |= in_uValue >> 16;
  109. in_uValue++;
  110. return in_uValue;
  111. }
  112. AkForceInline AkUInt32 ROTL32( AkUInt32 x, AkUInt32 r )
  113. {
  114. return ( x << r ) | ( x >> ( 32 - r ) );
  115. }
  116. AkForceInline AkUInt64 ROTL64( AkUInt64 x, AkUInt64 r )
  117. {
  118. return ( x << r ) | ( x >> ( 64 - r ) );
  119. }
  120. }
  121. /// Platform-dependent helpers
  122. namespace AKPLATFORM
  123. {
  124. inline void AkGetDefaultHighPriorityThreadProperties(AkThreadProperties& out_threadProperties)
  125. {
  126. AkGetDefaultThreadProperties(out_threadProperties);
  127. out_threadProperties.nPriority = AK_THREAD_PRIORITY_ABOVE_NORMAL;
  128. }
  129. #if defined _MSC_VER && defined AK_CPU_X86_64
  130. AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
  131. {
  132. unsigned long ret = 0;
  133. _BitScanForward64(&ret, in_bits);
  134. return ret;
  135. }
  136. #elif __clang__ || defined __GNUG__
  137. AkForceInline AkUInt32 AkBitScanForward64(AkUInt64 in_bits)
  138. {
  139. return __builtin_ctzll(in_bits);
  140. }
  141. #else
  142. AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
  143. {
  144. unsigned long ret = 0;
  145. if (in_bits)
  146. {
  147. while ((in_bits & 1ULL) == 0)
  148. {
  149. in_bits >>= 1;
  150. ret++;
  151. }
  152. }
  153. return ret;
  154. }
  155. #endif
  156. #if defined _MSC_VER
  157. AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)
  158. {
  159. unsigned long ret = 0;
  160. _BitScanForward(&ret, in_bits);
  161. return ret;
  162. }
  163. #elif __clang__ || defined __GNUG__
  164. AkForceInline AkUInt32 AkBitScanForward(AkUInt32 in_bits)
  165. {
  166. return __builtin_ctzl(in_bits);
  167. }
  168. #else
  169. AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)
  170. {
  171. unsigned long ret = 0;
  172. if (in_bits)
  173. {
  174. while ((in_bits & 1ULL) == 0)
  175. {
  176. in_bits >>= 1;
  177. ret++;
  178. }
  179. }
  180. return ret;
  181. }
  182. #endif
  183. // fallback implementation for when platform doesn't have its own implementation
  184. #if !defined(AK_LIMITEDSPINFORZERO)
  185. // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
  186. inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
  187. {
  188. AkInt64 endSpinTime = 0;
  189. AkInt64 currentTime = 0;
  190. PerformanceCounter(&endSpinTime);
  191. endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
  192. while (true)
  193. {
  194. // if pval is zero, skip out
  195. if (AkAtomicLoad32(in_pVal) == 0)
  196. {
  197. break;
  198. }
  199. AkSpinHint();
  200. // Check if we've hit the deadline for the timeout
  201. PerformanceCounter(&currentTime);
  202. if (currentTime > endSpinTime)
  203. {
  204. break;
  205. }
  206. }
  207. }
  208. #endif
  209. inline void AkSpinWaitForZero(AkAtomic32* in_pVal)
  210. {
  211. // do a limited spin on-the-spot until in_pVal hits zero
  212. AkLimitedSpinForZero(in_pVal);
  213. // if in_pVal is still non-zero, then the other thread is either blocked or waiting for us. Yield for real.
  214. while (AkAtomicLoad32(in_pVal))
  215. AkThreadYield();
  216. }
  217. }
  218. #ifndef AK_PERF_RECORDING_RESET
  219. #define AK_PERF_RECORDING_RESET()
  220. #endif
  221. #ifndef AK_PERF_RECORDING_START
  222. #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
  223. #endif
  224. #ifndef AK_PERF_RECORDING_STOP
  225. #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
  226. #endif
  227. #endif // _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H