diff --git a/.github/workflows/gcc.yml b/.github/workflows/gcc.yml index 7a71bfef..91fe6740 100644 --- a/.github/workflows/gcc.yml +++ b/.github/workflows/gcc.yml @@ -40,3 +40,5 @@ jobs: make -j -C test make -j -C test clean make -j -C test TRACYFLAGS=-DTRACY_ON_DEMAND + make -j -C test clean + make -j -C test TRACYFLAGS="-DTRACY_DELAYED_INIT -DTRACY_MANUAL_LIFETIME" diff --git a/AUTHORS b/AUTHORS index 747c9d66..52c7654b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,3 +11,4 @@ Thales Sabino (OpenCL support) Andrew Depke (Direct3D 12 support) Simonas Kazlauskas (OSX CI, external bindings) Jakub Žádník (csvexport utility) +Andrey Voroshilov (multi-DLL fixes) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index f7286f56..873b4e28 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -924,6 +924,25 @@ struct ProfilerThreadData # endif }; +# ifdef TRACY_MANUAL_LIFETIME +ProfilerData* s_profilerData = nullptr; +TRACY_API void StartupProfiler() +{ + s_profilerData = new ProfilerData; + s_profilerData->profiler.SpawnWorkerThreads(); +} +static ProfilerData& GetProfilerData() +{ + assert(s_profilerData); + return *s_profilerData; +} +TRACY_API void ShutdownProfiler() +{ + delete s_profilerData; + s_profilerData = nullptr; + rpmalloc_finalize(); +} +# else static std::atomic profilerDataLock { 0 }; static std::atomic profilerData { nullptr }; @@ -945,6 +964,7 @@ static ProfilerData& GetProfilerData() } return *ptr; } +# endif static ProfilerThreadData& GetProfilerThreadData() { @@ -966,10 +986,12 @@ std::atomic& GetThreadNameData() { return GetProfilerData().thr TRACY_API LuaZoneState& GetLuaZoneState() { return GetProfilerThreadData().luaZoneState; } # endif +# ifndef TRACY_MANUAL_LIFETIME namespace { const auto& __profiler_init = GetProfiler(); } +# endif #else TRACY_API void InitRPMallocThread() @@ -1094,6 +1116,13 @@ Profiler::Profiler() m_userPort = atoi( userPort ); } +#if !defined(TRACY_DELAYED_INIT) || !defined(TRACY_MANUAL_LIFETIME) + SpawnWorkerThreads(); +#endif +} + +void Profiler::SpawnWorkerThreads() +{ s_thread = (Thread*)tracy_malloc( sizeof( Thread ) ); new(s_thread) Thread( LaunchWorker, this ); @@ -1185,6 +1214,8 @@ void Profiler::Worker() s_profilerTid = syscall( SYS_gettid ); #endif + ThreadExitHandler threadExitHandler; + SetThreadName( "Tracy Profiler" ); #ifdef TRACY_DATA_PORT @@ -1605,6 +1636,8 @@ void Profiler::Worker() void Profiler::CompressWorker() { + ThreadExitHandler threadExitHandler; + SetThreadName( "Tracy DXT1" ); while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); rpmalloc_thread_initialize(); diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index 53f4c136..55d53015 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -41,6 +41,10 @@ namespace tracy { +#if defined(TRACY_DELAYED_INIT) && defined(TRACY_MANUAL_LIFETIME) +void StartupProfiler(); +void ShutdownProfiler(); +#endif class GpuCtx; class Profiler; @@ -119,6 +123,8 @@ public: Profiler(); ~Profiler(); + void SpawnWorkerThreads(); + static tracy_force_inline int64_t GetTime() { #ifdef TRACY_HW_TIMER diff --git a/client/TracySysTrace.cpp b/client/TracySysTrace.cpp index 68652886..653ada21 100644 --- a/client/TracySysTrace.cpp +++ b/client/TracySysTrace.cpp @@ -321,6 +321,7 @@ static void SetupVsync() s_threadVsync = (Thread*)tracy_malloc( sizeof( Thread ) ); new(s_threadVsync) Thread( [] (void*) { + ThreadExitHandler threadExitHandler; SetThreadName( "Tracy Vsync" ); ProcessTrace( &s_traceHandleVsync2, 1, nullptr, nullptr ); }, nullptr ); @@ -455,6 +456,7 @@ void SysTraceStop() void SysTraceWorker( void* ptr ) { + ThreadExitHandler threadExitHandler; SetThreadName( "Tracy SysTrace" ); ProcessTrace( &s_traceHandle2, 1, 0, 0 ); ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP ); @@ -955,6 +957,7 @@ static void ProcessTraceLines( int fd ) void SysTraceWorker( void* ptr ) { + ThreadExitHandler threadExitHandler; SetThreadName( "Tracy SysTrace" ); int pipefd[2]; if( pipe( pipefd ) == 0 ) @@ -1028,6 +1031,7 @@ static void ProcessTraceLines( int fd ) void SysTraceWorker( void* ptr ) { + ThreadExitHandler threadExitHandler; SetThreadName( "Tracy SysTrace" ); char tmp[256]; memcpy( tmp, BasePath, sizeof( BasePath ) - 1 ); diff --git a/client/TracyThread.hpp b/client/TracyThread.hpp index 7fca497b..28c64c54 100644 --- a/client/TracyThread.hpp +++ b/client/TracyThread.hpp @@ -10,6 +10,17 @@ namespace tracy { +class ThreadExitHandler +{ +public: + ~ThreadExitHandler() + { +#ifdef TRACY_MANUAL_LIFETIME + rpmalloc_thread_finalize(); +#endif + } +}; + #if defined _WIN32 || defined __CYGWIN__ class Thread diff --git a/manual/tracy.tex b/manual/tracy.tex index 8f78a127..35b4521f 100644 --- a/manual/tracy.tex +++ b/manual/tracy.tex @@ -427,6 +427,10 @@ For that you need a \emph{profiler DLL} to which your executable and the other D If you are targeting Windows with Microsoft Visual Studio or MinGW, add the \texttt{TRACY\_IMPORTS} define to your application. +If you are experiencing crashes or freezes when manually loading/unloading a separate DLL with Tracy integration, you might want to try defining both \texttt{TRACY\_DELAYED\_INIT} and \texttt{TRACY\_MANUAL\_LIFETIME} macros. + +\texttt{TRACY\_DELAYED\_INIT} enables a path where profiler data is gathered into one structure and initialized on the first request rather than statically at the DLL load at the expense of atomic load on each request to the profiler data. \texttt{TRACY\_MANUAL\_LIFETIME} flag augments this behavior to provide manual \texttt{StartupProfiler} and \texttt{ShutdownProfiler} functions that allow you to manually create and destroy the profiler data, removing the need to do an atomic load on each call, as well as letting you define an appropriate place to free the resources. + \subsubsection{Problematic platforms} Some OS vendors think that \emph{they} own and control the devices \emph{you} have paid for. This results in restricting usage of APIs that might 'confuse' you, or denying you access to information about what your computer is doing.