Compare commits

...

95 Commits
v0.4 ... sigint

Author SHA1 Message Date
Bartosz Taudul
8a2894f6e6 Handle SIGINT.
This allows to send the remaining data to the server, before profiled
application exits.
2018-12-29 01:24:49 +01:00
Bartosz Taudul
5cbe2c6ae5 Reorder tracy_lz4.cpp vs TracyProfiler.cpp in TracyClient.cpp.
This fixes deprecation warning in tracy_lz4.hpp, which was previously
present due to TracyProfiler.cpp including tracy_lz4.hpp before an
appropriate deprecation restraining macro was defined in tracy_lz4.cpp.
Note that this issue was only present if TracyClient.cpp was used to
include the profiler in a project. Including the profiler as a
collection of separate source files worked correctly, as the deprecated
function is only used by tracy_lz4.cpp.
2018-12-29 01:00:14 +01:00
Bartosz Taudul
b1ba2f9bf7 Fix extern "C" initialization. 2018-12-29 01:00:14 +01:00
Bartosz Taudul
1733961885 Proper printf type for DWORDLONG on cygwin. 2018-12-29 01:00:14 +01:00
Bartosz Taudul
ee718f18d9 Cygwin headers provide their own FORCEINLINE macro. 2018-12-29 01:00:14 +01:00
Bartosz Taudul
0a6c6606bf Don't use MSVC pragmas on gcc/clang (cygwin). 2018-12-29 01:00:14 +01:00
Miguel Fernandez
5e4b5850af Merged in Muitxer/tracy (pull request #28)
Moved NoMinMax before windows.h
2018-12-24 19:06:51 +00:00
Miguel Fernandez
baa870fa8c Moved NoMinMax before windows.h 2018-12-24 18:50:52 +00:00
Miguel Fernandez
1a50a15212 Merged in Muitxer/tracy (pull request #27)
Avoid conflicts with min/max macros
2018-12-24 18:50:19 +00:00
Miguel Fernandez
7c164375a4 Moved NoMinMax inside _MSC_VER 2018-12-24 18:49:53 +00:00
Miguel Fernandez
51bdb004f9 Avoid conflicts with min/max macros 2018-12-24 15:26:50 +00:00
Bartosz Taudul
d80bd2693c Update manual. 2018-12-22 17:46:30 +01:00
Bartosz Taudul
0ac83a27cc Update NEWS. 2018-12-22 17:41:29 +01:00
Bartosz Taudul
ea396354d0 ^F opens find zone menu and focuses on the input box. 2018-12-22 17:39:22 +01:00
Bartosz Taudul
2d143ce516 Add support for handling keyboard shortcuts. 2018-12-22 17:36:20 +01:00
Bartosz Taudul
4bb4a568ca Move initialization of View values to header. 2018-12-22 17:22:26 +01:00
Bartosz Taudul
e1bd5c092b Pressing enter key when entering client address automatically connects. 2018-12-22 17:14:22 +01:00
Bartosz Taudul
cd8d86edf3 Allow hiding "[unknown frames]" entries. 2018-12-21 21:10:29 +01:00
Bartosz Taudul
e9ce8fdfda Flush queues when opening listen socket fails. 2018-12-21 18:14:30 +01:00
Bartosz Taudul
a4be9b51b0 Use common queue clearing function. 2018-12-21 18:12:26 +01:00
Bartosz Taudul
331693d7f1 Use proper pattern for acquiring serial lock.
This fixes a potential hang during crash handling. Also, lock duration
is reduced.
2018-12-21 18:11:09 +01:00
Bartosz Taudul
4893bca12b Update manual. 2018-12-20 17:13:18 +01:00
Bartosz Taudul
2f45fd8b36 Update NEWS. 2018-12-20 17:08:24 +01:00
Bartosz Taudul
6fefffe8a5 Implement automated connection to a given IP address. 2018-12-20 17:07:15 +01:00
Bartosz Taudul
8c5670489c Freeing nullptr is valid. 2018-12-20 17:03:09 +01:00
Bartosz Taudul
407fb61a30 Display maximum number of waiting threads for a lock. 2018-12-19 18:34:53 +01:00
Bartosz Taudul
0f2b61cf24 Display wait and hold times of locks. 2018-12-19 18:28:48 +01:00
Bartosz Taudul
1d70e5e5c3 Document the maximum number of threads supported by locks. 2018-12-18 18:24:27 +01:00
Bartosz Taudul
621f7c891e Document right click on lock label in options menu. 2018-12-18 18:16:24 +01:00
Bartosz Taudul
30c2d0df85 Add lock information window section. 2018-12-18 18:14:26 +01:00
Bartosz Taudul
4e64ba7775 Document lock events interaction. 2018-12-18 17:56:02 +01:00
Bartosz Taudul
83958db840 Add information about collapsing labels. 2018-12-18 17:55:54 +01:00
Bartosz Taudul
70ec4b71e4 Move zone interaction out of view navigation section. 2018-12-18 17:45:18 +01:00
Bartosz Taudul
ac9dbfbc79 Add a note about source button highlight. 2018-12-18 17:28:00 +01:00
Bartosz Taudul
57b4f874cc Menu bar buttons are now toggles. 2018-12-18 17:24:19 +01:00
Bartosz Taudul
bd71190a4c Add separate section describing collapsed items. 2018-12-18 17:21:29 +01:00
Bartosz Taudul
0898873a02 Update NEWS. 2018-12-18 16:58:29 +01:00
Bartosz Taudul
df1a125fc0 Mirror find zone menu changes in compare menu. 2018-12-18 16:56:19 +01:00
Bartosz Taudul
a220f38fbd Add support for matching source locations ignoring case. 2018-12-18 16:52:29 +01:00
Bartosz Taudul
acddcbd9bf Add case-ignoring string matcher. 2018-12-18 16:52:05 +01:00
Bartosz Taudul
24235406a0 Enter key in find zone menu acts the same as pressing "find". 2018-12-18 16:40:23 +01:00
Bartosz Taudul
7fc03736f2 Add "ignore case" toggle to find zone menu. 2018-12-18 16:38:55 +01:00
Bartosz Taudul
a740074da6 Color tweaks. 2018-12-18 16:30:13 +01:00
Bartosz Taudul
b60d5b892a Unify coloring of highlighted buttons. 2018-12-18 16:30:13 +01:00
Bartosz Taudul
c2485fbcb0 Add visual notification of an active toggle. 2018-12-18 16:30:13 +01:00
Bartosz Taudul
9e18db01c9 Menu bar buttons are now toggles. 2018-12-18 16:30:13 +01:00
Rokas K. (rku)
85fbfeccf0 Merged in rokups/tracy/fix-macos-android-builds (pull request #25)
Fix MacOS/android builds
2018-12-18 15:20:44 +00:00
Rokas Kupstys
a931b9eaf1 HOST_NAME_MAX and LOGIN_NAME_MAX availability is not consistent across linux/android/macos platforms. However all of them do have versions of these macros with _POSIX_ prefix.
In addition to that hostname and user variables may be uninitialized in some configurations, however they are always used. Initializing these arrays fixes conditional depending on uninitialized memory warning uncovered by valgrind.
2018-12-18 17:19:03 +02:00
Bartosz Taudul
083320820f OSX doesn't define HOST_NAME_MAX and LOGIN_NAME_MAX.
Fix based on patch from Jack Skalski.
2018-12-17 15:11:59 +01:00
Bartosz Taudul
a7e615d42e Cosmetics. 2018-12-17 15:09:10 +01:00
Bartosz Taudul
79eb6a5836 Right click on lock in options to open info window. 2018-12-16 21:14:15 +01:00
Bartosz Taudul
aac8d85e6d Update NEWS. 2018-12-16 21:09:37 +01:00
Bartosz Taudul
9a7689c65d Display lock announce, terminate and life time. 2018-12-16 21:09:37 +01:00
Bartosz Taudul
7376ec65b0 Store lock announce and terminate time in trace dump. 2018-12-16 21:09:37 +01:00
Bartosz Taudul
9360df89b1 Store announce and terminate time of locks. 2018-12-16 21:07:26 +01:00
Bartosz Taudul
f42d52923a No-op processing of lock terminate events. 2018-12-16 20:46:33 +01:00
Bartosz Taudul
0b816ce0b7 Add lock termination event. 2018-12-16 20:46:33 +01:00
Bartosz Taudul
61ac0b8afc Send lock creation time. 2018-12-16 20:33:18 +01:00
Bartosz Taudul
91171a6674 Draw zig-zag pattern over collapsed locks. 2018-12-16 20:20:27 +01:00
Bartosz Taudul
abad5574f3 Middle click on lock event to zoom to it. 2018-12-16 20:04:45 +01:00
Bartosz Taudul
8f6f54e412 Clicking on a lock event also opens lock info window. 2018-12-16 20:01:40 +01:00
Bartosz Taudul
444d5e20f0 Add basic lock info window. 2018-12-16 19:58:11 +01:00
Bartosz Taudul
ff8c9ab6dc Properly terminate source file data. 2018-12-16 19:48:34 +01:00
Bartosz Taudul
80bd4275eb Document TRACY_CALLSTACK macro. 2018-12-13 15:42:53 +01:00
Bartosz Taudul
a54fab05e8 Update NEWS. 2018-12-13 14:44:20 +01:00
Bartosz Taudul
537cee911c Allow forcing call stack capture. 2018-12-13 14:43:37 +01:00
Bartosz Taudul
3c1231f5eb Update manual. 2018-11-25 19:36:17 +01:00
Bartosz Taudul
a9a2ca66ca Update NEWS. 2018-11-25 19:31:26 +01:00
Bartosz Taudul
1235a5aa0a Allow discarding active trace. 2018-11-25 19:31:26 +01:00
Bartosz Taudul
fec0017bb6 Add third state (stopped) to the pause/resume button. 2018-11-25 19:15:16 +01:00
Bartosz Taudul
f19b559f6e InitOnceExecuteOnce requires targeting Windows Vista.
Cygwin fix.
2018-11-25 19:03:17 +01:00
Bartosz Taudul
d8a9d6d3bf Update imguicolortextedit.
339d5ef00edcfb849c1281bcf176113199828522
2018-10-30 22:52:57 +01:00
Bartosz Taudul
6f9977638d Update AUTHORS list. 2018-10-29 17:53:28 +01:00
Sherief Farouk
853eec451f Merged in sherief/tracy-rpmalloc-bugfix (pull request #24)
Fix for using Tracy with multithreaded NT loader in Windows 10 RS5 (Issue #26).
2018-10-29 10:08:20 +00:00
Sherief Farouk
591f04ad0f Renamed preprocessor #define for consistency. 2018-10-28 22:41:08 -07:00
Sherief Farouk
5110d55f17 Fix for using Tracy with multithreaded NT loader in Windows 10 RS5 (Issue #26) [Take 2]. 2018-10-28 18:55:55 -07:00
Sherief Farouk
27447902ef Fix for using Tracy with multithreaded NT loader in Windows 10 RS5 (Issue #26). 2018-10-27 18:13:59 -07:00
Bartosz Taudul
d8bcb32951 Add freetype to libraries list. 2018-10-27 20:08:50 +02:00
Bartosz Taudul
dc4c8ef343 Statically link with freetype. 2018-10-27 20:06:54 +02:00
Bartosz Taudul
6f9b4aeac9 Document the connection history drop-down. 2018-10-23 20:12:36 +02:00
Bartosz Taudul
78beb7bd81 Allow removal of addresses from connection history. 2018-10-23 19:59:11 +02:00
Bartosz Taudul
a234510ef3 Update NEWS. 2018-10-23 19:50:09 +02:00
Bartosz Taudul
2af941eadc Allow selection from the 5 most commonly used addresses. 2018-10-23 19:50:09 +02:00
Bartosz Taudul
1eb46042be Track connection history. 2018-10-23 19:50:09 +02:00
Bartosz Taudul
63f0dd72a5 Allow cancelling pending connection. 2018-10-23 19:49:57 +02:00
Bartosz Taudul
c3ba314700 Update profiler screenshot. 2018-10-21 18:10:35 +02:00
Bartosz Taudul
b20b169a88 Document "go to frame" functionality. 2018-10-21 17:51:02 +02:00
Bartosz Taudul
54baec9e7e Fix drawing last collapsed non-contiguous frame. 2018-10-21 17:46:24 +02:00
Bartosz Taudul
56190c9614 Update NEWS. 2018-10-21 17:46:21 +02:00
Bartosz Taudul
556b3e8efe Add "go to frame" functionality. 2018-10-21 17:36:27 +02:00
Bartosz Taudul
793e955480 Fix crash when loading a trace with unresolved strings.
Unresolved strings ("???") are not saved, but the internal string
pointers are saved. Resolving such string pointers caused a crash.
2018-10-21 16:38:20 +02:00
Bartosz Taudul
9342ba0e71 Don't track last frames in offline mode. 2018-10-21 16:03:21 +02:00
Bartosz Taudul
2165881efc Document timeline view frame set changing. 2018-10-21 15:53:21 +02:00
Bartosz Taudul
759a4ac908 Update NEWS. 2018-10-21 15:46:53 +02:00
Bartosz Taudul
5280d6586b Switching active frame set by clicking on a frame. 2018-10-21 15:46:02 +02:00
24 changed files with 1752 additions and 490 deletions

View File

@@ -4,3 +4,4 @@ Bartosz Szreder <zgredder@gmail.com>
Arvid Gerstmann <dev@arvid-g.de>
Rokas Kupstys <rokups@zoho.com>
Till Rathmann <till.rathmann@gmx.de>
Sherief Farouk <sherief.personal@gmail.com>

27
NEWS
View File

@@ -6,6 +6,33 @@ Note: Release numbers are nothing more than numbers. There are some
"missing" versions due to trace file changes during development. This is not
a mistake.
v0.5 (xxxx-xx-xx)
-----------------
- Active frame set can be now switched by clicking on a frame set on the
timeline.
- Add ability to go to a specified frame.
- Most commonly used addresses can be now selected from the drop-down menu.
- Fixed corner case problem with profiler initialization on Windows.
- Added third state (stopped) to the pause/resume button. It will be used
after the connection to the client is terminated.
- Active trace can be discarded.
- Call stack capture may be forced through TRACY_CALLSTACK define.
- Lock info window has been added.
- Time of lock creation and termination is now being tracked.
- Menu bar buttons are now toggles that can also close their corresponding
windows.
- Find zone and compare menu improvements.
- Ability to ignore case during search.
- Pressing enter key will now start search, just like pressing the "find"
button.
- Using the ^F keyboard shortcut will open the find zone menu and focus
the input box.
- Added ability to automatically connect to an IP address in the graphical
profiler application (use "-a address" argument to enable).
- Pressing enter key after entering client address in the welcome dialog
will now automatically begin connection process.
v0.4 (2018-10-09)
-----------------

View File

@@ -59,10 +59,17 @@
#include "client/TracyProfiler.hpp"
#include "client/TracyScoped.hpp"
#define ZoneNamed( varname, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
#define ZoneNamedN( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
#define ZoneNamedC( varname, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
#define ZoneNamedNC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define ZoneNamed( varname, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
# define ZoneNamedN( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
# define ZoneNamedC( varname, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
# define ZoneNamedNC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), TRACY_CALLSTACK, active );
#else
# define ZoneNamed( varname, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
# define ZoneNamedN( varname, name, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
# define ZoneNamedC( varname, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
# define ZoneNamedNC( varname, name, color, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), active );
#endif
#define ZoneScoped ZoneNamed( ___tracy_scoped_zone, true )
#define ZoneScopedN( name ) ZoneNamedN( ___tracy_scoped_zone, name, true )
@@ -90,8 +97,13 @@
#define TracyMessage( txt, size ) tracy::Profiler::Message( txt, size );
#define TracyMessageL( txt ) tracy::Profiler::Message( txt );
#define TracyAlloc( ptr, size ) tracy::Profiler::MemAlloc( ptr, size );
#define TracyFree( ptr ) tracy::Profiler::MemFree( ptr );
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyAlloc( ptr, size ) tracy::Profiler::MemAllocCallstack( ptr, size, TRACY_CALLSTACK );
# define TracyFree( ptr ) tracy::Profiler::MemFreeCallstack( ptr, TRACY_CALLSTACK );
#else
# define TracyAlloc( ptr, size ) tracy::Profiler::MemAlloc( ptr, size );
# define TracyFree( ptr ) tracy::Profiler::MemFree( ptr );
#endif
#ifdef TRACY_HAS_CALLSTACK
# define ZoneNamedS( varname, depth, active ) static const tracy::SourceLocationData TracyConcat(__tracy_source_location,__LINE__) { nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::ScopedZone varname( &TracyConcat(__tracy_source_location,__LINE__), depth, active );

View File

@@ -15,9 +15,9 @@
#ifdef TRACY_ENABLE
#include "common/tracy_lz4.cpp"
#include "client/TracyProfiler.cpp"
#include "client/TracyCallstack.cpp"
#include "common/tracy_lz4.cpp"
#include "common/TracySocket.cpp"
#include "client/tracy_rpmalloc.cpp"

View File

@@ -30,10 +30,17 @@
#include "common/TracyAlloc.hpp"
#define TracyGpuContext tracy::s_gpuCtx.ptr = (tracy::GpuCtx*)tracy::tracy_malloc( sizeof( tracy::GpuCtx ) ); new(tracy::s_gpuCtx.ptr) tracy::GpuCtx;
#define TracyGpuNamedZone( varname, name ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__) );
#define TracyGpuNamedZoneC( varname, name, color ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__) );
#define TracyGpuZone( name ) TracyGpuNamedZone( ___tracy_gpu_zone, name )
#define TracyGpuZoneC( name, color ) TracyGpuNamedZoneC( ___tracy_gpu_zone, name, color )
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyGpuNamedZone( varname, name ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), TRACY_CALLSTACK );
# define TracyGpuNamedZoneC( varname, name, color ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), TRACY_CALLSTACK );
# define TracyGpuZone( name ) TracyGpuNamedZoneS( ___tracy_gpu_zone, name, TRACY_CALLSTACK )
# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneCS( ___tracy_gpu_zone, name, color, TRACY_CALLSTACK )
#else
# define TracyGpuNamedZone( varname, name ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__) );
# define TracyGpuNamedZoneC( varname, name, color ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::GpuCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__) );
# define TracyGpuZone( name ) TracyGpuNamedZone( ___tracy_gpu_zone, name )
# define TracyGpuZoneC( name, color ) TracyGpuNamedZoneC( ___tracy_gpu_zone, name, color )
#endif
#define TracyGpuCollect tracy::s_gpuCtx.ptr->Collect();
#ifdef TRACY_HAS_CALLSTACK

View File

@@ -27,10 +27,17 @@
#define TracyVkContext( physdev, device, queue, cmdbuf ) tracy::s_vkCtx.ptr = (tracy::VkCtx*)tracy::tracy_malloc( sizeof( tracy::VkCtx ) ); new(tracy::s_vkCtx.ptr) tracy::VkCtx( physdev, device, queue, cmdbuf );
#define TracyVkDestroy tracy::s_vkCtx.ptr->~VkCtx(); tracy::tracy_free( tracy::s_vkCtx.ptr ); tracy::s_vkCtx.ptr = nullptr;
#define TracyVkNamedZone( varname, cmdbuf, name ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::VkCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf );
#define TracyVkNamedZoneC( varname, cmdbuf, name, color ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::VkCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf );
#define TracyVkZone( cmdbuf, name ) TracyVkNamedZone( ___tracy_gpu_zone, cmdbuf, name )
#define TracyVkZoneC( cmdbuf, name, color ) TracyVkNamedZoneC( ___tracy_gpu_zone, cmdbuf, name, color )
#if defined TRACY_HAS_CALLSTACK && defined TRACY_CALLSTACK
# define TracyVkNamedZone( varname, cmdbuf, name ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::VkCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, TRACY_CALLSTACK );
# define TracyVkNamedZoneC( varname, cmdbuf, name, color ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::VkCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf, TRACY_CALLSTACK );
# define TracyVkZone( cmdbuf, name ) TracyVkNamedZoneS( ___tracy_gpu_zone, cmdbuf, name, TRACY_CALLSTACK )
# define TracyVkZoneC( cmdbuf, name, color ) TracyVkNamedZoneCS( ___tracy_gpu_zone, cmdbuf, name, color, TRACY_CALLSTACK )
#else
# define TracyVkNamedZone( varname, cmdbuf, name ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 }; tracy::VkCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf );
# define TracyVkNamedZoneC( varname, cmdbuf, name, color ) static const tracy::SourceLocationData TracyConcat(__tracy_gpu_source_location,__LINE__) { name, __FUNCTION__, __FILE__, (uint32_t)__LINE__, color }; tracy::VkCtxScope varname( &TracyConcat(__tracy_gpu_source_location,__LINE__), cmdbuf );
# define TracyVkZone( cmdbuf, name ) TracyVkNamedZone( ___tracy_gpu_zone, cmdbuf, name )
# define TracyVkZoneC( cmdbuf, name, color ) TracyVkNamedZoneC( ___tracy_gpu_zone, cmdbuf, name, color )
#endif
#define TracyVkCollect( cmdbuf ) tracy::s_vkCtx.ptr->Collect( cmdbuf );
#ifdef TRACY_HAS_CALLSTACK

View File

@@ -5,10 +5,14 @@
#if TRACY_HAS_CALLSTACK == 1
# include <windows.h>
# pragma warning( push )
# pragma warning( disable : 4091 )
# ifdef _MSC_VER
# pragma warning( push )
# pragma warning( disable : 4091 )
# endif
# include <dbghelp.h>
# pragma warning( pop )
# ifdef _MSC_VER
# pragma warning( pop )
# endif
#elif TRACY_HAS_CALLSTACK >= 2
# include <dlfcn.h>
# include <cxxabi.h>
@@ -19,7 +23,7 @@ namespace tracy
#if TRACY_HAS_CALLSTACK == 1
extern "C" t_RtlWalkFrameChain RtlWalkFrameChain = 0;
extern "C" { t_RtlWalkFrameChain RtlWalkFrameChain = 0; }
void InitCallstack()
{

View File

@@ -32,6 +32,7 @@ public:
auto item = token->enqueue_begin<tracy::moodycamel::CanAlloc>( magic );
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
MemWrite( &item->lockAnnounce.id, m_id );
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
MemWrite( &item->lockAnnounce.type, LockType::Lockable );
@@ -45,6 +46,24 @@ public:
Lockable( const Lockable& ) = delete;
Lockable& operator=( const Lockable& ) = delete;
~Lockable()
{
Magic magic;
auto& token = s_token.ptr;
auto& tail = token->get_tail_index();
auto item = token->enqueue_begin<tracy::moodycamel::CanAlloc>( magic );
MemWrite( &item->hdr.type, QueueType::LockTerminate );
MemWrite( &item->lockTerminate.id, m_id );
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
MemWrite( &item->lockTerminate.type, LockType::Lockable );
#ifdef TRACY_ON_DEMAND
s_profiler.DeferItem( *item );
#endif
tail.store( magic + 1, std::memory_order_release );
}
tracy_force_inline void lock()
{
#ifdef TRACY_ON_DEMAND
@@ -206,6 +225,7 @@ public:
auto item = token->enqueue_begin<tracy::moodycamel::CanAlloc>( magic );
MemWrite( &item->hdr.type, QueueType::LockAnnounce );
MemWrite( &item->lockAnnounce.id, m_id );
MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );
@@ -219,6 +239,24 @@ public:
SharedLockable( const SharedLockable& ) = delete;
SharedLockable& operator=( const SharedLockable& ) = delete;
~SharedLockable()
{
Magic magic;
auto& token = s_token.ptr;
auto& tail = token->get_tail_index();
auto item = token->enqueue_begin<tracy::moodycamel::CanAlloc>( magic );
MemWrite( &item->hdr.type, QueueType::LockTerminate );
MemWrite( &item->lockTerminate.id, m_id );
MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
MemWrite( &item->lockTerminate.type, LockType::SharedLockable );
#ifdef TRACY_ON_DEMAND
s_profiler.DeferItem( *item );
#endif
tail.store( magic + 1, std::memory_order_release );
}
tracy_force_inline void lock()
{
#ifdef TRACY_ON_DEMAND

View File

@@ -1,6 +1,9 @@
#ifdef TRACY_ENABLE
#ifdef _MSC_VER
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <winsock2.h>
# include <windows.h>
# include <tlhelp32.h>
@@ -56,6 +59,9 @@
#if defined _MSC_VER || defined __CYGWIN__
# include <lmcons.h>
extern "C" typedef LONG (WINAPI *t_RtlGetVersion)( PRTL_OSVERSIONINFOW );
# if _WIN32_WINNT >= _WIN32_WINNT_VISTA
# define TRACY_USE_INIT_ONCE
# endif
#else
# include <unistd.h>
# include <limits.h>
@@ -71,14 +77,48 @@ extern "C" typedef LONG (WINAPI *t_RtlGetVersion)( PRTL_OSVERSIONINFOW );
namespace tracy
{
#if defined TRACY_USE_INIT_ONCE
namespace
{
BOOL CALLBACK InitOnceCallback(
PINIT_ONCE initOnce,
PVOID Parameter,
PVOID *Context)
{
rpmalloc_initialize();
return TRUE;
}
INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT;
}
#endif //if defined TRACY_USE_INIT_ONCE
struct RPMallocInit
{
RPMallocInit() { rpmalloc_initialize(); }
RPMallocInit()
{
#if defined TRACY_USE_INIT_ONCE
InitOnceExecuteOnce(&InitOnce, InitOnceCallback, nullptr, nullptr);
//We must call rpmalloc_thread_initialize() explicitly here since the InitOnceCallback might
//not be called on this thread if another thread has executed it earlier.
rpmalloc_thread_initialize();
#else
rpmalloc_initialize();
#endif //if defined TRACY_USE_INIT_ONCE
}
};
struct RPMallocThreadInit
{
RPMallocThreadInit() { rpmalloc_thread_initialize(); }
RPMallocThreadInit()
{
#if defined TRACY_USE_INIT_ONCE
InitOnceExecuteOnce(&InitOnce, InitOnceCallback, nullptr, nullptr);
#endif //if defined TRACY_USE_INIT_ONCE
rpmalloc_thread_initialize();
}
};
struct InitTimeWrapper
@@ -252,10 +292,10 @@ static const char* GetHostInfo()
ptr += sprintf( ptr, "User: %s@%s\n", user, hostname );
#else
char hostname[HOST_NAME_MAX];
char user[LOGIN_NAME_MAX];
char hostname[_POSIX_HOST_NAME_MAX]{};
char user[_POSIX_LOGIN_NAME_MAX]{};
gethostname( hostname, HOST_NAME_MAX );
gethostname( hostname, _POSIX_HOST_NAME_MAX );
# if defined __ANDROID__
const auto login = getlogin();
if( login )
@@ -267,7 +307,7 @@ static const char* GetHostInfo()
memcpy( user, "(?)", 4 );
}
# else
getlogin_r( user, LOGIN_NAME_MAX );
getlogin_r( user, _POSIX_LOGIN_NAME_MAX );
# endif
ptr += sprintf( ptr, "User: %s@%s\n", user, hostname );
@@ -309,7 +349,11 @@ static const char* GetHostInfo()
MEMORYSTATUSEX statex;
statex.dwLength = sizeof( statex );
GlobalMemoryStatusEx( &statex );
# ifdef _MSC_VER
ptr += sprintf( ptr, "RAM: %I64u MB\n", statex.ullTotalPhys / 1024 / 1024 );
# else
ptr += sprintf( ptr, "RAM: %llu MB\n", statex.ullTotalPhys / 1024 / 1024 );
# endif
#elif defined __linux__
struct sysinfo sysInfo;
sysinfo( &sysInfo );
@@ -601,12 +645,16 @@ static void CrashHandler( int signal, siginfo_t* info, void* ucontext )
break;
}
break;
case SIGINT:
strcpy( msgPtr, "User interrupt.\n" );
while( *msgPtr ) msgPtr++;
break;
default:
abort();
}
while( *msgPtr ) msgPtr++;
if( signal != SIGPIPE )
if( signal != SIGPIPE && signal != SIGINT )
{
strcpy( msgPtr, "Fault address: 0x" );
while( *msgPtr ) msgPtr++;
@@ -659,7 +707,14 @@ static void CrashHandler( int signal, siginfo_t* info, void* ucontext )
s_profiler.RequestShutdown();
while( !s_profiler.HasShutdownFinished() ) { std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); };
abort();
if( signal == SIGINT )
{
exit( 0 );
}
else
{
abort();
}
}
#endif
@@ -823,6 +878,7 @@ Profiler::Profiler()
sigaction( SIGSEGV, &crashHandler, nullptr );
sigaction( SIGPIPE, &crashHandler, nullptr );
sigaction( SIGBUS, &crashHandler, nullptr );
sigaction( SIGINT, &crashHandler, nullptr );
#endif
#ifdef TRACY_HAS_CALLSTACK
@@ -896,7 +952,19 @@ void Profiler::Worker()
moodycamel::ConsumerToken token( s_queue );
ListenSocket listen;
listen.Listen( "8086", 8 );
if( !listen.Listen( "8086", 8 ) )
{
for(;;)
{
if( ShouldExit() )
{
m_shutdownFinished.store( true, std::memory_order_relaxed );
return;
}
ClearQueues( token );
}
}
for(;;)
{
@@ -1032,22 +1100,7 @@ void Profiler::Worker()
return;
}
while( s_queue.try_dequeue_bulk( token, m_itemBuf, BulkSize ) > 0 ) {}
bool lockHeld = true;
while( !m_serialLock.try_lock() )
{
if( m_shutdownManual.load( std::memory_order_relaxed ) )
{
lockHeld = false;
break;
}
}
m_serialQueue.swap( m_serialDequeue );
if( lockHeld )
{
m_serialLock.unlock();
}
m_serialDequeue.clear();
ClearQueues( token );
m_sock = listen.Accept();
if( m_sock )
@@ -1185,13 +1238,26 @@ void Profiler::ClearQueues( moodycamel::ConsumerToken& token )
for( size_t i=0; i<sz; i++ ) FreeAssociatedMemory( m_itemBuf[i] );
}
std::lock_guard<TracyMutex> lock( m_serialLock );
{
bool lockHeld = true;
while( !m_serialLock.try_lock() )
{
if( m_shutdownManual.load( std::memory_order_relaxed ) )
{
lockHeld = false;
break;
}
}
for( auto& v : m_serialQueue ) FreeAssociatedMemory( v );
m_serialQueue.clear();
if( lockHeld )
{
m_serialLock.unlock();
}
}
for( auto& v : m_serialDequeue ) FreeAssociatedMemory( v );
m_serialDequeue.clear();
for( auto& v : m_serialQueue ) FreeAssociatedMemory( v );
m_serialQueue.clear();
}
Profiler::DequeueStatus Profiler::Dequeue( moodycamel::ConsumerToken& token )

View File

@@ -101,6 +101,9 @@
# include <pthread.h>
# endif
# define ALIGNED_STRUCT(name, alignment) struct __attribute__((__aligned__(alignment))) name
# ifdef FORCEINLINE
# undef FORCEINLINE
# endif
# define FORCEINLINE inline __attribute__((__always_inline__))
# ifdef __arm__
# define atomic_thread_fence_acquire() __asm volatile("dmb ish" ::: "memory")

View File

@@ -9,7 +9,7 @@
namespace tracy
{
enum : uint32_t { ProtocolVersion = 0 };
enum : uint32_t { ProtocolVersion = 1 };
using lz4sz_t = uint32_t;

View File

@@ -26,6 +26,7 @@ enum class QueueType : uint8_t
FrameMarkMsgEnd,
SourceLocation,
LockAnnounce,
LockTerminate,
LockWait,
LockObtain,
LockRelease,
@@ -109,10 +110,18 @@ enum class LockType : uint8_t
struct QueueLockAnnounce
{
uint32_t id;
int64_t time;
uint64_t lckloc; // ptr
LockType type;
};
struct QueueLockTerminate
{
uint32_t id;
int64_t time;
LockType type;
};
struct QueueLockWait
{
uint32_t id;
@@ -264,6 +273,7 @@ struct QueueItem
QueueSourceLocation srcloc;
QueueZoneText zoneText;
QueueLockAnnounce lockAnnounce;
QueueLockTerminate lockTerminate;
QueueLockWait lockWait;
QueueLockObtain lockObtain;
QueueLockRelease lockRelease;
@@ -307,6 +317,7 @@ static const size_t QueueDataSize[] = {
sizeof( QueueHeader ) + sizeof( QueueFrameMark ), // end
sizeof( QueueHeader ) + sizeof( QueueSourceLocation ),
sizeof( QueueHeader ) + sizeof( QueueLockAnnounce ),
sizeof( QueueHeader ) + sizeof( QueueLockTerminate ),
sizeof( QueueHeader ) + sizeof( QueueLockWait ),
sizeof( QueueHeader ) + sizeof( QueueLockObtain ),
sizeof( QueueHeader ) + sizeof( QueueLockRelease ),

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 72 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -133,7 +133,7 @@ public:
struct Glyph
{
Char mChar;
PaletteIndex mColorIndex : 7;
PaletteIndex mColorIndex = PaletteIndex::Default;
bool mMultiLineComment : 1;
Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex), mMultiLineComment(false) {}
@@ -146,24 +146,33 @@ public:
{
typedef std::pair<std::string, PaletteIndex> TokenRegexString;
typedef std::vector<TokenRegexString> TokenRegexStrings;
typedef bool (*TokenizeCallback)(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex);
std::string mName;
Keywords mKeywords;
Identifiers mIdentifiers;
Identifiers mPreprocIdentifiers;
std::string mCommentStart, mCommentEnd;
bool mAutoIndentation;
TokenizeCallback mTokenize;
TokenRegexStrings mTokenRegexStrings;
bool mCaseSensitive;
static LanguageDefinition CPlusPlus();
static LanguageDefinition HLSL();
static LanguageDefinition GLSL();
static LanguageDefinition C();
static LanguageDefinition SQL();
static LanguageDefinition AngelScript();
static LanguageDefinition Lua();
LanguageDefinition()
: mTokenize(nullptr)
{
}
static const LanguageDefinition& CPlusPlus();
static const LanguageDefinition& HLSL();
static const LanguageDefinition& GLSL();
static const LanguageDefinition& C();
static const LanguageDefinition& SQL();
static const LanguageDefinition& AngelScript();
static const LanguageDefinition& Lua();
};
TextEditor();
@@ -179,16 +188,18 @@ public:
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
void SetText(const char* aText);
void SetText(const std::string& aText);
std::string GetText() const;
std::string GetSelectedText() const;
std::string GetCurrentLineText()const;
int GetTotalLines() const { return (int)mLines.size(); }
bool IsOverwrite() const { return mOverwrite; }
void SetReadOnly(bool aValue);
bool IsReadOnly() const { return mReadOnly; }
bool IsTextChanged() const { return mTextChanged; }
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
void SetCursorPosition(const Coordinates& aPosition);
@@ -275,7 +286,7 @@ private:
void Colorize(int aFromLine = 0, int aCount = -1);
void ColorizeRange(int aFromLine = 0, int aToLine = 0);
void ColorizeInternal();
int TextDistanceToLineStart(const Coordinates& aFrom) const;
float TextDistanceToLineStart(const Coordinates& aFrom) const;
void EnsureCursorVisible();
int GetPageSize() const;
int AppendBuffer(std::string& aBuffer, char chr, int aIndex);
@@ -293,7 +304,7 @@ private:
void RemoveLine(int aStart, int aEnd);
void RemoveLine(int aIndex);
Line& InsertLine(int aIndex);
void EnterCharacter(Char aChar);
void EnterCharacter(Char aChar, bool aShift);
void BackSpace();
void DeleteSelection();
std::string GetWordUnderCursor() const;
@@ -311,6 +322,9 @@ private:
bool mWithinRender;
bool mScrollToCursor;
bool mTextChanged;
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
int mLeftMargin;
bool mCursorPositionChanged;
int mColorRangeMin, mColorRangeMax;
SelectionMode mSelectionMode;

View File

@@ -14,6 +14,7 @@
\usepackage[hyphens]{url}
\usepackage{hyperref} % For hyperlinks in the PDF
\usepackage{fontawesome5}
\usepackage[os=win]{menukeys}
\usepackage[hmarginratio=1:1,top=32mm,columnsep=20pt]{geometry} % Document margins
\geometry{a4paper,textwidth=6.5in,hmarginratio=1:1,
@@ -495,6 +496,14 @@ To mark the location of lock being held, use the \texttt{LockMark(varname)} macr
Similarly, you can use \texttt{TracySharedLockable}, \texttt{TracySharedLockableN} and \texttt{SharedLockableBase} to mark locks implementing the SharedMutex requirement\footnote{\url{https://en.cppreference.com/w/cpp/named_req/SharedMutex}}. Note that while there's no support for timed mutices in Tracy, both \texttt{std::shared\_mutex} and \texttt{std::shared\_timed\_mutex} may be used\footnote{Since \texttt{std::shared\_mutex} was added in C++17, using \texttt{std::shared\_timed\_mutex} is the only way to have shared mutex functionality in C++14.}.
\begin{bclogo}[
noborder=true,
couleur=black!5,
logo=\bcattention
]{Caveats}
Due to limits of internal bookkeeping in the profiler, each lock may be used in no more than 64 threads. If you have many short lived temporary threads, consider using a thread pool to limit the numbers of created threads.
\end{bclogo}
\subsection{Plotting data}
Tracy is able to capture and draw numeric value changes over time. You may use it to analyze draw call counts, number of performed queries, etc. To report data, use the \texttt{TracyPlot(name, value)} macro.
@@ -627,6 +636,8 @@ Be aware that call stack collection is a relatively slow operation. Table~\ref{C
\label{CallstackTimes}
\end{table}
You can force call stack capture in the non-\texttt{S} postfixed macros by adding the \texttt{TRACY\_CALLSTACK} define, set to the desired call stack capture depth. This setting doesn't affect the explicit call stack macros.
\begin{bclogo}[
noborder=true,
couleur=black!5,
@@ -669,19 +680,22 @@ The \emph{queue delay} and \emph{timer resolution} parameters are calibration re
\subsection{Interactive profiling}
\label{interactiveprofiling}
If you want to look at the profile data in real-time (or load a saved trace file), you can use the data analysis utility contained in the \texttt{profiler} directory.
If you want to look at the profile data in real-time (or load a saved trace file), you can use the data analysis utility contained in the \texttt{profiler} directory. After starting the application, you will be greeted with a welcome dialog (figure~\ref{welcomedialog}), presenting a bunch of useful links (\faBook{}~\emph{User manual}, \faGlobeAmericas{}~\emph{Homepage} and \faVideo{}~\emph{Tutorial}).
After starting the application, you will be greeted with a welcome dialog (figure~\ref{welcomedialog}), presenting a bunch of useful links (\faBook{}~\emph{User manual}, \faGlobeAmericas{}~\emph{Homepage} and \faVideo{}~\emph{Tutorial}), along with the client address entry field and the \faWifi{}~\emph{Connect} button. A saved trace can be loaded from disk using the \faFolderOpen{}~\emph{Open saved trace} button.
The client \emph{address entry} field and the \faWifi{}~\emph{Connect} button are used to connect to a running client. You can use the connection history button~\faCaretDown{} to display a list of commonly used addresses, from which you can quickly select an address. You can remove entries from this list by hovering the \faMousePointer{}~mouse cursor over an entry and pressing the \emph{delete} button on the keyboard.
If you want to open a trace that you have stored on the disk, you can do so by pressing the \faFolderOpen{}~\emph{Open saved trace} button.
\begin{figure}[h]
\centering\begin{tikzpicture}
\draw (0, 0) rectangle (5, -2.9);
\draw[pattern=crosshatch dots] (0, 0) rectangle+(5, 0.3);
\draw (0, 0) rectangle (4.95, -2.9);
\draw[pattern=crosshatch dots] (0, 0) rectangle+(4.95, 0.3);
\draw[rounded corners=5pt] (0.1, -0.1) rectangle+(1.47, -0.5) node [midway] {\faBook};
\draw[rounded corners=5pt] (1.77, -0.1) rectangle+(1.47, -0.5) node [midway] {\faGlobeAmericas};
\draw[rounded corners=5pt] (3.37, -0.1) rectangle+(1.47, -0.5) node [midway] {\faVideo};
\draw (0.1, -0.9) rectangle+(4.8, -0.5) node [midway] {Address entry};
\draw (0.1, -0.9) rectangle+(4.1, -0.5) node [midway] {Address entry};
\draw[rounded corners=5pt] (4.33, -0.9) rectangle+(0.5, -0.5) node [midway] {\faCaretDown};
\draw[rounded corners=5pt] (0.1, -1.5) rectangle+(2, -0.5) node [midway] {\faWifi{}~Connect};
\draw[rounded corners=5pt] (0.1, -2.3) rectangle+(3.5, -0.5) node [midway] {\faFolderOpen{}~Open saved trace};
\end{tikzpicture}
@@ -693,7 +707,7 @@ Both connecting to a client and opening a saved trace will present you with the
If this is a real-time capture, you will also see the connection window (figure~\ref{connectioninfo}), with the capture status similar to the one displayed by the command line utility. This dialog also displays the connection speed graphed over time and the profiled application's current frames per second and frame time measurements. The circle displayed next to the bandwidth graph signals the connection status. If it's red, the connection is active. If it's gray, the client has disconnected.
You can use the \faSave{}~\emph{Save trace} button to save the current profile data to a file.
You can use the \faSave{}~\emph{Save trace} button to save the current profile data to a file. The \faExclamationTriangle{}~\emph{Discard} button is used to discard current trace.
\begin{figure}[h]
\centering\begin{tikzpicture}
@@ -706,11 +720,16 @@ You can use the \faSave{}~\emph{Save trace} button to save the current profile d
\draw (0.1, -1.1) node[anchor=north west] {Memory usage: 77.57 MB};
\draw (0.1, -1.6) node[anchor=north west] {FPS: 60 \hspace{5pt} Frame time: 16.7 ms};
\draw[rounded corners=5pt] (0.1, -2.1) rectangle+(2.2, -0.5) node [midway] {\faSave{}~Save trace};
\draw[rounded corners=5pt] (3.1, -2.1) rectangle+(2, -0.5) node [midway] {\faExclamationTriangle{}~Discard};
\end{tikzpicture}
\caption{Connection information window.}
\label{connectioninfo}
\end{figure}
\subsubsection{Automatic loading or connecting}
You can pass trace file name as an argument to the profiler application to open the capture, skipping the welcome dialog. You can also use the \texttt{-a address} argument to automatically connect to the given address.
\subsection{Connection speed}
Tracy will happily saturate a 1~Gbps network connection, as it can process up to 6~Gbps of uncompressed data. Note that at such data rates, the resulting capture will need to allocate about 1~GB of RAM per second.
@@ -771,7 +790,8 @@ The main profiler window is split into three sections, as seen on figure~\ref{ma
\draw (0.6, -0.7) node[anchor=north west] {Frames: 364};
\draw[rounded corners=5pt] (2.8, -0.7) rectangle+(0.4, -0.5) node [midway] {\faCaretRight};
\draw[rounded corners=5pt] (3.3, -0.7) rectangle+(0.5, -0.5) node [midway] {\faCaretDown};
\draw (3.9, -0.7) node[anchor=north west] {\faEye: 52.7 ms \hspace{5pt} \faDatabase: 6.06 s};
\draw[rounded corners=5pt] (3.9, -0.7) rectangle+(0.5, -0.5) node [midway] {\faCrosshairs};
\draw (4.5, -0.7) node[anchor=north west] {\faEye: 52.7 ms \hspace{5pt} \faDatabase: 6.06 s};
\draw (0.1, -1.3) rectangle+(14.8, -1) node [midway] {Frame time graph};
\draw (0.1, -2.4) rectangle+(14.8, -3) node [midway] {Timeline view};
@@ -786,19 +806,20 @@ The main profiler window is split into three sections, as seen on figure~\ref{ma
The control menu (top row of buttons) provides access to various features of the profiler. The buttons perform the following actions:
\begin{itemize}
\item \emph{\faPowerOff{} Close} -- This button unloads the current profiling trace and returns to the welcome menu, where another trace can be loaded. In live captures it is replaced by a pair of \emph{\faPause{} Pause} and \emph{\faPlay{} Resume} buttons.
\item \emph{\faPowerOff{} Close} -- This button unloads the current profiling trace and returns to the welcome menu, where another trace can be loaded. In live captures it is replaced by \emph{\faPause{}~Pause}, \emph{\faPlay{}~Resume} and \emph{\faSquare{}~Stopped} buttons.
\item \emph{\faPause{} Pause} -- While a live capture is in progress, the profiler will display the last three fully captured frames, so that you can see the current behavior of the program. Use this button\footnote{Or perform any action on the timeline view.} to stop the automatic updates of the timeline view (the capture will be still progressing).
\item \emph{\faPlay{} Resume} -- Use this button to resume following the most recent three frames in a live capture.
\item \emph{\faCog{} Options} -- Opens the settings menu (section~\ref{options}).
\item \emph{\faTags{} Messages} -- Opens the message log window (section~\ref{messages}), which displays custom messages sent by the client, as described in section~\ref{messagelog}.
\item \emph{\faSearch{} Find zone} -- This buttons opens the find zone window, which allows inspection of zone behavior statistics (section~\ref{findzone}).
\item \emph{\faSortAmountUp{} Statistics} -- Opens the statistics window, which displays zones sorted by their total time cost (section~\ref{statistics}).
\item \emph{\faSquare{} Stopped} -- Inactive button used to indicate that the client application was terminated.
\item \emph{\faCog{} Options} -- Toggles the settings menu (section~\ref{options}).
\item \emph{\faTags{} Messages} -- Toggles the message log window (section~\ref{messages}), which displays custom messages sent by the client, as described in section~\ref{messagelog}.
\item \emph{\faSearch{} Find zone} -- This buttons toggles the find zone window, which allows inspection of zone behavior statistics (section~\ref{findzone}).
\item \emph{\faSortAmountUp{} Statistics} -- Toggles the statistics window, which displays zones sorted by their total time cost (section~\ref{statistics}).
\item \emph{\faMemory{} Memory} -- Various memory profiling options may be accessed here (section~\ref{memorywindow}).
\item \emph{\faBalanceScale{} Compare} -- Opens the trace compare window, which allows you to see the performance difference between two profiling runs (section~\ref{compare}).
\item \emph{\faBalanceScale{} Compare} -- Toggles the trace compare window, which allows you to see the performance difference between two profiling runs (section~\ref{compare}).
\item \emph{\faFingerprint{} Info} -- Show general information about the trace (section~\ref{traceinfo}).
\end{itemize}
The frame information block consists of four elements: the current frame set name along with the number of captured frames, the two navigational buttons \faCaretLeft{} and \faCaretRight{}, which allow you to focus the timeline view on the previous or next frame, and the frame set selection button \faCaretDown{}, which is used to switch to a another frame set. For more information about marking frames, see section~\ref{markingframes}.
The frame information block consists of four elements: the current frame set name along with the number of captured frames, the two navigational buttons \faCaretLeft{} and \faCaretRight{}, which allow you to focus the timeline view on the previous or next frame, and the frame set selection button \faCaretDown{}, which is used to switch to a another frame set\footnote{See section~\ref{framesets} for another way to change the active frame set.}. The \emph{\faCrosshairs{}~Go to frame} button allows zooming the timeline view on the specified frame. For more information about marking frames, see section~\ref{markingframes}.
The last two items show the \faEye{}~view time range and \faDatabase{}~time span of the whole capture.
@@ -866,6 +887,13 @@ The timeline view may be focused on the frames, by clicking or dragging the \LMB
The timeline is the most important element of the profiler UI. All the captured data is displayed there, laid out on the horizontal axis, according to the flow of time. The view is split into three parts: the time scale, the frame sets and the combined zones, locks and plots display.
\subparagraph{Collapsed items}
\label{collapseditems}
Due to extreme differences in time scales, you will almost constantly see events that are too small to be displayed on the screen. Such events have preset minimum size (so they can be seen) and are marked with a zig-zag pattern, to indicate that you need to zoom-in to see more detail.
The zig-zag pattern can be seen applied to frame sets on figure~\ref{framesetsfig}, and to zones on figure~\ref{zoneslocks}.
\paragraph{Time scale}
The time scale is a quick aid in determining the relation between screen space and the time it represents (figure~\ref{timescale}).
@@ -899,6 +927,7 @@ The time scale is a quick aid in determining the relation between screen space a
The leftmost value on the scale represents the time at which the timeline starts. The rest of numbers label the notches on the scale, with some numbers omitted, if there's no space to display them.
\paragraph{Frame sets}
\label{framesets}
Frames from each frame set are displayed directly underneath the time scale. Each frame set occupies a separate row. The currently selected frame set is highlighted with bright colors, with the rest dimmed out.
@@ -928,12 +957,14 @@ Frames from each frame set are displayed directly underneath the time scale. Eac
\draw[densely dotted] (14.15, 0) -- +(0, -1.5);
\end{tikzpicture}
\caption{Frames on the timeline.}
\label{framesets}
\label{framesetsfig}
\end{figure}
On figure~\ref{framesets} we can see the fully described frames~312 and 347. The description consists of the frame name, which is \emph{Frame} for the default frame set (section~\ref{markingframes}) or the name you used for the secondary name set (section~\ref{secondaryframeset}), the frame number and the frame time. The frame~348 is too small to be fully displayed, so only the frame time is shown. The frame~349 is even smaller, with no space for any text. Moreover, frames~313~to~346 are too small to be displayed individually, so they are replaced with a zig-zag pattern.
On figure~\ref{framesetsfig} we can see the fully described frames~312 and 347. The description consists of the frame name, which is \emph{Frame} for the default frame set (section~\ref{markingframes}) or the name you used for the secondary name set (section~\ref{secondaryframeset}), the frame number and the frame time. The frame~348 is too small to be fully displayed, so only the frame time is shown. The frame~349 is even smaller, with no space for any text. Moreover, frames~313~to~346 are too small to be displayed individually, so they are replaced with a zig-zag pattern, as described in section~\ref{collapseditems}.
You can also see that there are frame separators, projected down to the rest of the timeline view. Note that only the separators for the currently selected frame set are displayed. See section~\ref{controlmenu} for instructions about changing the frame set.
You can also see that there are frame separators, projected down to the rest of the timeline view. Note that only the separators for the currently selected frame set are displayed. You can make a frame set active by clicking the \LMB{}~left mouse button on a frame set row you want to select (also see section~\ref{controlmenu}).
Clicking the \MMB{} middle mouse button on a frame will zoom the view to the extent of the frame.
\paragraph{Zones, locks and plots display}
\label{zoneslocksplots}
@@ -983,9 +1014,11 @@ The left hand side \emph{index area} of the timeline view displays various label
\item \emph{Yellow label} -- Plot.
\end{itemize}
Labels accompanied by the \faCaretDown{}~symbol can be collapsed out of the view, to reduce visual clutter.
\subparagraph{Zones}
In an example on figure~\ref{zoneslocks} you can see that there are two threads: \emph{Main thread} and \emph{Streaming thread}\footnote{By clicking on a thread name you can temporarily disable display of the zones in this thread.}. We can see that the \emph{Main thread} has two root level zones visible: \emph{Update} and \emph{Render}. The \emph{Update} zone is split into further sub-zones, some of which are too small to be displayed at the current zoom level. This is indicated by drawing a zig-zag pattern over the merged zones box, with the number of collapsed zones printed in place of zone name. We can also see that the \emph{Physics} zone acquires the \emph{Physics lock} mutex for the most of its run time.
In an example on figure~\ref{zoneslocks} you can see that there are two threads: \emph{Main thread} and \emph{Streaming thread}\footnote{By clicking on a thread name you can temporarily disable display of the zones in this thread.}. We can see that the \emph{Main thread} has two root level zones visible: \emph{Update} and \emph{Render}. The \emph{Update} zone is split into further sub-zones, some of which are too small to be displayed at the current zoom level. This is indicated by drawing a zig-zag pattern over the merged zones box (section~\ref{collapseditems}), with the number of collapsed zones printed in place of zone name. We can also see that the \emph{Physics} zone acquires the \emph{Physics lock} mutex for the most of its run time.
Meanwhile the \emph{Streaming thread} is performing some \emph{Streaming jobs}. The first \emph{Streaming job} sent a message (section~\ref{messagelog}), which in addition to being listed in the message log is being indicated by the triangle over the thread separator. When there are multiple messages in one place, the triangle outline changes to a filled triangle.
@@ -1011,6 +1044,8 @@ At high zoom levels, the zones will be displayed with additional markers, as pre
The GPU zones are displayed just like CPU zones, with an OpenGL/Vulkan context in place of a thread name.
Hovering the \faMousePointer{} mouse pointer over a zone will highlight all other zones that have the same source location with a white outline. Clicking the \LMB{} left mouse button on a zone will open zone information window (section~\ref{zoneinfo}). Clicking the \MMB{} middle mouse button on a zone will zoom the view to the extent of the zone.
\subparagraph{Locks}
Mutual exclusion zones are displayed in each thread that tries to acquire them. There are three color-coded kinds of lock event regions that may be displayed. Note that when the timeline view is zoomed out, the contention regions are always displayed over the uncontented ones.
@@ -1021,6 +1056,8 @@ Mutual exclusion zones are displayed in each thread that tries to acquire them.
\item \emph{Red region} -- The thread wants to acquire the lock, but is blocked by other thread, or threads in case of shared lock.
\end{itemize}
Hovering the \faMousePointer{}~mouse pointer over a lock event will display important information, for example a list of threads that are currently blocking, or which are blocked by the lock. Clicking the \LMB{}~left mouse button on a lock event or a lock label will open the lock information window, as described in section~\ref{lockwindow}. Clicking the \MMB{}~middle mouse button on a lock event will zoom the view to the extent of the event.
\subparagraph{Plots}
The numerical data values (figure~\ref{plot}) are plotted right below the zones and locks. Note that the minimum and maximum values currently displayed on the plot are visible on the screen, along with the y range of the plot. The discrete data points are indicated with little rectangles. Multiple data points are indicated by a filled rectangle.
@@ -1041,7 +1078,7 @@ The numerical data values (figure~\ref{plot}) are plotted right below the zones
\label{plot}
\end{figure}
Note that when memory profiling (section~\ref{memoryprofiling}) is enabled, Tracy will automatically generate a \emph{\faMemory{} Memory usage} plot, which has extended capabilities. Hovering over a data point (memory allocation event) will display duration of the allocation. Clicking the \LMB{} left mouse button on the data point will open the memory allocation information window, which will display the duration of the allocation as long as the window is open.
When memory profiling (section~\ref{memoryprofiling}) is enabled, Tracy will automatically generate a \emph{\faMemory{}~Memory usage} plot, which has extended capabilities. Hovering over a data point (memory allocation event) will visually display duration of the allocation. Clicking the \LMB{} left mouse button on the data point will open the memory allocation information window, which will display the duration of the allocation as long as the window is open.
\subsubsection{Navigating the view}
@@ -1051,8 +1088,6 @@ The timeline view may be scrolled both vertically and horizontally by dragging t
You can zoom in and out the timeline view by using the \Scroll{} mouse scroll. You can select a range to which you want to zoom-in by dragging the \MMB{} middle mouse button. Dragging the \MMB{} middle mouse button while the \emph{control} key is pressed will zoom-out.
Hovering the \faMousePointer{} mouse pointer over a zone will highlight all other zones that have the same source location with a white outline. Clicking the \LMB{} left mouse button on a zone will open zone information window (section~\ref{zoneinfo}). Clicking the \MMB{} middle mouse button on a zone, of a frame will zoom the view to the extent of the zone or the frame.
\subsection{Options menu}
\label{options}
@@ -1066,7 +1101,7 @@ In this window you can set various trace-related options. The timeline view migh
\item \emph{Shortened} -- If there's no space for full zone name, the namespaces will be shortened to one letter (e.g.\ \texttt{s::sort}).
\item \emph{None} -- If there's no space for full zone name, the namespaces will be omitted (e.g.\ \texttt{sort}).
\end{itemize}
\item \emph{\faLock{} Draw locks} -- Controls the display of locks. If the \emph{Only contended} option is selected, the non-blocking regions of locks won't be displayed (see section~\ref{zoneslocksplots}). The \emph{Locks} drop-down allows disabling display of locks on a per-lock basis.
\item \emph{\faLock{} Draw locks} -- Controls the display of locks. If the \emph{Only contended} option is selected, the non-blocking regions of locks won't be displayed (see section~\ref{zoneslocksplots}). The \emph{Locks} drop-down allows disabling display of locks on a per-lock basis. Clicking the \RMB{}~right mouse button on a lock label opens the lock information window (section~\ref{lockwindow}).
\item \emph{\faSignature{} Draw plots} -- Allows disabling display of plots. Individual plots can be disabled in the \emph{Plots} drop-down.
\item \emph{\faRandom{} Visible threads} -- Here you can disable display of selected threads.
\item \emph{\faImages{} Visible frame sets} -- Frame set display can be enabled or disabled here. Note that disabled frame sets are still available for selection in the frame set selection drop-down (section~\ref{controlmenu}), but are marked with a dimmed font.
@@ -1189,6 +1224,14 @@ Clicking the \LMB{} left mouse button on group name will highlight the group tim
The average and median zone times are displayed on the histogram as a red (average) and blue (median) vertical bars. When a group is selected, additional bars will indicate the average group time (orange) and median group time (green). You can disable drawing of either set of markers by clicking on the check-box next to the color legend.
\begin{bclogo}[
noborder=true,
couleur=black!5,
logo=\bclampe
]{Keyboard shortcut}
You may press \keys{\ctrl + F} to open or focus the find zone window and set the keyboard input on the search box.
\end{bclogo}
\subsection{Compare traces window}
\label{compare}
@@ -1314,7 +1357,7 @@ The zone information window has the following controls available:
\item \emph{\faArrowUp{} Go to parent} -- Switches the zone information window to display current zone's parent zone (if available).
\item \emph{\faChartBar{} Statistics} -- Displays the zone general performance characteristics in the find zone window (section~\ref{findzone}).
\item \emph{\faAlignJustify{} Call stack} -- Views the current zone's call stack in the call stack window (section~\ref{callstackwindow}). The button will be highlighted, if the call stack window shows the zone's call stack. Only available if zone had captured call stack data (section~\ref{collectingcallstacks}).
\item \emph{\faFile*{} Source} -- Display source file view window with the zone source code (only available if applicable, see section~\ref{sourceview}).
\item \emph{\faFile*{} Source} -- Display source file view window with the zone source code (only available if applicable, see section~\ref{sourceview}). Button will be highlighted, if the source file is being currently displayed (but the focused source line might be different).
\item \emph{\faArrowLeft{} Go back} -- Returns to the previously viewed zone. The viewing history is lost when the zone information window is closed, or when the type of displayed zone changes (from CPU to GPU or vice versa).
\end{itemize}
@@ -1343,6 +1386,11 @@ Source file view works on the local files you have on your disk. The traces them
\end{itemize}
\end{bclogo}
\subsection{Lock information window}
\label{lockwindow}
This window presents information and statistics about a lock. The lock events count represents the total number collected of wait, obtain and release events. The announce, termination and lock lifetime measure the time from the lockable construction until destruction.
\newpage
\appendix
\appendixpage
@@ -1408,6 +1456,11 @@ The following libraries are included with and used by the Tracy Profiler:
\item flat\_hash\_map -- \url{https://github.com/skarupke/flat\_hash\_map}
\end{itemize}
\item FreeType License
\begin{itemize}
\item FreeType -- \url{https://www.freetype.org/}
\end{itemize}
\end{itemize}
\end{document}

View File

@@ -42,7 +42,14 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Linkage-freetype>static</Linkage-freetype>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Linkage-freetype>static</Linkage-freetype>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>

View File

@@ -1,11 +1,14 @@
#include <algorithm>
#include <assert.h>
#include <inttypes.h>
#include <imgui.h>
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unordered_map>
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#include <memory>
@@ -17,6 +20,7 @@
# include <shellapi.h>
#endif
#include "../../server/tracy_pdqsort.h"
#include "../../server/TracyBadVersion.hpp"
#include "../../server/TracyFileRead.hpp"
#include "../../server/TracyImGui.hpp"
@@ -56,6 +60,18 @@ static void SetWindowTitleCallback( const char* title )
s_customTitle = true;
}
std::vector<std::unordered_map<std::string, uint64_t>::const_iterator> RebuildConnectionHistory( const std::unordered_map<std::string, uint64_t>& connHistMap )
{
std::vector<std::unordered_map<std::string, uint64_t>::const_iterator> ret;
ret.reserve( connHistMap.size() );
for( auto it = connHistMap.begin(); it != connHistMap.end(); ++it )
{
ret.emplace_back( it );
}
tracy::pdqsort_branchless( ret.begin(), ret.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second > rhs->second; } );
return ret;
}
int main( int argc, char** argv )
{
std::unique_ptr<tracy::View> view;
@@ -69,6 +85,10 @@ int main( int argc, char** argv )
view = std::make_unique<tracy::View>( *f );
}
}
else if( argc == 3 && strcmp( argv[1], "-a" ) == 0 )
{
view = std::make_unique<tracy::View>( argv[2] );
}
char title[128];
sprintf( title, "Tracy server %i.%i.%i", tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch );
@@ -90,6 +110,30 @@ int main( int argc, char** argv )
}
}
std::string connHistFile = tracy::GetSavePath( "connection.history" );
std::unordered_map<std::string, uint64_t> connHistMap;
std::vector<std::unordered_map<std::string, uint64_t>::const_iterator> connHistVec;
{
FILE* f = fopen( connHistFile.c_str(), "rb" );
if( f )
{
uint64_t sz;
fread( &sz, 1, sizeof( sz ), f );
for( uint64_t i=0; i<sz; i++ )
{
uint64_t ssz, cnt;
fread( &ssz, 1, sizeof( ssz ), f );
assert( ssz < 1024 );
char tmp[1024];
fread( tmp, 1, ssz, f );
fread( &cnt, 1, sizeof( cnt ), f );
connHistMap.emplace( std::string( tmp, tmp+ssz ), cnt );
}
fclose( f );
connHistVec = RebuildConnectionHistory( connHistMap );
}
}
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if( !glfwInit() ) return 1;
@@ -230,9 +274,50 @@ int main( int argc, char** argv )
}
ImGui::Separator();
ImGui::Text( "Connect to client" );
ImGui::InputText( "Address", addr, 1024 );
if( ImGui::Button( ICON_FA_WIFI " Connect" ) && *addr && !loadThread.joinable() )
bool connectClicked = false;
connectClicked |= ImGui::InputText( "", addr, 1024, ImGuiInputTextFlags_EnterReturnsTrue );
if( !connHistVec.empty() )
{
ImGui::SameLine();
if( ImGui::BeginCombo( "##frameCombo", nullptr, ImGuiComboFlags_NoPreview ) )
{
int idxRemove = -1;
const auto sz = std::min<size_t>( 5, connHistVec.size() );
for( size_t i=0; i<sz; i++ )
{
const auto& str = connHistVec[i]->first;
if( ImGui::Selectable( str.c_str() ) )
{
memcpy( addr, str.c_str(), str.size() + 1 );
}
if( ImGui::IsItemHovered() && ImGui::IsKeyPressed( ImGui::GetKeyIndex( ImGuiKey_Delete ), false ) )
{
idxRemove = (int)i;
}
}
if( idxRemove >= 0 )
{
connHistMap.erase( connHistVec[idxRemove] );
connHistVec = RebuildConnectionHistory( connHistMap );
}
ImGui::EndCombo();
}
}
connectClicked |= ImGui::Button( ICON_FA_WIFI " Connect" );
if( connectClicked && *addr && !loadThread.joinable() )
{
std::string addrStr( addr );
auto it = connHistMap.find( addr );
if( it != connHistMap.end() )
{
it->second++;
}
else
{
connHistMap.emplace( std::move( addr ), 1 );
}
connHistVec = RebuildConnectionHistory( connHistMap );
view = std::make_unique<tracy::View>( addr, fixedWidth, SetWindowTitleCallback );
}
ImGui::Separator();
@@ -361,22 +446,24 @@ int main( int argc, char** argv )
}
}
FILE* f = fopen( winPosFile.c_str(), "wb" );
if( f )
{
FILE* f = fopen( winPosFile.c_str(), "wb" );
if( f )
{
#ifdef GLFW_MAXIMIZED
uint32_t maximized = glfwGetWindowAttrib( window, GLFW_MAXIMIZED );
if( maximized ) glfwRestoreWindow( window );
uint32_t maximized = glfwGetWindowAttrib( window, GLFW_MAXIMIZED );
if( maximized ) glfwRestoreWindow( window );
#else
uint32_t maximized = 0;
uint32_t maximized = 0;
#endif
glfwGetWindowPos( window, &x, &y );
glfwGetWindowSize( window, &w, &h );
glfwGetWindowPos( window, &x, &y );
glfwGetWindowSize( window, &w, &h );
uint32_t data[5] = { uint32_t( x ), uint32_t( y ), uint32_t( w ), uint32_t( h ), maximized };
fwrite( data, 1, sizeof( data ), f );
fclose( f );
uint32_t data[5] = { uint32_t( x ), uint32_t( y ), uint32_t( w ), uint32_t( h ), maximized };
fwrite( data, 1, sizeof( data ), f );
fclose( f );
}
}
// Cleanup
@@ -387,5 +474,22 @@ int main( int argc, char** argv )
glfwDestroyWindow(window);
glfwTerminate();
{
FILE* f = fopen( connHistFile.c_str(), "wb" );
if( f )
{
uint64_t sz = uint64_t( connHistMap.size() );
fwrite( &sz, 1, sizeof( uint64_t ), f );
for( auto& v : connHistMap )
{
sz = uint64_t( v.first.size() );
fwrite( &sz, 1, sizeof( uint64_t ), f );
fwrite( v.first.c_str(), 1, sz, f );
fwrite( &v.second, 1, sizeof( v.second ), f );
}
fclose( f );
}
}
return 0;
}

View File

@@ -231,6 +231,8 @@ struct LockMap
flat_hash_map<uint64_t, uint8_t, nohash<uint64_t>> threadMap;
std::vector<uint64_t> threadList;
LockType type;
int64_t timeAnnounce;
int64_t timeTerminate;
bool valid;
};

View File

@@ -7,7 +7,7 @@ namespace Version
{
enum { Major = 0 };
enum { Minor = 4 };
enum { Patch = 0 };
enum { Patch = 1 };
}
}

View File

@@ -267,6 +267,21 @@ static void TextFocused( const char* label, const char* value )
ImGui::Text( "%s", value );
}
static void SetButtonHighlightColor()
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.35f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.35f, 0.8f, 0.8f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.35f, 0.7f, 0.7f ) );
}
static void ToggleButton( const char* label, bool& toggle )
{
const auto active = toggle;
if( active ) SetButtonHighlightColor();
if( ImGui::Button( label ) ) toggle = !toggle;
if( active ) ImGui::PopStyleColor( 3 );
}
enum { MinVisSize = 3 };
enum { MinFrameSize = 5 };
@@ -275,43 +290,10 @@ static View* s_instance = nullptr;
View::View( const char* addr, ImFont* fixedWidth, SetTitleCallback stcb )
: m_worker( addr )
, m_staticView( false )
, m_frameScale( 0 )
, m_pause( false )
, m_frameStart( 0 )
, m_zvStart( 0 )
, m_zvEnd( 0 )
, m_zvHeight( 0 )
, m_zvScroll( 0 )
, m_zoneInfoWindow( nullptr )
, m_zoneSrcLocHighlight( 0 )
, m_lockHighlight { -1 }
, m_msgHighlight( nullptr )
, m_msgToFocus( nullptr )
, m_gpuInfoWindow( nullptr )
, m_callstackInfoWindow( 0 )
, m_memoryAllocInfoWindow( -1 )
, m_memoryAllocHover( -1 )
, m_memoryAllocHoverWait( 0 )
, m_frames( nullptr )
, m_gpuThread( 0 )
, m_gpuStart( 0 )
, m_gpuEnd( 0 )
, m_showOptions( false )
, m_showMessages( false )
, m_showStatistics( false )
, m_showInfo( false )
, m_drawGpuZones( true )
, m_drawZones( true )
, m_drawLocks( true )
, m_drawPlots( true )
, m_onlyContendedLocks( true )
, m_statSort( 0 )
, m_statSelf( false )
, m_showCallstackFrameAddress( false )
, m_namespace( Namespace::Full )
, m_textEditorFont( fixedWidth )
, m_stcb( stcb )
, m_titleSet( false )
{
assert( s_instance == nullptr );
s_instance = this;
@@ -322,47 +304,16 @@ View::View( const char* addr, ImFont* fixedWidth, SetTitleCallback stcb )
View::View( FileRead& f, ImFont* fixedWidth, SetTitleCallback stcb )
: m_worker( f )
, m_staticView( true )
, m_frameScale( 0 )
, m_pause( false )
, m_frameStart( 0 )
, m_zvStart( 0 )
, m_zvEnd( 0 )
, m_zvHeight( 0 )
, m_zvScroll( 0 )
, m_zoneInfoWindow( nullptr )
, m_zoneSrcLocHighlight( 0 )
, m_msgHighlight( nullptr )
, m_msgToFocus( nullptr )
, m_gpuInfoWindow( nullptr )
, m_callstackInfoWindow( 0 )
, m_memoryAllocInfoWindow( -1 )
, m_memoryAllocHover( -1 )
, m_memoryAllocHoverWait( 0 )
, m_pause( true )
, m_frames( m_worker.GetFramesBase() )
, m_gpuThread( 0 )
, m_gpuStart( 0 )
, m_gpuEnd( 0 )
, m_showOptions( false )
, m_showMessages( false )
, m_showStatistics( false )
, m_showInfo( false )
, m_drawGpuZones( true )
, m_drawZones( true )
, m_drawLocks( true )
, m_drawPlots( true )
, m_onlyContendedLocks( true )
, m_statSort( 0 )
, m_statSelf( false )
, m_showCallstackFrameAddress( false )
, m_namespace( Namespace::Full )
, m_textEditorFont( fixedWidth )
, m_stcb( stcb )
, m_titleSet( false )
{
assert( s_instance == nullptr );
s_instance = this;
InitTextEditor();
SetViewToLastFrames();
}
View::~View()
@@ -392,9 +343,10 @@ void View::SetTextEditorFile( const char* fileName, int line )
fseek( f, 0, SEEK_END );
const auto sz = ftell( f );
fseek( f, 0, SEEK_SET );
auto data = new char[sz];
auto data = new char[sz+1];
fread( data, 1, sz, f );
fclose( f );
data[sz] = '\0';
m_textEditor->SetText( data );
delete[] data;
}
@@ -503,10 +455,12 @@ bool View::Draw()
static const char* MainWindowButtons[] = {
#ifdef TRACY_EXTENDED_FONT
ICON_FA_PLAY " Resume",
ICON_FA_PAUSE " Pause"
ICON_FA_PAUSE " Pause",
ICON_FA_SQUARE " Stopped"
#else
"Resume",
"Pause"
"Pause",
"Stopped"
#endif
};
@@ -523,8 +477,21 @@ bool View::DrawImpl()
TextCentered( ICON_FA_WIFI );
#endif
ImGui::Text( "Waiting for connection..." );
bool wasCancelled = ImGui::Button( "Cancel" );
ImGui::End();
return true;
return !wasCancelled;
}
const auto& io = ImGui::GetIO();
assert( m_shortcut == ShortcutAction::None );
if( io.KeyCtrl )
{
if( ImGui::IsKeyPressed( 'F' ) )
{
m_findZone.show = true;
m_shortcut = ShortcutAction::OpenFind;
}
}
if( !m_frames ) m_frames = m_worker.GetFramesBase();
@@ -541,7 +508,7 @@ bool View::DrawImpl()
bool* keepOpenPtr = nullptr;
if( !m_staticView )
{
DrawConnection();
if( !DrawConnection() ) return false;
}
else
{
@@ -580,7 +547,16 @@ bool View::DrawImpl()
std::lock_guard<TracyMutex> lock( m_worker.GetDataLock() );
if( !m_worker.IsDataStatic() )
{
if( ImGui::Button( m_pause ? MainWindowButtons[0] : MainWindowButtons[1], ImVec2( bw, 0 ) ) ) m_pause = !m_pause;
if( m_worker.IsConnected() )
{
if( ImGui::Button( m_pause ? MainWindowButtons[0] : MainWindowButtons[1], ImVec2( bw, 0 ) ) ) m_pause = !m_pause;
}
else
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor( 0.3f, 0.3f, 0.3f, 1.0f ) );
ImGui::ButtonEx( MainWindowButtons[2], ImVec2( bw, 0 ), ImGuiButtonFlags_Disabled );
ImGui::PopStyleColor( 1 );
}
}
else
{
@@ -596,45 +572,45 @@ bool View::DrawImpl()
}
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_COG " Options" ) ) m_showOptions = true;
ToggleButton( ICON_FA_COG " Options", m_showOptions );
#else
if( ImGui::Button( "Options" ) ) m_showOptions = true;
ToggleButton( "Options", m_showOptions );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_TAGS " Messages" ) ) m_showMessages = true;
ToggleButton( ICON_FA_TAGS " Messages", m_showMessages );
#else
if( ImGui::Button( "Messages" ) ) m_showMessages = true;
ToggleButton( "Messages", m_showMessages );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_SEARCH " Find zone" ) ) m_findZone.show = true;
ToggleButton( ICON_FA_SEARCH " Find zone", m_findZone.show );
#else
if( ImGui::Button( "Find zone" ) ) m_findZone.show = true;
ToggleButton( "Find zone", m_findZone.show );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_SORT_AMOUNT_UP " Statistics" ) ) m_showStatistics = true;
ToggleButton( ICON_FA_SORT_AMOUNT_UP " Statistics", m_showStatistics );
#else
if( ImGui::Button( "Statistics" ) ) m_showStatistics = true;
ToggleButton( "Statistics", m_showStatistics );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_MEMORY " Memory" ) ) m_memInfo.show = true;
ToggleButton( ICON_FA_MEMORY " Memory", m_memInfo.show );
#else
if( ImGui::Button( "Memory" ) ) m_memInfo.show = true;
ToggleButton( "Memory", m_memInfo.show );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_BALANCE_SCALE " Compare" ) ) m_compare.show = true;
ToggleButton( ICON_FA_BALANCE_SCALE " Compare", m_compare.show );
#else
if( ImGui::Button( "Compare" ) ) m_compare.show = true;
ToggleButton( "Compare", m_compare.show );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_FINGERPRINT " Info" ) ) m_showInfo = true;
ToggleButton( ICON_FA_FINGERPRINT " Info", m_showInfo );
#else
if( ImGui::Button( "Info" ) ) m_showInfo = true;
ToggleButton( "Info", m_showInfo );
#endif
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
@@ -680,6 +656,18 @@ bool View::DrawImpl()
ImGui::EndCombo();
}
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
ToggleButton( ICON_FA_CROSSHAIRS, m_goToFrame );
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
ImGui::Text( "Go to frame" );
ImGui::EndTooltip();
}
#else
ToggleButton( "Go to", m_goToFrame );
#endif
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
#ifdef TRACY_EXTENDED_FONT
@@ -721,8 +709,9 @@ bool View::DrawImpl()
if( m_memoryAllocInfoWindow >= 0 ) DrawMemoryAllocWindow();
if( m_showInfo ) DrawInfo();
if( m_textEditorFile ) DrawTextEditor();
if( m_goToFrame ) DrawGoToFrame();
if( m_lockInfoWindow != InvalidId ) DrawLockInfoWindow();
const auto& io = ImGui::GetIO();
if( m_zoomAnim.active )
{
m_zoomAnim.progress += io.DeltaTime * m_zoomAnim.lenMod;
@@ -745,11 +734,12 @@ bool View::DrawImpl()
m_zoneinfoBuzzAnim.Update( io.DeltaTime );
m_findZoneBuzzAnim.Update( io.DeltaTime );
m_optionsLockBuzzAnim.Update( io.DeltaTime );
m_lockInfoAnim.Update( io.DeltaTime );
return keepOpen;
}
void View::DrawConnection()
bool View::DrawConnection()
{
const auto ty = ImGui::GetFontSize();
const auto cs = ty * 0.9f;
@@ -826,7 +816,41 @@ void View::DrawConnection()
}
}
ImGui::SameLine( 0, ty * 4 );
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_EXCLAMATION_TRIANGLE " Discard" ) )
#else
if( ImGui::Button( "Discard" ) )
#endif
{
ImGui::OpenPopup( "Confirm trace discard" );
}
if( ImGui::BeginPopupModal( "Confirm trace discard", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) )
{
#ifdef TRACY_EXTENDED_FONT
TextCentered( ICON_FA_EXCLAMATION_TRIANGLE );
#endif
ImGui::Text( "All unsaved profiling data will be lost!" );
ImGui::Text( "Are you sure you want to proceed?" );
ImGui::Separator();
if( ImGui::Button( "Yes" ) )
{
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
ImGui::End();
return false;
}
ImGui::SameLine( 0, ty * 2 );
if( ImGui::Button( "No", ImVec2( ty * 8, 0 ) ) )
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::End();
return true;
}
static ImU32 GetFrameColor( uint64_t frameTime )
@@ -893,15 +917,7 @@ void View::DrawFrames()
if( !m_pause )
{
m_frameStart = ( total < onScreen * group ) ? 0 : total - onScreen * group;
m_zvStart = m_worker.GetFrameBegin( *m_frames, std::max( 0, total - 4 ) );
if( total == 1 )
{
m_zvEnd = m_worker.GetLastTime();
}
else
{
m_zvEnd = m_worker.GetFrameBegin( *m_frames, total - 1 );
}
SetViewToLastFrames();
}
if( hover )
@@ -1438,17 +1454,33 @@ bool View::DrawZoneFrames( const FrameData& frames )
if( prev != -1 )
{
DrawZigZag( draw, wpos + ImVec2( 0, round( ty / 2 ) ), ( prev - m_zvStart ) * pxns, ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_zvStart ) * pxns, ty / 4, inactiveColor );
if( frames.continuous )
{
DrawZigZag( draw, wpos + ImVec2( 0, round( ty / 2 ) ), ( prev - m_zvStart ) * pxns, ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_zvStart ) * pxns, ty / 4, inactiveColor );
}
else
{
const auto begin = ( prev - m_zvStart ) * pxns;
const auto end = ( m_worker.GetFrameBegin( frames, zrange.second-1 ) - m_zvStart ) * pxns;
DrawZigZag( draw, wpos + ImVec2( 0, round( ty / 2 ) ), begin, std::max( begin + MinFrameSize, end ), ty / 4, inactiveColor );
}
prev = -1;
}
if( hover && !tooltipDisplayed )
if( hover )
{
ImGui::BeginTooltip();
ImGui::TextDisabled( "Frame set:" );
ImGui::SameLine();
ImGui::Text( "%s", frames.name == 0 ? "Frames" : m_worker.GetString( frames.name ) );
ImGui::EndTooltip();
if( !tooltipDisplayed )
{
ImGui::BeginTooltip();
ImGui::TextDisabled( "Frame set:" );
ImGui::SameLine();
ImGui::Text( "%s", frames.name == 0 ? "Frames" : m_worker.GetString( frames.name ) );
ImGui::EndTooltip();
}
if( ImGui::IsMouseClicked( 0 ) )
{
m_frames = &frames;
}
}
return hover;
@@ -2713,6 +2745,15 @@ int View::DrawLocks( uint64_t tid, bool hover, double pxns, const ImVec2& wpos,
bool itemHovered = hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( pxend, double( w + 10 ) ), offset + ty ) );
if( itemHovered )
{
if( ImGui::IsMouseClicked( 0 ) )
{
m_lockInfoWindow = v.first;
}
if( ImGui::IsMouseClicked( 2 ) )
{
ZoomToRange( t0, t1 );
}
if( condensed > 1 )
{
ImGui::BeginTooltip();
@@ -2996,6 +3037,10 @@ int View::DrawLocks( uint64_t tid, bool hover, double pxns, const ImVec2& wpos,
const auto coutline = drawState == LockState::HasLock ? 0xFF3BA33B : ( drawState == LockState::HasBlockingLock ? 0xFF3BA3A3 : 0xFF3B3BD6 );
draw->AddRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( pxend, double( w + 10 ) ), offset + ty ), coutline );
}
else if( condensed > 1 )
{
DrawZigZag( draw, wpos + ImVec2( 0, offset + round( ty / 2 ) ), px0, pxend, ty / 4, DarkenColor( cfilled ) );
}
const auto rx0 = ( t0 - m_zvStart ) * pxns;
if( dsz >= MinVisSize )
@@ -3048,6 +3093,11 @@ int View::DrawLocks( uint64_t tid, bool hover, double pxns, const ImVec2& wpos,
ImGui::Separator();
TextFocused( "Lock events:", RealToString( v.second.timeline.size(), true ) );
ImGui::EndTooltip();
if( ImGui::IsMouseClicked( 0 ) )
{
m_lockInfoWindow = v.first;
}
}
cnt++;
}
@@ -3458,13 +3508,16 @@ void View::DrawInfoWindow()
}
template<typename T>
void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, BuzzAnim<const void*>& anim, View& view, std::function<void(T)> showZone )
void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, BuzzAnim<const void*>& anim, View& view, bool& showUnknownFrames, std::function<void(T)> showZone )
{
bool expand = ImGui::TreeNode( "Zone trace" );
ImGui::SameLine();
ImGui::TextDisabled( "(%s)", RealToString( trace.size(), true ) );
if( !expand ) return;
ImGui::SameLine();
if( ImGui::SmallButton( showUnknownFrames ? "Hide unknown frames" : "Show unknown frames" ) ) showUnknownFrames = !showUnknownFrames;
if( !trace.empty() )
{
T prev = zone;
@@ -3474,7 +3527,10 @@ void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, B
auto curr = trace[i];
if( prev->callstack == 0 || curr->callstack == 0 )
{
ImGui::TextDisabled( "[unknown frames]" );
if( showUnknownFrames )
{
ImGui::TextDisabled( "[unknown frames]" );
}
}
else if( prev->callstack != curr->callstack )
{
@@ -3545,7 +3601,10 @@ void DrawZoneTrace( T zone, const std::vector<T>& trace, const Worker& worker, B
auto last = trace.empty() ? zone : trace.back();
if( last->callstack == 0 )
{
ImGui::TextDisabled( "[unknown frames]" );
if( showUnknownFrames )
{
ImGui::TextDisabled( "[unknown frames]" );
}
}
else
{
@@ -3639,9 +3698,7 @@ void View::DrawZoneInfoWindow()
bool hilite = m_callstackInfoWindow == ev.callstack;
if( hilite )
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f ) );
SetButtonHighlightColor();
}
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )
@@ -3663,9 +3720,7 @@ void View::DrawZoneInfoWindow()
bool hilite = m_textEditorFile == fileName;
if( hilite )
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f ) );
SetButtonHighlightColor();
}
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_FILE_ALT " Source" ) )
@@ -3849,7 +3904,7 @@ void View::DrawZoneInfoWindow()
parent = GetZoneParent( *parent );
}
int idx = 0;
DrawZoneTrace<const ZoneEvent*>( &ev, zoneTrace, m_worker, m_zoneinfoBuzzAnim, *this, [&idx, this] ( const ZoneEvent* v ) {
DrawZoneTrace<const ZoneEvent*>( &ev, zoneTrace, m_worker, m_zoneinfoBuzzAnim, *this, m_showUnknownFrames, [&idx, this] ( const ZoneEvent* v ) {
const auto& srcloc = m_worker.GetSourceLocation( v->srcloc );
const auto txt = m_worker.GetZoneName( *v, srcloc );
ImGui::PushID( idx++ );
@@ -4000,9 +4055,7 @@ void View::DrawGpuInfoWindow()
bool hilite = m_callstackInfoWindow == ev.callstack;
if( hilite )
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f ) );
SetButtonHighlightColor();
}
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )
@@ -4024,9 +4077,7 @@ void View::DrawGpuInfoWindow()
bool hilite = m_textEditorFile == fileName;
if( hilite )
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f ) );
SetButtonHighlightColor();
}
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_FILE_ALT " Source" ) )
@@ -4100,7 +4151,7 @@ void View::DrawGpuInfoWindow()
parent = GetZoneParent( *parent );
}
int idx = 0;
DrawZoneTrace<const GpuEvent*>( &ev, zoneTrace, m_worker, m_zoneinfoBuzzAnim, *this, [&idx, this] ( const GpuEvent* v ) {
DrawZoneTrace<const GpuEvent*>( &ev, zoneTrace, m_worker, m_zoneinfoBuzzAnim, *this, m_showUnknownFrames, [&idx, this] ( const GpuEvent* v ) {
const auto& srcloc = m_worker.GetSourceLocation( v->srcloc );
const auto txt = m_worker.GetZoneName( *v, srcloc );
ImGui::PushID( idx++ );
@@ -4301,6 +4352,14 @@ void View::DrawOptions()
Visible( &l.second ) = false;
}
}
ImGui::SameLine();
ImGui::TextDisabled( "(?)" );
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
ImGui::Text( "Right click on lock name to open lock information window." );
ImGui::EndTooltip();
}
for( const auto& l : m_worker.GetLockMap() )
{
@@ -4312,6 +4371,10 @@ void View::DrawOptions()
char buf[1024];
sprintf( buf, "%" PRIu32 ": %s", l.first, m_worker.GetString( m_worker.GetSourceLocation( l.second.srcloc ).function ) );
ImGui::Checkbox( buf, &Visible( &l.second ) );
if( ImGui::IsItemClicked( 1 ) )
{
m_lockInfoWindow = l.first;
}
if( m_optionsLockBuzzAnim.Match( l.second.srcloc ) )
{
const auto time = m_optionsLockBuzzAnim.Time();
@@ -4586,6 +4649,8 @@ uint64_t View::GetSelectionTarget( const Worker::ZoneThreadData& ev, FindZone::G
void View::DrawFindZone()
{
if( m_shortcut == ShortcutAction::OpenFind ) ImGui::SetNextWindowFocus();
ImGui::Begin( "Find zone", &m_findZone.show );
#ifdef TRACY_NO_STATISTICS
ImGui::TextWrapped( "Collection of statistical data is disabled in this build." );
@@ -4598,13 +4663,21 @@ void View::DrawFindZone()
return;
}
ImGui::InputText( "", m_findZone.pattern, 1024 );
ImGui::SameLine();
bool findClicked = false;
ImGui::PushItemWidth( -0.01f );
if( m_shortcut == ShortcutAction::OpenFind )
{
ImGui::SetKeyboardFocusHere();
m_shortcut = ShortcutAction::None;
}
findClicked |= ImGui::InputText( "", m_findZone.pattern, 1024, ImGuiInputTextFlags_EnterReturnsTrue );
ImGui::PopItemWidth();
#ifdef TRACY_EXTENDED_FONT
const bool findClicked = ImGui::Button( ICON_FA_SEARCH " Find" );
findClicked |= ImGui::Button( ICON_FA_SEARCH " Find" );
#else
const bool findClicked = ImGui::Button( "Find" );
findClicked |= ImGui::Button( "Find" );
#endif
ImGui::SameLine();
@@ -4616,6 +4689,9 @@ void View::DrawFindZone()
{
m_findZone.Reset();
}
ImGui::SameLine();
ImGui::Checkbox( "Ignore case", &m_findZone.ignoreCase );
if( findClicked )
{
@@ -5597,13 +5673,16 @@ void View::DrawCompare()
return;
}
ImGui::InputText( "", m_compare.pattern, 1024 );
ImGui::SameLine();
bool findClicked = false;
ImGui::PushItemWidth( -0.01f );
findClicked |= ImGui::InputText( "", m_compare.pattern, 1024, ImGuiInputTextFlags_EnterReturnsTrue );
ImGui::PopItemWidth();
#ifdef TRACY_EXTENDED_FONT
const bool findClicked = ImGui::Button( ICON_FA_SEARCH " Find" );
findClicked |= ImGui::Button( ICON_FA_SEARCH " Find" );
#else
const bool findClicked = ImGui::Button( "Find" );
findClicked |= ImGui::Button( "Find" );
#endif
ImGui::SameLine();
@@ -5615,6 +5694,9 @@ void View::DrawCompare()
{
m_compare.Reset();
}
ImGui::SameLine();
ImGui::Checkbox( "Ignore case", &m_compare.ignoreCase );
if( findClicked )
{
@@ -6931,9 +7013,7 @@ void View::DrawInfo()
bool hilite = m_callstackInfoWindow == crash.callstack;
if( hilite )
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f ) );
SetButtonHighlightColor();
}
#ifdef TRACY_EXTENDED_FONT
if( ImGui::Button( ICON_FA_ALIGN_JUSTIFY " Call stack" ) )
@@ -6981,6 +7061,171 @@ void View::DrawTextEditor()
if( !show ) m_textEditorFile = nullptr;
}
void View::DrawGoToFrame()
{
static int frameNum = 1;
const bool mainFrameSet = m_frames->name == 0;
const auto numFrames = mainFrameSet ? m_frames->frames.size() - 1 : m_frames->frames.size();
const auto frameOffset = mainFrameSet ? 0 : 1;
ImGui::Begin( "Go to frame", &m_goToFrame, ImGuiWindowFlags_AlwaysAutoResize );
ImGui::InputInt( "Frame", &frameNum );
frameNum = std::min( std::max( frameNum, 1 ), int( numFrames ) );
if( ImGui::Button( "Go to" ) )
{
ZoomToRange( m_worker.GetFrameBegin( *m_frames, frameNum - frameOffset ), m_worker.GetFrameEnd( *m_frames, frameNum - frameOffset ) );
}
ImGui::End();
}
void View::DrawLockInfoWindow()
{
auto it = m_worker.GetLockMap().find( m_lockInfoWindow );
assert( it != m_worker.GetLockMap().end() );
const auto& lock = it->second;
const auto& srcloc = m_worker.GetSourceLocation( lock.srcloc );
auto fileName = m_worker.GetString( srcloc.file );
int64_t timeAnnounce = lock.timeAnnounce;
int64_t timeTerminate = lock.timeTerminate;
if( !lock.timeline.empty() )
{
if( timeAnnounce == 0 )
{
timeAnnounce = lock.timeline.front()->time;
}
if( timeTerminate == 0 )
{
timeTerminate = lock.timeline.back()->time;
}
}
bool waitState = false;
bool holdState = false;
int64_t waitStartTime = 0;
int64_t holdStartTime = 0;
int64_t waitTotalTime = 0;
int64_t holdTotalTime = 0;
uint32_t maxWaitingThreads = 0;
for( auto& v : lock.timeline )
{
if( holdState )
{
if( v->lockCount == 0 )
{
holdTotalTime += v->time - holdStartTime;
holdState = false;
}
}
else
{
if( v->lockCount != 0 )
{
holdStartTime = v->time;
holdState = true;
}
}
if( waitState )
{
if( v->waitList == 0 )
{
waitTotalTime += v->time - waitStartTime;
waitState = false;
}
else
{
maxWaitingThreads = std::max<uint32_t>( maxWaitingThreads, TracyCountBits( v->waitList ) );
}
}
else
{
if( v->waitList != 0 )
{
waitStartTime = v->time;
waitState = true;
maxWaitingThreads = std::max<uint32_t>( maxWaitingThreads, TracyCountBits( v->waitList ) );
}
}
}
bool visible = true;
ImGui::Begin( "Lock info", &visible, ImGuiWindowFlags_AlwaysAutoResize );
ImGui::Text( "Lock #%" PRIu32 ": %s", m_lockInfoWindow, m_worker.GetString( srcloc.function ) );
ImGui::TextDisabled( "Location:" );
if( m_lockInfoAnim.Match( m_lockInfoWindow ) )
{
const auto time = m_lockInfoAnim.Time();
const auto indentVal = sin( time * 60.f ) * 10.f * time;
ImGui::SameLine( 0, ImGui::GetStyle().ItemSpacing.x + indentVal );
}
else
{
ImGui::SameLine();
}
ImGui::Text( "%s:%i", fileName, srcloc.line );
if( ImGui::IsItemClicked( 1 ) )
{
if( FileExists( fileName ) )
{
SetTextEditorFile( fileName, srcloc.line );
}
else
{
m_lockInfoAnim.Enable( m_lockInfoWindow, 0.5f );
}
}
ImGui::Separator();
switch( lock.type )
{
case LockType::Lockable:
TextFocused( "Type:", "lockable" );
break;
case LockType::SharedLockable:
TextFocused( "Type:", "shared lockable" );
break;
default:
assert( false );
break;
}
TextFocused( "Lock events:", RealToString( lock.timeline.size(), true ) );
ImGui::Separator();
const auto announce = timeAnnounce - m_worker.GetTimeBegin();
const auto terminate = timeTerminate - m_worker.GetTimeBegin();
const auto lifetime = timeTerminate - timeAnnounce;
TextFocused( "Announce time:", TimeToString( announce ) );
TextFocused( "Terminate time:", TimeToString( terminate ) );
TextFocused( "Lifetime:", TimeToString( lifetime ) );
ImGui::Separator();
TextFocused( "Lock hold time:", TimeToString( holdTotalTime ) );
ImGui::SameLine();
ImGui::TextDisabled( "(%.2f%%)", holdTotalTime / float( lifetime ) * 100.f );
TextFocused( "Lock wait time:", TimeToString( waitTotalTime ) );
ImGui::SameLine();
ImGui::TextDisabled( "(%.2f%%)", waitTotalTime / float( lifetime ) * 100.f );
TextFocused( "Max waiting threads:", RealToString( maxWaitingThreads, true ) );
ImGui::Separator();
const auto threadList = ImGui::TreeNode( "Thread list" );
ImGui::SameLine();
ImGui::TextDisabled( "(%zu)", lock.threadList.size() );
if( threadList )
{
for( const auto& t : lock.threadList )
{
ImGui::Text( "%s", m_worker.GetThreadString( t ) );
ImGui::SameLine();
ImGui::TextDisabled( "(0x%" PRIX64 ")", t );
}
ImGui::TreePop();
}
ImGui::End();
if( !visible ) m_lockInfoWindow = InvalidId;
}
template<class T>
void View::ListMemData( T ptr, T end, std::function<void(T&)> DrawAddress, const char* id )
{
@@ -8285,7 +8530,7 @@ const ZoneEvent* View::FindZoneAtTime( uint64_t thread, int64_t time ) const
#ifndef TRACY_NO_STATISTICS
void View::FindZones()
{
m_findZone.match = m_worker.GetMatchingSourceLocation( m_findZone.pattern );
m_findZone.match = m_worker.GetMatchingSourceLocation( m_findZone.pattern, m_findZone.ignoreCase );
if( m_findZone.match.empty() ) return;
auto it = m_findZone.match.begin();
@@ -8304,7 +8549,7 @@ void View::FindZones()
void View::FindZonesCompare()
{
m_compare.match[0] = m_worker.GetMatchingSourceLocation( m_compare.pattern );
m_compare.match[0] = m_worker.GetMatchingSourceLocation( m_compare.pattern, m_compare.ignoreCase );
if( !m_compare.match[0].empty() )
{
auto it = m_compare.match[0].begin();
@@ -8321,7 +8566,7 @@ void View::FindZonesCompare()
}
}
m_compare.match[1] = m_compare.second->GetMatchingSourceLocation( m_compare.pattern );
m_compare.match[1] = m_compare.second->GetMatchingSourceLocation( m_compare.pattern, m_compare.ignoreCase );
if( !m_compare.match[1].empty() )
{
auto it = m_compare.match[1].begin();
@@ -8345,9 +8590,7 @@ void View::SmallCallstackButton( const char* name, uint32_t callstack, int& idx
bool hilite = m_callstackInfoWindow == callstack;
if( hilite )
{
ImGui::PushStyleColor( ImGuiCol_Button, (ImVec4)ImColor::HSV( 0.f, 0.6f, 0.6f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV( 0.f, 0.7f, 0.7f ) );
ImGui::PushStyleColor( ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV( 0.f, 0.8f, 0.8f ) );
SetButtonHighlightColor();
}
ImGui::PushID( idx++ );
if( ImGui::SmallButton( name ) )
@@ -8365,4 +8608,19 @@ void View::SmallCallstackButton( const char* name, uint32_t callstack, int& idx
}
}
void View::SetViewToLastFrames()
{
const int total = m_worker.GetFrameCount( *m_frames );
m_zvStart = m_worker.GetFrameBegin( *m_frames, std::max( 0, total - 4 ) );
if( total == 1 )
{
m_zvEnd = m_worker.GetLastTime();
}
else
{
m_zvEnd = m_worker.GetFrameBegin( *m_frames, total - 1 );
}
}
}

View File

@@ -64,6 +64,14 @@ private:
Short
};
enum class ShortcutAction : uint8_t
{
None,
OpenFind
};
enum { InvalidId = 0xFFFFFFFF };
void InitTextEditor();
const char* ShortenNamespace( const char* name ) const;
@@ -73,7 +81,7 @@ private:
void DrawTextContrast( ImDrawList* draw, const ImVec2& pos, uint32_t color, const char* text );
bool DrawImpl();
void DrawConnection();
bool DrawConnection();
void DrawFrames();
bool DrawZoneFramesHeader();
bool DrawZoneFrames( const FrameData& frames );
@@ -99,6 +107,8 @@ private:
void DrawMemoryAllocWindow();
void DrawInfo();
void DrawTextEditor();
void DrawGoToFrame();
void DrawLockInfoWindow();
template<class T>
void ListMemData( T ptr, T end, std::function<void(T&)> DrawAddress, const char* id = nullptr );
@@ -150,6 +160,7 @@ private:
const char* GetPlotName( const PlotData* plot ) const;
void SmallCallstackButton( const char* name, uint32_t callstack, int& idx );
void SetViewToLastFrames();
flat_hash_map<const void*, bool, nohash<const void*>> m_visible;
flat_hash_map<uint64_t, bool, nohash<uint64_t>> m_visibleMsgThread;
@@ -199,62 +210,67 @@ private:
Worker m_worker;
bool m_staticView;
int m_frameScale;
int m_frameScale = 0;
bool m_pause;
int m_frameStart;
int m_frameStart = 0;
int64_t m_zvStart;
int64_t m_zvEnd;
int64_t m_zvStart = 0;
int64_t m_zvEnd = 0;
int64_t m_lastTime;
int8_t m_lastCpu;
int m_zvHeight;
int m_zvScroll;
int m_zvHeight = 0;
int m_zvScroll = 0;
const ZoneEvent* m_zoneInfoWindow;
const ZoneEvent* m_zoneInfoWindow = nullptr;
const ZoneEvent* m_zoneHighlight;
DecayValue<uint64_t> m_zoneSrcLocHighlight;
LockHighlight m_lockHighlight;
DecayValue<const MessageData*> m_msgHighlight;
const MessageData* m_msgToFocus;
const GpuEvent* m_gpuInfoWindow;
DecayValue<uint64_t> m_zoneSrcLocHighlight = 0;
LockHighlight m_lockHighlight { -1 };
DecayValue<const MessageData*> m_msgHighlight = nullptr;
const MessageData* m_msgToFocus = nullptr;
const GpuEvent* m_gpuInfoWindow = nullptr;
const GpuEvent* m_gpuHighlight;
uint64_t m_gpuInfoWindowThread;
uint32_t m_callstackInfoWindow;
int64_t m_memoryAllocInfoWindow;
int64_t m_memoryAllocHover;
int m_memoryAllocHoverWait;
uint32_t m_callstackInfoWindow = 0;
int64_t m_memoryAllocInfoWindow = -1;
int64_t m_memoryAllocHover = -1;
int m_memoryAllocHoverWait = 0;
const FrameData* m_frames;
uint32_t m_lockInfoWindow = InvalidId;
Region m_highlight;
Region m_highlightZoom;
uint64_t m_gpuThread;
int64_t m_gpuStart;
int64_t m_gpuEnd;
uint64_t m_gpuThread = 0;
int64_t m_gpuStart = 0;
int64_t m_gpuEnd = 0;
bool m_showOptions;
bool m_showMessages;
bool m_showStatistics;
bool m_showInfo;
bool m_drawGpuZones;
bool m_drawZones;
bool m_drawLocks;
bool m_drawPlots;
bool m_onlyContendedLocks;
bool m_showOptions = false;
bool m_showMessages = false;
bool m_showStatistics = false;
bool m_showInfo = false;
bool m_drawGpuZones = true;
bool m_drawZones = true;
bool m_drawLocks = true;
bool m_drawPlots = true;
bool m_onlyContendedLocks = true;
bool m_goToFrame = false;
int m_statSort;
bool m_statSelf;
bool m_showCallstackFrameAddress;
int m_statSort = 0;
bool m_statSelf = false;
bool m_showCallstackFrameAddress = false;
bool m_showUnknownFrames = true;
Namespace m_namespace;
ShortcutAction m_shortcut = ShortcutAction::None;
Namespace m_namespace = Namespace::Full;
Animation m_zoomAnim;
BuzzAnim<int> m_callstackBuzzAnim;
BuzzAnim<int> m_callstackTreeBuzzAnim;
BuzzAnim<const void*> m_zoneinfoBuzzAnim;
BuzzAnim<int> m_findZoneBuzzAnim;
BuzzAnim<uint32_t> m_optionsLockBuzzAnim;
BuzzAnim<uint32_t> m_lockInfoAnim;
Vector<const ZoneEvent*> m_zoneInfoStack;
Vector<const GpuEvent*> m_gpuInfoStack;
@@ -265,7 +281,7 @@ private:
float m_rootWidth, m_rootHeight;
SetTitleCallback m_stcb;
bool m_titleSet;
bool m_titleSet = false;
struct FindZone {
enum : uint64_t { Unselected = std::numeric_limits<uint64_t>::max() - 1 };
@@ -279,6 +295,7 @@ private:
};
bool show = false;
bool ignoreCase = false;
std::vector<int32_t> match;
std::map<uint64_t, Group> groups;
size_t processed;
@@ -357,6 +374,7 @@ private:
struct {
bool show = false;
bool ignoreCase = false;
std::unique_ptr<Worker> second;
std::thread loadThread;
int badVer = 0;

View File

@@ -4,6 +4,13 @@
# include <sys/time.h>
#endif
#if defined _MSC_VER || defined __MINGW32__
# include <malloc.h>
#else
# include <alloca.h>
#endif
#include <cctype>
#include <chrono>
#include <mutex>
#include <string.h>
@@ -392,7 +399,11 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
{
uint64_t id, ptr;
f.Read2( id, ptr );
m_data.strings.emplace( id, pointerMap.find( ptr )->second );
auto it = pointerMap.find( ptr );
if( it != pointerMap.end() )
{
m_data.strings.emplace( id, it->second );
}
}
f.Read( sz );
@@ -400,7 +411,11 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
{
uint64_t id, ptr;
f.Read2( id, ptr );
m_data.threadNames.emplace( id, pointerMap.find( ptr )->second );
auto it = pointerMap.find( ptr );
if( it != pointerMap.end() )
{
m_data.threadNames.emplace( id, it->second );
}
}
if( fileVer >= FileVersion( 0, 3, 201 ) )
@@ -503,6 +518,14 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
f.Read( lockmap.srcloc );
f.Read( lockmap.type );
f.Read( lockmap.valid );
if( fileVer >= FileVersion( 0, 4, 1 ) )
{
f.Read2( lockmap.timeAnnounce, lockmap.timeTerminate );
}
else
{
lockmap.timeAnnounce = lockmap.timeTerminate = 0;
}
f.Read( tsz );
for( uint64_t i=0; i<tsz; i++ )
{
@@ -1199,7 +1222,26 @@ const char* Worker::GetZoneName( const GpuEvent& ev, const SourceLocation& srclo
}
}
std::vector<int32_t> Worker::GetMatchingSourceLocation( const char* query ) const
static bool strstr_nocase( const char* l, const char* r )
{
const auto lsz = strlen( l );
const auto rsz = strlen( r );
auto ll = (char*)alloca( lsz + 1 );
auto rl = (char*)alloca( lsz + 1 );
for( size_t i=0; i<lsz; i++ )
{
ll[i] = tolower( l[i] );
}
ll[lsz] = '\0';
for( size_t i=0; i<rsz; i++ )
{
rl[i] = tolower( r[i] );
}
rl[rsz] = '\0';
return strstr( ll, rl ) != nullptr;
}
std::vector<int32_t> Worker::GetMatchingSourceLocation( const char* query, bool ignoreCase ) const
{
std::vector<int32_t> match;
@@ -1210,7 +1252,16 @@ std::vector<int32_t> Worker::GetMatchingSourceLocation( const char* query ) cons
assert( it != m_data.sourceLocation.end() );
const auto& srcloc = it->second;
const auto str = GetString( srcloc.name.active ? srcloc.name : srcloc.function );
if( strstr( str, query ) != nullptr )
bool found = false;
if( ignoreCase )
{
found = strstr_nocase( str, query );
}
else
{
found = strstr( str, query ) != nullptr;
}
if( found )
{
match.push_back( (int32_t)i );
}
@@ -1219,7 +1270,16 @@ std::vector<int32_t> Worker::GetMatchingSourceLocation( const char* query ) cons
for( auto& srcloc : m_data.sourceLocationPayload )
{
const auto str = GetString( srcloc->name.active ? srcloc->name : srcloc->function );
if( strstr( str, query ) != nullptr )
bool found = false;
if( ignoreCase )
{
found = strstr_nocase( str, query );
}
else
{
found = strstr( str, query ) != nullptr;
}
if( found )
{
auto it = m_data.sourceLocationPayloadMap.find( srcloc );
assert( it != m_data.sourceLocationPayloadMap.end() );
@@ -1943,6 +2003,9 @@ void Worker::Process( const QueueItem& ev )
case QueueType::LockAnnounce:
ProcessLockAnnounce( ev.lockAnnounce );
break;
case QueueType::LockTerminate:
ProcessLockTerminate( ev.lockTerminate );
break;
case QueueType::LockWait:
ProcessLockWait( ev.lockWait );
break;
@@ -2217,6 +2280,8 @@ void Worker::ProcessLockAnnounce( const QueueLockAnnounce& ev )
LockMap lm;
lm.srcloc = ShrinkSourceLocation( ev.lckloc );
lm.type = ev.type;
lm.timeAnnounce = TscTime( ev.time );
lm.timeTerminate = 0;
lm.valid = true;
m_data.lockMap.emplace( ev.id, std::move( lm ) );
}
@@ -2224,17 +2289,39 @@ void Worker::ProcessLockAnnounce( const QueueLockAnnounce& ev )
{
it->second.srcloc = ShrinkSourceLocation( ev.lckloc );
assert( it->second.type == ev.type );
it->second.timeAnnounce = TscTime( ev.time );
it->second.valid = true;
}
CheckSourceLocation( ev.lckloc );
}
void Worker::ProcessLockTerminate( const QueueLockTerminate& ev )
{
auto it = m_data.lockMap.find( ev.id );
if( it == m_data.lockMap.end() )
{
LockMap lm;
lm.type = ev.type;
lm.timeAnnounce = 0;
lm.timeTerminate = TscTime( ev.time );
lm.valid = false;
m_data.lockMap.emplace( ev.id, std::move( lm ) );
}
else
{
assert( it->second.type == ev.type );
it->second.timeTerminate = TscTime( ev.time );
}
}
void Worker::ProcessLockWait( const QueueLockWait& ev )
{
auto it = m_data.lockMap.find( ev.id );
if( it == m_data.lockMap.end() )
{
LockMap lm;
lm.timeAnnounce = 0;
lm.timeTerminate = 0;
lm.valid = false;
lm.type = ev.type;
it = m_data.lockMap.emplace( ev.id, std::move( lm ) ).first;
@@ -2588,6 +2675,8 @@ void Worker::ProcessMemAlloc( const QueueMemAlloc& ev )
bool Worker::ProcessMemFree( const QueueMemFree& ev )
{
if( ev.ptr == 0 ) return false;
auto it = m_data.memory.active.find( ev.ptr );
if( it == m_data.memory.active.end() )
{
@@ -3180,6 +3269,8 @@ void Worker::Write( FileWrite& f )
f.Write( &v.second.srcloc, sizeof( v.second.srcloc ) );
f.Write( &v.second.type, sizeof( v.second.type ) );
f.Write( &v.second.valid, sizeof( v.second.valid ) );
f.Write( &v.second.timeAnnounce, sizeof( v.second.timeAnnounce ) );
f.Write( &v.second.timeTerminate, sizeof( v.second.timeTerminate ) );
sz = v.second.threadList.size();
f.Write( &sz, sizeof( sz ) );
for( auto& t : v.second.threadList )

View File

@@ -238,7 +238,7 @@ public:
tracy_force_inline const Vector<ZoneEvent*>& GetZoneChildren( int32_t idx ) const { return m_data.m_zoneChildren[idx]; }
tracy_force_inline const Vector<GpuEvent*>& GetGpuChildren( int32_t idx ) const { return m_data.m_gpuChildren[idx]; }
std::vector<int32_t> GetMatchingSourceLocation( const char* query ) const;
std::vector<int32_t> GetMatchingSourceLocation( const char* query, bool ignoreCase ) const;
#ifndef TRACY_NO_STATISTICS
const SourceLocationZones& GetZonesForSourceLocation( int32_t srcloc ) const;
@@ -284,6 +284,7 @@ private:
tracy_force_inline void ProcessZoneText( const QueueZoneText& ev );
tracy_force_inline void ProcessZoneName( const QueueZoneText& ev );
tracy_force_inline void ProcessLockAnnounce( const QueueLockAnnounce& ev );
tracy_force_inline void ProcessLockTerminate( const QueueLockTerminate& ev );
tracy_force_inline void ProcessLockWait( const QueueLockWait& ev );
tracy_force_inline void ProcessLockObtain( const QueueLockObtain& ev );
tracy_force_inline void ProcessLockRelease( const QueueLockRelease& ev );