TracyLua.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. #ifndef __TRACYLUA_HPP__
  2. #define __TRACYLUA_HPP__
  3. // Include this file after you include lua headers.
  4. #ifndef TRACY_ENABLE
  5. #include <string.h>
  6. namespace tracy
  7. {
  8. namespace detail
  9. {
  10. static inline int noop( lua_State* L ) { return 0; }
  11. }
  12. static inline void LuaRegister( lua_State* L )
  13. {
  14. lua_newtable( L );
  15. lua_pushcfunction( L, detail::noop );
  16. lua_setfield( L, -2, "ZoneBegin" );
  17. lua_pushcfunction( L, detail::noop );
  18. lua_setfield( L, -2, "ZoneBeginN" );
  19. lua_pushcfunction( L, detail::noop );
  20. lua_setfield( L, -2, "ZoneBeginS" );
  21. lua_pushcfunction( L, detail::noop );
  22. lua_setfield( L, -2, "ZoneBeginNS" );
  23. lua_pushcfunction( L, detail::noop );
  24. lua_setfield( L, -2, "ZoneEnd" );
  25. lua_pushcfunction( L, detail::noop );
  26. lua_setfield( L, -2, "ZoneText" );
  27. lua_pushcfunction( L, detail::noop );
  28. lua_setfield( L, -2, "ZoneName" );
  29. lua_pushcfunction( L, detail::noop );
  30. lua_setfield( L, -2, "Message" );
  31. lua_setglobal( L, "tracy" );
  32. }
  33. static inline char* FindEnd( char* ptr )
  34. {
  35. unsigned int cnt = 1;
  36. while( cnt != 0 )
  37. {
  38. if( *ptr == '(' ) cnt++;
  39. else if( *ptr == ')' ) cnt--;
  40. ptr++;
  41. }
  42. return ptr;
  43. }
  44. static inline void LuaRemove( char* script )
  45. {
  46. while( *script )
  47. {
  48. if( strncmp( script, "tracy.", 6 ) == 0 )
  49. {
  50. if( strncmp( script + 6, "Zone", 4 ) == 0 )
  51. {
  52. if( strncmp( script + 10, "End()", 5 ) == 0 )
  53. {
  54. memset( script, ' ', 15 );
  55. script += 15;
  56. }
  57. else if( strncmp( script + 10, "Begin()", 7 ) == 0 )
  58. {
  59. memset( script, ' ', 17 );
  60. script += 17;
  61. }
  62. else if( strncmp( script + 10, "Text(", 5 ) == 0 )
  63. {
  64. auto end = FindEnd( script + 15 );
  65. memset( script, ' ', end - script );
  66. script = end;
  67. }
  68. else if( strncmp( script + 10, "Name(", 5 ) == 0 )
  69. {
  70. auto end = FindEnd( script + 15 );
  71. memset( script, ' ', end - script );
  72. script = end;
  73. }
  74. else if( strncmp( script + 10, "BeginN(", 7 ) == 0 )
  75. {
  76. auto end = FindEnd( script + 17 );
  77. memset( script, ' ', end - script );
  78. script = end;
  79. }
  80. else if( strncmp( script + 10, "BeginS(", 7 ) == 0 )
  81. {
  82. auto end = FindEnd( script + 17 );
  83. memset( script, ' ', end - script );
  84. script = end;
  85. }
  86. else if( strncmp( script + 10, "BeginNS(", 8 ) == 0 )
  87. {
  88. auto end = FindEnd( script + 18 );
  89. memset( script, ' ', end - script );
  90. script = end;
  91. }
  92. else
  93. {
  94. script += 10;
  95. }
  96. }
  97. else if( strncmp( script + 6, "Message(", 8 ) == 0 )
  98. {
  99. auto end = FindEnd( script + 14 );
  100. memset( script, ' ', end - script );
  101. script = end;
  102. }
  103. else
  104. {
  105. script += 6;
  106. }
  107. }
  108. else
  109. {
  110. script++;
  111. }
  112. }
  113. }
  114. }
  115. #else
  116. #include <assert.h>
  117. #include <limits>
  118. #include "common/TracyColor.hpp"
  119. #include "common/TracyAlign.hpp"
  120. #include "common/TracyForceInline.hpp"
  121. #include "common/TracySystem.hpp"
  122. #include "client/TracyProfiler.hpp"
  123. namespace tracy
  124. {
  125. #ifdef TRACY_ON_DEMAND
  126. TRACY_API LuaZoneState& GetLuaZoneState();
  127. #endif
  128. namespace detail
  129. {
  130. #ifdef TRACY_HAS_CALLSTACK
  131. static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
  132. {
  133. assert( depth <= 64 );
  134. lua_Debug dbg[64];
  135. const char* func[64];
  136. uint32_t fsz[64];
  137. uint32_t ssz[64];
  138. uint8_t cnt;
  139. uint16_t spaceNeeded = sizeof( cnt );
  140. for( cnt=0; cnt<depth; cnt++ )
  141. {
  142. if( lua_getstack( L, cnt+1, dbg+cnt ) == 0 ) break;
  143. lua_getinfo( L, "Snl", dbg+cnt );
  144. func[cnt] = dbg[cnt].name ? dbg[cnt].name : dbg[cnt].short_src;
  145. fsz[cnt] = uint32_t( strlen( func[cnt] ) );
  146. ssz[cnt] = uint32_t( strlen( dbg[cnt].source ) );
  147. spaceNeeded += fsz[cnt] + ssz[cnt];
  148. }
  149. spaceNeeded += cnt * ( 4 + 2 + 2 ); // source line, function string length, source string length
  150. auto ptr = (char*)tracy_malloc( spaceNeeded + 2 );
  151. auto dst = ptr;
  152. memcpy( dst, &spaceNeeded, 2 ); dst += 2;
  153. memcpy( dst, &cnt, 1 ); dst++;
  154. for( uint8_t i=0; i<cnt; i++ )
  155. {
  156. const uint32_t line = dbg[i].currentline;
  157. memcpy( dst, &line, 4 ); dst += 4;
  158. assert( fsz[i] <= std::numeric_limits<uint16_t>::max() );
  159. memcpy( dst, fsz+i, 2 ); dst += 2;
  160. memcpy( dst, func[i], fsz[i] ); dst += fsz[i];
  161. assert( ssz[i] <= std::numeric_limits<uint16_t>::max() );
  162. memcpy( dst, ssz+i, 2 ); dst += 2;
  163. memcpy( dst, dbg[i].source, ssz[i] ), dst += ssz[i];
  164. }
  165. assert( dst - ptr == spaceNeeded + 2 );
  166. TracyLfqPrepare( QueueType::CallstackAlloc );
  167. MemWrite( &item->callstackAllocFat.ptr, (uint64_t)ptr );
  168. MemWrite( &item->callstackAllocFat.nativePtr, (uint64_t)Callstack( depth ) );
  169. TracyLfqCommit;
  170. }
  171. static inline int LuaZoneBeginS( lua_State* L )
  172. {
  173. #ifdef TRACY_ON_DEMAND
  174. const auto zoneCnt = GetLuaZoneState().counter++;
  175. if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
  176. GetLuaZoneState().active = GetProfiler().IsConnected();
  177. if( !GetLuaZoneState().active ) return 0;
  178. #endif
  179. #ifdef TRACY_CALLSTACK
  180. const uint32_t depth = TRACY_CALLSTACK;
  181. #else
  182. const auto depth = uint32_t( lua_tointeger( L, 1 ) );
  183. #endif
  184. SendLuaCallstack( L, depth );
  185. TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
  186. lua_Debug dbg;
  187. lua_getstack( L, 1, &dbg );
  188. lua_getinfo( L, "Snl", &dbg );
  189. const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src );
  190. MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
  191. MemWrite( &item->zoneBegin.srcloc, srcloc );
  192. TracyLfqCommit;
  193. return 0;
  194. }
  195. static inline int LuaZoneBeginNS( lua_State* L )
  196. {
  197. #ifdef TRACY_ON_DEMAND
  198. const auto zoneCnt = GetLuaZoneState().counter++;
  199. if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
  200. GetLuaZoneState().active = GetProfiler().IsConnected();
  201. if( !GetLuaZoneState().active ) return 0;
  202. #endif
  203. #ifdef TRACY_CALLSTACK
  204. const uint32_t depth = TRACY_CALLSTACK;
  205. #else
  206. const auto depth = uint32_t( lua_tointeger( L, 2 ) );
  207. #endif
  208. SendLuaCallstack( L, depth );
  209. TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
  210. lua_Debug dbg;
  211. lua_getstack( L, 1, &dbg );
  212. lua_getinfo( L, "Snl", &dbg );
  213. size_t nsz;
  214. const auto name = lua_tolstring( L, 1, &nsz );
  215. const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz );
  216. MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
  217. MemWrite( &item->zoneBegin.srcloc, srcloc );
  218. TracyLfqCommit;
  219. return 0;
  220. }
  221. #endif
  222. static inline int LuaZoneBegin( lua_State* L )
  223. {
  224. #if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
  225. return LuaZoneBeginS( L );
  226. #else
  227. #ifdef TRACY_ON_DEMAND
  228. const auto zoneCnt = GetLuaZoneState().counter++;
  229. if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
  230. GetLuaZoneState().active = GetProfiler().IsConnected();
  231. if( !GetLuaZoneState().active ) return 0;
  232. #endif
  233. TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLoc );
  234. lua_Debug dbg;
  235. lua_getstack( L, 1, &dbg );
  236. lua_getinfo( L, "Snl", &dbg );
  237. const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src );
  238. MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
  239. MemWrite( &item->zoneBegin.srcloc, srcloc );
  240. TracyLfqCommit;
  241. return 0;
  242. #endif
  243. }
  244. static inline int LuaZoneBeginN( lua_State* L )
  245. {
  246. #if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
  247. return LuaZoneBeginNS( L );
  248. #else
  249. #ifdef TRACY_ON_DEMAND
  250. const auto zoneCnt = GetLuaZoneState().counter++;
  251. if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
  252. GetLuaZoneState().active = GetProfiler().IsConnected();
  253. if( !GetLuaZoneState().active ) return 0;
  254. #endif
  255. TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLoc );
  256. lua_Debug dbg;
  257. lua_getstack( L, 1, &dbg );
  258. lua_getinfo( L, "Snl", &dbg );
  259. size_t nsz;
  260. const auto name = lua_tolstring( L, 1, &nsz );
  261. const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz );
  262. MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
  263. MemWrite( &item->zoneBegin.srcloc, srcloc );
  264. TracyLfqCommit;
  265. return 0;
  266. #endif
  267. }
  268. static inline int LuaZoneEnd( lua_State* L )
  269. {
  270. #ifdef TRACY_ON_DEMAND
  271. assert( GetLuaZoneState().counter != 0 );
  272. GetLuaZoneState().counter--;
  273. if( !GetLuaZoneState().active ) return 0;
  274. if( !GetProfiler().IsConnected() )
  275. {
  276. GetLuaZoneState().active = false;
  277. return 0;
  278. }
  279. #endif
  280. TracyLfqPrepare( QueueType::ZoneEnd );
  281. MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
  282. TracyLfqCommit;
  283. return 0;
  284. }
  285. static inline int LuaZoneText( lua_State* L )
  286. {
  287. #ifdef TRACY_ON_DEMAND
  288. if( !GetLuaZoneState().active ) return 0;
  289. if( !GetProfiler().IsConnected() )
  290. {
  291. GetLuaZoneState().active = false;
  292. return 0;
  293. }
  294. #endif
  295. auto txt = lua_tostring( L, 1 );
  296. const auto size = strlen( txt );
  297. assert( size < std::numeric_limits<uint16_t>::max() );
  298. auto ptr = (char*)tracy_malloc( size );
  299. memcpy( ptr, txt, size );
  300. TracyLfqPrepare( QueueType::ZoneText );
  301. MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
  302. MemWrite( &item->zoneTextFat.size, (uint16_t)size );
  303. TracyLfqCommit;
  304. return 0;
  305. }
  306. static inline int LuaZoneName( lua_State* L )
  307. {
  308. #ifdef TRACY_ON_DEMAND
  309. if( !GetLuaZoneState().active ) return 0;
  310. if( !GetProfiler().IsConnected() )
  311. {
  312. GetLuaZoneState().active = false;
  313. return 0;
  314. }
  315. #endif
  316. auto txt = lua_tostring( L, 1 );
  317. const auto size = strlen( txt );
  318. assert( size < std::numeric_limits<uint16_t>::max() );
  319. auto ptr = (char*)tracy_malloc( size );
  320. memcpy( ptr, txt, size );
  321. TracyLfqPrepare( QueueType::ZoneName );
  322. MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
  323. MemWrite( &item->zoneTextFat.size, (uint16_t)size );
  324. TracyLfqCommit;
  325. return 0;
  326. }
  327. static inline int LuaMessage( lua_State* L )
  328. {
  329. #ifdef TRACY_ON_DEMAND
  330. if( !GetProfiler().IsConnected() ) return 0;
  331. #endif
  332. auto txt = lua_tostring( L, 1 );
  333. const auto size = strlen( txt );
  334. assert( size < std::numeric_limits<uint16_t>::max() );
  335. TracyLfqPrepare( QueueType::Message );
  336. auto ptr = (char*)tracy_malloc( size );
  337. memcpy( ptr, txt, size );
  338. MemWrite( &item->messageFat.time, Profiler::GetTime() );
  339. MemWrite( &item->messageFat.text, (uint64_t)ptr );
  340. MemWrite( &item->messageFat.size, (uint16_t)size );
  341. TracyLfqCommit;
  342. return 0;
  343. }
  344. }
  345. static inline void LuaRegister( lua_State* L )
  346. {
  347. lua_newtable( L );
  348. lua_pushcfunction( L, detail::LuaZoneBegin );
  349. lua_setfield( L, -2, "ZoneBegin" );
  350. lua_pushcfunction( L, detail::LuaZoneBeginN );
  351. lua_setfield( L, -2, "ZoneBeginN" );
  352. #ifdef TRACY_HAS_CALLSTACK
  353. lua_pushcfunction( L, detail::LuaZoneBeginS );
  354. lua_setfield( L, -2, "ZoneBeginS" );
  355. lua_pushcfunction( L, detail::LuaZoneBeginNS );
  356. lua_setfield( L, -2, "ZoneBeginNS" );
  357. #else
  358. lua_pushcfunction( L, detail::LuaZoneBegin );
  359. lua_setfield( L, -2, "ZoneBeginS" );
  360. lua_pushcfunction( L, detail::LuaZoneBeginN );
  361. lua_setfield( L, -2, "ZoneBeginNS" );
  362. #endif
  363. lua_pushcfunction( L, detail::LuaZoneEnd );
  364. lua_setfield( L, -2, "ZoneEnd" );
  365. lua_pushcfunction( L, detail::LuaZoneText );
  366. lua_setfield( L, -2, "ZoneText" );
  367. lua_pushcfunction( L, detail::LuaZoneName );
  368. lua_setfield( L, -2, "ZoneName" );
  369. lua_pushcfunction( L, detail::LuaMessage );
  370. lua_setfield( L, -2, "Message" );
  371. lua_setglobal( L, "tracy" );
  372. }
  373. static inline void LuaRemove( char* script ) {}
  374. }
  375. #endif
  376. #endif