Version

menu_open
Wwise SDK 2022.1.15
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_HARMONY )
56 
57 #elif defined (AK_PS4)
59 
60 #elif defined (AK_PS5)
62 
63 #elif defined (AK_EMSCRIPTEN)
64 #include <AK/Tools/Emscripten/AkPlatformFuncs.h>
65 
66 #elif defined (AK_LINUX)
67 
68 #ifdef AK_GGP
69 #include <AK/Tools/GGP/AkPlatformFuncs.h>
70 #endif
72 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
73 
74 #elif defined (AK_QNX)
75 #include <AK/Tools/QNX/AkPlatformFuncs.h>
76 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
77 
78 #elif defined (AK_NX)
80 
81 #else
82 #error AkPlatformFuncs.h: Undefined platform
83 #endif
84 
85 #ifndef AkPrefetchZero
86 #define AkPrefetchZero(___Dest, ___Size)
87 #endif
88 
89 #ifndef AkPrefetchZeroAligned
90 #define AkPrefetchZeroAligned(___Dest, ___Size)
91 #endif
92 
93 #ifndef AkZeroMemAligned
94 #define AkZeroMemAligned(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
95 #endif
96 #ifndef AkZeroMemLarge
97 #define AkZeroMemLarge(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
98 #endif
99 #ifndef AkZeroMemSmall
100 #define AkZeroMemSmall(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
101 #endif
102 
103 #ifndef AkAllocaSIMD
104 #ifdef __clang__
105 #if __has_builtin( __builtin_alloca_with_align )
106 #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, 128 )
107 #else
108 // work around alloca alignment issues in versions of clang before 4.0
109 #define AkAllocaSIMD( _size_ ) (void*)( ( ( uintptr_t )AkAlloca( _size_ + 16 ) + 0xF ) & ~0xF )
110 #endif
111 #else
112 #define AkAllocaSIMD( _size_ ) AkAlloca( _size_ )
113 #endif
114 #endif
115 
116 #ifndef AK_THREAD_INIT_CODE
117 #define AK_THREAD_INIT_CODE(_threadProperties)
118 #endif
119 
120 /// Utility functions
121 namespace AK
122 {
123  /// Count non-zero bits.
124  /// \return Number of channels.
126  {
127  AkUInt32 num = 0;
128  while( in_uWord ){ ++num; in_uWord &= in_uWord-1; }
129  return num;
130  }
131 
132  /// Computes the next power of two given a value.
133  /// \return next power of two.
135  {
136  in_uValue--;
137  in_uValue |= in_uValue >> 1;
138  in_uValue |= in_uValue >> 2;
139  in_uValue |= in_uValue >> 4;
140  in_uValue |= in_uValue >> 8;
141  in_uValue |= in_uValue >> 16;
142  in_uValue++;
143  return in_uValue;
144  }
145 
147  {
148  return ( x << r ) | ( x >> ( 32 - r ) );
149  }
150 
152  {
153  return ( x << r ) | ( x >> ( 64 - r ) );
154  }
155 }
156 
157 /// Platform-dependent helpers
158 namespace AKPLATFORM
159 {
161  {
162  AkGetDefaultThreadProperties(out_threadProperties);
163  out_threadProperties.nPriority = AK_THREAD_PRIORITY_ABOVE_NORMAL;
164  }
165 
166 
167 #if defined _MSC_VER && defined AK_CPU_X86_64
168  AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
169  {
170  unsigned long ret = 0;
171  _BitScanForward64(&ret, in_bits);
172  return ret;
173  }
174 #elif __clang__ || defined __GNUG__
176  {
177  return __builtin_ctzll(in_bits);
178  }
179 #else
180  AkForceInline AkUInt32 AkBitScanForward64(unsigned long long in_bits)
181  {
182  unsigned long ret = 0;
183  if (in_bits)
184  {
185  while ((in_bits & 1ULL) == 0)
186  {
187  in_bits >>= 1;
188  ret++;
189  }
190  }
191  return ret;
192  }
193 #endif
194 
195 #if defined _MSC_VER
196  AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)
197  {
198  unsigned long ret = 0;
199  _BitScanForward(&ret, in_bits);
200  return ret;
201  }
202 
203 #elif __clang__ || defined __GNUG__
205  {
206  return __builtin_ctzl(in_bits);
207  }
208 #else
209  AkForceInline AkUInt32 AkBitScanForward(unsigned long in_bits)
210  {
211  unsigned long ret = 0;
212  if (in_bits)
213  {
214  while ((in_bits & 1ULL) == 0)
215  {
216  in_bits >>= 1;
217  ret++;
218  }
219  }
220  return ret;
221  }
222 #endif
223 
224  // fallback implementations for when platform don't have their own implementation
225 #if !defined(AK_LIMITEDSPINFORZERO)
226  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
227  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
228  {
229  AkInt64 endSpinTime = 0;
230  AkInt64 currentTime = 0;
231  PerformanceCounter(&endSpinTime);
232  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
233  while (true)
234  {
235  // if pval is zero, skip out
236  if (AkAtomicLoad32(in_pVal) == 0)
237  {
238  break;
239  }
240  AkSpinHint();
241 
242  // Check if we've hit the deadline for the timeout
243  PerformanceCounter(&currentTime);
244  if (currentTime > endSpinTime)
245  {
246  break;
247  }
248  }
249  }
250 
251  // Waits for a limited amount of time for in_pVal to get atomically shift from the expected value to the proposed one
252  // returns true if acquisition succeeded
253  inline bool AkLimitedSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
254  {
255  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
256  {
257  return true;
258  }
259 
260  // Cas failed, start the slower evaluation
261  AkInt64 endSpinTime = 0;
262  AkInt64 currentTime = 0;
263  PerformanceCounter(&endSpinTime);
264  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
265  while (true)
266  {
267  // attempt cas to acquire and if successful, skip out
268  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
269  {
270  return true;
271  }
272  AkSpinHint();
273 
274  // Check if we've hit the deadline for the timeout
275  PerformanceCounter(&currentTime);
276  if (currentTime > endSpinTime)
277  {
278  return false;
279  }
280  }
281  }
282 #endif
283 
284  inline void AkSpinWaitForZero(AkAtomic32* in_pVal)
285  {
286  if (AkAtomicLoad32(in_pVal) == 0)
287  {
288  return;
289  }
290 
291  // do a limited spin on-the-spot until in_pVal hits zero
292  AkLimitedSpinForZero(in_pVal);
293 
294  // if in_pVal is still non-zero, then the other thread is either blocked or waiting for us. Yield for real.
295  while (AkAtomicLoad32(in_pVal))
296  AkThreadYield();
297  }
298 
299  // Waits for a limited amount of time for in_pVal to get atomically shift from 0 to 1
300  inline void AkSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
301  {
302  // do a limited spin on-the-spot until in_pVal can successfully hit 1
303  // or if it fails, then the other thread is either blocked or waiting for us. Yield for real.
304  while (!AkLimitedSpinToAcquire(in_pVal, in_proposed, in_expected))
305  {
306  AkThreadYield();
307  }
308  }
309 }
310 
311 #ifndef AK_PERF_RECORDING_RESET
312 #define AK_PERF_RECORDING_RESET()
313 #endif
314 #ifndef AK_PERF_RECORDING_START
315 #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
316 #endif
317 #ifndef AK_PERF_RECORDING_STOP
318 #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
319 #endif
320 
321 #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