Version
menu_open
link
Wwise SDK 2022.1.12
AkPlatformFuncs.h
Go to the documentation of this file.
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 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 // AkPlatformFuncs.h
28 
29 /// \file
30 /// Platform-dependent functions definition.
31 
32 #ifndef _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H
33 #define _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H
34 
37 
38 // Uncomment the following to enable built-in platform profiler markers in the sound engine
39 //#define AK_ENABLE_INSTRUMENT
40 
41 #if defined(AK_WIN)
43 
44 #elif defined (AK_XBOX)
45 #include <AK/Tools/XboxOne/AkPlatformFuncs.h>
46 
47 #elif defined (AK_APPLE)
49 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
50 
51 #elif defined( AK_ANDROID ) || defined ( AK_LINUX_AOSP )
53 
54 #elif defined (AK_PS4)
56 
57 #elif defined (AK_PS5)
59 
60 #elif defined (AK_EMSCRIPTEN)
61 #include <AK/Tools/Emscripten/AkPlatformFuncs.h>
62 
63 #elif defined (AK_LINUX)
64 
65 #ifdef AK_GGP
66 #include <AK/Tools/GGP/AkPlatformFuncs.h>
67 #endif
69 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
70 
71 #elif defined (AK_QNX)
72 #include <AK/Tools/QNX/AkPlatformFuncs.h>
73 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
74 
75 #elif defined (AK_NX)
77 
78 #else
79 #error AkPlatformFuncs.h: Undefined platform
80 #endif
81 
82 #ifndef AkPrefetchZero
83 #define AkPrefetchZero(___Dest, ___Size)
84 #endif
85 
86 #ifndef AkPrefetchZeroAligned
87 #define AkPrefetchZeroAligned(___Dest, ___Size)
88 #endif
89 
90 #ifndef AkZeroMemAligned
91 #define AkZeroMemAligned(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
92 #endif
93 #ifndef AkZeroMemLarge
94 #define AkZeroMemLarge(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
95 #endif
96 #ifndef AkZeroMemSmall
97 #define AkZeroMemSmall(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
98 #endif
99 
100 #ifndef AkAllocaSIMD
101 #ifdef __clang__
102 #if __has_builtin( __builtin_alloca_with_align )
103 #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, 128 )
104 #else
105 // work around alloca alignment issues in versions of clang before 4.0
106 #define AkAllocaSIMD( _size_ ) (void*)( ( ( uintptr_t )AkAlloca( _size_ + 16 ) + 0xF ) & ~0xF )
107 #endif
108 #else
109 #define AkAllocaSIMD( _size_ ) AkAlloca( _size_ )
110 #endif
111 #endif
112 
113 #ifndef AK_THREAD_INIT_CODE
114 #define AK_THREAD_INIT_CODE(_threadProperties)
115 #endif
116 
117 /// Utility functions
118 namespace AK
119 {
120  /// Count non-zero bits.
121  /// \return Number of channels.
123  {
124  AkUInt32 num = 0;
125  while( in_uWord ){ ++num; in_uWord &= in_uWord-1; }
126  return num;
127  }
128 
129  /// Computes the next power of two given a value.
130  /// \return next power of two.
132  {
133  in_uValue--;
134  in_uValue |= in_uValue >> 1;
135  in_uValue |= in_uValue >> 2;
136  in_uValue |= in_uValue >> 4;
137  in_uValue |= in_uValue >> 8;
138  in_uValue |= in_uValue >> 16;
139  in_uValue++;
140  return in_uValue;
141  }
142 
144  {
145  return ( x << r ) | ( x >> ( 32 - r ) );
146  }
147 
149  {
150  return ( x << r ) | ( x >> ( 64 - r ) );
151  }
152 }
153 
154 /// Platform-dependent helpers
155 namespace AKPLATFORM
156 {
158  {
159  AkGetDefaultThreadProperties(out_threadProperties);
160  out_threadProperties.nPriority = AK_THREAD_PRIORITY_ABOVE_NORMAL;
161  }
162 
163 
164 #if defined _MSC_VER && defined AK_CPU_X86_64
165  AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
166  {
167  unsigned long ret = 0;
168  _BitScanForward64(&ret, in_bits);
169  return ret;
170  }
171 #elif __clang__ || defined __GNUG__
173  {
174  return __builtin_ctzll(in_bits);
175  }
176 #else
177  AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
178  {
179  unsigned long ret = 0;
180  if (in_bits)
181  {
182  while ((in_bits & 1ULL) == 0)
183  {
184  in_bits >>= 1;
185  ret++;
186  }
187  }
188  return ret;
189  }
190 #endif
191 
192 #if defined _MSC_VER
193  AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)
194  {
195  unsigned long ret = 0;
196  _BitScanForward(&ret, in_bits);
197  return ret;
198  }
199 
200 #elif __clang__ || defined __GNUG__
202  {
203  return __builtin_ctzl(in_bits);
204  }
205 #else
206  AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)
207  {
208  unsigned long ret = 0;
209  if (in_bits)
210  {
211  while ((in_bits & 1ULL) == 0)
212  {
213  in_bits >>= 1;
214  ret++;
215  }
216  }
217  return ret;
218  }
219 #endif
220 
221  // fallback implementations for when platform don't have their own implementation
222 #if !defined(AK_LIMITEDSPINFORZERO)
223  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
224  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
225  {
226  AkInt64 endSpinTime = 0;
227  AkInt64 currentTime = 0;
228  PerformanceCounter(&endSpinTime);
229  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
230  while (true)
231  {
232  // if pval is zero, skip out
233  if (AkAtomicLoad32(in_pVal) == 0)
234  {
235  break;
236  }
237  AkSpinHint();
238 
239  // Check if we've hit the deadline for the timeout
240  PerformanceCounter(&currentTime);
241  if (currentTime > endSpinTime)
242  {
243  break;
244  }
245  }
246  }
247 
248  // Waits for a limited amount of time for in_pVal to get atomically shift from the expected value to the proposed one
249  // returns true if acquisition succeeded
250  inline bool AkLimitedSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
251  {
252  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
253  {
254  return true;
255  }
256 
257  // Cas failed, start the slower evaluation
258  AkInt64 endSpinTime = 0;
259  AkInt64 currentTime = 0;
260  PerformanceCounter(&endSpinTime);
261  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
262  while (true)
263  {
264  // attempt cas to acquire and if successful, skip out
265  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
266  {
267  return true;
268  }
269  AkSpinHint();
270 
271  // Check if we've hit the deadline for the timeout
272  PerformanceCounter(&currentTime);
273  if (currentTime > endSpinTime)
274  {
275  return false;
276  }
277  }
278  }
279 #endif
280 
281  inline void AkSpinWaitForZero(AkAtomic32* in_pVal)
282  {
283  if (AkAtomicLoad32(in_pVal) == 0)
284  {
285  return;
286  }
287 
288  // do a limited spin on-the-spot until in_pVal hits zero
289  AkLimitedSpinForZero(in_pVal);
290 
291  // if in_pVal is still non-zero, then the other thread is either blocked or waiting for us. Yield for real.
292  while (AkAtomicLoad32(in_pVal))
293  AkThreadYield();
294  }
295 
296  // Waits for a limited amount of time for in_pVal to get atomically shift from 0 to 1
297  inline void AkSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
298  {
299  // do a limited spin on-the-spot until in_pVal can successfully hit 1
300  // or if it fails, then the other thread is either blocked or waiting for us. Yield for real.
301  while (!AkLimitedSpinToAcquire(in_pVal, in_proposed, in_expected))
302  {
303  AkThreadYield();
304  }
305  }
306 }
307 
308 #ifndef AK_PERF_RECORDING_RESET
309 #define AK_PERF_RECORDING_RESET()
310 #endif
311 #ifndef AK_PERF_RECORDING_START
312 #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
313 #endif
314 #ifndef AK_PERF_RECORDING_STOP
315 #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
316 #endif
317 
318 #endif // _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H
Audiokinetic namespace.
int nPriority
Thread priority.
Platform-dependent helpers.
AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
__forceinline int AkAtomicCas32(AkAtomic32 *pDest, long proposed, long expected)
Definition: AkAtomic.h:67
AkForceInline AkUInt32 ROTL32(AkUInt32 x, AkUInt32 r)
#define AK_THREAD_PRIORITY_ABOVE_NORMAL
int32_t AkInt32
Signed 32-bit integer.
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
void AkSpinHint(void)
Definition: AkAtomic.h:42
AkForceInline AkUInt32 GetNextPowerOfTwo(AkUInt32 in_uValue)
AkForceInline void AkGetDefaultThreadProperties(AkThreadProperties &out_threadProperties)
Platform Independent Helper.
void AkLimitedSpinForZero(AkAtomic32 *in_pVal)
bool AkLimitedSpinToAcquire(AkAtomic32 *in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
AkReal32 g_fFreqRatio
void AkGetDefaultHighPriorityThreadProperties(AkThreadProperties &out_threadProperties)
int64_t AkInt64
Signed 64-bit integer.
AkForceInline AkUInt32 GetNumNonZeroBits(AkUInt32 in_uWord)
uint64_t AkUInt64
Unsigned 64-bit integer.
volatile long AkAtomic32
Definition: AkAtomic.h:42
AkForceInline AkUInt64 ROTL64(AkUInt64 x, AkUInt64 r)
void AkSpinToAcquire(AkAtomic32 *in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
void AkSpinWaitForZero(AkAtomic32 *in_pVal)
uint32_t AkUInt32
Unsigned 32-bit integer.
#define AkThreadYield()
Definition: AkAtomic.h:33
#define AkForceInline
Definition: AkTypes.h:63
__forceinline long AkAtomicLoad32(AkAtomic32 *pSrc)
Definition: AkAtomic.h:57
AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise