Blender  V3.3
btQuickprof.cpp
Go to the documentation of this file.
1 /*
2 
3 ***************************************************************************************************
4 **
5 ** profile.cpp
6 **
7 ** Real-Time Hierarchical Profiling for Game Programming Gems 3
8 **
9 ** by Greg Hjelstrom & Byon Garrabrant
10 **
11 ***************************************************************************************************/
12 
13 // Credits: The Clock class was inspired by the Timer classes in
14 // Ogre (www.ogre3d.org).
15 
16 #include "btQuickprof.h"
17 #include "btThreads.h"
18 
19 #ifdef __CELLOS_LV2__
20 #include <sys/sys_time.h>
21 #include <sys/time_util.h>
22 #include <stdio.h>
23 #endif
24 
25 #if defined(SUNOS) || defined(__SUNOS__)
26 #include <stdio.h>
27 #endif
28 #ifdef __APPLE__
29 #include <mach/mach_time.h>
30 #include <TargetConditionals.h>
31 #endif
32 
33 #if defined(WIN32) || defined(_WIN32)
34 
35 #define BT_USE_WINDOWS_TIMERS
36 #define WIN32_LEAN_AND_MEAN
37 #define NOWINRES
38 #define NOMCX
39 #define NOIME
40 
41 #ifdef _XBOX
42 #include <Xtl.h>
43 #else //_XBOX
44 #include <windows.h>
45 
46 #if WINVER < 0x0602
47 #define GetTickCount64 GetTickCount
48 #endif
49 
50 #endif //_XBOX
51 
52 #include <time.h>
53 
54 #else //_WIN32
55 #include <sys/time.h>
56 
57 #ifdef BT_LINUX_REALTIME
58 //required linking against rt (librt)
59 #include <time.h>
60 #endif //BT_LINUX_REALTIME
61 
62 #endif //_WIN32
63 
64 #define mymin(a, b) (a > b ? a : b)
65 
67 {
68 #ifdef BT_USE_WINDOWS_TIMERS
69  LARGE_INTEGER mClockFrequency;
70  LONGLONG mStartTick;
71  LARGE_INTEGER mStartTime;
72 #else
73 #ifdef __CELLOS_LV2__
75 #else
76 #ifdef __APPLE__
77  uint64_t mStartTimeNano;
78 #endif
79  struct timeval mStartTime;
80 #endif
81 #endif //__CELLOS_LV2__
82 };
83 
86 {
87  m_data = new btClockData;
88 #ifdef BT_USE_WINDOWS_TIMERS
89  QueryPerformanceFrequency(&m_data->mClockFrequency);
90 #endif
91  reset();
92 }
93 
95 {
96  delete m_data;
97 }
98 
100 {
101  m_data = new btClockData;
102  *m_data = *other.m_data;
103 }
104 
106 {
107  *m_data = *other.m_data;
108  return *this;
109 }
110 
113 {
114 #ifdef BT_USE_WINDOWS_TIMERS
115  QueryPerformanceCounter(&m_data->mStartTime);
116  m_data->mStartTick = GetTickCount64();
117 #else
118 #ifdef __CELLOS_LV2__
119 
120  typedef uint64_t ClockSize;
121  ClockSize newTime;
122  //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
123  SYS_TIMEBASE_GET(newTime);
124  m_data->mStartTime = newTime;
125 #else
126 #ifdef __APPLE__
127  m_data->mStartTimeNano = mach_absolute_time();
128 #endif
129  gettimeofday(&m_data->mStartTime, 0);
130 #endif
131 #endif
132 }
133 
136 unsigned long long int btClock::getTimeMilliseconds()
137 {
138 #ifdef BT_USE_WINDOWS_TIMERS
139  LARGE_INTEGER currentTime;
140  QueryPerformanceCounter(&currentTime);
141  LONGLONG elapsedTime = currentTime.QuadPart -
142  m_data->mStartTime.QuadPart;
143  // Compute the number of millisecond ticks elapsed.
144  unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
145  m_data->mClockFrequency.QuadPart);
146 
147  return msecTicks;
148 #else
149 
150 #ifdef __CELLOS_LV2__
151  uint64_t freq = sys_time_get_timebase_frequency();
152  double dFreq = ((double)freq) / 1000.0;
153  typedef uint64_t ClockSize;
154  ClockSize newTime;
155  SYS_TIMEBASE_GET(newTime);
156  //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
157 
158  return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
159 #else
160 
161  struct timeval currentTime;
162  gettimeofday(&currentTime, 0);
163  return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
164  (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
165 #endif //__CELLOS_LV2__
166 #endif
167 }
168 
171 unsigned long long int btClock::getTimeMicroseconds()
172 {
173 #ifdef BT_USE_WINDOWS_TIMERS
174  //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
175  LARGE_INTEGER currentTime, elapsedTime;
176 
177  QueryPerformanceCounter(&currentTime);
178  elapsedTime.QuadPart = currentTime.QuadPart -
179  m_data->mStartTime.QuadPart;
180  elapsedTime.QuadPart *= 1000000;
181  elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
182 
183  return (unsigned long long)elapsedTime.QuadPart;
184 #else
185 
186 #ifdef __CELLOS_LV2__
187  uint64_t freq = sys_time_get_timebase_frequency();
188  double dFreq = ((double)freq) / 1000000.0;
189  typedef uint64_t ClockSize;
190  ClockSize newTime;
191  //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
192  SYS_TIMEBASE_GET(newTime);
193 
194  return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
195 #else
196 
197  struct timeval currentTime;
198  gettimeofday(&currentTime, 0);
199  return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
200  (currentTime.tv_usec - m_data->mStartTime.tv_usec);
201 #endif //__CELLOS_LV2__
202 #endif
203 }
204 
205 unsigned long long int btClock::getTimeNanoseconds()
206 {
207 #ifdef BT_USE_WINDOWS_TIMERS
208  //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
209  LARGE_INTEGER currentTime, elapsedTime;
210 
211  QueryPerformanceCounter(&currentTime);
212  elapsedTime.QuadPart = currentTime.QuadPart -
213  m_data->mStartTime.QuadPart;
214  elapsedTime.QuadPart *= 1000000000;
215  elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
216 
217  return (unsigned long long)elapsedTime.QuadPart;
218 #else
219 
220 #ifdef __CELLOS_LV2__
221  uint64_t freq = sys_time_get_timebase_frequency();
222  double dFreq = ((double)freq) / 1e9;
223  typedef uint64_t ClockSize;
224  ClockSize newTime;
225  //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
226  SYS_TIMEBASE_GET(newTime);
227 
228  return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
229 #else
230 #ifdef __APPLE__
231  uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
232  static long double conversion = 0.0L;
233  if (0.0L == conversion)
234  {
235  // attempt to get conversion to nanoseconds
236  mach_timebase_info_data_t info;
237  int err = mach_timebase_info(&info);
238  if (err)
239  {
240  btAssert(0);
241  conversion = 1.;
242  }
243  conversion = info.numer / info.denom;
244  }
245  return (ticks * conversion);
246 
247 #else //__APPLE__
248 
249 #ifdef BT_LINUX_REALTIME
250  timespec ts;
251  clock_gettime(CLOCK_REALTIME, &ts);
252  return 1000000000 * ts.tv_sec + ts.tv_nsec;
253 #else
254  struct timeval currentTime;
255  gettimeofday(&currentTime, 0);
256  return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
257  (currentTime.tv_usec - m_data->mStartTime.tv_usec) * 1000;
258 #endif //BT_LINUX_REALTIME
259 
260 #endif //__APPLE__
261 #endif //__CELLOS_LV2__
262 #endif
263 }
264 
268 {
269  static const btScalar microseconds_to_seconds = btScalar(0.000001);
270  return btScalar(getTimeMicroseconds()) * microseconds_to_seconds;
271 }
272 
273 #ifndef BT_NO_PROFILE
274 
275 static btClock gProfileClock;
276 
277 inline void Profile_Get_Ticks(unsigned long int* ticks)
278 {
279  *ticks = (unsigned long int)gProfileClock.getTimeMicroseconds();
280 }
281 
282 inline float Profile_Get_Tick_Rate(void)
283 {
284  // return 1000000.f;
285  return 1000.f;
286 }
287 
288 /***************************************************************************************************
289 **
290 ** CProfileNode
291 **
292 ***************************************************************************************************/
293 
294 /***********************************************************************************************
295  * INPUT: *
296  * name - pointer to a static string which is the name of this profile node *
297  * parent - parent pointer *
298  * *
299  * WARNINGS: *
300  * The name is assumed to be a static pointer, only the pointer is stored and compared for *
301  * efficiency reasons. *
302  *=============================================================================================*/
303 CProfileNode::CProfileNode(const char* name, CProfileNode* parent) : Name(name),
304  TotalCalls(0),
305  TotalTime(0),
306  StartTime(0),
307  RecursionCounter(0),
308  Parent(parent),
309  Child(NULL),
310  Sibling(NULL),
311  m_userPtr(0)
312 {
313  Reset();
314 }
315 
316 void CProfileNode::CleanupMemory()
317 {
318  delete (Child);
319  Child = NULL;
320  delete (Sibling);
321  Sibling = NULL;
322 }
323 
324 CProfileNode::~CProfileNode(void)
325 {
326  CleanupMemory();
327 }
328 
329 /***********************************************************************************************
330  * INPUT: *
331  * name - static string pointer to the name of the node we are searching for *
332  * *
333  * WARNINGS: *
334  * All profile names are assumed to be static strings so this function uses pointer compares *
335  * to find the named node. *
336  *=============================================================================================*/
337 CProfileNode* CProfileNode::Get_Sub_Node(const char* name)
338 {
339  // Try to find this sub node
340  CProfileNode* child = Child;
341  while (child)
342  {
343  if (child->Name == name)
344  {
345  return child;
346  }
347  child = child->Sibling;
348  }
349 
350  // We didn't find it, so add it
351 
352  CProfileNode* node = new CProfileNode(name, this);
353  node->Sibling = Child;
354  Child = node;
355  return node;
356 }
357 
358 void CProfileNode::Reset(void)
359 {
360  TotalCalls = 0;
361  TotalTime = 0.0f;
362 
363  if (Child)
364  {
365  Child->Reset();
366  }
367  if (Sibling)
368  {
369  Sibling->Reset();
370  }
371 }
372 
373 void CProfileNode::Call(void)
374 {
375  TotalCalls++;
376  if (RecursionCounter++ == 0)
377  {
378  Profile_Get_Ticks(&StartTime);
379  }
380 }
381 
382 bool CProfileNode::Return(void)
383 {
384  if (--RecursionCounter == 0 && TotalCalls != 0)
385  {
386  unsigned long int time;
387  Profile_Get_Ticks(&time);
388 
389  time -= StartTime;
390  TotalTime += (float)time / Profile_Get_Tick_Rate();
391  }
392  return (RecursionCounter == 0);
393 }
394 
395 /***************************************************************************************************
396 **
397 ** CProfileIterator
398 **
399 ***************************************************************************************************/
400 CProfileIterator::CProfileIterator(CProfileNode* start)
401 {
402  CurrentParent = start;
403  CurrentChild = CurrentParent->Get_Child();
404 }
405 
406 void CProfileIterator::First(void)
407 {
408  CurrentChild = CurrentParent->Get_Child();
409 }
410 
411 void CProfileIterator::Next(void)
412 {
413  CurrentChild = CurrentChild->Get_Sibling();
414 }
415 
416 bool CProfileIterator::Is_Done(void)
417 {
418  return CurrentChild == NULL;
419 }
420 
421 void CProfileIterator::Enter_Child(int index)
422 {
423  CurrentChild = CurrentParent->Get_Child();
424  while ((CurrentChild != NULL) && (index != 0))
425  {
426  index--;
427  CurrentChild = CurrentChild->Get_Sibling();
428  }
429 
430  if (CurrentChild != NULL)
431  {
432  CurrentParent = CurrentChild;
433  CurrentChild = CurrentParent->Get_Child();
434  }
435 }
436 
437 void CProfileIterator::Enter_Parent(void)
438 {
439  if (CurrentParent->Get_Parent() != NULL)
440  {
441  CurrentParent = CurrentParent->Get_Parent();
442  }
443  CurrentChild = CurrentParent->Get_Child();
444 }
445 
446 /***************************************************************************************************
447 **
448 ** CProfileManager
449 **
450 ***************************************************************************************************/
451 
452 CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT] = {
453  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
454  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
455  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
456  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
457  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
458  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
459  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
460  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
461  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
462  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
463  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
464  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
465  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
466  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
467  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
468  CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL)};
469 
470 CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT] =
471  {
472  &gRoots[0],
473  &gRoots[1],
474  &gRoots[2],
475  &gRoots[3],
476  &gRoots[4],
477  &gRoots[5],
478  &gRoots[6],
479  &gRoots[7],
480  &gRoots[8],
481  &gRoots[9],
482  &gRoots[10],
483  &gRoots[11],
484  &gRoots[12],
485  &gRoots[13],
486  &gRoots[14],
487  &gRoots[15],
488  &gRoots[16],
489  &gRoots[17],
490  &gRoots[18],
491  &gRoots[19],
492  &gRoots[20],
493  &gRoots[21],
494  &gRoots[22],
495  &gRoots[23],
496  &gRoots[24],
497  &gRoots[25],
498  &gRoots[26],
499  &gRoots[27],
500  &gRoots[28],
501  &gRoots[29],
502  &gRoots[30],
503  &gRoots[31],
504  &gRoots[32],
505  &gRoots[33],
506  &gRoots[34],
507  &gRoots[35],
508  &gRoots[36],
509  &gRoots[37],
510  &gRoots[38],
511  &gRoots[39],
512  &gRoots[40],
513  &gRoots[41],
514  &gRoots[42],
515  &gRoots[43],
516  &gRoots[44],
517  &gRoots[45],
518  &gRoots[46],
519  &gRoots[47],
520  &gRoots[48],
521  &gRoots[49],
522  &gRoots[50],
523  &gRoots[51],
524  &gRoots[52],
525  &gRoots[53],
526  &gRoots[54],
527  &gRoots[55],
528  &gRoots[56],
529  &gRoots[57],
530  &gRoots[58],
531  &gRoots[59],
532  &gRoots[60],
533  &gRoots[61],
534  &gRoots[62],
535  &gRoots[63],
536 };
537 
538 int CProfileManager::FrameCounter = 0;
539 unsigned long int CProfileManager::ResetTime = 0;
540 
541 CProfileIterator* CProfileManager::Get_Iterator(void)
542 {
543  int threadIndex = btQuickprofGetCurrentThreadIndex2();
544  if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
545  return 0;
546 
547  return new CProfileIterator(&gRoots[threadIndex]);
548 }
549 
550 void CProfileManager::CleanupMemory(void)
551 {
552  for (int i = 0; i < BT_QUICKPROF_MAX_THREAD_COUNT; i++)
553  {
554  gRoots[i].CleanupMemory();
555  }
556 }
557 
558 /***********************************************************************************************
559  * CProfileManager::Start_Profile -- Begin a named profile *
560  * *
561  * Steps one level deeper into the tree, if a child already exists with the specified name *
562  * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
563  * *
564  * INPUT: *
565  * name - name of this profiling record *
566  * *
567  * WARNINGS: *
568  * The string used is assumed to be a static string; pointer compares are used throughout *
569  * the profiling code for efficiency. *
570  *=============================================================================================*/
571 void CProfileManager::Start_Profile(const char* name)
572 {
573  int threadIndex = btQuickprofGetCurrentThreadIndex2();
574  if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
575  return;
576 
577  if (name != gCurrentNodes[threadIndex]->Get_Name())
578  {
579  gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node(name);
580  }
581 
582  gCurrentNodes[threadIndex]->Call();
583 }
584 
585 /***********************************************************************************************
586  * CProfileManager::Stop_Profile -- Stop timing and record the results. *
587  *=============================================================================================*/
588 void CProfileManager::Stop_Profile(void)
589 {
590  int threadIndex = btQuickprofGetCurrentThreadIndex2();
591  if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
592  return;
593 
594  // Return will indicate whether we should back up to our parent (we may
595  // be profiling a recursive function)
596  if (gCurrentNodes[threadIndex]->Return())
597  {
598  gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Parent();
599  }
600 }
601 
602 /***********************************************************************************************
603  * CProfileManager::Reset -- Reset the contents of the profiling system *
604  * *
605  * This resets everything except for the tree structure. All of the timing data is reset. *
606  *=============================================================================================*/
607 void CProfileManager::Reset(void)
608 {
609  gProfileClock.reset();
610  int threadIndex = btQuickprofGetCurrentThreadIndex2();
611  if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
612  return;
613  gRoots[threadIndex].Reset();
614  gRoots[threadIndex].Call();
615  FrameCounter = 0;
616  Profile_Get_Ticks(&ResetTime);
617 }
618 
619 /***********************************************************************************************
620  * CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
621  *=============================================================================================*/
622 void CProfileManager::Increment_Frame_Counter(void)
623 {
624  FrameCounter++;
625 }
626 
627 /***********************************************************************************************
628  * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
629  *=============================================================================================*/
630 float CProfileManager::Get_Time_Since_Reset(void)
631 {
632  unsigned long int time;
633  Profile_Get_Ticks(&time);
634  time -= ResetTime;
635  return (float)time / Profile_Get_Tick_Rate();
636 }
637 
638 #include <stdio.h>
639 
640 void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
641 {
642  profileIterator->First();
643  if (profileIterator->Is_Done())
644  return;
645 
646  float accumulated_time = 0, parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
647  int i;
648  int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
649  for (i = 0; i < spacing; i++) printf(".");
650  printf("----------------------------------\n");
651  for (i = 0; i < spacing; i++) printf(".");
652  printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time);
653  float totalTime = 0.f;
654 
655  int numChildren = 0;
656 
657  for (i = 0; !profileIterator->Is_Done(); i++, profileIterator->Next())
658  {
659  numChildren++;
660  float current_total_time = profileIterator->Get_Current_Total_Time();
661  accumulated_time += current_total_time;
662  float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
663  {
664  int i;
665  for (i = 0; i < spacing; i++) printf(".");
666  }
667  printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n", i, profileIterator->Get_Current_Name(), fraction, (current_total_time / (double)frames_since_reset), profileIterator->Get_Current_Total_Calls());
668  totalTime += current_total_time;
669  //recurse into children
670  }
671 
672  if (parent_time < accumulated_time)
673  {
674  //printf("what's wrong\n");
675  }
676  for (i = 0; i < spacing; i++) printf(".");
677  printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:", parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
678 
679  for (i = 0; i < numChildren; i++)
680  {
681  profileIterator->Enter_Child(i);
682  dumpRecursive(profileIterator, spacing + 3);
683  profileIterator->Enter_Parent();
684  }
685 }
686 
687 void CProfileManager::dumpAll()
688 {
689  CProfileIterator* profileIterator = 0;
690  profileIterator = CProfileManager::Get_Iterator();
691 
692  dumpRecursive(profileIterator, 0);
693 
694  CProfileManager::Release_Iterator(profileIterator);
695 }
696 
697 
698 void btEnterProfileZoneDefault(const char* name)
699 {
700 }
702 {
703 }
704 
705 #else
706 void btEnterProfileZoneDefault(const char* name)
707 {
708 }
710 {
711 }
712 #endif //BT_NO_PROFILE
713 
714 
715 // clang-format off
716 #if defined(_WIN32) && (defined(__MINGW32__) || defined(__MINGW64__))
717  #define BT_HAVE_TLS 1
718 #elif __APPLE__ && !TARGET_OS_IPHONE
719  // TODO: Modern versions of iOS support TLS now with updated version checking.
720  #define BT_HAVE_TLS 1
721 #elif __linux__
722  #define BT_HAVE_TLS 1
723 #endif
724 
725 // __thread is broken on Andorid clang until r12b. See
726 // https://github.com/android-ndk/ndk/issues/8
727 #if defined(__ANDROID__) && defined(__clang__)
728  #if __has_include(<android/ndk-version.h>)
729  #include <android/ndk-version.h>
730  #endif // __has_include(<android/ndk-version.h>)
731  #if defined(__NDK_MAJOR__) && \
732  ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
733  #undef BT_HAVE_TLS
734  #endif
735 #endif // defined(__ANDROID__) && defined(__clang__)
736 // clang-format on
737 
739 {
740  const unsigned int kNullIndex = ~0U;
741 
742 #if BT_THREADSAFE
743  return btGetCurrentThreadIndex();
744 #else
745 #if defined(BT_HAVE_TLS)
746  static __thread unsigned int sThreadIndex = kNullIndex;
747 #elif defined(_WIN32)
748  __declspec(thread) static unsigned int sThreadIndex = kNullIndex;
749 #else
750  unsigned int sThreadIndex = 0;
751  return -1;
752 #endif
753 
754  static int gThreadCounter = 0;
755 
756  if (sThreadIndex == kNullIndex)
757  {
758  sThreadIndex = gThreadCounter++;
759  }
760  return sThreadIndex;
761 #endif //BT_THREADSAFE
762 }
763 
766 
767 void btEnterProfileZone(const char* name)
768 {
769  (bts_enterFunc)(name);
770 }
772 {
773  (bts_leaveFunc)();
774 }
775 
777 {
778  return bts_enterFunc;
779 }
781 {
782  return bts_leaveFunc;
783 }
784 
786 {
787  bts_enterFunc = enterFunc;
788 }
790 {
791  bts_leaveFunc = leaveFunc;
792 }
793 
795 {
796  btEnterProfileZone(name);
797 }
798 
800 {
802 }
typedef float(TangentPoint)[2]
typedef double(DMatrix)[4][4]
__declspec(dllexport) DWORD NvOptimusEnablement=0x00000001
#define U
btAlignedObjectArray< btScalar > m_data
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc *enterFunc)
static btEnterProfileZoneFunc * bts_enterFunc
btLeaveProfileZoneFunc * btGetCurrentLeaveProfileZoneFunc()
void btLeaveProfileZone()
void btLeaveProfileZoneDefault()
void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc *leaveFunc)
void btEnterProfileZoneDefault(const char *name)
void btEnterProfileZone(const char *name)
unsigned int btQuickprofGetCurrentThreadIndex2()
static btLeaveProfileZoneFunc * bts_leaveFunc
btEnterProfileZoneFunc * btGetCurrentEnterProfileZoneFunc()
void() btLeaveProfileZoneFunc()
Definition: btQuickprof.h:56
const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT
Definition: btQuickprof.h:68
void() btEnterProfileZoneFunc(const char *msg)
Definition: btQuickprof.h:55
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:295
unsigned int btGetCurrentThreadIndex()
Definition: btThreads.cpp:290
static ThreadsafeCounter gThreadCounter
Definition: btThreads.cpp:247
CProfileSample(const char *name)
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
Definition: btQuickprof.h:23
btScalar getTimeSeconds()
unsigned long long int getTimeNanoseconds()
void reset()
Resets the initial reference time.
unsigned long long int getTimeMilliseconds()
unsigned long long int getTimeMicroseconds()
btClock()
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
Definition: btQuickprof.cpp:85
btClock & operator=(const btClock &other)
Definition: thread.h:34
OperationNode * node
double time
unsigned __int64 uint64_t
Definition: stdint.h:90
struct timeval mStartTime
Definition: btQuickprof.cpp:79
static FT_Error err