Version

menu_open
Attention : vous avez été redirigé vers la plus récente documentation correspondant à votre version générale ( 2022.1.16.8522 ). Si vous souhaitez accéder à la documentation de votre version précise, veuillez télécharger la documentation hors ligne depuis l'Audiokinetic Launcher et sélectionner l'option de documentation Offline dans l'application de création Wwise.
Wwise SDK 2022.1.16
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 // some platforms will define their own optimized bitscan functions
167 #if !defined(AK_BIT_SCAN_INSTRUCTIONS)
168 
169  // AkPopCount64 returns how many set bits there are in the provided value
170  // e.g. 0b0000`1111`0000`0011 would return 6
171 #if defined(__clang__) || defined (__GNUC__)
173  {
174  return __builtin_popcountll(in_bits);
175  }
176 #else
178  {
179  AkUInt32 num = 0;
180  while (in_bits) { ++num; in_bits &= in_bits - 1; }
181  return num;
182  }
183 #endif
184 
185  // AkPopCount returns how many set bits there are in the provided value
186  // e.g. 0b0000`1111`0000`0011 would return 6
187 #if defined(__clang__) || defined (__GNUC__)
189  {
190  return __builtin_popcount(in_bits);
191  }
192 #else
194  {
195  AkUInt32 num = 0;
196  while (in_bits) { ++num; in_bits &= in_bits - 1; }
197  return num;
198  }
199 #endif
200 
201  // AkBitScanForward returns how many 0s there are until the least-significant-bit is set
202  // (or the length of the param if the value is zero)
203  // e.g. 0b0000`0000`0001`0000 would return 4
204 #if defined _MSC_VER && (defined AK_CPU_X86_64 || defined AK_CPU_ARM_64)
206  {
207  unsigned long ret = 0;
208  _BitScanForward64(&ret, in_bits);
209  return in_bits ? ret : 64;
210  }
211 #elif defined(__clang__) || defined (__GNUC__)
213  {
214  return in_bits ? __builtin_ctzll(in_bits) : 64;
215  }
216 #else
218  {
219  if (in_bits == 0) return 64;
220  AkUInt32 ret = 0;
221  if ((in_bits & 0x00000000FFFFFFFFULL) == 0) { ret += 32; in_bits >>= 32; }
222  if ((in_bits & 0x000000000000FFFFULL) == 0) { ret += 16; in_bits >>= 16; }
223  if ((in_bits & 0x00000000000000FFULL) == 0) { ret += 8; in_bits >>= 8; }
224  if ((in_bits & 0x000000000000000FULL) == 0) { ret += 4; in_bits >>= 4; }
225  if ((in_bits & 0x0000000000000003ULL) == 0) { ret += 2; in_bits >>= 2; }
226  if ((in_bits & 0x0000000000000001ULL) == 0) { ret += 1; in_bits >>= 1; }
227  return ret;
228  }
229 #endif
230 
231 #if defined _MSC_VER
233  {
234  unsigned long ret = 0;
235  _BitScanForward(&ret, in_bits);
236  return in_bits ? ret : 32;
237  }
238 
239 #elif defined(__clang__) || defined (__GNUC__)
241  {
242  return in_bits ? __builtin_ctz(in_bits) : 32;
243  }
244 #else
246  {
247  if (in_bits == 0) return 32;
248  AkUInt32 ret = 0;
249  if ((in_bits & 0x0000FFFFULL) == 0) { ret += 16; in_bits >>= 16; }
250  if ((in_bits & 0x000000FFULL) == 0) { ret += 8; in_bits >>= 8; }
251  if ((in_bits & 0x0000000FULL) == 0) { ret += 4; in_bits >>= 4; }
252  if ((in_bits & 0x00000003ULL) == 0) { ret += 2; in_bits >>= 2; }
253  if ((in_bits & 0x00000001ULL) == 0) { ret += 1; in_bits >>= 1; }
254  return ret;
255  }
256 #endif
257 
258  // AkBitScanReverse returns how many 0s there are after the most-significant-bit is set
259  // (or the length of the param if the value is zero)
260  // e.g. 0b0000`0000`0001`0000 would return 11
261 #if defined _MSC_VER && (defined AK_CPU_X86_64 || defined AK_CPU_ARM_64)
263  {
264  unsigned long ret = 0;
265  _BitScanReverse64(&ret, in_bits);
266  return in_bits ? 63 - ret : 64;
267  }
268 #elif defined(__clang__) || defined (__GNUC__)
270  {
271  return in_bits ? __builtin_clzll(in_bits) : 64;
272  }
273 #else
275  {
276  if (in_bits == 0) return 64;
277  int ret = 0;
278  if ((in_bits & 0xFFFFFFFF00000000ULL) == 0) { ret += 32; in_bits <<= 32; }
279  if ((in_bits & 0xFFFF000000000000ULL) == 0) { ret += 16; in_bits <<= 16; }
280  if ((in_bits & 0xFF00000000000000ULL) == 0) { ret += 8; in_bits <<= 8; }
281  if ((in_bits & 0xF000000000000000ULL) == 0) { ret += 4; in_bits <<= 4; }
282  if ((in_bits & 0xC000000000000000ULL) == 0) { ret += 2; in_bits <<= 2; }
283  if ((in_bits & 0x8000000000000000ULL) == 0) { ret += 1; in_bits <<= 1; }
284  return ret;
285  }
286 #endif
287 
288 #if defined _MSC_VER
290  {
291  unsigned long ret = 0;
292  _BitScanReverse(&ret, in_bits);
293  return in_bits ? 31 - ret : 32;
294  }
295 #elif defined(__clang__) || defined (__GNUC__)
297  {
298  return in_bits ? __builtin_clz(in_bits) : 32;
299  }
300 #else
302  {
303  if (in_bits == 0) return 32;
304  int ret = 0;
305  if ((in_bits & 0xFFFF0000ULL) == 0) { ret += 16; in_bits <<= 16; }
306  if ((in_bits & 0xFF000000ULL) == 0) { ret += 8; in_bits <<= 8; }
307  if ((in_bits & 0xF0000000ULL) == 0) { ret += 4; in_bits <<= 4; }
308  if ((in_bits & 0xC0000000ULL) == 0) { ret += 2; in_bits <<= 2; }
309  if ((in_bits & 0x80000000ULL) == 0) { ret += 1; in_bits <<= 1; }
310  return ret;
311  }
312 #endif
313 
314 #endif // defined(AK_BIT_SCAN_INSTRUCTIONS)
315 
316  // fallback implementations for when platform don't have their own implementation
317 #if !defined(AK_LIMITEDSPINFORZERO)
318  // Waits for a limited amount of time for in_pVal to hit zero (without yielding the thread)
319  inline void AkLimitedSpinForZero(AkAtomic32* in_pVal)
320  {
321  AkInt64 endSpinTime = 0;
322  AkInt64 currentTime = 0;
323  PerformanceCounter(&endSpinTime);
324  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
325  while (true)
326  {
327  // if pval is zero, skip out
328  if (AkAtomicLoad32(in_pVal) == 0)
329  {
330  break;
331  }
332  AkSpinHint();
333 
334  // Check if we've hit the deadline for the timeout
335  PerformanceCounter(&currentTime);
336  if (currentTime > endSpinTime)
337  {
338  break;
339  }
340  }
341  }
342 
343  // Waits for a limited amount of time for in_pVal to get atomically shift from the expected value to the proposed one
344  // returns true if acquisition succeeded
345  inline bool AkLimitedSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
346  {
347  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
348  {
349  return true;
350  }
351 
352  // Cas failed, start the slower evaluation
353  AkInt64 endSpinTime = 0;
354  AkInt64 currentTime = 0;
355  PerformanceCounter(&endSpinTime);
356  endSpinTime += AkInt64(AK::g_fFreqRatio * 0.01); // only spin for about 10us
357  while (true)
358  {
359  // attempt cas to acquire and if successful, skip out
360  if (AkAtomicCas32(in_pVal, in_proposed, in_expected))
361  {
362  return true;
363  }
364  AkSpinHint();
365 
366  // Check if we've hit the deadline for the timeout
367  PerformanceCounter(&currentTime);
368  if (currentTime > endSpinTime)
369  {
370  return false;
371  }
372  }
373  }
374 #endif
375 
376  inline void AkSpinWaitForZero(AkAtomic32* in_pVal)
377  {
378  if (AkAtomicLoad32(in_pVal) == 0)
379  {
380  return;
381  }
382 
383  // do a limited spin on-the-spot until in_pVal hits zero
384  AkLimitedSpinForZero(in_pVal);
385 
386  // if in_pVal is still non-zero, then the other thread is either blocked or waiting for us. Yield for real.
387  while (AkAtomicLoad32(in_pVal))
388  AkThreadYield();
389  }
390 
391  // Waits for a limited amount of time for in_pVal to get atomically shift from 0 to 1
392  inline void AkSpinToAcquire(AkAtomic32* in_pVal, AkInt32 in_proposed, AkInt32 in_expected)
393  {
394  // do a limited spin on-the-spot until in_pVal can successfully hit 1
395  // or if it fails, then the other thread is either blocked or waiting for us. Yield for real.
396  while (!AkLimitedSpinToAcquire(in_pVal, in_proposed, in_expected))
397  {
398  AkThreadYield();
399  }
400  }
401 }
402 
403 #ifndef AK_PERF_RECORDING_RESET
404 #define AK_PERF_RECORDING_RESET()
405 #endif
406 #ifndef AK_PERF_RECORDING_START
407 #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
408 #endif
409 #ifndef AK_PERF_RECORDING_STOP
410 #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )
411 #endif
412 
413 #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