Bullet Collision Detection & Physics Library: btQuickprof.cpp Source File

Bullet Collision Detection & Physics Library

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
66 struct btClockData
67 {
68 #ifdef BT_USE_WINDOWS_TIMERS
69 LARGE_INTEGER mClockFrequency;
70 LONGLONG mStartTick;
71 LARGE_INTEGER mStartTime;
72 #else
73 #ifdef __CELLOS_LV2__
74 uint64_t mStartTime;
75 #else
76 #ifdef __APPLE__
77 uint64_t mStartTimeNano;
78 #endif
79 struct timeval mStartTime;
80 #endif
81 #endif //__CELLOS_LV2__
82 };
83
85 btClock::btClock()
86 {
87 m_data = new btClockData;
88 #ifdef BT_USE_WINDOWS_TIMERS
89 QueryPerformanceFrequency(&m_data->mClockFrequency);
90 #endif
91 reset();
92 }
93
94 btClock::~btClock()
95 {
96 delete m_data;
97 }
98
99 btClock::btClock(const btClock& other)
100 {
101 m_data = new btClockData;
102 *m_data = *other.m_data;
103 }
104
105 btClock& btClock::operator=(const btClock& other)
106 {
107 *m_data = *other.m_data;
108 return *this;
109 }
110
112 void btClock::reset()
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
267 btScalar btClock::getTimeSeconds()
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 }
701 void btLeaveProfileZoneDefault()
702 {
703 }
704
705 #else
706 void btEnterProfileZoneDefault(const char* name)
707 {
708 }
709 void btLeaveProfileZoneDefault()
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
738 unsigned int btQuickprofGetCurrentThreadIndex2()
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
764 static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
765 static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;
766
767 void btEnterProfileZone(const char* name)
768 {
769 (bts_enterFunc)(name);
770 }
771 void btLeaveProfileZone()
772 {
773 (bts_leaveFunc)();
774 }
775
776 btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc()
777 {
778 return bts_enterFunc;
779 }
780 btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc()
781 {
782 return bts_leaveFunc;
783 }
784
785 void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc)
786 {
787 bts_enterFunc = enterFunc;
788 }
789 void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc)
790 {
791 bts_leaveFunc = leaveFunc;
792 }
793
794 CProfileSample::CProfileSample(const char* name)
795 {
796 btEnterProfileZone(name);
797 }
798
799 CProfileSample::~CProfileSample(void)
800 {
801 btLeaveProfileZone();
802 }
SIMD_EPSILON
#define SIMD_EPSILON
Definition: btScalar.h:523
CProfileSample::CProfileSample
CProfileSample(const char *name)
Definition: btQuickprof.cpp:794
uint64_t
unsigned long long int uint64_t
Definition: btConvexHullComputer.cpp:33
btEnterProfileZoneFunc
void() btEnterProfileZoneFunc(const char *msg)
Definition: btQuickprof.h:55
btGetCurrentEnterProfileZoneFunc
btEnterProfileZoneFunc * btGetCurrentEnterProfileZoneFunc()
Definition: btQuickprof.cpp:776
btClock::getTimeSeconds
btScalar getTimeSeconds()
Returns the time in s since the last call to reset or since the Clock was created.
Definition: btQuickprof.cpp:267
btQuickprofGetCurrentThreadIndex2
unsigned int btQuickprofGetCurrentThreadIndex2()
Definition: btQuickprof.cpp:738
btAssert
#define btAssert(x)
Definition: btScalar.h:133
btClock::getTimeNanoseconds
unsigned long long int getTimeNanoseconds()
Definition: btQuickprof.cpp:205
btClock
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling...
Definition: btQuickprof.h:22
btClockData::mStartTime
LARGE_INTEGER mStartTime
Definition: btQuickprof.cpp:71
btClock::reset
void reset()
Resets the initial reference time.
Definition: btQuickprof.cpp:112
btSetCustomEnterProfileZoneFunc
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc *enterFunc)
Definition: btQuickprof.cpp:785
btGetCurrentLeaveProfileZoneFunc
btLeaveProfileZoneFunc * btGetCurrentLeaveProfileZoneFunc()
Definition: btQuickprof.cpp:780
btEnterProfileZone
void btEnterProfileZone(const char *name)
Definition: btQuickprof.cpp:767
btClock::btClock
btClock()
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling...
Definition: btQuickprof.cpp:85
btClock::m_data
struct btClockData * m_data
Definition: btQuickprof.h:50
gThreadCounter
static ThreadsafeCounter gThreadCounter
Definition: btThreads.cpp:247
btLeaveProfileZone
void btLeaveProfileZone()
Definition: btQuickprof.cpp:771
btClock::getTimeMicroseconds
unsigned long long int getTimeMicroseconds()
Returns the time in us since the last call to reset or since the Clock was created.
Definition: btQuickprof.cpp:171
btSetCustomLeaveProfileZoneFunc
void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc *leaveFunc)
Definition: btQuickprof.cpp:789
btClock::~btClock
~btClock()
Definition: btQuickprof.cpp:94
btClock::operator=
btClock & operator=(const btClock &other)
Definition: btQuickprof.cpp:105
btClock::getTimeMilliseconds
unsigned long long int getTimeMilliseconds()
Returns the time in ms since the last call to reset or since the btClock was created.
Definition: btQuickprof.cpp:136
btQuickprof.h
btThreads.h
BT_QUICKPROF_MAX_THREAD_COUNT
const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT
Definition: btQuickprof.h:68
bts_enterFunc
static btEnterProfileZoneFunc * bts_enterFunc
Definition: btQuickprof.cpp:764
btLeaveProfileZoneFunc
void() btLeaveProfileZoneFunc()
Definition: btQuickprof.h:56
btClockData
Definition: btQuickprof.cpp:66
btLeaveProfileZoneDefault
void btLeaveProfileZoneDefault()
Definition: btQuickprof.cpp:709
CProfileSample::~CProfileSample
~CProfileSample(void)
Definition: btQuickprof.cpp:799
U
unsigned int U
Definition: btGjkEpa3.h:78
GetTickCount64
#define GetTickCount64
Definition: btQuickprof.cpp:47
btClockData::mClockFrequency
LARGE_INTEGER mClockFrequency
Definition: btQuickprof.cpp:69
btGetCurrentThreadIndex
unsigned int btGetCurrentThreadIndex()
Definition: btThreads.cpp:290
btClockData::mStartTick
LONGLONG mStartTick
Definition: btQuickprof.cpp:70
bts_leaveFunc
static btLeaveProfileZoneFunc * bts_leaveFunc
Definition: btQuickprof.cpp:765
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
btEnterProfileZoneDefault
void btEnterProfileZoneDefault(const char *name)
Definition: btQuickprof.cpp:706