profiler.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Copyright (c) 2012-2025 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "core/containers/array.inl"
  6. #include "core/math/vector3.inl"
  7. #include "core/memory/globals.h"
  8. #include "core/thread/scoped_mutex.inl"
  9. #include "core/time.h"
  10. #include "device/profiler.h"
  11. #include <new>
  12. namespace crown
  13. {
  14. namespace profiler_globals
  15. {
  16. char _mem[sizeof(Buffer)];
  17. Buffer *_buffer = NULL;
  18. void init()
  19. {
  20. _buffer = new (_mem)Buffer(default_allocator());
  21. }
  22. void shutdown()
  23. {
  24. _buffer->~Buffer();
  25. _buffer = NULL;
  26. }
  27. const char *buffer_begin()
  28. {
  29. return array::begin(*_buffer);
  30. }
  31. const char *buffer_end()
  32. {
  33. return array::end(*_buffer);
  34. }
  35. } // namespace profiler_globals
  36. namespace profiler
  37. {
  38. enum { THREAD_BUFFER_SIZE = 4 * 1024 };
  39. static char _thread_buffer[THREAD_BUFFER_SIZE];
  40. static u32 _thread_buffer_size = 0;
  41. static Mutex _buffer_mutex;
  42. static void flush_local_buffer()
  43. {
  44. ScopedMutex sm(_buffer_mutex);
  45. array::push(*profiler_globals::_buffer, _thread_buffer, _thread_buffer_size);
  46. _thread_buffer_size = 0;
  47. }
  48. template<typename T>
  49. static void push(ProfilerEventType::Enum type, const T &ev)
  50. {
  51. if (_thread_buffer_size + 2*sizeof(u32) + sizeof(ev) >= THREAD_BUFFER_SIZE)
  52. flush_local_buffer();
  53. char *p = _thread_buffer + _thread_buffer_size;
  54. *(u32 *)p = type;
  55. p += sizeof(u32);
  56. *(u32 *)p = sizeof(ev);
  57. p += sizeof(u32);
  58. *(T *)p = ev;
  59. _thread_buffer_size += 2*sizeof(u32) + sizeof(ev);
  60. }
  61. void enter_profile_scope(const char *name)
  62. {
  63. EnterProfileScope ev;
  64. ev.name = name;
  65. ev.time = time::now();
  66. push(ProfilerEventType::ENTER_PROFILE_SCOPE, ev);
  67. }
  68. void leave_profile_scope()
  69. {
  70. LeaveProfileScope ev;
  71. ev.time = time::now();
  72. push(ProfilerEventType::LEAVE_PROFILE_SCOPE, ev);
  73. }
  74. void record_float(const char *name, f32 value)
  75. {
  76. RecordFloat ev;
  77. ev.name = name;
  78. ev.value = value;
  79. push(ProfilerEventType::RECORD_FLOAT, ev);
  80. }
  81. void record_vector3(const char *name, const Vector3 &value)
  82. {
  83. RecordVector3 ev;
  84. ev.name = name;
  85. ev.value = value;
  86. push(ProfilerEventType::RECORD_VECTOR3, ev);
  87. }
  88. void allocate_memory(const char *name, u32 size)
  89. {
  90. AllocateMemory ev;
  91. ev.name = name;
  92. ev.size = size;
  93. push(ProfilerEventType::ALLOCATE_MEMORY, ev);
  94. }
  95. void deallocate_memory(const char *name, u32 size)
  96. {
  97. DeallocateMemory ev;
  98. ev.name = name;
  99. ev.size = size;
  100. push(ProfilerEventType::DEALLOCATE_MEMORY, ev);
  101. }
  102. } // namespace profiler
  103. namespace profiler_globals
  104. {
  105. void flush()
  106. {
  107. profiler::flush_local_buffer();
  108. u32 end = ProfilerEventType::COUNT;
  109. array::push(*_buffer, (const char *)&end, (u32)sizeof(end));
  110. }
  111. void clear()
  112. {
  113. array::clear(*_buffer);
  114. }
  115. } // namespace profiler_globals
  116. } // namespace crown