mirror of
https://github.com/wolfpld/tracy.git
synced 2026-07-02 03:58:56 +00:00
Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a2894f6e6 | ||
|
|
5cbe2c6ae5 | ||
|
|
b1ba2f9bf7 | ||
|
|
1733961885 | ||
|
|
ee718f18d9 | ||
|
|
0a6c6606bf | ||
|
|
5e4b5850af | ||
|
|
baa870fa8c | ||
|
|
1a50a15212 | ||
|
|
7c164375a4 | ||
|
|
51bdb004f9 | ||
|
|
d80bd2693c | ||
|
|
0ac83a27cc | ||
|
|
ea396354d0 | ||
|
|
2d143ce516 | ||
|
|
4bb4a568ca | ||
|
|
e1bd5c092b | ||
|
|
cd8d86edf3 | ||
|
|
e9ce8fdfda | ||
|
|
a4be9b51b0 | ||
|
|
331693d7f1 | ||
|
|
4893bca12b | ||
|
|
2f45fd8b36 | ||
|
|
6fefffe8a5 | ||
|
|
8c5670489c | ||
|
|
407fb61a30 | ||
|
|
0f2b61cf24 | ||
|
|
1d70e5e5c3 | ||
|
|
621f7c891e | ||
|
|
30c2d0df85 | ||
|
|
4e64ba7775 | ||
|
|
83958db840 | ||
|
|
70ec4b71e4 | ||
|
|
ac9dbfbc79 | ||
|
|
57b4f874cc | ||
|
|
bd71190a4c | ||
|
|
0898873a02 | ||
|
|
df1a125fc0 | ||
|
|
a220f38fbd | ||
|
|
acddcbd9bf | ||
|
|
24235406a0 | ||
|
|
7fc03736f2 | ||
|
|
a740074da6 | ||
|
|
b60d5b892a | ||
|
|
c2485fbcb0 | ||
|
|
9e18db01c9 | ||
|
|
85fbfeccf0 | ||
|
|
a931b9eaf1 | ||
|
|
083320820f | ||
|
|
a7e615d42e | ||
|
|
79eb6a5836 | ||
|
|
aac8d85e6d | ||
|
|
9a7689c65d | ||
|
|
7376ec65b0 | ||
|
|
9360df89b1 | ||
|
|
f42d52923a | ||
|
|
0b816ce0b7 | ||
|
|
61ac0b8afc | ||
|
|
91171a6674 | ||
|
|
abad5574f3 | ||
|
|
8f6f54e412 | ||
|
|
444d5e20f0 | ||
|
|
ff8c9ab6dc | ||
|
|
80bd4275eb | ||
|
|
a54fab05e8 | ||
|
|
537cee911c | ||
|
|
3c1231f5eb | ||
|
|
a9a2ca66ca | ||
|
|
1235a5aa0a | ||
|
|
fec0017bb6 | ||
|
|
f19b559f6e | ||
|
|
d8a9d6d3bf | ||
|
|
6f9977638d | ||
|
|
853eec451f | ||
|
|
591f04ad0f | ||
|
|
5110d55f17 | ||
|
|
27447902ef | ||
|
|
d8bcb32951 | ||
|
|
dc4c8ef343 | ||
|
|
6f9b4aeac9 | ||
|
|
78beb7bd81 | ||
|
|
a234510ef3 | ||
|
|
2af941eadc | ||
|
|
1eb46042be | ||
|
|
63f0dd72a5 | ||
|
|
c3ba314700 | ||
|
|
b20b169a88 | ||
|
|
54baec9e7e | ||
|
|
56190c9614 | ||
|
|
556b3e8efe | ||
|
|
793e955480 | ||
|
|
9342ba0e71 | ||
|
|
2165881efc | ||
|
|
759a4ac908 | ||
|
|
5280d6586b |
1
AUTHORS
1
AUTHORS
@@ -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
27
NEWS
@@ -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)
|
||||
-----------------
|
||||
|
||||
|
||||
24
Tracy.hpp
24
Tracy.hpp
@@ -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 );
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
enum : uint32_t { ProtocolVersion = 0 };
|
||||
enum : uint32_t { ProtocolVersion = 1 };
|
||||
|
||||
using lz4sz_t = uint32_t;
|
||||
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
BIN
doc/profiler.png
BIN
doc/profiler.png
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
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Version
|
||||
{
|
||||
enum { Major = 0 };
|
||||
enum { Minor = 4 };
|
||||
enum { Patch = 0 };
|
||||
enum { Patch = 1 };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user