mirror of
https://github.com/wolfpld/tracy
synced 2025-04-29 12:23:53 +00:00
No functional changes here. Only the variable retrieval was separated from filling in the queue items. While with the async queue this makes no difference, it will be important when the serial queue is used here.
432 lines
12 KiB
C++
432 lines
12 KiB
C++
#ifndef __TRACYLUA_HPP__
|
|
#define __TRACYLUA_HPP__
|
|
|
|
// Include this file after you include lua headers.
|
|
|
|
#ifndef TRACY_ENABLE
|
|
|
|
#include <string.h>
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
namespace detail
|
|
{
|
|
static inline int noop( lua_State* L ) { return 0; }
|
|
}
|
|
|
|
static inline void LuaRegister( lua_State* L )
|
|
{
|
|
lua_newtable( L );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneBegin" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneBeginN" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneBeginS" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneBeginNS" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneEnd" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneText" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "ZoneName" );
|
|
lua_pushcfunction( L, detail::noop );
|
|
lua_setfield( L, -2, "Message" );
|
|
lua_setglobal( L, "tracy" );
|
|
}
|
|
|
|
static inline char* FindEnd( char* ptr )
|
|
{
|
|
unsigned int cnt = 1;
|
|
while( cnt != 0 )
|
|
{
|
|
if( *ptr == '(' ) cnt++;
|
|
else if( *ptr == ')' ) cnt--;
|
|
ptr++;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
static inline void LuaRemove( char* script )
|
|
{
|
|
while( *script )
|
|
{
|
|
if( strncmp( script, "tracy.", 6 ) == 0 )
|
|
{
|
|
if( strncmp( script + 6, "Zone", 4 ) == 0 )
|
|
{
|
|
if( strncmp( script + 10, "End()", 5 ) == 0 )
|
|
{
|
|
memset( script, ' ', 15 );
|
|
script += 15;
|
|
}
|
|
else if( strncmp( script + 10, "Begin()", 7 ) == 0 )
|
|
{
|
|
memset( script, ' ', 17 );
|
|
script += 17;
|
|
}
|
|
else if( strncmp( script + 10, "Text(", 5 ) == 0 )
|
|
{
|
|
auto end = FindEnd( script + 15 );
|
|
memset( script, ' ', end - script );
|
|
script = end;
|
|
}
|
|
else if( strncmp( script + 10, "Name(", 5 ) == 0 )
|
|
{
|
|
auto end = FindEnd( script + 15 );
|
|
memset( script, ' ', end - script );
|
|
script = end;
|
|
}
|
|
else if( strncmp( script + 10, "BeginN(", 7 ) == 0 )
|
|
{
|
|
auto end = FindEnd( script + 17 );
|
|
memset( script, ' ', end - script );
|
|
script = end;
|
|
}
|
|
else if( strncmp( script + 10, "BeginS(", 7 ) == 0 )
|
|
{
|
|
auto end = FindEnd( script + 17 );
|
|
memset( script, ' ', end - script );
|
|
script = end;
|
|
}
|
|
else if( strncmp( script + 10, "BeginNS(", 8 ) == 0 )
|
|
{
|
|
auto end = FindEnd( script + 18 );
|
|
memset( script, ' ', end - script );
|
|
script = end;
|
|
}
|
|
else
|
|
{
|
|
script += 10;
|
|
}
|
|
}
|
|
else if( strncmp( script + 6, "Message(", 8 ) == 0 )
|
|
{
|
|
auto end = FindEnd( script + 14 );
|
|
memset( script, ' ', end - script );
|
|
script = end;
|
|
}
|
|
else
|
|
{
|
|
script += 6;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
script++;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#include <assert.h>
|
|
#include <limits>
|
|
|
|
#include "common/TracyColor.hpp"
|
|
#include "common/TracyAlign.hpp"
|
|
#include "common/TracyForceInline.hpp"
|
|
#include "common/TracySystem.hpp"
|
|
#include "client/TracyProfiler.hpp"
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
#ifdef TRACY_ON_DEMAND
|
|
TRACY_API LuaZoneState& GetLuaZoneState();
|
|
#endif
|
|
|
|
namespace detail
|
|
{
|
|
|
|
#ifdef TRACY_HAS_CALLSTACK
|
|
static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
|
|
{
|
|
assert( depth <= 64 );
|
|
lua_Debug dbg[64];
|
|
const char* func[64];
|
|
uint32_t fsz[64];
|
|
uint32_t ssz[64];
|
|
|
|
uint8_t cnt;
|
|
uint16_t spaceNeeded = sizeof( cnt );
|
|
for( cnt=0; cnt<depth; cnt++ )
|
|
{
|
|
if( lua_getstack( L, cnt+1, dbg+cnt ) == 0 ) break;
|
|
lua_getinfo( L, "Snl", dbg+cnt );
|
|
func[cnt] = dbg[cnt].name ? dbg[cnt].name : dbg[cnt].short_src;
|
|
fsz[cnt] = uint32_t( strlen( func[cnt] ) );
|
|
ssz[cnt] = uint32_t( strlen( dbg[cnt].source ) );
|
|
spaceNeeded += fsz[cnt] + ssz[cnt];
|
|
}
|
|
spaceNeeded += cnt * ( 4 + 2 + 2 ); // source line, function string length, source string length
|
|
|
|
auto ptr = (char*)tracy_malloc( spaceNeeded + 2 );
|
|
auto dst = ptr;
|
|
memcpy( dst, &spaceNeeded, 2 ); dst += 2;
|
|
memcpy( dst, &cnt, 1 ); dst++;
|
|
for( uint8_t i=0; i<cnt; i++ )
|
|
{
|
|
const uint32_t line = dbg[i].currentline;
|
|
memcpy( dst, &line, 4 ); dst += 4;
|
|
assert( fsz[i] <= std::numeric_limits<uint16_t>::max() );
|
|
memcpy( dst, fsz+i, 2 ); dst += 2;
|
|
memcpy( dst, func[i], fsz[i] ); dst += fsz[i];
|
|
assert( ssz[i] <= std::numeric_limits<uint16_t>::max() );
|
|
memcpy( dst, ssz+i, 2 ); dst += 2;
|
|
memcpy( dst, dbg[i].source, ssz[i] ), dst += ssz[i];
|
|
}
|
|
assert( dst - ptr == spaceNeeded + 2 );
|
|
|
|
TracyLfqPrepare( QueueType::CallstackAlloc );
|
|
MemWrite( &item->callstackAllocFat.ptr, (uint64_t)ptr );
|
|
MemWrite( &item->callstackAllocFat.nativePtr, (uint64_t)Callstack( depth ) );
|
|
TracyLfqCommit;
|
|
}
|
|
|
|
static inline int LuaZoneBeginS( lua_State* L )
|
|
{
|
|
#ifdef TRACY_ON_DEMAND
|
|
const auto zoneCnt = GetLuaZoneState().counter++;
|
|
if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
|
|
GetLuaZoneState().active = GetProfiler().IsConnected();
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
#endif
|
|
|
|
#ifdef TRACY_CALLSTACK
|
|
const uint32_t depth = TRACY_CALLSTACK;
|
|
#else
|
|
const auto depth = uint32_t( lua_tointeger( L, 1 ) );
|
|
#endif
|
|
SendLuaCallstack( L, depth );
|
|
|
|
lua_Debug dbg;
|
|
lua_getstack( L, 1, &dbg );
|
|
lua_getinfo( L, "Snl", &dbg );
|
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src );
|
|
|
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
|
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
TracyLfqCommit;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int LuaZoneBeginNS( lua_State* L )
|
|
{
|
|
#ifdef TRACY_ON_DEMAND
|
|
const auto zoneCnt = GetLuaZoneState().counter++;
|
|
if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
|
|
GetLuaZoneState().active = GetProfiler().IsConnected();
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
#endif
|
|
|
|
#ifdef TRACY_CALLSTACK
|
|
const uint32_t depth = TRACY_CALLSTACK;
|
|
#else
|
|
const auto depth = uint32_t( lua_tointeger( L, 2 ) );
|
|
#endif
|
|
SendLuaCallstack( L, depth );
|
|
|
|
lua_Debug dbg;
|
|
lua_getstack( L, 1, &dbg );
|
|
lua_getinfo( L, "Snl", &dbg );
|
|
size_t nsz;
|
|
const auto name = lua_tolstring( L, 1, &nsz );
|
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz );
|
|
|
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLocCallstack );
|
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
TracyLfqCommit;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static inline int LuaZoneBegin( lua_State* L )
|
|
{
|
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
|
return LuaZoneBeginS( L );
|
|
#else
|
|
#ifdef TRACY_ON_DEMAND
|
|
const auto zoneCnt = GetLuaZoneState().counter++;
|
|
if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
|
|
GetLuaZoneState().active = GetProfiler().IsConnected();
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
#endif
|
|
|
|
lua_Debug dbg;
|
|
lua_getstack( L, 1, &dbg );
|
|
lua_getinfo( L, "Snl", &dbg );
|
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src );
|
|
|
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLoc );
|
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
TracyLfqCommit;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static inline int LuaZoneBeginN( lua_State* L )
|
|
{
|
|
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
|
|
return LuaZoneBeginNS( L );
|
|
#else
|
|
#ifdef TRACY_ON_DEMAND
|
|
const auto zoneCnt = GetLuaZoneState().counter++;
|
|
if( zoneCnt != 0 && !GetLuaZoneState().active ) return 0;
|
|
GetLuaZoneState().active = GetProfiler().IsConnected();
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
#endif
|
|
|
|
lua_Debug dbg;
|
|
lua_getstack( L, 1, &dbg );
|
|
lua_getinfo( L, "Snl", &dbg );
|
|
size_t nsz;
|
|
const auto name = lua_tolstring( L, 1, &nsz );
|
|
const auto srcloc = Profiler::AllocSourceLocation( dbg.currentline, dbg.source, dbg.name ? dbg.name : dbg.short_src, name, nsz );
|
|
|
|
TracyLfqPrepare( QueueType::ZoneBeginAllocSrcLoc );
|
|
MemWrite( &item->zoneBegin.time, Profiler::GetTime() );
|
|
MemWrite( &item->zoneBegin.srcloc, srcloc );
|
|
TracyLfqCommit;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static inline int LuaZoneEnd( lua_State* L )
|
|
{
|
|
#ifdef TRACY_ON_DEMAND
|
|
assert( GetLuaZoneState().counter != 0 );
|
|
GetLuaZoneState().counter--;
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
if( !GetProfiler().IsConnected() )
|
|
{
|
|
GetLuaZoneState().active = false;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
TracyLfqPrepare( QueueType::ZoneEnd );
|
|
MemWrite( &item->zoneEnd.time, Profiler::GetTime() );
|
|
TracyLfqCommit;
|
|
return 0;
|
|
}
|
|
|
|
static inline int LuaZoneText( lua_State* L )
|
|
{
|
|
#ifdef TRACY_ON_DEMAND
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
if( !GetProfiler().IsConnected() )
|
|
{
|
|
GetLuaZoneState().active = false;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
auto txt = lua_tostring( L, 1 );
|
|
const auto size = strlen( txt );
|
|
assert( size < std::numeric_limits<uint16_t>::max() );
|
|
|
|
auto ptr = (char*)tracy_malloc( size );
|
|
memcpy( ptr, txt, size );
|
|
|
|
TracyLfqPrepare( QueueType::ZoneText );
|
|
MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
|
|
MemWrite( &item->zoneTextFat.size, (uint16_t)size );
|
|
TracyLfqCommit;
|
|
return 0;
|
|
}
|
|
|
|
static inline int LuaZoneName( lua_State* L )
|
|
{
|
|
#ifdef TRACY_ON_DEMAND
|
|
if( !GetLuaZoneState().active ) return 0;
|
|
if( !GetProfiler().IsConnected() )
|
|
{
|
|
GetLuaZoneState().active = false;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
auto txt = lua_tostring( L, 1 );
|
|
const auto size = strlen( txt );
|
|
assert( size < std::numeric_limits<uint16_t>::max() );
|
|
|
|
auto ptr = (char*)tracy_malloc( size );
|
|
memcpy( ptr, txt, size );
|
|
|
|
TracyLfqPrepare( QueueType::ZoneName );
|
|
MemWrite( &item->zoneTextFat.text, (uint64_t)ptr );
|
|
MemWrite( &item->zoneTextFat.size, (uint16_t)size );
|
|
TracyLfqCommit;
|
|
return 0;
|
|
}
|
|
|
|
static inline int LuaMessage( lua_State* L )
|
|
{
|
|
#ifdef TRACY_ON_DEMAND
|
|
if( !GetProfiler().IsConnected() ) return 0;
|
|
#endif
|
|
|
|
auto txt = lua_tostring( L, 1 );
|
|
const auto size = strlen( txt );
|
|
assert( size < std::numeric_limits<uint16_t>::max() );
|
|
|
|
auto ptr = (char*)tracy_malloc( size );
|
|
memcpy( ptr, txt, size );
|
|
|
|
TracyLfqPrepare( QueueType::Message );
|
|
MemWrite( &item->messageFat.time, Profiler::GetTime() );
|
|
MemWrite( &item->messageFat.text, (uint64_t)ptr );
|
|
MemWrite( &item->messageFat.size, (uint16_t)size );
|
|
TracyLfqCommit;
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
static inline void LuaRegister( lua_State* L )
|
|
{
|
|
lua_newtable( L );
|
|
lua_pushcfunction( L, detail::LuaZoneBegin );
|
|
lua_setfield( L, -2, "ZoneBegin" );
|
|
lua_pushcfunction( L, detail::LuaZoneBeginN );
|
|
lua_setfield( L, -2, "ZoneBeginN" );
|
|
#ifdef TRACY_HAS_CALLSTACK
|
|
lua_pushcfunction( L, detail::LuaZoneBeginS );
|
|
lua_setfield( L, -2, "ZoneBeginS" );
|
|
lua_pushcfunction( L, detail::LuaZoneBeginNS );
|
|
lua_setfield( L, -2, "ZoneBeginNS" );
|
|
#else
|
|
lua_pushcfunction( L, detail::LuaZoneBegin );
|
|
lua_setfield( L, -2, "ZoneBeginS" );
|
|
lua_pushcfunction( L, detail::LuaZoneBeginN );
|
|
lua_setfield( L, -2, "ZoneBeginNS" );
|
|
#endif
|
|
lua_pushcfunction( L, detail::LuaZoneEnd );
|
|
lua_setfield( L, -2, "ZoneEnd" );
|
|
lua_pushcfunction( L, detail::LuaZoneText );
|
|
lua_setfield( L, -2, "ZoneText" );
|
|
lua_pushcfunction( L, detail::LuaZoneName );
|
|
lua_setfield( L, -2, "ZoneName" );
|
|
lua_pushcfunction( L, detail::LuaMessage );
|
|
lua_setfield( L, -2, "Message" );
|
|
lua_setglobal( L, "tracy" );
|
|
}
|
|
|
|
static inline void LuaRemove( char* script ) {}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|