Version
menu_open
link
Target Platform(s):

include/AK/Tools/Win32/AkPlatformFuncs.h

Go to the documentation of this file.
00001 
00002 //
00003 // AkPlatformFuncs.h
00004 //
00005 // Audiokinetic platform-dependent functions definition.
00006 //
00007 // Copyright (c) 2006 Audiokinetic Inc. / All Rights Reserved
00008 //
00010 
00011 #ifndef _AK_PLATFORM_FUNCS_H_
00012 #define _AK_PLATFORM_FUNCS_H_
00013 
00014 #include "malloc.h"
00015 #include <AK/Tools/Common/AkAssert.h>
00016 #include <AK/SoundEngine/Common/AkTypes.h>
00017 #include <windows.h>
00018 //#define AK_ENABLE_PERF_RECORDING
00019 #if defined(AK_ENABLE_PERF_RECORDING)
00020 #include <stdio.h>
00021 #endif
00022 
00023 #ifdef AK_USE_THREAD_EMULATION
00024     #include <AK/Tools/Win32/ThreadEmulation.h>
00025 #endif
00026 
00027 #if defined(_WIN64)
00028 // on 64 bit, removes warning C4985: 'ceil': attributes not present on previous declaration.
00029 // see http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=294649
00030 #include <math.h>
00031 #endif // _WIN64
00032 #include <intrin.h>
00033 
00034 //-----------------------------------------------------------------------------
00035 // Platform-specific thread properties definition.
00036 //-----------------------------------------------------------------------------
00037 struct AkThreadProperties
00038 {
00039     int                 nPriority;      
00040     AkUInt32            dwAffinityMask; 
00041     AkUInt32            uStackSize;     
00042 };
00043 
00044 //-----------------------------------------------------------------------------
00045 // External variables.
00046 //-----------------------------------------------------------------------------
00047 // g_fFreqRatio is used by time helpers to return time values in milliseconds.
00048 // It is declared and updated by the sound engine.
00049 namespace AK
00050 {
00051     extern AkReal32 g_fFreqRatio;
00052 }
00053 
00054 //-----------------------------------------------------------------------------
00055 // Defines for Win32.
00056 //-----------------------------------------------------------------------------
00057 #define AK_DECLARE_THREAD_ROUTINE( FuncName )   DWORD WINAPI FuncName(LPVOID lpParameter)
00058 #define AK_THREAD_RETURN( _param_ )             return (_param_);
00059 #define AK_THREAD_ROUTINE_PARAMETER             lpParameter
00060 #define AK_GET_THREAD_ROUTINE_PARAMETER_PTR(type) reinterpret_cast<type*>( AK_THREAD_ROUTINE_PARAMETER )
00061 #define AK_RETURN_THREAD_OK                     0x00000000
00062 #define AK_RETURN_THREAD_ERROR                  0x00000001
00063 #if defined AK_CPU_X86_64
00064 #define AK_DEFAULT_STACK_SIZE                   (65536)
00065 #else
00066 #define AK_DEFAULT_STACK_SIZE                   (32768)
00067 #endif
00068 #define AK_THREAD_PRIORITY_NORMAL               THREAD_PRIORITY_NORMAL
00069 #define AK_THREAD_PRIORITY_ABOVE_NORMAL         THREAD_PRIORITY_ABOVE_NORMAL
00070 
00071 // NULL objects
00072 #define AK_NULL_THREAD                          NULL
00073 
00074 #define AK_INFINITE                             INFINITE
00075 
00076 #define AkMakeLong(a,b)                         MAKELONG((a),(b))
00077 
00078 #define AkMax(x1, x2)   (((x1) > (x2))? (x1): (x2))
00079 #define AkMin(x1, x2)   (((x1) < (x2))? (x1): (x2))
00080 #define AkClamp(x, min, max)  ((x) < (min)) ? (min) : (((x) > (max) ? (max) : (x)))
00081 
00082 namespace AKPLATFORM
00083 {
00084     // Simple automatic event API
00085     // ------------------------------------------------------------------
00086     
00088     inline void AkClearEvent( AkEvent & out_event )
00089     {
00090         out_event = NULL;
00091     }
00092 
00094     inline AKRESULT AkCreateEvent( AkEvent & out_event )
00095     {
00096 #ifdef AK_USE_METRO_API
00097         out_event = CreateEventEx(nullptr, nullptr, 0, STANDARD_RIGHTS_ALL|EVENT_MODIFY_STATE);
00098 #else
00099         out_event = ::CreateEvent( NULL,                    // No security attributes
00100                                     false,                  // Reset type: automatic
00101                                     false,                  // Initial signaled state: not signaled
00102                                     NULL                    // No name
00103                                    );
00104 #endif
00105         return ( out_event ) ? AK_Success : AK_Fail;
00106     }
00107 
00109     inline void AkDestroyEvent( AkEvent & io_event )
00110     {
00111         if ( io_event )
00112             ::CloseHandle( io_event );
00113         io_event = NULL;
00114     }
00115 
00117     inline void AkWaitForEvent( AkEvent & in_event )
00118     {
00119 #ifdef AK_USE_METRO_API
00120 #ifdef AK_ENABLE_ASSERTS
00121         DWORD dwWaitResult = 
00122 #endif // AK_ENABLE_ASSERTS
00123             ::WaitForSingleObjectEx( in_event, INFINITE, FALSE );
00124         AKASSERT( dwWaitResult == WAIT_OBJECT_0 );
00125 #else
00126         AKVERIFY( ::WaitForSingleObject( in_event, INFINITE ) == WAIT_OBJECT_0 );
00127 #endif
00128     }
00129 
00131     inline void AkSignalEvent( const AkEvent & in_event )
00132     {
00133         AKVERIFY( ::SetEvent( in_event ) );
00134     }
00135 
00136     
00137     // Atomic Operations
00138     // ------------------------------------------------------------------
00139 
00141     inline AkInt32 AkInterlockedIncrement( AkInt32 * pValue )
00142     {
00143         return InterlockedIncrement( pValue );
00144     }
00145 
00147     inline AkInt32 AkInterlockedDecrement( AkInt32 * pValue )
00148     {
00149         return InterlockedDecrement( pValue );
00150     }
00151 
00152 #ifdef AK_CPU_X86_64
00153     inline bool AkInterlockedCompareExchange( volatile AkInt64* io_pDest, AkInt64 in_newValue, AkInt64 in_expectedOldVal )
00154     {
00155         return _InterlockedCompareExchange64(io_pDest, in_newValue, in_expectedOldVal) == in_expectedOldVal;
00156     }
00157 #endif
00158 
00159     inline bool AkInterlockedCompareExchange( volatile AkInt32* io_pDest, AkInt32 in_newValue, AkInt32 in_expectedOldVal )
00160     {
00161         return InterlockedCompareExchange(io_pDest, in_newValue, in_expectedOldVal) == in_expectedOldVal;
00162     }
00163 
00164 #if defined AK_CPU_X86 || defined AK_CPU_ARM
00165     inline bool AkInterlockedCompareExchange( volatile AkIntPtr* io_pDest, AkIntPtr in_newValue, AkIntPtr in_expectedOldVal )
00166     {
00167         return InterlockedCompareExchange((volatile LONG_PTR*)io_pDest, (LONG_PTR)in_newValue, (LONG_PTR)in_expectedOldVal) == in_expectedOldVal;
00168     }
00169 #endif      
00170 
00171     //Ensure that all write operations are complete.  Necessary only on platforms that don't garentee the order of writes.
00172     inline void AkMemoryBarrier() 
00173     {
00174         _ReadWriteBarrier();
00175     }
00176 
00177     // Threads
00178     // ------------------------------------------------------------------
00179 
00181     inline bool AkIsValidThread( AkThread * in_pThread )
00182     {
00183         return (*in_pThread != AK_NULL_THREAD);
00184     }
00185 
00187     inline void AkClearThread( AkThread * in_pThread )
00188     {
00189         *in_pThread = AK_NULL_THREAD;
00190     }
00191 
00193     inline void AkCloseThread( AkThread * in_pThread )
00194     {
00195         AKASSERT( in_pThread );
00196         AKASSERT( *in_pThread );
00197         AKVERIFY( ::CloseHandle( *in_pThread ) );
00198         AkClearThread( in_pThread );
00199     }
00200 
00201 #define AkExitThread( _result ) return _result;
00202 
00204     inline void AkGetDefaultThreadProperties( AkThreadProperties & out_threadProperties )
00205     {
00206         out_threadProperties.nPriority = AK_THREAD_PRIORITY_NORMAL;
00207         out_threadProperties.uStackSize= AK_DEFAULT_STACK_SIZE;
00208         out_threadProperties.dwAffinityMask = 0;
00209     }
00210 
00212     inline void AkSetThreadName( DWORD in_dwThreadID, LPCSTR in_szThreadName )
00213     {
00214 #if defined AK_USE_THREAD_EMULATION
00215         UNREFERENCED_PARAMETER( in_dwThreadID );
00216         UNREFERENCED_PARAMETER( in_szThreadName );
00217 #else
00218         const DWORD MS_VC_EXCEPTION=0x406D1388;
00219 
00220 #pragma pack(push,8)
00221         typedef struct tagTHREADNAME_INFO
00222         {
00223             DWORD dwType;
00224             LPCSTR szName;
00225             DWORD dwThreadID;
00226             DWORD dwFlags;
00227         } THREADNAME_INFO;
00228 #pragma pack(pop)
00229 
00230         THREADNAME_INFO info;
00231         info.dwType = 0x1000;
00232         info.szName = in_szThreadName;
00233         info.dwThreadID = in_dwThreadID;
00234         info.dwFlags = 0;
00235 
00236         __try
00237         {
00238             RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
00239         }
00240 #pragma warning(suppress: 6312 6322)
00241         __except(EXCEPTION_CONTINUE_EXECUTION)
00242         {
00243         }
00244 #endif
00245     }
00246 
00248     inline void AkCreateThread( 
00249         AkThreadRoutine pStartRoutine,                  // Thread routine.
00250         void * pParams,                                 // Routine params.
00251         const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
00252         AkThread * out_pThread,                         // Returned thread handle.
00253         const char * in_szThreadName )                      // Opt thread name.
00254     {
00255         AKASSERT( out_pThread != NULL );
00256         AKASSERT( (in_threadProperties.nPriority >= THREAD_PRIORITY_LOWEST && in_threadProperties.nPriority <= THREAD_PRIORITY_HIGHEST)
00257             || ( in_threadProperties.nPriority == THREAD_PRIORITY_TIME_CRITICAL ) );
00258 
00259 #ifdef AK_USE_THREAD_EMULATION
00260         UNREFERENCED_PARAMETER( in_threadProperties );
00261         UNREFERENCED_PARAMETER( in_szThreadName );
00262        *out_pThread = AK::ThreadEmulation::CreateThread( pStartRoutine,                   // Thread start routine
00263                                        pParams,                         // Thread function parameter
00264                                        0 );                             // Creation flags: create running
00265 #else
00266         DWORD dwThreadID;
00267         *out_pThread = ::CreateThread( NULL,                            // No security attributes
00268                                        in_threadProperties.uStackSize,  // StackSize (0 uses system default)
00269                                        pStartRoutine,                   // Thread start routine
00270                                        pParams,                         // Thread function parameter
00271                                        0,                               // Creation flags: create running
00272                                        &dwThreadID );
00273 
00274         // ::CreateThread() return NULL if it fails.
00275         if ( !*out_pThread )
00276         {
00277             AkClearThread( out_pThread );
00278             return;
00279         }
00280 
00281         // Set thread name.
00282         AkSetThreadName( dwThreadID, in_szThreadName );
00283 
00284         // Set properties.
00285         if ( !::SetThreadPriority( *out_pThread, in_threadProperties.nPriority ) )
00286         {
00287             AKASSERT( !"Failed setting IO thread priority" );
00288             AkCloseThread( out_pThread );
00289             return;
00290         }
00291         if ( in_threadProperties.dwAffinityMask )
00292         {
00293 #ifndef AK_XBOXONE_ADK
00294             if ( !::SetThreadAffinityMask( *out_pThread, in_threadProperties.dwAffinityMask ) )
00295             {
00296                 AKASSERT( !"Failed setting IO thread affinity mask" );
00297                 AkCloseThread( out_pThread );
00298             }
00299 #endif
00300         }
00301 #endif
00302     }
00303 
00305     inline void AkWaitForSingleThread( AkThread * in_pThread )
00306     {
00307         AKASSERT( in_pThread );
00308         AKASSERT( *in_pThread );
00309 #ifdef AK_USE_METRO_API
00310         ::WaitForSingleObjectEx( *in_pThread, INFINITE, FALSE );
00311 #else
00312         ::WaitForSingleObject( *in_pThread, INFINITE );
00313 #endif
00314     }
00315 
00317     inline AkThreadID CurrentThread()
00318     {
00319         return ::GetCurrentThreadId();
00320     }
00321 
00323     inline void AkSleep( AkUInt32 in_ulMilliseconds )
00324     {
00325 #ifdef AK_USE_THREAD_EMULATION
00326         AK::ThreadEmulation::Sleep( in_ulMilliseconds );
00327 #else
00328 		::Sleep( in_ulMilliseconds );
00329 #endif
00330     }
00331 
00332     // Optimized memory functions
00333     // --------------------------------------------------------------------
00334 
00336     inline void AkMemCpy( void * pDest, const void * pSrc, AkUInt32 uSize )
00337     {
00338         memcpy( pDest, pSrc, uSize );
00339     }
00340 
00342     inline void AkMemSet( void * pDest, AkInt32 iVal, AkUInt32 uSize )
00343     {
00344         memset( pDest, iVal, uSize );
00345     }
00346 
00347     // Time functions
00348     // ------------------------------------------------------------------
00349 
00351     inline void PerformanceCounter( AkInt64 * out_piLastTime )
00352     {
00353         ::QueryPerformanceCounter( (LARGE_INTEGER*)out_piLastTime );
00354     }
00355 
00357     inline void PerformanceFrequency( AkInt64 * out_piFreq )
00358     {
00359         ::QueryPerformanceFrequency( (LARGE_INTEGER*)out_piFreq );
00360     }
00361 
00363     inline void UpdatePerformanceFrequency()
00364     {
00365         AkInt64 iFreq;
00366         PerformanceFrequency( &iFreq );
00367         AK::g_fFreqRatio = (AkReal32)( iFreq / 1000 );
00368     }
00369 
00371     inline AkReal32 Elapsed( const AkInt64 & in_iNow, const AkInt64 & in_iStart )
00372     {
00373         return ( in_iNow - in_iStart ) / AK::g_fFreqRatio;
00374     }
00375 
00377     inline AkInt32 AkWideCharToChar( const wchar_t* in_pszUnicodeString,
00378                                      AkUInt32   in_uiOutBufferSize,
00379                                      char*  io_pszAnsiString )
00380     {
00381         int iWritten = ::WideCharToMultiByte(CP_ACP,                                                                    // code page
00382                                     0,                                                                      // performance and mapping flags
00383                                     in_pszUnicodeString,                                                    // wide-character string
00384                                     (int)AkMin( ( (AkUInt32)wcslen( in_pszUnicodeString )), in_uiOutBufferSize-1 ), // number of chars in string : -1 = NULL terminated string.
00385                                     io_pszAnsiString,                                                       // buffer for new string
00386                                     in_uiOutBufferSize,                                                     // size of buffer
00387                                     NULL,                                                                   // default for unmappable chars
00388                                     NULL);                                                                  // set when default char used
00389         io_pszAnsiString[iWritten] = 0;
00390         return iWritten;
00391     }
00392 
00394     inline AkInt32 AkCharToWideChar( const char*    in_pszAnsiString,
00395                                      AkUInt32       in_uiOutBufferSize,
00396                                      void*          io_pvUnicodeStringBuffer )
00397     {
00398         return ::MultiByteToWideChar(   CP_ACP,                             // code page
00399                                         0,                                  // performance and mapping flags
00400                                         in_pszAnsiString,                   // wide-character string
00401                                         -1,                                 // number of chars in string : -1 = NULL terminated string.
00402                                         (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
00403                                         in_uiOutBufferSize);                // size of buffer
00404     }
00405 
00407     inline AkInt32 AkUtf8ToWideChar( const char*    in_pszUtf8String,
00408                                      AkUInt32       in_uiOutBufferSize,
00409                                      void*          io_pvUnicodeStringBuffer )
00410     {
00411         return ::MultiByteToWideChar(   CP_UTF8,                            // code page
00412                                         0,                                  // performance and mapping flags
00413                                         in_pszUtf8String,                   // wide-character string
00414                                         -1,                                 // number of chars in string : -1 = NULL terminated string.
00415                                         (wchar_t*)io_pvUnicodeStringBuffer, // buffer for new string
00416                                         in_uiOutBufferSize);                // size of buffer
00417     }
00418 
00420     inline void SafeStrCpy( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
00421     {
00422         size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, wcslen( in_pSrc ) + 1 );
00423         wcsncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
00424         in_pDest[iSizeCopy] = '\0';
00425     }
00426 
00428     inline void SafeStrCpy( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
00429     {
00430         size_t iSizeCopy = AkMin( in_uDestMaxNumChars - 1, strlen( in_pSrc ) + 1 );
00431         strncpy_s( in_pDest, in_uDestMaxNumChars, in_pSrc, iSizeCopy );
00432         in_pDest[iSizeCopy] = '\0';
00433     }
00434 
00436     inline void SafeStrCat( wchar_t * in_pDest, const wchar_t* in_pSrc, size_t in_uDestMaxNumChars )
00437     {
00438         int iAvailableSize = (int)( in_uDestMaxNumChars - wcslen( in_pDest ) - 1 );
00439         wcsncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)wcslen( in_pSrc ) ) );
00440     }
00441 
00443     inline void SafeStrCat( char * in_pDest, const char* in_pSrc, size_t in_uDestMaxNumChars )
00444     {
00445         int iAvailableSize = (int)( in_uDestMaxNumChars - strlen( in_pDest ) - 1 );
00446         strncat_s( in_pDest, in_uDestMaxNumChars, in_pSrc, AkMin( iAvailableSize, (int)strlen( in_pSrc ) ) );
00447     }
00448 
00450     #define AkAlloca( _size_ ) _alloca( _size_ )
00451 
00453 #if ! ( defined(AK_USE_METRO_API) || defined(AK_OPTIMIZED) )
00454     inline void OutputDebugMsg( const wchar_t* in_pszMsg )
00455     {
00456         OutputDebugStringW( in_pszMsg );
00457     }
00458 
00460     inline void OutputDebugMsg( const char* in_pszMsg )
00461     {
00462         OutputDebugStringA( in_pszMsg );
00463     }
00464 #else
00465     inline void OutputDebugMsg( const wchar_t* ){}
00466     inline void OutputDebugMsg( const char* ){}
00467 #endif
00468 
00477     #define CONVERT_WIDE_TO_OSCHAR( _wstring_, _oscharstring_ ) ( _oscharstring_ ) = (AkOSChar*)( _wstring_ )
00478 
00487     #define CONVERT_CHAR_TO_OSCHAR( _astring_, _oscharstring_ ) \
00488            _oscharstring_ = (AkOSChar*)AkAlloca( (1 + strlen( _astring_ )) * sizeof(AkOSChar)); \
00489            AKPLATFORM::AkCharToWideChar( _astring_, (AkUInt32)(1 + strlen(_astring_ )), (AkOSChar*)( _oscharstring_ ) )
00490 
00499     #define CONVERT_OSCHAR_TO_WIDE( _osstring_, _wstring_ ) _wstring_ = _osstring_
00500 
00509     #define CONVERT_OSCHAR_TO_CHAR( _osstring_, _astring_ ) \
00510             _astring_ = (char*)AkAlloca( 1 + wcslen( _osstring_ )); \
00511             AKPLATFORM::AkWideCharToChar( _osstring_, AkUInt32(1 + wcslen( _osstring_ )), _astring_ );
00512 
00515     inline size_t AkUtf16StrLen( const AkUtf16* in_pStr )
00516     {
00517         return ( wcslen( in_pStr ) );
00518     }
00519 
00522     inline size_t OsStrLen( const AkOSChar* in_pszString )
00523     {
00524         return ( wcslen( in_pszString ) );
00525     }
00526 
00528     #define AK_OSPRINTF swprintf_s
00529 
00536     inline int OsStrCmp( const AkOSChar* in_pszString1, const AkOSChar* in_pszString2 )
00537     {
00538         return ( wcscmp( in_pszString1,  in_pszString2 ) );
00539     }
00540     
00541     #define AK_UTF16_TO_WCHAR(  in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00542     #define AK_WCHAR_TO_UTF16(  in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00543     #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00544     #define AK_UTF16_TO_CHAR(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkWideCharToChar( in_pSrc, in_MaxSize, in_pdDest )
00545     #define AK_CHAR_TO_UTF16(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkCharToWideChar( in_pSrc, in_MaxSize, in_pdDest )
00546     #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::SafeStrCpy(     in_pdDest, in_pSrc, in_MaxSize )
00547 
00548     // Use with AkOSChar.
00549     #define AK_PATH_SEPARATOR   (L"\\")
00550 
00551     #if defined(AK_ENABLE_PERF_RECORDING)
00552     
00553         static AkUInt32 g_uAkPerfRecExecCount = 0;  
00554         static AkReal32 g_fAkPerfRecExecTime = 0.f;
00555 
00556         #define AK_PERF_RECORDING_RESET()   \
00557             AKPLATFORM::g_uAkPerfRecExecCount = 0;\
00558             AKPLATFORM::g_fAkPerfRecExecTime = 0.f;
00559 
00560         #define AK_PERF_RECORDING_START( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )                       \
00561             AkInt64 iAkPerfRecTimeBefore;                                                                                           \
00562             if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) )    \
00563                 AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeBefore );
00564 
00565         #define AK_PERF_RECORDING_STOP( __StorageName__, __uExecutionCountStart__, __uExecutionCountStop__ )                        \
00566         if ( (AKPLATFORM::g_uAkPerfRecExecCount >= (__uExecutionCountStart__)) && (AKPLATFORM::g_uAkPerfRecExecCount <= (__uExecutionCountStop__)) )    \
00567             {                                                                                                                       \
00568                 AkInt64 iAkPerfRecTimeAfter;                                                                                        \
00569                 AKPLATFORM::PerformanceCounter( &iAkPerfRecTimeAfter );                                                             \
00570                 AKPLATFORM::g_fAkPerfRecExecTime += AKPLATFORM::Elapsed( iAkPerfRecTimeAfter, iAkPerfRecTimeBefore );                           \
00571                 if ( AKPLATFORM::g_uAkPerfRecExecCount == (__uExecutionCountStop__) )                                                           \
00572                 {                                                                                                                   \
00573                     AkReal32 fAverageExecutionTime = AKPLATFORM::g_fAkPerfRecExecTime/((__uExecutionCountStop__)-(__uExecutionCountStart__));   \
00574                     char str[256];                                                                                                  \
00575                     sprintf_s(str, 256, "%s average execution time: %f\n", __StorageName__, fAverageExecutionTime);                 \
00576                     AKPLATFORM::OutputDebugMsg( str );                                                                              \
00577                 }                                                                                                                   \
00578             }                                                                                                                       \
00579             AKPLATFORM::g_uAkPerfRecExecCount++;
00580     #endif // AK_ENABLE_PERF_RECORDING
00581 }
00582 
00583 #endif  // _AK_PLATFORM_FUNCS_H_

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