menu
 
Version
2022.1.19.8584

2024.1.6.8842

2023.1.14.8770

2022.1.19.8584

2021.1.14.8108

2019.2.15.7667

2019.1.11.7296

2018.1.11.6987

2017.2.10.6745

2017.1.9.6501

2016.2.6.6153

2015.1.9.5624

menu

Wwise SDK 2022.1.19
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) 2025 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 #elif defined (AK_OUNCE)
83 
84 #else
85 #error AkPlatformFuncs.h: Undefined platform
86 #endif
87 
88 #ifndef AkPrefetchZero
89 #define AkPrefetchZero(___Dest, ___Size)
90 #endif
91 
92 #ifndef AkPrefetchZeroAligned
93 #define AkPrefetchZeroAligned(___Dest, ___Size)
94 #endif
95 
96 #ifndef AkZeroMemAligned
97 #define AkZeroMemAligned(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
98 #endif
99 #ifndef AkZeroMemLarge
100 #define AkZeroMemLarge(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
101 #endif
102 #ifndef AkZeroMemSmall
103 #define AkZeroMemSmall(___Dest, ___Size) AKPLATFORM::AkMemSet(___Dest, 0, ___Size);
104 #endif
105 
106 #ifndef AkAllocaSIMD
107 #ifdef __clang__
108 #if __has_builtin( __builtin_alloca_with_align )
109 #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, 128 )
110 #else
111 // work around alloca alignment issues in versions of clang before 4.0
112 #define AkAllocaSIMD( _size_ ) (void*)( ( ( uintptr_t )AkAlloca( _size_ + 16 ) + 0xF ) & ~0xF )
113 #endif
114 #else
115 #define AkAllocaSIMD( _size_ ) AkAlloca( _size_ )
116 #endif
117 #endif
118 
119 #ifndef AK_THREAD_INIT_CODE
120 #define AK_THREAD_INIT_CODE(_threadProperties)
121 #endif
122 
123 /// Utility functions
124 namespace AK
125 {
126  /// Count non-zero bits.
127  /// \return Number of channels.
129  {
130  AkUInt32 num = 0;
131  while( in_uWord ){ ++num; in_uWord &= in_uWord-1; }
132  return num;
133  }
134 
135  /// Computes the next power of two given a value.
136  /// \return next power of two.
138  {
139  in_uValue--;
140  in_uValue |= in_uValue >> 1;
141  in_uValue |= in_uValue >> 2;
142  in_uValue |= in_uValue >> 4;
143  in_uValue |= in_uValue >> 8;
144  in_uValue |= in_uValue >> 16;
145  in_uValue++;
146  return in_uValue;
147  }
148 
150  {
151  return ( x << r ) | ( x >> ( 32 - r ) );
152  }
153 
155  {
156  return ( x << r ) | ( x >> ( 64 - r ) );
157  }
158 }
159 
160 /// Platform-dependent helpers
161 namespace AKPLATFORM
162 {
164  {
165  AkGetDefaultThreadProperties(out_threadProperties);
166  out_threadProperties.nPriority = AK_THREAD_PRIORITY_ABOVE_NORMAL;
167  }
168 
169 // some platforms will define their own optimized bitscan functions
170 #if !defined(AK_BIT_SCAN_INSTRUCTIONS)
171 
172  // AkPopCount64 returns how many set bits there are in the provided value
173  // e.g. 0b0000`1111`0000`0011 would return 6
174 #if defined(__clang__) || defined (__GNUC__)
176  {
177  return __builtin_popcountll(in_bits);
178  }
179 #else
181  {
182  AkUInt32 num = 0;
183  while (in_bits) { ++num; in_bits &= in_bits - 1; }
184  return num;
185  }
186 #endif
187 
188  // AkPopCount returns how many set bits there are in the provided value
189  // e.g. 0b0000`1111`0000`0011 would return 6
190 #if defined(__clang__) || defined (__GNUC__)
192  {
193  return __builtin_popcount(in_bits);
194  }
195 #else
197  {
198  AkUInt32 num = 0;
199  while (in_bits) { ++num; in_bits &= in_bits - 1; }
200  return num;
201  }
202 #endif
203 
204  // AkBitScanForward returns how many 0s there are until the least-significant-bit is set
205  // (or the length of the param if the value is zero)
206  // e.g. 0b0000`0000`0001`0000 would return 4
207 #if defined _MSC_VER && (defined AK_CPU_X86_64 || defined AK_CPU_ARM_64)
209  {
210  unsigned long ret = 0;
211  _BitScanForward64(&ret, in_bits);
212  return in_bits ? ret : 64;
213  }
214 #elif defined(__clang__) || defined (__GNUC__)
216  {
217  return in_bits ? __builtin_ctzll(in_bits) : 64;
218  }
219 #else
221  {
222  if (in_bits == 0) return 64;
223  AkUInt32 ret = 0;
224  if ((in_bits & 0x00000000FFFFFFFFULL) == 0) { ret += 32; in_bits >>= 32; }
225  if ((in_bits & 0x000000000000FFFFULL) == 0) { ret += 16; in_bits >>= 16; }
226  if ((in_bits & 0x00000000000000FFULL) == 0) { ret += 8; in_bits >>= 8; }
227  if ((in_bits & 0x000000000000000FULL) == 0) { ret += 4; in_bits >>= 4; }
228  if ((in_bits & 0x0000000000000003ULL) == 0) { ret += 2; in_bits >>= 2; }
229  if ((in_bits & 0x0000000000000001ULL) == 0) { ret += 1; in_bits >>= 1; }
230  return ret;
231  }
232 #endif
233 
234 #if defined _MSC_VER
236  {
237  unsigned long ret = 0;
238  _BitScanForward(&ret, in_bits);
239  return in_bits ? ret : 32;
240  }
241 
242 #elif defined(__clang__) || defined (__GNUC__)
244  {
245  return in_bits ? __builtin_ctz(in_bits) : 32;
246  }
247 #else
249  {
250  if (in_bits == 0) return 32;
251  AkUInt32 ret = 0;
252  if ((in_bits & 0x0000FFFFULL) == 0) { ret += 16; in_bits >>= 16; }
253  if ((in_bits & 0x000000FFULL) == 0) { ret += 8; in_bits >>= 8; }
254  if ((in_bits & 0x0000000FULL) == 0) { ret += 4; in_bits >>= 4; }
255  if ((in_bits & 0x00000003ULL) == 0) { ret += 2; in_bits >>= 2; }
256  if ((in_bits & 0x00000001ULL) == 0) { ret += 1; in_bits >>= 1; }
257  return ret;
258  }
259 #endif
260 
261  // AkBitScanReverse returns how many 0s there are after the most-significant-bit is set
262  // (or the length of the param if the value is zero)
263  // e.g. 0b0000`0000`0001`0000 would return 11
264 #if defined _MSC_VER && (defined AK_CPU_X86_64 || defined AK_CPU_ARM_64)
266  {
267  unsigned long ret = 0;
268  _BitScanReverse64(&ret, in_bits);
269  return in_bits ? 63 - ret : 64;
270  }
271 #elif defined(__clang__) || defined (__GNUC__)
273  {
274  return in_bits ? __builtin_clzll(in_bits) : 64;
275  }
276 #else
278  {
279  if (in_bits == 0) return 64;
280  int ret = 0;
281  if ((in_bits & 0xFFFFFFFF00000000ULL) == 0) { ret += 32; in_bits <<= 32; }
282  if ((in_bits & 0xFFFF000000000000ULL) == 0) { ret += 16; in_bits <<= 16; }
283  if ((in_bits & 0xFF00000000000000ULL) == 0) { ret += 8; in_bits <<= 8; }
284  if ((in_bits & 0xF000000000000000ULL) == 0) { ret += 4; in_bits <<= 4; }
285  if ((in_bits & 0xC000000000000000ULL) == 0) { ret += 2; in_bits <<= 2; }
286  if ((in_bits & 0x8000000000000000ULL) == 0) { ret += 1; in_bits <<= 1; }
287  return ret;
288  }
289 #endif
290 
291 #if defined _MSC_VER
293  {
294  unsigned long ret = 0;
295  _BitScanReverse(&ret, in_bits);
296  return in_bits ? 31 - ret : 32;
297  }
298 #elif defined(__clang__) || defined (__GNUC__)
300  {
301  return in_bits ? __builtin_clz(in_bits) : 32;
302  }
303 #else
305  {
306  if (in_bits == 0) return 32;
307  int ret = 0;
308  if ((in_bits & 0xFFFF0000ULL) == 0) { ret += 16; in_bits <<= 16; }
309  if ((in_bits & 0xFF000000ULL) == 0) { ret += 8; in_bits <<= 8; }
310  if ((in_bits & 0xF0000000ULL) == 0) { ret += 4; in_bits <<= 4; }
311  if ((in_bits & 0xC0000000ULL) == 0) { ret += 2; in_bits <<= 2; }
312  if ((in_bits & 0x80000000ULL) == 0) { ret += 1; in_bits <<= 1; }
313  return ret;
314  }
315 #endif
316 
317 #endif // defined(AK_BIT_SCAN_INSTRUCTIONS)
318 
319  // fallback implementations for when platform don't have their own implementation
320 #if !defined(AK_LIMITEDSPINFORZERO)
321  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
322  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
323  {
324  AkInt64 endSpinTime = 0;
325  AkInt64 currentTime = 0;
326  PerformanceCounter(&endSpinTime);
327  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
328  while (true)
329  {
330  // if pval is zero, skip out
331  if (AkAtomicLoad32(in_pVal) == 0)
332  {
333  break;
334  }
335  AkSpinHint();
336 
337  // Check if we've hit the deadline for the timeout
338  PerformanceCounter(&currentTime);
339  if (currentTime > endSpinTime)
340  {
341  break;
342  }
343  }
344  }
345 
346  // Waits for a limited amount of time for in_pVal to get atomically shift from the expected value to the proposed one
347  // returns true if acquisition succeeded
348  inline bool AkLimitedSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
349  {
350  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
351  {
352  return true;
353  }
354 
355  // Cas failed, start the slower evaluation
356  AkInt64 endSpinTime = 0;
357  AkInt64 currentTime = 0;
358  PerformanceCounter(&endSpinTime);
359  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
360  while (true)
361  {
362  // attempt cas to acquire and if successful, skip out
363  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
364  {
365  return true;
366  }
367  AkSpinHint();
368 
369  // Check if we've hit the deadline for the timeout
370  PerformanceCounter(&currentTime);
371  if (currentTime > endSpinTime)
372  {
373  return false;
374  }
375  }
376  }
377 #endif
378 
379  inline void AkSpinWaitForZero(AkAtomic32* in_pVal)
380  {
381  if (AkAtomicLoad32(in_pVal) == 0)
382  {
383  return;
384  }
385 
386  // do a limited spin on-the-spot until in_pVal hits zero
387  AkLimitedSpinForZero(in_pVal);
388 
389  // if in_pVal is still non-zero, then the other thread is either blocked or waiting for us. Yield for real.
390  while (AkAtomicLoad32(in_pVal))
391  AkThreadYield();
392  }
393 
394  // Waits for a limited amount of time for in_pVal to get atomically shift from 0 to 1
395  inline void AkSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
396  {
397  // do a limited spin on-the-spot until in_pVal can successfully hit 1
398  // or if it fails, then the other thread is either blocked or waiting for us. Yield for real.
399  while (!AkLimitedSpinToAcquire(in_pVal, in_proposed, in_expected))
400  {
401  AkThreadYield();
402  }
403  }
404 }
405 
406 #ifndef AK_PERF_RECORDING_RESET
407 #define AK_PERF_RECORDING_RESET()
408 #endif
409 #ifndef AK_PERF_RECORDING_START
410 #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
411 #endif
412 #ifndef AK_PERF_RECORDING_STOP
413 #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
414 #endif
415 
416 #endif // _AK_TOOLS_COMMON_AKPLATFORMFUNCS_H
Audiokinetic namespace.
AkForceInline AkUInt32 AkBitScanReverse64(AkUInt64 in_bits)
int nPriority
Thread priority.
Platform-dependent helpers.
__forceinline int AkAtomicCas32(AkAtomic32 *pDest, long proposed, long expected)
Definition: AkAtomic.h:67
AkForceInline AkUInt32 ROTL32(AkUInt32 x, AkUInt32 r)
AkForceInline AkUInt32 AkPopCount(AkUInt32 in_bits)
#define AK_THREAD_PRIORITY_ABOVE_NORMAL
AkForceInline AkUInt32 AkBitScanForward64(AkUInt64 in_bits)
int32_t AkInt32
Signed 32-bit integer.
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
void AkSpinHint(void)
Definition: AkAtomic.h:42
AkForceInline AkUInt32 AkBitScanReverse(AkUInt32 in_bits)
AkForceInline AkUInt32 GetNextPowerOfTwo(AkUInt32 in_uValue)
AkForceInline void AkGetDefaultThreadProperties(AkThreadProperties &out_threadProperties)
Platform Independent Helper.
void AkLimitedSpinForZero(AkAtomic32 *in_pVal)
AkForceInline AkUInt32 AkBitScanForward(AkUInt32 in_bits)
bool AkLimitedSpinToAcquire(AkAtomic32 *in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
AkReal32 g_fFreqRatio
void AkGetDefaultHighPriorityThreadProperties(AkThreadProperties &out_threadProperties)
AkForceInline AkUInt32 AkPopCount64(AkUInt64 in_bits)
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

Cette page a-t-elle été utile ?

Besoin d'aide ?

Des questions ? Des problèmes ? Besoin de plus d'informations ? Contactez-nous, nous pouvons vous aider !

Visitez notre page d'Aide

Décrivez-nous de votre projet. Nous sommes là pour vous aider.

Enregistrez votre projet et nous vous aiderons à démarrer sans aucune obligation !

Partir du bon pied avec Wwise