2019-06-22 11:40:00 +00:00
# ifdef _MSC_VER
# pragma warning( disable: 4267 ) // conversion from don't care to whatever, possible loss of data
# endif
2019-01-19 11:03:30 +00:00
# ifdef __MINGW32__
# define __STDC_FORMAT_MACROS
# endif
2017-09-14 19:28:40 +00:00
# include <algorithm>
2017-09-12 23:33:50 +00:00
# include <assert.h>
2017-10-21 11:32:51 +00:00
# include <chrono>
2017-09-22 20:11:30 +00:00
# include <inttypes.h>
2017-09-16 23:41:18 +00:00
# include <limits>
2017-10-06 00:19:25 +00:00
# include <math.h>
2017-11-15 20:49:41 +00:00
# include <mutex>
2018-09-02 00:30:06 +00:00
# include <numeric>
2018-03-13 15:23:10 +00:00
# include <stddef.h>
2017-09-18 23:24:31 +00:00
# include <stdlib.h>
2017-10-03 21:26:41 +00:00
# include <time.h>
2017-09-12 23:33:50 +00:00
2018-07-13 22:39:01 +00:00
# include "../common/TracyMutex.hpp"
2018-09-09 17:28:53 +00:00
# include "../common/TracyProtocol.hpp"
2017-09-12 23:33:50 +00:00
# include "../common/TracySystem.hpp"
2017-12-08 22:11:08 +00:00
# include "tracy_pdqsort.h"
2018-04-21 22:52:33 +00:00
# include "TracyBadVersion.hpp"
# include "TracyFileRead.hpp"
2017-09-30 14:20:08 +00:00
# include "TracyFileWrite.hpp"
2018-08-17 12:54:28 +00:00
# include "TracyFilesystem.hpp"
2017-09-17 22:18:36 +00:00
# include "TracyImGui.hpp"
2017-10-28 21:12:11 +00:00
# include "TracyPopcnt.hpp"
2019-06-18 18:43:28 +00:00
# include "TracyPrint.hpp"
2017-09-12 23:33:50 +00:00
# include "TracyView.hpp"
2018-08-17 12:44:41 +00:00
# include "../imguicolortextedit/TextEditor.h"
2017-09-30 12:56:09 +00:00
# ifdef TRACY_FILESELECTOR
# include ".. / nfd / nfd.h"
# endif
2018-08-17 21:22:13 +00:00
# ifdef TRACY_EXTENDED_FONT
# include "IconsFontAwesome5.h"
# endif
2018-07-13 21:41:12 +00:00
# ifndef M_PI_2
# define M_PI_2 1.57079632679489661923
# endif
2017-09-12 23:33:50 +00:00
namespace tracy
{
2019-03-06 17:25:39 +00:00
static double s_time = 0 ;
2019-02-27 19:55:58 +00:00
static const char * s_tracyStackFrames [ ] = {
" tracy::Callstack " ,
2019-03-01 00:41:10 +00:00
" tracy::GpuCtxScope::{ctor} " ,
2019-02-27 19:55:58 +00:00
" tracy::Profiler::SendCallstack " ,
" tracy::Profiler::SendCallstack(int, unsigned long) " ,
2019-03-01 00:41:10 +00:00
" tracy::Profiler::MemAllocCallstack " ,
" tracy::Profiler::MemAllocCallstack(void const*, unsigned long, int) " ,
" tracy::Profiler::MemFreeCallstack " ,
" tracy::Profiler::MemFreeCallstack(void const*, int) " ,
" tracy::ScopedZone::{ctor} " ,
2019-02-27 19:55:58 +00:00
" tracy::ScopedZone::ScopedZone(tracy::SourceLocationData const*, int, bool) " ,
nullptr
} ;
2018-08-08 18:07:41 +00:00
2018-12-18 15:28:09 +00:00
static void SetButtonHighlightColor ( )
{
2018-12-18 15:29:54 +00:00
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 ) ) ;
2018-12-18 15:28:09 +00:00
}
2018-12-18 15:13:11 +00:00
static void ToggleButton ( const char * label , bool & toggle )
{
2018-12-18 15:22:12 +00:00
const auto active = toggle ;
2018-12-18 15:28:09 +00:00
if ( active ) SetButtonHighlightColor ( ) ;
2018-12-18 15:13:11 +00:00
if ( ImGui : : Button ( label ) ) toggle = ! toggle ;
2018-12-18 15:22:12 +00:00
if ( active ) ImGui : : PopStyleColor ( 3 ) ;
2018-12-18 15:13:11 +00:00
}
2019-02-24 15:01:58 +00:00
static inline uint64_t GetThreadBit ( uint8_t thread )
{
return uint64_t ( 1 ) < < thread ;
}
static inline bool IsThreadWaiting ( uint64_t bitlist , uint64_t threadBit )
{
return ( bitlist & threadBit ) ! = 0 ;
}
static inline bool AreOtherWaiting ( uint64_t bitlist , uint64_t threadBit )
{
return ( bitlist & ~ threadBit ) ! = 0 ;
}
2017-10-06 16:25:30 +00:00
enum { MinVisSize = 3 } ;
2018-08-05 11:29:44 +00:00
enum { MinFrameSize = 5 } ;
2017-09-23 13:39:39 +00:00
2017-09-12 23:33:50 +00:00
static View * s_instance = nullptr ;
2017-11-11 21:56:05 +00:00
2018-08-17 15:24:18 +00:00
View : : View ( const char * addr , ImFont * fixedWidth , SetTitleCallback stcb )
2018-02-13 13:57:47 +00:00
: m_worker ( addr )
2017-09-30 14:58:02 +00:00
, m_staticView ( false )
2017-09-18 22:26:40 +00:00
, m_pause ( false )
2018-08-04 17:47:09 +00:00
, m_frames ( nullptr )
2018-08-17 13:18:09 +00:00
, m_textEditorFont ( fixedWidth )
2018-08-17 15:24:18 +00:00
, m_stcb ( stcb )
2017-09-21 00:10:20 +00:00
{
2017-09-12 23:33:50 +00:00
assert ( s_instance = = nullptr ) ;
s_instance = this ;
2017-09-21 00:10:20 +00:00
2018-08-17 12:44:41 +00:00
InitTextEditor ( ) ;
2017-11-11 00:39:34 +00:00
}
2018-08-17 15:24:18 +00:00
View : : View ( FileRead & f , ImFont * fixedWidth , SetTitleCallback stcb )
2018-02-13 13:57:47 +00:00
: m_worker ( f )
, m_staticView ( true )
2018-10-21 14:03:21 +00:00
, m_pause ( true )
2018-08-04 17:47:09 +00:00
, m_frames ( m_worker . GetFramesBase ( ) )
2018-08-17 13:18:09 +00:00
, m_textEditorFont ( fixedWidth )
2018-08-17 15:24:18 +00:00
, m_stcb ( stcb )
2017-11-14 22:37:44 +00:00
{
2018-02-13 13:57:47 +00:00
assert ( s_instance = = nullptr ) ;
s_instance = this ;
2018-08-17 12:44:41 +00:00
2019-01-06 18:20:17 +00:00
m_notificationTime = 4 ;
m_notificationText = std : : string ( " Trace loaded in " ) + TimeToString ( m_worker . GetLoadTime ( ) ) ;
2018-08-17 12:44:41 +00:00
InitTextEditor ( ) ;
2018-10-21 14:03:21 +00:00
SetViewToLastFrames ( ) ;
2017-11-14 22:37:44 +00:00
}
2018-02-13 13:57:47 +00:00
View : : ~ View ( )
2017-09-21 23:30:57 +00:00
{
2018-02-13 13:57:47 +00:00
m_worker . Shutdown ( ) ;
2017-09-21 23:30:57 +00:00
2018-07-28 16:47:33 +00:00
if ( m_compare . loadThread . joinable ( ) ) m_compare . loadThread . join ( ) ;
2019-05-28 17:56:18 +00:00
if ( m_saveThread . joinable ( ) ) m_saveThread . join ( ) ;
2018-07-28 16:47:33 +00:00
2019-06-06 21:14:49 +00:00
if ( m_frameTexture ) FreeTexture ( m_frameTexture ) ;
2019-06-11 23:26:49 +00:00
if ( m_playback . texture ) FreeTexture ( m_playback . texture ) ;
2019-06-06 20:14:25 +00:00
2018-02-13 13:57:47 +00:00
assert ( s_instance ! = nullptr ) ;
s_instance = nullptr ;
2017-09-26 16:54:48 +00:00
}
2018-08-17 12:44:41 +00:00
void View : : InitTextEditor ( )
{
m_textEditor = std : : make_unique < TextEditor > ( ) ;
m_textEditor - > SetReadOnly ( true ) ;
m_textEditor - > SetLanguageDefinition ( TextEditor : : LanguageDefinition : : CPlusPlus ( ) ) ;
2019-06-22 12:24:39 +00:00
m_textEditor - > SetShowWhitespaces ( m_textEditorWhitespace ) ;
2018-08-17 12:54:28 +00:00
m_textEditorFile = nullptr ;
}
void View : : SetTextEditorFile ( const char * fileName , int line )
{
2018-08-17 13:24:52 +00:00
if ( ! m_textEditorFile | | strcmp ( m_textEditorFile , fileName ) ! = 0 )
{
FILE * f = fopen ( fileName , " rb " ) ;
fseek ( f , 0 , SEEK_END ) ;
const auto sz = ftell ( f ) ;
fseek ( f , 0 , SEEK_SET ) ;
2018-12-16 18:48:34 +00:00
auto data = new char [ sz + 1 ] ;
2018-08-17 23:16:15 +00:00
fread ( data , 1 , sz , f ) ;
2018-08-17 13:24:52 +00:00
fclose ( f ) ;
2018-12-16 18:48:34 +00:00
data [ sz ] = ' \0 ' ;
2018-08-17 13:24:52 +00:00
m_textEditor - > SetText ( data ) ;
2018-08-17 23:16:15 +00:00
delete [ ] data ;
2018-08-17 13:24:52 +00:00
}
2018-08-17 13:21:37 +00:00
m_textEditor - > SetCursorPosition ( TextEditor : : Coordinates ( line - 1 , 0 ) ) ;
2018-08-17 12:54:28 +00:00
m_textEditorFile = fileName ;
2018-08-17 12:44:41 +00:00
}
2017-10-22 11:56:05 +00:00
const char * View : : ShortenNamespace ( const char * name ) const
{
if ( m_namespace = = Namespace : : Full ) return name ;
if ( m_namespace = = Namespace : : Short )
{
auto ptr = name ;
while ( * ptr ! = ' \0 ' ) ptr + + ;
while ( ptr > name & & * ptr ! = ' : ' ) ptr - - ;
if ( * ptr = = ' : ' ) ptr + + ;
return ptr ;
}
static char buf [ 1024 ] ;
auto dst = buf ;
auto ptr = name ;
for ( ; ; )
{
auto start = ptr ;
while ( * ptr ! = ' \0 ' & & * ptr ! = ' : ' ) ptr + + ;
if ( * ptr = = ' \0 ' )
{
memcpy ( dst , start , ptr - start + 1 ) ;
return buf ;
}
* dst + + = * start ;
* dst + + = ' : ' ;
while ( * ptr = = ' : ' ) ptr + + ;
}
}
2018-01-17 11:49:50 +00:00
void View : : DrawHelpMarker ( const char * desc ) const
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " (?) " ) ;
2018-03-24 13:42:48 +00:00
if ( ImGui : : IsItemHovered ( ) )
2018-01-17 11:49:50 +00:00
{
2019-02-10 02:02:54 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
2018-01-17 11:49:50 +00:00
ImGui : : BeginTooltip ( ) ;
2019-02-10 02:02:54 +00:00
ImGui : : PushTextWrapPos ( 450.0f * ty / 15.f ) ;
2018-01-17 11:49:50 +00:00
ImGui : : TextUnformatted ( desc ) ;
ImGui : : PopTextWrapPos ( ) ;
ImGui : : EndTooltip ( ) ;
}
}
2017-11-25 14:45:16 +00:00
void View : : DrawTextContrast ( ImDrawList * draw , const ImVec2 & pos , uint32_t color , const char * text )
{
2019-06-05 23:45:41 +00:00
draw - > AddText ( pos + ImVec2 ( 1 , 1 ) , 0xAA000000 , text ) ;
2017-11-25 14:45:16 +00:00
draw - > AddText ( pos , color , text ) ;
}
2018-04-29 23:16:08 +00:00
bool View : : Draw ( )
2017-09-15 00:30:22 +00:00
{
2018-09-09 17:28:53 +00:00
HandshakeStatus status = ( HandshakeStatus ) s_instance - > m_worker . GetHandshakeStatus ( ) ;
2019-02-12 00:41:09 +00:00
switch ( status )
2018-09-09 17:28:53 +00:00
{
2019-02-12 00:41:09 +00:00
case HandshakeProtocolMismatch :
2018-09-09 17:28:53 +00:00
ImGui : : OpenPopup ( " Protocol mismatch " ) ;
2019-02-12 00:41:09 +00:00
break ;
case HandshakeNotAvailable :
2018-09-09 17:42:06 +00:00
ImGui : : OpenPopup ( " Client not ready " ) ;
2019-02-12 00:41:09 +00:00
break ;
case HandshakeDropped :
ImGui : : OpenPopup ( " Client disconnected " ) ;
break ;
default :
break ;
2018-09-09 17:42:06 +00:00
}
2018-09-09 17:28:53 +00:00
2019-01-14 22:42:58 +00:00
const auto & failure = s_instance - > m_worker . GetFailureType ( ) ;
if ( failure ! = Worker : : Failure : : None )
{
ImGui : : OpenPopup ( " Instrumentation failure " ) ;
}
2018-09-09 17:28:53 +00:00
if ( ImGui : : BeginPopupModal ( " Protocol mismatch " , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) )
{
# ifdef TRACY_EXTENDED_FONT
TextCentered ( ICON_FA_EXCLAMATION_TRIANGLE ) ;
# endif
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " The client you are trying to connect to uses incompatible protocol version. \n Make sure you are using the same Tracy version on both client and server. " ) ;
2018-09-09 17:28:53 +00:00
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " My bad " ) )
{
ImGui : : CloseCurrentPopup ( ) ;
2018-09-09 17:42:06 +00:00
ImGui : : EndPopup ( ) ;
return false ;
}
ImGui : : EndPopup ( ) ;
}
if ( ImGui : : BeginPopupModal ( " Client not ready " , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) )
{
# ifdef TRACY_EXTENDED_FONT
TextCentered ( ICON_FA_LIGHTBULB ) ;
# endif
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " The client you are trying to connect to is no longer able to sent profiling data, \n because another server was already connected to it. \n You can do the following: \n \n 1. Restart the client application. \n 2. Rebuild the client application with on-demand mode enabled. " ) ;
2018-09-09 17:42:06 +00:00
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " I understand " ) )
{
ImGui : : CloseCurrentPopup ( ) ;
2018-09-09 17:28:53 +00:00
ImGui : : EndPopup ( ) ;
return false ;
}
ImGui : : EndPopup ( ) ;
}
2019-02-12 00:41:09 +00:00
if ( ImGui : : BeginPopupModal ( " Client disconnected " , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) )
{
# ifdef TRACY_EXTENDED_FONT
TextCentered ( ICON_FA_HANDSHAKE ) ;
# endif
ImGui : : TextUnformatted ( " The client you are trying to connect to has disconnected during the initial \n connection handshake. Please check your network configuration. " ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " Will do " ) )
{
ImGui : : CloseCurrentPopup ( ) ;
ImGui : : EndPopup ( ) ;
return false ;
}
ImGui : : EndPopup ( ) ;
}
2019-01-14 22:42:58 +00:00
if ( ImGui : : BeginPopupModal ( " Instrumentation failure " , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) )
{
const auto & data = s_instance - > m_worker . GetFailureData ( ) ;
# ifdef TRACY_EXTENDED_FONT
TextCentered ( ICON_FA_SKULL ) ;
# endif
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Profiling session terminated due to improper instrumentation. \n Please correct your program and try again. " ) ;
ImGui : : TextUnformatted ( " Reason: " ) ;
2019-01-14 22:42:58 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( Worker : : GetFailureString ( failure ) ) ;
2019-01-14 22:42:58 +00:00
ImGui : : Separator ( ) ;
2019-01-15 17:54:41 +00:00
if ( data . srcloc ! = 0 )
2019-01-14 22:42:58 +00:00
{
2019-01-15 17:54:41 +00:00
const auto & srcloc = s_instance - > m_worker . GetSourceLocation ( data . srcloc ) ;
if ( srcloc . name . active )
{
TextFocused ( " Zone name: " , s_instance - > m_worker . GetString ( srcloc . name ) ) ;
}
TextFocused ( " Function: " , s_instance - > m_worker . GetString ( srcloc . function ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Location: " ) ;
2019-01-15 17:54:41 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s:%i " , s_instance - > m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2019-01-14 22:42:58 +00:00
}
2019-02-28 18:31:45 +00:00
if ( data . thread ! = 0 )
{
TextFocused ( " Thread: " , s_instance - > m_worker . GetThreadString ( data . thread ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , data . thread ) ;
}
2019-01-14 22:42:58 +00:00
ImGui : : Separator ( ) ;
if ( ImGui : : Button ( " I understand " ) )
{
ImGui : : CloseCurrentPopup ( ) ;
s_instance - > m_worker . ClearFailure ( ) ;
}
ImGui : : EndPopup ( ) ;
}
2019-03-06 23:57:25 +00:00
s_time + = ImGui : : GetIO ( ) . DeltaTime ;
2018-04-29 23:16:08 +00:00
return s_instance - > DrawImpl ( ) ;
2017-09-15 00:30:22 +00:00
}
2018-04-21 20:42:32 +00:00
static const char * MainWindowButtons [ ] = {
2018-08-17 21:24:25 +00:00
# ifdef TRACY_EXTENDED_FONT
ICON_FA_PLAY " Resume " ,
2018-11-25 18:15:16 +00:00
ICON_FA_PAUSE " Pause " ,
ICON_FA_SQUARE " Stopped "
2018-08-17 21:24:25 +00:00
# else
2018-04-21 20:42:32 +00:00
" Resume " ,
2018-11-25 18:15:16 +00:00
" Pause " ,
" Stopped "
2018-08-17 21:24:25 +00:00
# endif
2018-04-21 20:42:32 +00:00
} ;
enum { MainWindowButtonsCount = sizeof ( MainWindowButtons ) / sizeof ( * MainWindowButtons ) } ;
2018-04-29 23:16:08 +00:00
bool View : : DrawImpl ( )
2017-09-15 00:30:22 +00:00
{
2018-02-13 13:57:47 +00:00
if ( ! m_worker . HasData ( ) )
2017-09-20 18:38:12 +00:00
{
2018-07-10 18:47:09 +00:00
char tmp [ 2048 ] ;
sprintf ( tmp , " %s###Connection " , m_worker . GetAddr ( ) . c_str ( ) ) ;
ImGui : : Begin ( tmp , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ;
2018-08-17 21:56:06 +00:00
# ifdef TRACY_EXTENDED_FONT
TextCentered ( ICON_FA_WIFI ) ;
# endif
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Waiting for connection... " ) ;
2019-03-07 16:00:40 +00:00
DrawWaitingDots ( s_time ) ;
ImGui : : Spacing ( ) ;
ImGui : : Separator ( ) ;
2018-10-23 17:03:01 +00:00
bool wasCancelled = ImGui : : Button ( " Cancel " ) ;
2017-09-20 18:38:12 +00:00
ImGui : : End ( ) ;
2018-10-23 17:03:01 +00:00
return ! wasCancelled ;
2017-09-30 14:58:02 +00:00
}
2017-09-30 12:37:21 +00:00
2019-06-02 11:15:55 +00:00
if ( m_saveThreadState . load ( std : : memory_order_relaxed ) = = SaveThreadState : : NeedsJoin )
2019-05-28 17:56:18 +00:00
{
m_saveThread . join ( ) ;
2019-06-02 11:15:55 +00:00
m_saveThreadState . store ( SaveThreadState : : Inert , std : : memory_order_relaxed ) ;
2019-05-28 17:56:18 +00:00
}
2018-12-22 16:36:20 +00:00
const auto & io = ImGui : : GetIO ( ) ;
assert ( m_shortcut = = ShortcutAction : : None ) ;
if ( io . KeyCtrl )
{
if ( ImGui : : IsKeyPressed ( ' F ' ) )
{
2018-12-22 16:39:22 +00:00
m_findZone . show = true ;
2018-12-22 16:36:20 +00:00
m_shortcut = ShortcutAction : : OpenFind ;
}
}
2018-08-04 17:47:09 +00:00
if ( ! m_frames ) m_frames = m_worker . GetFramesBase ( ) ;
2018-03-24 22:43:51 +00:00
const auto th = ImGui : : GetTextLineHeight ( ) ;
2018-04-21 20:42:32 +00:00
float bw = 0 ;
for ( int i = 0 ; i < MainWindowButtonsCount ; i + + )
{
bw = std : : max ( bw , ImGui : : CalcTextSize ( MainWindowButtons [ i ] ) . x ) ;
}
bw + = th ;
2018-03-24 22:43:51 +00:00
2018-04-29 23:16:08 +00:00
bool keepOpen = true ;
bool * keepOpenPtr = nullptr ;
2019-06-22 12:04:48 +00:00
( void ) keepOpenPtr ;
2018-04-29 23:16:08 +00:00
if ( ! m_staticView )
{
2018-11-25 18:29:20 +00:00
if ( ! DrawConnection ( ) ) return false ;
2018-04-29 23:16:08 +00:00
}
else
{
keepOpenPtr = & keepOpen ;
}
2018-08-17 15:00:56 +00:00
# ifdef TRACY_ROOT_WINDOW
2018-08-17 15:24:18 +00:00
if ( ! m_titleSet & & m_stcb )
{
m_titleSet = true ;
m_stcb ( m_worker . GetCaptureName ( ) . c_str ( ) ) ;
}
2018-08-17 15:00:56 +00:00
auto & style = ImGui : : GetStyle ( ) ;
const auto wrPrev = style . WindowRounding ;
const auto wbsPrev = style . WindowBorderSize ;
const auto wpPrev = style . WindowPadding ;
style . WindowRounding = 0.f ;
style . WindowBorderSize = 0.f ;
style . WindowPadding = ImVec2 ( 4.f , 4.f ) ;
2019-03-07 00:18:24 +00:00
style . Colors [ ImGuiCol_WindowBg ] = ImVec4 ( 0.129f , 0.137f , 0.11f , 1.f ) ;
2018-08-17 15:00:56 +00:00
ImGui : : SetNextWindowPos ( ImVec2 ( 0 , 0 ) ) ;
ImGui : : SetNextWindowSize ( ImVec2 ( m_rootWidth , m_rootHeight ) ) ;
2018-08-30 00:08:08 +00:00
ImGui : : Begin ( " Timeline view###Profiler " , nullptr , ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoMove ) ;
2018-08-17 15:00:56 +00:00
style . WindowRounding = wrPrev ;
style . WindowBorderSize = wbsPrev ;
style . WindowPadding = wpPrev ;
2019-03-07 00:18:24 +00:00
style . Colors [ ImGuiCol_WindowBg ] = ImVec4 ( 0.11f , 0.11f , 0.08f , 1.f ) ;
2018-08-17 15:00:56 +00:00
# else
2018-08-17 15:24:18 +00:00
char tmp [ 2048 ] ;
sprintf ( tmp , " %s###Profiler " , m_worker . GetCaptureName ( ) . c_str ( ) ) ;
ImGui : : SetNextWindowSize ( ImVec2 ( 1550 , 800 ) , ImGuiCond_FirstUseEver ) ;
2018-07-26 21:38:45 +00:00
ImGui : : Begin ( tmp , keepOpenPtr , ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBringToFrontOnFocus ) ;
2018-08-17 15:00:56 +00:00
# endif
2019-05-28 17:56:18 +00:00
std : : shared_lock < std : : shared_mutex > lock ( m_worker . GetDataLock ( ) ) ;
2018-03-24 13:45:01 +00:00
if ( ! m_worker . IsDataStatic ( ) )
{
2018-11-25 18:15:16 +00:00
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 ) ;
}
2018-03-24 13:45:01 +00:00
}
2018-08-17 14:34:58 +00:00
else
{
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 ) ) ;
2018-08-17 16:33:56 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-08-17 21:22:13 +00:00
if ( ImGui : : Button ( ICON_FA_POWER_OFF ) ) keepOpen = false ;
2018-08-17 16:33:56 +00:00
# else
2018-08-17 14:34:58 +00:00
if ( ImGui : : Button ( " Close " ) ) keepOpen = false ;
2018-08-17 16:33:56 +00:00
# endif
2018-08-17 14:34:58 +00:00
ImGui : : PopStyleColor ( 3 ) ;
}
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_COG " Options " , m_showOptions ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Options " , m_showOptions ) ;
2018-08-17 17:03:35 +00:00
# endif
2017-09-30 12:37:21 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_TAGS " Messages " , m_showMessages ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Messages " , m_showMessages ) ;
2018-08-17 17:03:35 +00:00
# endif
2017-10-14 12:36:30 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_SEARCH " Find zone " , m_findZone . show ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Find zone " , m_findZone . show ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-03-24 13:40:48 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_SORT_AMOUNT_UP " Statistics " , m_showStatistics ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Statistics " , m_showStatistics ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-01-17 11:49:50 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_MEMORY " Memory " , m_memInfo . show ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Memory " , m_memInfo . show ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-04-01 18:34:21 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_BALANCE_SCALE " Compare " , m_compare . show ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Compare " , m_compare . show ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_FINGERPRINT " Info " , m_showInfo ) ;
2018-08-17 17:03:35 +00:00
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Info " , m_showInfo ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-08-08 17:25:13 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-02-27 01:26:43 +00:00
if ( ImGui : : SmallButton ( " " ICON_FA_CARET_LEFT " " ) ) ZoomToPrevFrame ( ) ;
2018-08-17 17:03:35 +00:00
# else
2019-02-27 01:26:43 +00:00
if ( ImGui : : SmallButton ( " < " ) ) ZoomToPrevFrame ( ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-08-08 16:40:31 +00:00
ImGui : : SameLine ( ) ;
{
2019-02-21 19:24:08 +00:00
const auto vis = Vis ( m_frames ) . visible ;
2018-08-08 16:40:31 +00:00
if ( ! vis )
{
ImGui : : PushStyleColor ( ImGuiCol_Text , GImGui - > Style . Colors [ ImGuiCol_TextDisabled ] ) ;
}
ImGui : : Text ( " %s: %s " , m_frames - > name = = 0 ? " Frames " : m_worker . GetString ( m_frames - > name ) , RealToString ( m_worker . GetFrameCount ( * m_frames ) , true ) ) ;
if ( ! vis )
{
ImGui : : PopStyleColor ( ) ;
}
}
ImGui : : SameLine ( ) ;
2018-08-17 17:03:35 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-02-27 01:26:43 +00:00
if ( ImGui : : SmallButton ( " " ICON_FA_CARET_RIGHT " " ) ) ZoomToNextFrame ( ) ;
2018-08-17 17:03:35 +00:00
# else
2019-02-27 01:26:43 +00:00
if ( ImGui : : SmallButton ( " > " ) ) ZoomToNextFrame ( ) ;
2018-08-17 17:03:35 +00:00
# endif
2018-08-08 16:40:31 +00:00
ImGui : : SameLine ( ) ;
2018-08-04 19:43:29 +00:00
if ( ImGui : : BeginCombo ( " ##frameCombo " , nullptr , ImGuiComboFlags_NoPreview ) )
{
auto & frames = m_worker . GetFrames ( ) ;
for ( auto & fd : frames )
{
bool isSelected = m_frames = = fd ;
if ( ImGui : : Selectable ( fd - > name = = 0 ? " Frames " : m_worker . GetString ( fd - > name ) , isSelected ) )
{
m_frames = fd ;
}
if ( isSelected )
{
ImGui : : SetItemDefaultFocus ( ) ;
}
2019-02-22 20:04:41 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( fd - > frames . size ( ) , true ) ) ;
2018-08-04 19:43:29 +00:00
}
ImGui : : EndCombo ( ) ;
}
ImGui : : SameLine ( ) ;
2018-10-21 15:36:27 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:13:11 +00:00
ToggleButton ( ICON_FA_CROSSHAIRS , m_goToFrame ) ;
2018-10-21 15:36:27 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Go to frame " ) ;
2018-10-21 15:36:27 +00:00
ImGui : : EndTooltip ( ) ;
}
# else
2018-12-18 15:13:11 +00:00
ToggleButton ( " Go to " , m_goToFrame ) ;
2018-10-21 15:36:27 +00:00
# endif
ImGui : : SameLine ( ) ;
2018-10-05 21:02:23 +00:00
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
ImGui : : Text ( ICON_FA_EYE " %-10s " , TimeToString ( m_zvEnd - m_zvStart ) ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " View span " ) ;
ImGui : : EndTooltip ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : Text ( ICON_FA_DATABASE " %-10s " , TimeToString ( m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ) ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Time span " ) ;
ImGui : : EndTooltip ( ) ;
}
# else
ImGui : : Text ( " View span: %-10s Time span: %-10s " , TimeToString ( m_zvEnd - m_zvStart ) , TimeToString ( m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ) ) ;
# endif
2019-06-02 13:00:50 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
if ( ! m_worker . IsBackgroundDone ( ) )
{
ImGui : : SameLine ( ) ;
2019-06-22 12:37:17 +00:00
# ifdef TRACY_EXTENDED_FONT
TextDisabledUnformatted ( ICON_FA_TASKS ) ;
ImGui : : SameLine ( ) ;
2019-06-02 13:00:50 +00:00
const auto pos = ImGui : : GetCursorPos ( ) ;
ImGui : : TextUnformatted ( " " ) ;
ImGui : : GetWindowDrawList ( ) - > AddCircleFilled ( pos + ImVec2 ( 0 , ty * 0.75f ) , ty * ( 0.2f + ( sin ( s_time * 8 ) + 1 ) * 0.125f ) , 0xFF888888 , 10 ) ;
2019-06-22 12:37:17 +00:00
# else
const auto pos = ImGui : : GetCursorPos ( ) ;
ImGui : : TextUnformatted ( " " ) ;
ImGui : : GetWindowDrawList ( ) - > AddCircleFilled ( pos + ImVec2 ( 0 , ty * 0.75f ) , ty * ( 0.2f + ( sin ( s_time * 8 ) + 1 ) * 0.125f ) , 0xFF888888 , 10 ) ;
# endif
2019-06-02 13:00:50 +00:00
}
2019-06-02 11:15:55 +00:00
if ( m_saveThreadState . load ( std : : memory_order_relaxed ) = = SaveThreadState : : Saving )
2019-05-28 17:56:18 +00:00
{
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
ImGui : : TextUnformatted ( ICON_FA_SAVE " Saving trace... " ) ;
# else
ImGui : : TextUnformatted ( " Saving trace... " ) ;
# endif
m_notificationTime = 0 ;
}
else if ( m_notificationTime > 0 )
2019-01-06 18:14:24 +00:00
{
m_notificationTime - = io . DeltaTime ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( m_notificationText . c_str ( ) ) ;
2019-01-06 18:14:24 +00:00
}
2019-06-16 22:59:16 +00:00
m_frameHover = - 1 ;
2017-09-30 12:37:21 +00:00
DrawFrames ( ) ;
DrawZones ( ) ;
ImGui : : End ( ) ;
m_zoneHighlight = nullptr ;
2017-11-12 00:28:07 +00:00
m_gpuHighlight = nullptr ;
2017-11-12 00:25:44 +00:00
DrawInfoWindow ( ) ;
2017-11-12 00:28:07 +00:00
2017-10-13 11:32:23 +00:00
if ( m_showOptions ) DrawOptions ( ) ;
2017-10-14 12:36:30 +00:00
if ( m_showMessages ) DrawMessages ( ) ;
2018-01-17 11:49:50 +00:00
if ( m_findZone . show ) DrawFindZone ( ) ;
2018-03-24 13:40:48 +00:00
if ( m_showStatistics ) DrawStatistics ( ) ;
2018-04-01 19:24:30 +00:00
if ( m_memInfo . show ) DrawMemory ( ) ;
2018-09-27 21:16:10 +00:00
if ( m_memInfo . showAllocList ) DrawAllocList ( ) ;
2018-04-21 22:52:33 +00:00
if ( m_compare . show ) DrawCompare ( ) ;
2018-06-20 11:23:08 +00:00
if ( m_callstackInfoWindow ! = 0 ) DrawCallstackWindow ( ) ;
2018-07-19 13:43:45 +00:00
if ( m_memoryAllocInfoWindow > = 0 ) DrawMemoryAllocWindow ( ) ;
2018-08-08 17:25:13 +00:00
if ( m_showInfo ) DrawInfo ( ) ;
2018-08-17 13:33:12 +00:00
if ( m_textEditorFile ) DrawTextEditor ( ) ;
2018-10-21 15:36:27 +00:00
if ( m_goToFrame ) DrawGoToFrame ( ) ;
2018-12-16 18:58:11 +00:00
if ( m_lockInfoWindow ! = InvalidId ) DrawLockInfoWindow ( ) ;
2019-06-11 23:26:49 +00:00
if ( m_showPlayback ) DrawPlayback ( ) ;
2017-09-30 12:37:21 +00:00
2017-11-27 21:41:30 +00:00
if ( m_zoomAnim . active )
2017-09-30 12:37:21 +00:00
{
2019-02-21 19:00:29 +00:00
m_zoomAnim . progress + = io . DeltaTime * 3.33f ;
2017-11-27 21:41:30 +00:00
if ( m_zoomAnim . progress > = 1.f )
{
m_zoomAnim . active = false ;
m_zvStart = m_zoomAnim . start1 ;
m_zvEnd = m_zoomAnim . end1 ;
}
else
{
const auto v = sqrt ( sin ( M_PI_2 * m_zoomAnim . progress ) ) ;
m_zvStart = int64_t ( m_zoomAnim . start0 + ( m_zoomAnim . start1 - m_zoomAnim . start0 ) * v ) ;
m_zvEnd = int64_t ( m_zoomAnim . end0 + ( m_zoomAnim . end1 - m_zoomAnim . end0 ) * v ) ;
}
2017-09-30 12:37:21 +00:00
}
2018-04-29 23:16:08 +00:00
2018-08-17 20:23:16 +00:00
m_callstackBuzzAnim . Update ( io . DeltaTime ) ;
2018-08-17 20:51:26 +00:00
m_callstackTreeBuzzAnim . Update ( io . DeltaTime ) ;
2018-08-18 12:26:10 +00:00
m_zoneinfoBuzzAnim . Update ( io . DeltaTime ) ;
2018-08-18 18:35:25 +00:00
m_findZoneBuzzAnim . Update ( io . DeltaTime ) ;
2018-09-18 14:14:32 +00:00
m_optionsLockBuzzAnim . Update ( io . DeltaTime ) ;
2018-12-16 18:58:11 +00:00
m_lockInfoAnim . Update ( io . DeltaTime ) ;
2019-03-08 23:15:23 +00:00
m_statBuzzAnim . Update ( io . DeltaTime ) ;
2018-08-17 20:23:16 +00:00
2018-04-29 23:16:08 +00:00
return keepOpen ;
2017-09-30 12:37:21 +00:00
}
2018-11-25 18:29:20 +00:00
bool View : : DrawConnection ( )
2017-09-30 12:37:21 +00:00
{
2017-10-18 21:25:35 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto cs = ty * 0.9f ;
2017-09-15 00:30:22 +00:00
{
2019-05-28 17:56:18 +00:00
std : : shared_lock < std : : shared_mutex > lock ( m_worker . GetMbpsDataLock ( ) ) ;
2018-08-04 12:50:31 +00:00
char tmp [ 2048 ] ;
sprintf ( tmp , " %s###Connection " , m_worker . GetAddr ( ) . c_str ( ) ) ;
ImGui : : Begin ( tmp , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ;
2018-02-13 13:57:47 +00:00
const auto & mbpsVector = m_worker . GetMbpsData ( ) ;
const auto mbps = mbpsVector . back ( ) ;
2017-09-15 00:30:22 +00:00
char buf [ 64 ] ;
if ( mbps < 0.1f )
{
2017-09-16 23:41:18 +00:00
sprintf ( buf , " %6.2f Kbps " , mbps * 1000.f ) ;
2017-09-15 00:30:22 +00:00
}
else
{
2017-09-16 23:41:18 +00:00
sprintf ( buf , " %6.2f Mbps " , mbps ) ;
2017-09-15 00:30:22 +00:00
}
2017-10-18 21:25:35 +00:00
ImGui : : Dummy ( ImVec2 ( cs , 0 ) ) ;
2017-09-17 22:31:38 +00:00
ImGui : : SameLine ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : PlotLines ( buf , mbpsVector . data ( ) , mbpsVector . size ( ) , 0 , nullptr , 0 , std : : numeric_limits < float > : : max ( ) , ImVec2 ( 150 , 0 ) ) ;
ImGui : : Text ( " Ratio %.1f%% Real: %6.2f Mbps " , m_worker . GetCompRatio ( ) * 100.f , mbps / m_worker . GetCompRatio ( ) ) ;
2019-04-01 17:55:54 +00:00
ImGui : : Text ( " Query backlog: %s " , RealToString ( m_worker . GetSendQueueSize ( ) , true ) ) ;
2017-09-15 00:30:22 +00:00
}
2017-09-15 18:31:59 +00:00
2018-08-08 18:38:43 +00:00
ImGui : : Text ( " Memory usage: %s " , MemSizeToString ( memUsage . load ( std : : memory_order_relaxed ) ) ) ;
2017-09-16 23:22:46 +00:00
2017-09-17 22:31:38 +00:00
const auto wpos = ImGui : : GetWindowPos ( ) + ImGui : : GetWindowContentRegionMin ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : GetWindowDrawList ( ) - > AddCircleFilled ( wpos + ImVec2 ( 1 + cs * 0.5 , 3 + ty * 0.5 ) , cs * 0.5 , m_worker . IsConnected ( ) ? 0xFF2222CC : 0xFF444444 , 10 ) ;
2017-09-17 22:31:38 +00:00
2017-09-15 22:57:50 +00:00
{
2019-05-28 17:57:18 +00:00
std : : shared_lock < std : : shared_mutex > lock ( m_worker . GetDataLock ( ) ) ;
2018-08-04 17:47:09 +00:00
const auto sz = m_worker . GetFrameCount ( * m_frames ) ;
2017-09-15 22:57:50 +00:00
if ( sz > 1 )
{
2018-08-04 17:47:09 +00:00
const auto dt = m_worker . GetFrameTime ( * m_frames , sz - 2 ) ;
2017-09-15 22:57:50 +00:00
const auto dtm = dt / 1000000.f ;
const auto fps = 1000.f / dtm ;
2017-09-16 23:41:18 +00:00
ImGui : : Text ( " FPS: %6.1f Frame time: %.2f ms " , fps , dtm ) ;
2017-09-15 22:57:50 +00:00
}
}
2017-09-18 00:37:25 +00:00
2018-08-17 16:36:06 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 11:15:55 +00:00
if ( ImGui : : Button ( ICON_FA_SAVE " Save trace " ) & & m_saveThreadState . load ( std : : memory_order_relaxed ) = = SaveThreadState : : Inert )
2018-08-17 16:36:06 +00:00
# else
2019-06-02 11:15:55 +00:00
if ( ImGui : : Button ( " Save trace " ) & & m_saveThreadState . load ( std : : memory_order_relaxed ) = = SaveThreadState : : Inert )
2018-08-17 16:36:06 +00:00
# endif
2017-09-30 12:56:09 +00:00
{
# ifdef TRACY_FILESELECTOR
nfdchar_t * fn ;
auto res = NFD_SaveDialog ( " tracy " , nullptr , & fn ) ;
if ( res = = NFD_OKAY )
# else
const char * fn = " trace.tracy " ;
# endif
{
2017-10-12 20:38:11 +00:00
std : : unique_ptr < FileWrite > f ;
const auto sz = strlen ( fn ) ;
if ( sz < 7 | | memcmp ( fn + sz - 6 , " .tracy " , 6 ) ! = 0 )
{
char tmp [ 1024 ] ;
sprintf ( tmp , " %s.tracy " , fn ) ;
f . reset ( FileWrite : : Open ( tmp ) ) ;
}
else
{
f . reset ( FileWrite : : Open ( fn ) ) ;
}
2017-09-30 14:20:08 +00:00
if ( f )
{
2019-06-02 11:15:55 +00:00
m_saveThreadState . store ( SaveThreadState : : Saving , std : : memory_order_relaxed ) ;
2019-05-28 17:56:18 +00:00
m_saveThread = std : : thread ( [ this , f { std : : move ( f ) } ] {
std : : shared_lock < std : : shared_mutex > lock ( m_worker . GetDataLock ( ) ) ;
m_worker . Write ( * f ) ;
2019-06-02 11:15:55 +00:00
m_saveThreadState . store ( SaveThreadState : : NeedsJoin , std : : memory_order_relaxed ) ;
2019-05-28 17:56:18 +00:00
} ) ;
2017-09-30 14:20:08 +00:00
}
2017-09-30 12:56:09 +00:00
}
}
2019-01-24 18:00:34 +00:00
ImGui : : SameLine ( 0 , 2 * ty ) ;
# ifdef TRACY_EXTENDED_FONT
const char * stopStr = ICON_FA_PLUG " Stop " ;
# else
const char * stopStr = " Stop " ;
# endif
2019-05-28 17:57:18 +00:00
std : : shared_lock < std : : shared_mutex > lock ( m_worker . GetDataLock ( ) ) ;
2019-01-24 18:00:34 +00:00
if ( m_worker . IsConnected ( ) )
{
if ( ImGui : : Button ( stopStr ) )
{
m_worker . Disconnect ( ) ;
}
}
else
{
ImGui : : PushStyleColor ( ImGuiCol_Button , ( ImVec4 ) ImColor ( 0.3f , 0.3f , 0.3f , 1.0f ) ) ;
ImGui : : ButtonEx ( stopStr , ImVec2 ( 0 , 0 ) , ImGuiButtonFlags_Disabled ) ;
ImGui : : PopStyleColor ( 1 ) ;
}
ImGui : : SameLine ( ) ;
2018-11-25 18:29:20 +00:00
# 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
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " All unsaved profiling data will be lost! " ) ;
ImGui : : TextUnformatted ( " Are you sure you want to proceed? " ) ;
2018-11-25 18:29:20 +00:00
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 ( ) ;
}
2017-09-18 00:37:25 +00:00
ImGui : : End ( ) ;
2018-11-25 18:29:20 +00:00
return true ;
2017-09-18 00:37:25 +00:00
}
static ImU32 GetFrameColor ( uint64_t frameTime )
{
enum { BestTime = 1000 * 1000 * 1000 / 143 } ;
enum { GoodTime = 1000 * 1000 * 1000 / 59 } ;
enum { BadTime = 1000 * 1000 * 1000 / 29 } ;
2017-09-18 17:03:29 +00:00
return frameTime > BadTime ? 0xFF2222DD :
frameTime > GoodTime ? 0xFF22DDDD :
frameTime > BestTime ? 0xFF22DD22 : 0xFFDD9900 ;
2017-09-18 00:37:25 +00:00
}
2017-09-19 22:05:45 +00:00
static int GetFrameWidth ( int frameScale )
{
2018-04-14 14:50:04 +00:00
return frameScale = = 0 ? 4 : ( frameScale < 0 ? 6 : 1 ) ;
2017-09-19 22:05:45 +00:00
}
static int GetFrameGroup ( int frameScale )
{
return frameScale < 2 ? 1 : ( 1 < < ( frameScale - 1 ) ) ;
}
2017-09-18 00:37:25 +00:00
void View : : DrawFrames ( )
{
2018-08-04 17:47:09 +00:00
assert ( m_worker . GetFrameCount ( * m_frames ) ! = 0 ) ;
2017-09-20 19:21:21 +00:00
2018-06-28 22:35:44 +00:00
const auto Height = 40 * ImGui : : GetTextLineHeight ( ) / 15.f ;
2017-09-18 00:37:25 +00:00
enum { MaxFrameTime = 50 * 1000 * 1000 } ; // 50ms
ImGuiWindow * window = ImGui : : GetCurrentWindow ( ) ;
if ( window - > SkipItems ) return ;
2017-09-18 23:24:31 +00:00
auto & io = ImGui : : GetIO ( ) ;
2017-09-20 00:19:39 +00:00
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
2017-09-18 00:37:25 +00:00
const auto wspace = ImGui : : GetWindowContentRegionMax ( ) - ImGui : : GetWindowContentRegionMin ( ) ;
const auto w = wspace . x ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-09-20 00:19:39 +00:00
ImGui : : InvisibleButton ( " ##frames " , ImVec2 ( w , Height ) ) ;
bool hover = ImGui : : IsItemHovered ( ) ;
2017-09-18 00:37:25 +00:00
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( w , Height ) , 0x33FFFFFF ) ;
2017-09-19 22:08:15 +00:00
const auto wheel = io . MouseWheel ;
const auto prevScale = m_frameScale ;
2017-09-18 20:12:39 +00:00
if ( hover )
2017-09-18 00:37:25 +00:00
{
if ( wheel > 0 )
{
2018-04-14 14:50:04 +00:00
if ( m_frameScale > = 0 ) m_frameScale - - ;
2017-09-18 00:37:25 +00:00
}
else if ( wheel < 0 )
{
if ( m_frameScale < 10 ) m_frameScale + + ;
}
}
2017-09-18 19:26:22 +00:00
2017-09-19 22:05:45 +00:00
const int fwidth = GetFrameWidth ( m_frameScale ) ;
const int group = GetFrameGroup ( m_frameScale ) ;
2018-08-04 17:47:09 +00:00
const int total = m_worker . GetFrameCount ( * m_frames ) ;
2017-09-18 23:24:14 +00:00
const int onScreen = ( w - 2 ) / fwidth ;
2017-09-20 19:21:21 +00:00
if ( ! m_pause )
{
m_frameStart = ( total < onScreen * group ) ? 0 : total - onScreen * group ;
2018-10-21 14:03:21 +00:00
SetViewToLastFrames ( ) ;
2017-09-20 19:21:21 +00:00
}
2017-09-18 19:26:22 +00:00
2017-09-19 19:10:31 +00:00
if ( hover )
2017-09-18 23:24:31 +00:00
{
2017-09-19 19:10:31 +00:00
if ( ImGui : : IsMouseDragging ( 1 , 0 ) )
{
m_pause = true ;
const auto delta = ImGui : : GetMouseDragDelta ( 1 , 0 ) . x ;
if ( abs ( delta ) > = fwidth )
{
const auto d = ( int ) delta / fwidth ;
m_frameStart = std : : max ( 0 , m_frameStart - d * group ) ;
io . MouseClickedPos [ 1 ] . x = io . MousePos . x + d * fwidth - delta ;
}
}
const auto mx = io . MousePos . x ;
if ( mx > wpos . x & & mx < wpos . x + w - 1 )
2017-09-18 23:24:31 +00:00
{
2017-09-19 19:10:31 +00:00
const auto mo = mx - ( wpos . x + 1 ) ;
const auto off = mo * group / fwidth ;
2017-09-19 22:08:15 +00:00
const int sel = m_frameStart + off ;
if ( sel < total )
{
2017-09-19 19:10:31 +00:00
ImGui : : BeginTooltip ( ) ;
if ( group > 1 )
{
2018-08-04 17:47:09 +00:00
auto f = m_worker . GetFrameTime ( * m_frames , sel ) ;
2017-09-19 19:10:31 +00:00
auto g = std : : min ( group , total - sel ) ;
for ( int j = 1 ; j < g ; j + + )
{
2018-08-04 17:47:09 +00:00
f = std : : max ( f , m_worker . GetFrameTime ( * m_frames , sel + j ) ) ;
2017-09-19 19:10:31 +00:00
}
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Frames: " ) ;
2018-06-29 16:43:23 +00:00
ImGui : : SameLine ( ) ;
2018-07-29 19:56:30 +00:00
ImGui : : Text ( " %s - %s (%s) " , RealToString ( sel , true ) , RealToString ( sel + g - 1 , true ) , RealToString ( g , true ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-06-29 16:43:23 +00:00
TextFocused ( " Max frame time: " , TimeToString ( f ) ) ;
2017-09-19 19:10:31 +00:00
}
else
{
2019-06-16 22:59:16 +00:00
m_frameHover = sel ;
2018-08-04 19:46:26 +00:00
if ( m_frames - > name = = 0 )
2017-10-16 23:17:55 +00:00
{
2018-08-04 19:46:26 +00:00
const auto offset = m_worker . GetFrameOffset ( ) ;
if ( sel = = 0 )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Tracy initialization " ) ;
2018-08-04 19:46:26 +00:00
ImGui : : Separator ( ) ;
TextFocused ( " Time: " , TimeToString ( m_worker . GetFrameTime ( * m_frames , sel ) ) ) ;
}
else if ( offset = = 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Frame: " ) ;
2018-08-04 19:46:26 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( RealToString ( sel , true ) ) ;
2018-08-04 19:46:26 +00:00
ImGui : : Separator ( ) ;
TextFocused ( " Frame time: " , TimeToString ( m_worker . GetFrameTime ( * m_frames , sel ) ) ) ;
}
else if ( sel = = 1 )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Missed frames " ) ;
2018-08-04 19:46:26 +00:00
ImGui : : Separator ( ) ;
TextFocused ( " Time: " , TimeToString ( m_worker . GetFrameTime ( * m_frames , 1 ) ) ) ;
}
else
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Frame: " ) ;
2018-08-04 19:46:26 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( RealToString ( sel + offset - 1 , true ) ) ;
2018-08-04 19:46:26 +00:00
ImGui : : Separator ( ) ;
TextFocused ( " Frame time: " , TimeToString ( m_worker . GetFrameTime ( * m_frames , sel ) ) ) ;
}
2018-07-10 20:51:24 +00:00
}
else
{
2018-08-04 19:46:26 +00:00
ImGui : : TextDisabled ( " %s: " , m_worker . GetString ( m_frames - > name ) ) ;
2018-07-10 20:51:24 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( RealToString ( sel + 1 , true ) ) ;
2018-07-10 20:51:24 +00:00
ImGui : : Separator ( ) ;
2018-08-04 17:47:09 +00:00
TextFocused ( " Frame time: " , TimeToString ( m_worker . GetFrameTime ( * m_frames , sel ) ) ) ;
2018-07-10 20:51:24 +00:00
}
2017-09-19 19:10:31 +00:00
}
2018-08-04 17:51:50 +00:00
TextFocused ( " Time from start of program: " , TimeToString ( m_worker . GetFrameBegin ( * m_frames , sel ) - m_worker . GetTimeBegin ( ) ) ) ;
2019-06-06 20:43:39 +00:00
auto fi = m_worker . GetFrameImage ( * m_frames , sel ) ;
if ( fi )
{
if ( fi ! = m_frameTexturePtr )
{
2019-06-06 21:14:49 +00:00
if ( ! m_frameTexture ) m_frameTexture = MakeTexture ( ) ;
2019-06-08 10:17:18 +00:00
UpdateTexture ( m_frameTexture , m_worker . UnpackFrameImage ( * fi ) , fi - > w , fi - > h ) ;
2019-06-06 21:10:01 +00:00
m_frameTexturePtr = fi ;
2019-06-06 20:43:39 +00:00
}
ImGui : : Separator ( ) ;
2019-06-12 13:30:08 +00:00
if ( fi - > flip )
{
ImGui : : Image ( m_frameTexture , ImVec2 ( fi - > w , fi - > h ) , ImVec2 ( 0 , 1 ) , ImVec2 ( 1 , 0 ) ) ;
}
else
{
ImGui : : Image ( m_frameTexture , ImVec2 ( fi - > w , fi - > h ) ) ;
}
2019-06-06 20:43:39 +00:00
}
2017-09-19 19:10:31 +00:00
ImGui : : EndTooltip ( ) ;
2017-09-22 22:46:15 +00:00
2019-06-22 22:11:46 +00:00
if ( io . KeyCtrl )
2017-09-22 22:46:15 +00:00
{
2019-06-22 22:11:46 +00:00
if ( fi & & ImGui : : IsMouseDown ( 0 ) )
{
m_showPlayback = true ;
m_playback . pause = true ;
SetPlaybackFrame ( m_frames - > frames [ sel ] . frameImage ) ;
}
2017-09-22 22:46:15 +00:00
}
2019-06-22 22:11:46 +00:00
else
2017-09-22 22:46:15 +00:00
{
2019-06-22 22:11:46 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_pause = true ;
m_zoomAnim . active = false ;
if ( ! m_playback . pause & & m_playback . sync ) m_playback . pause = true ;
m_zvStart = m_worker . GetFrameBegin ( * m_frames , sel ) ;
m_zvEnd = m_worker . GetFrameEnd ( * m_frames , sel + group - 1 ) ;
if ( m_zvStart = = m_zvEnd ) m_zvStart - - ;
}
else if ( ImGui : : IsMouseDragging ( 0 ) )
{
const auto t0 = std : : min ( m_zvStart , m_worker . GetFrameBegin ( * m_frames , sel ) ) ;
const auto t1 = std : : max ( m_zvEnd , m_worker . GetFrameEnd ( * m_frames , sel + group - 1 ) ) ;
ZoomToRange ( t0 , t1 ) ;
}
2017-09-22 22:46:15 +00:00
}
2017-09-19 19:10:31 +00:00
}
2017-09-19 22:08:15 +00:00
if ( m_pause & & wheel ! = 0 )
{
const int pfwidth = GetFrameWidth ( prevScale ) ;
const int pgroup = GetFrameGroup ( prevScale ) ;
const auto oldoff = mo * pgroup / pfwidth ;
m_frameStart = std : : min ( total , std : : max ( 0 , m_frameStart - int ( off - oldoff ) ) ) ;
}
2017-09-18 23:24:31 +00:00
}
}
2017-09-18 19:32:26 +00:00
int i = 0 , idx = 0 ;
2017-09-18 22:26:40 +00:00
while ( i < onScreen & & m_frameStart + idx < total )
2017-09-18 00:37:25 +00:00
{
2018-08-04 17:47:09 +00:00
auto f = m_worker . GetFrameTime ( * m_frames , m_frameStart + idx ) ;
2017-09-18 20:12:39 +00:00
int g ;
2017-09-18 19:32:26 +00:00
if ( group > 1 )
{
2017-09-18 22:26:40 +00:00
g = std : : min ( group , total - ( m_frameStart + idx ) ) ;
2017-09-18 19:32:26 +00:00
for ( int j = 1 ; j < g ; j + + )
{
2018-08-04 17:47:09 +00:00
f = std : : max ( f , m_worker . GetFrameTime ( * m_frames , m_frameStart + idx + j ) ) ;
2017-09-18 19:32:26 +00:00
}
}
2019-06-22 20:48:32 +00:00
const auto h = std : : max ( 1.f , float ( std : : min < uint64_t > ( MaxFrameTime , f ) ) / MaxFrameTime * ( Height - 2 ) ) ;
2017-09-18 00:37:25 +00:00
if ( fwidth ! = 1 )
{
2017-09-19 19:10:31 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( 1 + i * fwidth , Height - 1 - h ) , wpos + ImVec2 ( fwidth + i * fwidth , Height - 1 ) , GetFrameColor ( f ) ) ;
2017-09-18 00:37:25 +00:00
}
else
{
draw - > AddLine ( wpos + ImVec2 ( 1 + i , Height - 2 - h ) , wpos + ImVec2 ( 1 + i , Height - 2 ) , GetFrameColor ( f ) ) ;
}
2017-09-19 19:10:31 +00:00
2017-09-18 19:26:22 +00:00
i + + ;
2017-09-18 19:32:26 +00:00
idx + = group ;
2017-09-18 00:37:25 +00:00
}
2017-09-20 19:21:29 +00:00
2019-06-22 21:59:57 +00:00
const auto zrange = m_worker . GetFrameRange ( * m_frames , m_zvStart , m_zvEnd ) ;
2018-02-13 13:57:47 +00:00
if ( zrange . second > m_frameStart & & zrange . first < m_frameStart + onScreen * group )
2017-09-20 19:21:29 +00:00
{
2018-02-13 13:57:47 +00:00
auto x1 = std : : min ( onScreen * fwidth , ( zrange . second - m_frameStart ) * fwidth / group ) ;
auto x0 = std : : max ( 0 , ( zrange . first - m_frameStart ) * fwidth / group ) ;
2017-09-20 19:21:29 +00:00
if ( x0 = = x1 ) x1 = x0 + 1 ;
draw - > AddRectFilled ( wpos + ImVec2 ( 1 + x0 , 0 ) , wpos + ImVec2 ( 1 + x1 , Height ) , 0x55DD22DD ) ;
}
2017-09-15 00:30:22 +00:00
}
2017-10-12 20:27:17 +00:00
void View : : HandleZoneViewMouse ( int64_t timespan , const ImVec2 & wpos , float w , double & pxns )
2017-09-20 22:57:26 +00:00
{
2017-10-15 14:42:56 +00:00
assert ( timespan > 0 ) ;
2017-10-12 20:27:17 +00:00
auto & io = ImGui : : GetIO ( ) ;
2017-09-20 22:57:26 +00:00
2017-10-15 14:42:56 +00:00
const auto nspx = double ( timespan ) / w ;
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-03-04 21:21:35 +00:00
m_highlight . active = true ;
m_highlight . start = m_highlight . end = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
2017-10-15 14:42:56 +00:00
}
else if ( ImGui : : IsMouseDragging ( 0 , 0 ) )
{
2018-03-04 21:21:35 +00:00
m_highlight . end = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
2017-10-15 14:42:56 +00:00
}
else
{
2018-03-04 21:21:35 +00:00
m_highlight . active = false ;
2017-10-15 14:42:56 +00:00
}
2018-07-29 18:15:49 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
m_highlightZoom . active = true ;
m_highlightZoom . start = m_highlightZoom . end = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
}
else if ( ImGui : : IsMouseDragging ( 2 , 0 ) )
{
m_highlightZoom . end = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
}
else if ( m_highlightZoom . active )
{
2018-08-04 23:19:08 +00:00
if ( m_highlightZoom . start ! = m_highlightZoom . end )
2018-07-29 18:50:21 +00:00
{
2018-08-04 23:19:08 +00:00
const auto s = std : : min ( m_highlightZoom . start , m_highlightZoom . end ) ;
const auto e = std : : max ( m_highlightZoom . start , m_highlightZoom . end ) ;
// ZoomToRange disables m_highlightZoom.active
if ( io . KeyCtrl )
{
const auto tsOld = m_zvEnd - m_zvStart ;
const auto tsNew = e - s ;
const auto mul = double ( tsOld ) / tsNew ;
const auto left = s - m_zvStart ;
const auto right = m_zvEnd - e ;
2018-07-29 18:50:21 +00:00
2018-08-04 23:19:08 +00:00
ZoomToRange ( m_zvStart - left * mul , m_zvEnd + right * mul ) ;
}
else
{
ZoomToRange ( s , e ) ;
}
2018-07-29 18:50:21 +00:00
}
else
{
2018-08-04 23:19:08 +00:00
m_highlightZoom . active = false ;
2018-07-29 18:50:21 +00:00
}
2018-07-29 18:15:49 +00:00
}
2017-10-12 20:27:17 +00:00
if ( ImGui : : IsMouseDragging ( 1 , 0 ) )
{
m_pause = true ;
2019-06-21 11:08:41 +00:00
m_zoomAnim . active = false ;
if ( ! m_playback . pause & & m_playback . sync ) m_playback . pause = true ;
2017-10-15 14:20:45 +00:00
const auto delta = ImGui : : GetMouseDragDelta ( 1 , 0 ) ;
const auto dpx = int64_t ( delta . x * nspx ) ;
2017-10-12 20:27:17 +00:00
if ( dpx ! = 0 )
{
m_zvStart - = dpx ;
m_zvEnd - = dpx ;
io . MouseClickedPos [ 1 ] . x = io . MousePos . x ;
}
2017-10-15 14:20:45 +00:00
if ( delta . y ! = 0 )
{
auto y = ImGui : : GetScrollY ( ) ;
ImGui : : SetScrollY ( y - delta . y ) ;
io . MouseClickedPos [ 1 ] . y = io . MousePos . y ;
}
2017-10-12 20:27:17 +00:00
}
2017-09-20 22:57:26 +00:00
2017-10-12 20:27:17 +00:00
const auto wheel = io . MouseWheel ;
if ( wheel ! = 0 )
{
const double mouse = io . MousePos . x - wpos . x ;
const auto p = mouse / w ;
2019-03-06 00:15:38 +00:00
2019-04-01 16:39:09 +00:00
int64_t t0 , t1 ;
if ( m_zoomAnim . active )
2017-10-12 20:27:17 +00:00
{
2019-04-01 16:39:09 +00:00
t0 = m_zoomAnim . start1 ;
t1 = m_zoomAnim . end1 ;
2017-10-12 20:27:17 +00:00
}
2019-03-06 00:15:38 +00:00
else
2017-10-12 20:27:17 +00:00
{
2019-04-01 16:39:09 +00:00
t0 = m_zvStart ;
t1 = m_zvEnd ;
}
const auto zoomSpan = t1 - t0 ;
const auto p1 = zoomSpan * p ;
const auto p2 = zoomSpan - p1 ;
if ( wheel > 0 )
{
t0 + = int64_t ( p1 * 0.25 ) ;
t1 - = int64_t ( p2 * 0.25 ) ;
}
else if ( zoomSpan < 1000ll * 1000 * 1000 * 60 * 60 )
{
t0 - = std : : max ( int64_t ( 1 ) , int64_t ( p1 * 0.25 ) ) ;
t1 + = std : : max ( int64_t ( 1 ) , int64_t ( p2 * 0.25 ) ) ;
2017-10-12 20:27:17 +00:00
}
2019-04-01 16:39:09 +00:00
ZoomToRange ( t0 , t1 ) ;
2017-10-12 20:27:17 +00:00
}
}
2018-08-04 19:19:24 +00:00
const char * View : : GetFrameText ( const FrameData & fd , int i , uint64_t ftime , uint64_t offset ) const
2017-10-22 15:48:01 +00:00
{
2018-08-04 19:19:24 +00:00
static char buf [ 1024 ] ;
if ( fd . name = = 0 )
2018-07-10 20:51:24 +00:00
{
2018-08-04 19:19:24 +00:00
if ( i = = 0 )
{
sprintf ( buf , " Tracy init (%s) " , TimeToString ( ftime ) ) ;
}
else if ( offset = = 0 )
{
sprintf ( buf , " Frame %s (%s) " , RealToString ( i , true ) , TimeToString ( ftime ) ) ;
}
else if ( i = = 1 )
{
sprintf ( buf , " Missed frames (%s) " , TimeToString ( ftime ) ) ;
}
else
{
sprintf ( buf , " Frame %s (%s) " , RealToString ( i + offset - 1 , true ) , TimeToString ( ftime ) ) ;
}
2018-07-10 20:51:24 +00:00
}
else
{
2018-08-04 21:21:58 +00:00
sprintf ( buf , " %s %s (%s) " , m_worker . GetString ( fd . name ) , RealToString ( i + 1 , true ) , TimeToString ( ftime ) ) ;
2018-07-10 20:51:24 +00:00
}
2017-10-22 15:48:01 +00:00
return buf ;
}
2018-08-04 19:10:03 +00:00
bool View : : DrawZoneFramesHeader ( )
2017-10-12 20:27:17 +00:00
{
2017-09-20 22:57:26 +00:00
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
2017-10-12 20:27:17 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - ImGui : : GetStyle ( ) . ScrollbarSize ;
2017-09-20 22:57:26 +00:00
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-22 15:48:01 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
2017-09-20 22:57:26 +00:00
2018-08-04 19:10:03 +00:00
ImGui : : InvisibleButton ( " ##zoneFrames " , ImVec2 ( w , ty * 1.5 ) ) ;
2017-09-20 22:57:26 +00:00
bool hover = ImGui : : IsItemHovered ( ) ;
2017-09-20 23:39:07 +00:00
auto timespan = m_zvEnd - m_zvStart ;
auto pxns = w / double ( timespan ) ;
2017-09-20 22:57:26 +00:00
2017-10-12 20:27:17 +00:00
if ( hover ) HandleZoneViewMouse ( timespan , wpos , w , pxns ) ;
2017-09-20 23:13:23 +00:00
2017-11-26 01:18:17 +00:00
{
const auto nspx = 1.0 / pxns ;
const auto scale = std : : max ( 0.0 , round ( log10 ( nspx ) + 2 ) ) ;
const auto step = pow ( 10 , scale ) ;
const auto dx = step * pxns ;
double x = 0 ;
int tw = 0 ;
int tx = 0 ;
int64_t tt = 0 ;
while ( x < w )
{
draw - > AddLine ( wpos + ImVec2 ( x , 0 ) , wpos + ImVec2 ( x , round ( ty * 0.5 ) ) , 0x66FFFFFF ) ;
if ( tw = = 0 )
{
char buf [ 128 ] ;
2018-08-04 17:51:50 +00:00
const auto t = m_zvStart - m_worker . GetTimeBegin ( ) ;
2017-11-26 01:24:13 +00:00
auto txt = TimeToString ( t ) ;
if ( t > = 0 )
{
sprintf ( buf , " +%s " , txt ) ;
txt = buf ;
}
draw - > AddText ( wpos + ImVec2 ( x , round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
2017-11-26 01:18:17 +00:00
}
else if ( x > tx + tw + ty * 2 )
{
tx = x ;
auto txt = TimeToString ( tt ) ;
draw - > AddText ( wpos + ImVec2 ( x , round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
2019-02-10 15:04:04 +00:00
if ( scale ! = 0 )
2017-11-26 01:18:17 +00:00
{
2019-02-10 15:04:04 +00:00
for ( int i = 1 ; i < 5 ; i + + )
{
draw - > AddLine ( wpos + ImVec2 ( x + i * dx / 10 , 0 ) , wpos + ImVec2 ( x + i * dx / 10 , round ( ty * 0.25 ) ) , 0x33FFFFFF ) ;
}
draw - > AddLine ( wpos + ImVec2 ( x + 5 * dx / 10 , 0 ) , wpos + ImVec2 ( x + 5 * dx / 10 , round ( ty * 0.375 ) ) , 0x33FFFFFF ) ;
for ( int i = 6 ; i < 10 ; i + + )
{
draw - > AddLine ( wpos + ImVec2 ( x + i * dx / 10 , 0 ) , wpos + ImVec2 ( x + i * dx / 10 , round ( ty * 0.25 ) ) , 0x33FFFFFF ) ;
}
2017-11-26 01:18:17 +00:00
}
x + = dx ;
tt + = step ;
}
}
2018-08-04 19:10:03 +00:00
return hover ;
}
2018-08-04 21:32:53 +00:00
static uint32_t DarkenColor ( uint32_t color )
{
return 0xFF000000 |
( std : : min < int > ( 0xFF , ( ( ( color & 0x00FF0000 ) > > 16 ) * 2 / 3 ) ) < < 16 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x0000FF00 ) > > 8 ) * 2 / 3 ) ) < < 8 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x000000FF ) ) * 2 / 3 ) ) ) ;
}
2018-08-04 21:11:47 +00:00
static void DrawZigZag ( ImDrawList * draw , const ImVec2 & wpos , double start , double end , double h , uint32_t color )
{
int mode = 0 ;
while ( start < end )
{
double step = std : : min ( end - start , mode = = 0 ? h / 2 : h ) ;
switch ( mode )
{
case 0 :
draw - > AddLine ( wpos + ImVec2 ( start , 0 ) , wpos + ImVec2 ( start + step , round ( - step ) ) , color ) ;
mode = 1 ;
break ;
case 1 :
draw - > AddLine ( wpos + ImVec2 ( start , round ( - h / 2 ) ) , wpos + ImVec2 ( start + step , round ( step - h / 2 ) ) , color ) ;
mode = 2 ;
break ;
case 2 :
draw - > AddLine ( wpos + ImVec2 ( start , round ( h / 2 ) ) , wpos + ImVec2 ( start + step , round ( h / 2 - step ) ) , color ) ;
mode = 1 ;
break ;
default :
assert ( false ) ;
break ;
} ;
start + = step ;
}
}
2018-10-05 19:10:37 +00:00
static uint32_t GetColorMuted ( uint32_t color , bool active )
{
if ( active )
{
return 0xFF000000 | color ;
}
else
{
return 0x66000000 | color ;
}
}
2018-08-04 19:10:03 +00:00
bool View : : DrawZoneFrames ( const FrameData & frames )
{
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - ImGui : : GetStyle ( ) . ScrollbarSize ;
const auto wh = ImGui : : GetContentRegionAvail ( ) . y ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
const auto ty = ImGui : : GetFontSize ( ) ;
ImGui : : InvisibleButton ( " ##zoneFrames " , ImVec2 ( w , ty ) ) ;
bool hover = ImGui : : IsItemHovered ( ) ;
auto timespan = m_zvEnd - m_zvStart ;
auto pxns = w / double ( timespan ) ;
if ( hover ) HandleZoneViewMouse ( timespan , wpos , w , pxns ) ;
2018-08-05 11:29:44 +00:00
const auto nspx = 1.0 / pxns ;
2018-08-04 19:10:03 +00:00
const std : : pair < int , int > zrange = m_worker . GetFrameRange ( frames , m_zvStart , m_zvEnd ) ;
2018-04-14 14:50:04 +00:00
if ( zrange . first < 0 ) return hover ;
2017-09-20 22:57:26 +00:00
2018-08-04 21:11:47 +00:00
int64_t prev = - 1 ;
2018-08-05 11:29:44 +00:00
int64_t prevEnd = - 1 ;
2018-10-05 18:59:00 +00:00
int64_t endPos = - 1 ;
2018-08-05 11:33:18 +00:00
bool tooltipDisplayed = false ;
2018-10-05 19:03:04 +00:00
const auto activeFrameSet = m_frames = = & frames ;
2018-08-04 21:11:47 +00:00
2018-10-05 19:10:37 +00:00
const auto inactiveColor = GetColorMuted ( 0x888888 , activeFrameSet ) ;
const auto activeColor = GetColorMuted ( 0xFFFFFF , activeFrameSet ) ;
const auto redColor = GetColorMuted ( 0x4444FF , activeFrameSet ) ;
2019-05-11 11:47:06 +00:00
int i = zrange . first ;
while ( i < zrange . second )
2017-10-22 15:48:01 +00:00
{
2018-08-04 19:10:03 +00:00
const auto ftime = m_worker . GetFrameTime ( frames , i ) ;
const auto fbegin = m_worker . GetFrameBegin ( frames , i ) ;
const auto fend = m_worker . GetFrameEnd ( frames , i ) ;
2017-10-22 15:48:01 +00:00
const auto fsz = pxns * ftime ;
2018-08-04 19:10:03 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns , 0 ) , wpos + ImVec2 ( ( fend - m_zvStart ) * pxns , ty ) ) )
2017-09-20 23:18:24 +00:00
{
2018-08-05 11:33:18 +00:00
tooltipDisplayed = true ;
2017-10-22 15:48:01 +00:00
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( GetFrameText ( frames , i , ftime , m_worker . GetFrameOffset ( ) ) ) ;
2018-08-04 19:10:03 +00:00
TextFocused ( " Time from start of program: " , TimeToString ( m_worker . GetFrameBegin ( frames , i ) - m_worker . GetTimeBegin ( ) ) ) ;
2019-06-06 20:14:25 +00:00
auto fi = m_worker . GetFrameImage ( frames , i ) ;
if ( fi )
{
if ( fi ! = m_frameTexturePtr )
{
2019-06-06 21:14:49 +00:00
if ( ! m_frameTexture ) m_frameTexture = MakeTexture ( ) ;
2019-06-08 10:17:18 +00:00
UpdateTexture ( m_frameTexture , m_worker . UnpackFrameImage ( * fi ) , fi - > w , fi - > h ) ;
2019-06-06 21:10:01 +00:00
m_frameTexturePtr = fi ;
2019-06-06 20:14:25 +00:00
}
2019-06-06 20:32:20 +00:00
ImGui : : Separator ( ) ;
2019-06-12 13:30:08 +00:00
if ( fi - > flip )
{
ImGui : : Image ( m_frameTexture , ImVec2 ( fi - > w , fi - > h ) , ImVec2 ( 0 , 1 ) , ImVec2 ( 1 , 0 ) ) ;
}
else
{
ImGui : : Image ( m_frameTexture , ImVec2 ( fi - > w , fi - > h ) ) ;
}
2019-06-12 21:14:19 +00:00
2019-06-16 14:49:21 +00:00
if ( ImGui : : GetIO ( ) . KeyCtrl & & ImGui : : IsMouseClicked ( 0 ) )
2019-06-12 21:14:19 +00:00
{
m_showPlayback = true ;
m_playback . pause = true ;
2019-06-12 22:12:06 +00:00
SetPlaybackFrame ( frames . frames [ i ] . frameImage ) ;
2019-06-12 21:14:19 +00:00
}
2019-06-06 20:14:25 +00:00
}
2017-10-22 15:48:01 +00:00
ImGui : : EndTooltip ( ) ;
2017-09-20 23:18:24 +00:00
2017-10-22 15:48:01 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
2017-10-16 23:17:55 +00:00
{
2017-11-27 21:12:26 +00:00
ZoomToRange ( fbegin , fend ) ;
2017-10-16 23:17:55 +00:00
}
2019-06-16 22:59:16 +00:00
if ( activeFrameSet ) m_frameHover = i ;
2017-10-22 15:48:01 +00:00
}
2018-08-05 11:29:44 +00:00
if ( fsz < MinFrameSize )
2018-08-04 21:11:47 +00:00
{
2018-08-05 11:29:44 +00:00
if ( ! frames . continuous & & prev ! = - 1 )
2018-08-05 00:23:26 +00:00
{
2018-08-05 11:29:44 +00:00
if ( ( fbegin - prevEnd ) * pxns > = MinFrameSize )
{
2018-10-05 19:10:37 +00:00
DrawZigZag ( draw , wpos + ImVec2 ( 0 , round ( ty / 2 ) ) , ( prev - m_zvStart ) * pxns , ( prevEnd - m_zvStart ) * pxns , ty / 4 , inactiveColor ) ;
2018-08-05 11:29:44 +00:00
prev = - 1 ;
}
else
2018-08-05 00:23:26 +00:00
{
2018-08-05 11:29:44 +00:00
prevEnd = std : : max < int64_t > ( fend , fbegin + MinFrameSize * nspx ) ;
2018-08-05 00:23:26 +00:00
}
}
2018-08-05 11:29:44 +00:00
if ( prev = = - 1 )
2018-08-05 00:23:26 +00:00
{
prev = fbegin ;
2018-08-05 11:29:44 +00:00
prevEnd = std : : max < int64_t > ( fend , fbegin + MinFrameSize * nspx ) ;
2018-08-05 00:23:26 +00:00
}
2018-08-05 11:29:44 +00:00
2019-05-11 11:47:06 +00:00
const auto begin = frames . frames . begin ( ) + i ;
const auto end = frames . frames . begin ( ) + zrange . second ;
auto it = std : : lower_bound ( begin , end , int64_t ( fbegin + MinVisSize * nspx ) , [ this , & frames ] ( const auto & l , const auto & r ) { return m_worker . GetFrameEnd ( frames , std : : distance ( frames . frames . begin ( ) , & l ) ) < r ; } ) ;
if ( it = = begin ) + + it ;
i + = std : : distance ( begin , it ) ;
2018-08-04 21:11:47 +00:00
continue ;
}
2018-08-05 11:29:44 +00:00
2018-08-04 21:11:47 +00:00
if ( prev ! = - 1 )
{
2018-08-05 11:29:44 +00:00
if ( frames . continuous )
{
2018-10-05 19:10:37 +00:00
DrawZigZag ( draw , wpos + ImVec2 ( 0 , round ( ty / 2 ) ) , ( prev - m_zvStart ) * pxns , ( fbegin - m_zvStart ) * pxns , ty / 4 , inactiveColor ) ;
2018-08-05 11:29:44 +00:00
}
else
{
2018-10-05 19:10:37 +00:00
DrawZigZag ( draw , wpos + ImVec2 ( 0 , round ( ty / 2 ) ) , ( prev - m_zvStart ) * pxns , ( prevEnd - m_zvStart ) * pxns , ty / 4 , inactiveColor ) ;
2018-08-05 11:29:44 +00:00
}
2018-08-04 21:11:47 +00:00
prev = - 1 ;
}
2017-10-22 15:48:01 +00:00
2018-10-05 19:03:04 +00:00
if ( activeFrameSet )
2017-10-22 15:48:01 +00:00
{
2018-10-05 18:59:00 +00:00
if ( fbegin > = m_zvStart & & endPos ! = fbegin )
2018-08-05 00:23:26 +00:00
{
draw - > AddLine ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns , 0 ) , wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns , wh ) , 0x22FFFFFF ) ;
}
2018-10-05 18:59:00 +00:00
if ( fend < = m_zvEnd )
2018-08-05 00:23:26 +00:00
{
draw - > AddLine ( wpos + ImVec2 ( ( fend - m_zvStart ) * pxns , 0 ) , wpos + ImVec2 ( ( fend - m_zvStart ) * pxns , wh ) , 0x22FFFFFF ) ;
}
2018-10-05 18:59:00 +00:00
endPos = fend ;
2017-10-22 15:48:01 +00:00
}
2018-08-04 21:11:47 +00:00
auto buf = GetFrameText ( frames , i , ftime , m_worker . GetFrameOffset ( ) ) ;
auto tx = ImGui : : CalcTextSize ( buf ) . x ;
2018-10-05 19:10:37 +00:00
uint32_t color = ( frames . name = = 0 & & i = = 0 ) ? redColor : activeColor ;
2017-10-22 15:48:01 +00:00
2019-06-22 21:49:30 +00:00
if ( fsz - 7 < = tx )
2018-08-04 21:11:47 +00:00
{
buf = TimeToString ( ftime ) ;
tx = ImGui : : CalcTextSize ( buf ) . x ;
}
2017-10-28 19:55:01 +00:00
2018-08-04 21:11:47 +00:00
if ( fbegin > = m_zvStart )
{
draw - > AddLine ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns + 2 , 1 ) , wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns + 2 , ty - 1 ) , color ) ;
}
if ( fend < = m_zvEnd )
{
draw - > AddLine ( wpos + ImVec2 ( ( fend - m_zvStart ) * pxns - 2 , 1 ) , wpos + ImVec2 ( ( fend - m_zvStart ) * pxns - 2 , ty - 1 ) , color ) ;
}
2019-06-22 21:49:30 +00:00
if ( fsz - 7 > tx )
2018-08-04 21:11:47 +00:00
{
2019-06-22 21:49:30 +00:00
const auto f0 = ( fbegin - m_zvStart ) * pxns + 2 ;
const auto f1 = ( fend - m_zvStart ) * pxns - 2 ;
const auto x0 = f0 + 1 ;
const auto x1 = f1 - 1 ;
const auto te = x1 - tx ;
auto tpos = ( x0 + te ) / 2 ;
if ( tpos < 0 )
{
tpos = std : : min ( std : : min ( 0. , te - tpos ) , te ) ;
}
else if ( tpos > w - tx )
{
tpos = std : : max ( double ( w - tx ) , x0 ) ;
}
tpos = round ( tpos ) ;
draw - > AddLine ( wpos + ImVec2 ( std : : max ( - 10.0 , f0 ) , round ( ty / 2 ) ) , wpos + ImVec2 ( tpos , round ( ty / 2 ) ) , color ) ;
draw - > AddLine ( wpos + ImVec2 ( std : : max ( - 10.0 , tpos + tx + 1 ) , round ( ty / 2 ) ) , wpos + ImVec2 ( std : : min ( w + 20.0 , f1 ) , round ( ty / 2 ) ) , color ) ;
draw - > AddText ( wpos + ImVec2 ( tpos , 0 ) , color , buf ) ;
2017-09-20 22:57:26 +00:00
}
2018-08-04 21:11:47 +00:00
else
{
draw - > AddLine ( wpos + ImVec2 ( std : : max ( - 10.0 , ( fbegin - m_zvStart ) * pxns + 2 ) , round ( ty / 2 ) ) , wpos + ImVec2 ( std : : min ( w + 20.0 , ( fend - m_zvStart ) * pxns - 2 ) , round ( ty / 2 ) ) , color ) ;
}
2019-05-11 11:47:06 +00:00
i + + ;
2018-08-04 21:11:47 +00:00
}
if ( prev ! = - 1 )
{
2018-10-21 15:46:24 +00:00
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 ) ;
}
2017-10-22 15:48:01 +00:00
}
2017-09-20 22:57:26 +00:00
2018-10-21 13:46:02 +00:00
if ( hover )
2018-08-05 11:33:18 +00:00
{
2018-10-21 13:46:02 +00:00
if ( ! tooltipDisplayed )
{
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Frame set: " ) ;
2018-10-21 13:46:02 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( frames . name = = 0 ? " Frames " : m_worker . GetString ( frames . name ) ) ;
2018-10-21 13:46:02 +00:00
ImGui : : EndTooltip ( ) ;
}
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_frames = & frames ;
}
2018-08-05 11:33:18 +00:00
}
2017-10-13 13:26:18 +00:00
return hover ;
2017-10-12 20:27:17 +00:00
}
2019-02-21 20:18:41 +00:00
static float AdjustThreadPosition ( View : : VisData & vis , float wy , int & offset )
{
if ( vis . offset < offset )
{
vis . offset = offset ;
}
else if ( vis . offset > offset )
{
const auto diff = vis . offset - offset ;
const auto move = std : : max ( 2.0 , diff * 10.0 * ImGui : : GetIO ( ) . DeltaTime ) ;
offset = vis . offset = int ( std : : max < double > ( vis . offset - move , offset ) ) ;
}
return offset + wy ;
}
static void AdjustThreadHeight ( View : : VisData & vis , int oldOffset , int & offset )
{
const auto h = offset - oldOffset ;
if ( vis . height > h )
{
vis . height = h ;
offset = oldOffset + vis . height ;
}
else if ( vis . height < h )
{
const auto diff = h - vis . height ;
const auto move = std : : max ( 2.0 , diff * 10.0 * ImGui : : GetIO ( ) . DeltaTime ) ;
vis . height = int ( std : : min < double > ( vis . height + move , h ) ) ;
offset = oldOffset + vis . height ;
}
}
2017-10-12 20:27:17 +00:00
void View : : DrawZones ( )
{
2018-08-05 14:45:34 +00:00
m_msgHighlight . Decay ( nullptr ) ;
m_zoneSrcLocHighlight . Decay ( 0 ) ;
2019-02-17 15:20:56 +00:00
m_lockHoverHighlight . Decay ( InvalidId ) ;
2019-06-16 15:05:56 +00:00
m_zoneHover = nullptr ;
2017-10-14 13:47:06 +00:00
2017-10-12 20:27:17 +00:00
if ( m_zvStart = = m_zvEnd ) return ;
assert ( m_zvStart < m_zvEnd ) ;
2019-01-29 22:11:49 +00:00
if ( ImGui : : GetCurrentWindow ( ) - > SkipItems ) return ;
2017-10-12 20:27:17 +00:00
2017-11-11 22:13:54 +00:00
m_gpuThread = 0 ;
m_gpuStart = 0 ;
m_gpuEnd = 0 ;
2017-10-13 13:26:18 +00:00
const auto linepos = ImGui : : GetCursorScreenPos ( ) ;
const auto lineh = ImGui : : GetContentRegionAvail ( ) . y ;
2019-02-24 17:35:03 +00:00
auto draw = ImGui : : GetWindowDrawList ( ) ;
2019-03-01 00:20:20 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - ImGui : : GetStyle ( ) . ScrollbarSize ;
2019-02-24 17:35:03 +00:00
const auto timespan = m_zvEnd - m_zvStart ;
auto pxns = w / double ( timespan ) ;
{
const auto tbegin = m_worker . GetTimeBegin ( ) ;
const auto tend = m_worker . GetLastTime ( ) ;
if ( tbegin > m_zvStart )
{
draw - > AddRectFilled ( linepos , linepos + ImVec2 ( ( tbegin - m_zvStart ) * pxns , lineh ) , 0x44000000 ) ;
}
if ( tend < m_zvEnd )
{
draw - > AddRectFilled ( linepos + ImVec2 ( ( tend - m_zvStart ) * pxns , 0 ) , linepos + ImVec2 ( w , lineh ) , 0x44000000 ) ;
}
}
2018-08-04 19:10:03 +00:00
bool drawMouseLine = DrawZoneFramesHeader ( ) ;
auto & frames = m_worker . GetFrames ( ) ;
for ( auto fd : frames )
{
2019-02-21 19:24:08 +00:00
if ( Vis ( fd ) . visible )
2018-08-04 19:26:01 +00:00
{
drawMouseLine | = DrawZoneFrames ( * fd ) ;
}
2018-08-04 19:10:03 +00:00
}
2017-10-12 20:27:17 +00:00
2019-06-02 11:58:30 +00:00
const auto yMin = ImGui : : GetCursorScreenPos ( ) . y ;
const auto yMax = linepos . y + lineh ;
2017-10-12 20:27:17 +00:00
ImGui : : BeginChild ( " ##zoneWin " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) , ImGui : : GetContentRegionAvail ( ) . y ) , false , ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_NoScrollWithMouse ) ;
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
const auto h = std : : max < float > ( m_zvHeight , ImGui : : GetContentRegionAvail ( ) . y - 4 ) ; // magic border value
ImGui : : InvisibleButton ( " ##zones " , ImVec2 ( w , h ) ) ;
bool hover = ImGui : : IsItemHovered ( ) ;
2019-06-02 11:40:35 +00:00
draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-12 20:27:17 +00:00
2017-10-13 13:26:18 +00:00
if ( hover )
{
drawMouseLine = true ;
HandleZoneViewMouse ( timespan , wpos , w , pxns ) ;
}
2017-09-21 00:16:01 +00:00
2017-10-28 10:37:34 +00:00
const auto nspx = 1.0 / pxns ;
2017-10-12 17:47:56 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
2017-10-12 20:27:17 +00:00
int offset = 0 ;
2017-10-12 17:47:56 +00:00
const auto to = 9.f ;
const auto th = ( ty - to ) * sqrt ( 3 ) * 0.5 ;
2017-11-11 21:56:05 +00:00
// gpu zones
if ( m_drawGpuZones )
{
2018-02-13 13:57:47 +00:00
for ( size_t i = 0 ; i < m_worker . GetGpuData ( ) . size ( ) ; i + + )
2017-11-11 21:56:05 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & v = m_worker . GetGpuData ( ) [ i ] ;
2019-02-21 19:24:08 +00:00
auto & vis = Vis ( v ) ;
2019-02-21 20:18:41 +00:00
if ( ! vis . visible )
{
vis . height = 0 ;
vis . offset = 0 ;
continue ;
}
2019-02-21 19:24:08 +00:00
bool & showFull = vis . showFull ;
2017-11-11 21:56:05 +00:00
2019-02-21 20:18:41 +00:00
const auto yPos = AdjustThreadPosition ( vis , wpos . y , offset ) ;
const auto oldOffset = offset ;
2019-02-22 23:59:09 +00:00
ImGui : : PushClipRect ( wpos , wpos + ImVec2 ( w , oldOffset + vis . height ) , true ) ;
2019-02-23 00:14:08 +00:00
int depth = 0 ;
offset + = ostep ;
if ( showFull & & ! v - > timeline . empty ( ) & & v - > timeline . front ( ) - > gpuStart ! = std : : numeric_limits < int64_t > : : max ( ) )
2017-11-11 21:56:05 +00:00
{
2019-02-23 00:14:08 +00:00
const auto begin = v - > timeline . front ( ) - > gpuStart ;
const auto drift = GpuDrift ( v ) ;
2019-03-18 17:40:03 +00:00
depth = DispatchGpuZoneLevel ( v - > timeline , hover , pxns , int64_t ( nspx ) , wpos , offset , 0 , v - > thread , yMin , yMax , begin , drift ) ;
2019-02-23 00:14:08 +00:00
offset + = ostep * depth ;
}
offset + = ostep * 0.2f ;
if ( ! m_drawEmptyLabels & & showFull & & depth = = 0 )
{
vis . height = 0 ;
vis . offset = 0 ;
offset = oldOffset ;
}
else if ( yPos + ostep > = yMin & & yPos < = yMax )
{
draw - > AddLine ( wpos + ImVec2 ( 0 , oldOffset + ostep - 1 ) , wpos + ImVec2 ( w , oldOffset + ostep - 1 ) , 0x33FFFFFF ) ;
2018-04-20 20:45:29 +00:00
if ( showFull )
2017-11-17 23:33:53 +00:00
{
2019-02-23 00:14:08 +00:00
draw - > AddTriangleFilled ( wpos + ImVec2 ( to / 2 , oldOffset + to / 2 ) , wpos + ImVec2 ( ty - to / 2 , oldOffset + to / 2 ) , wpos + ImVec2 ( ty * 0.5 , oldOffset + to / 2 + th ) , 0xFFFFAAAA ) ;
2017-11-17 23:33:53 +00:00
}
2018-04-20 20:45:29 +00:00
else
{
2019-02-23 00:14:08 +00:00
draw - > AddTriangle ( wpos + ImVec2 ( to / 2 , oldOffset + to / 2 ) , wpos + ImVec2 ( to / 2 , oldOffset + ty - to / 2 ) , wpos + ImVec2 ( to / 2 + th , oldOffset + ty * 0.5 ) , 0xFF886666 , 2.0f ) ;
2018-04-20 20:45:29 +00:00
}
2018-06-17 16:33:05 +00:00
const bool isVulkan = v - > thread = = 0 ;
2018-04-20 20:45:29 +00:00
char buf [ 64 ] ;
2018-06-17 16:33:05 +00:00
if ( isVulkan )
{
sprintf ( buf , " Vulkan context %zu " , i ) ;
}
else
{
sprintf ( buf , " OpenGL context %zu " , i ) ;
}
2019-06-05 23:40:23 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ty , oldOffset ) , showFull ? 0xFFFFAAAA : 0xFF886666 , buf ) ;
2017-11-17 23:33:53 +00:00
2019-02-23 00:14:08 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , oldOffset ) , wpos + ImVec2 ( ty + ImGui : : CalcTextSize ( buf ) . x , oldOffset + ty ) ) )
2017-11-17 23:56:05 +00:00
{
2018-04-20 20:45:29 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
2017-11-17 23:56:05 +00:00
{
2018-04-20 20:45:29 +00:00
showFull = ! showFull ;
2017-11-17 23:56:05 +00:00
}
2019-02-24 15:51:26 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
const auto t0 = v - > timeline . front ( ) - > gpuStart ;
if ( t0 ! = std : : numeric_limits < int64_t > : : max ( ) )
{
// FIXME
const auto t1 = std : : min ( m_worker . GetLastTime ( ) , m_worker . GetZoneEnd ( * v - > timeline . back ( ) ) ) ;
ZoomToRange ( t0 , t1 ) ;
}
}
2018-04-20 20:45:29 +00:00
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( buf ) ;
2018-04-20 20:45:29 +00:00
ImGui : : Separator ( ) ;
2018-06-17 16:33:05 +00:00
if ( ! isVulkan )
{
2018-06-29 16:46:05 +00:00
TextFocused ( " Thread: " , m_worker . GetThreadString ( v - > thread ) ) ;
2018-06-17 16:33:05 +00:00
}
2018-04-20 20:45:29 +00:00
if ( ! v - > timeline . empty ( ) )
{
const auto t = v - > timeline . front ( ) - > gpuStart ;
if ( t ! = std : : numeric_limits < int64_t > : : max ( ) )
{
2018-08-04 17:51:50 +00:00
TextFocused ( " Appeared at " , TimeToString ( t - m_worker . GetTimeBegin ( ) ) ) ;
2018-04-20 20:45:29 +00:00
}
}
2018-06-29 16:46:05 +00:00
TextFocused ( " Zone count: " , RealToString ( v - > count , true ) ) ;
TextFocused ( " Top-level zones: " , RealToString ( v - > timeline . size ( ) , true ) ) ;
2018-06-17 16:33:05 +00:00
if ( isVulkan )
{
2018-06-29 16:46:05 +00:00
TextFocused ( " Timestamp accuracy: " , TimeToString ( v - > period ) ) ;
2018-06-17 16:33:05 +00:00
}
else
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Query accuracy bits: " ) ;
2018-06-29 16:46:05 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %i " , v - > accuracyBits ) ;
2018-06-17 16:33:05 +00:00
}
2018-04-20 20:45:29 +00:00
ImGui : : EndTooltip ( ) ;
2017-11-17 23:56:05 +00:00
}
2017-11-11 21:56:05 +00:00
}
2019-02-21 20:18:41 +00:00
AdjustThreadHeight ( vis , oldOffset , offset ) ;
ImGui : : PopClipRect ( ) ;
2017-11-11 21:56:05 +00:00
}
}
// zones
2019-03-24 12:37:43 +00:00
const auto & threadData = m_worker . GetThreadData ( ) ;
if ( threadData . size ( ) ! = m_threadOrder . size ( ) )
{
m_threadOrder . reserve ( threadData . size ( ) ) ;
2019-06-22 12:07:26 +00:00
for ( size_t i = m_threadOrder . size ( ) ; i < threadData . size ( ) ; i + + )
2019-03-24 12:37:43 +00:00
{
m_threadOrder . push_back ( threadData [ i ] ) ;
}
}
auto & crash = m_worker . GetCrashEvent ( ) ;
2017-11-11 21:56:05 +00:00
LockHighlight nextLockHighlight { - 1 } ;
2019-03-24 12:37:43 +00:00
for ( const auto & v : m_threadOrder )
2017-09-21 00:16:01 +00:00
{
2019-02-21 19:24:08 +00:00
auto & vis = Vis ( v ) ;
2019-02-21 20:18:41 +00:00
if ( ! vis . visible )
{
vis . height = 0 ;
vis . offset = 0 ;
continue ;
}
2019-06-09 15:46:59 +00:00
bool showFull = vis . showFull ;
2017-10-14 13:03:28 +00:00
2019-02-21 20:18:41 +00:00
const auto yPos = AdjustThreadPosition ( vis , wpos . y , offset ) ;
const auto oldOffset = offset ;
2019-02-22 23:59:09 +00:00
ImGui : : PushClipRect ( wpos , wpos + ImVec2 ( w , offset + vis . height ) , true ) ;
2019-02-23 00:14:08 +00:00
int depth = 0 ;
offset + = ostep ;
if ( showFull )
2018-04-20 20:45:29 +00:00
{
2019-02-23 00:14:08 +00:00
m_lastCpu = - 1 ;
if ( m_drawZones )
{
2019-03-18 17:40:03 +00:00
depth = DispatchZoneLevel ( v - > timeline , hover , pxns , int64_t ( nspx ) , wpos , offset , 0 , yMin , yMax ) ;
2019-02-23 00:14:08 +00:00
offset + = ostep * depth ;
}
if ( m_drawLocks )
{
const auto lockDepth = DrawLocks ( v - > id , hover , pxns , wpos , offset , nextLockHighlight , yMin , yMax ) ;
offset + = ostep * lockDepth ;
depth + = lockDepth ;
}
}
offset + = ostep * 0.2f ;
auto msgit = std : : lower_bound ( v - > messages . begin ( ) , v - > messages . end ( ) , m_zvStart , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
2019-03-01 00:30:56 +00:00
auto msgend = std : : lower_bound ( msgit , v - > messages . end ( ) , m_zvEnd + 1 , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
2019-02-23 00:14:08 +00:00
2019-02-23 00:34:45 +00:00
if ( ! m_drawEmptyLabels & & showFull & & depth = = 0 & & msgit = = msgend & & crash . thread ! = v - > id )
2019-02-23 00:14:08 +00:00
{
2019-06-09 15:51:37 +00:00
auto & vis = Vis ( v ) ;
2019-02-23 00:14:08 +00:00
vis . height = 0 ;
vis . offset = 0 ;
offset = oldOffset ;
}
else if ( yPos + ostep > = yMin & & yPos < = yMax )
{
draw - > AddLine ( wpos + ImVec2 ( 0 , oldOffset + ostep - 1 ) , wpos + ImVec2 ( w , oldOffset + ostep - 1 ) , 0x33FFFFFF ) ;
2017-10-14 13:03:28 +00:00
2018-08-20 00:36:58 +00:00
const auto labelColor = crash . thread = = v - > id ? ( showFull ? 0xFF2222FF : 0xFF111188 ) : ( showFull ? 0xFFFFFFFF : 0xFF888888 ) ;
2018-04-20 20:45:29 +00:00
if ( showFull )
2017-10-14 13:03:28 +00:00
{
2019-02-23 00:14:08 +00:00
draw - > AddTriangleFilled ( wpos + ImVec2 ( to / 2 , oldOffset + to / 2 ) , wpos + ImVec2 ( ty - to / 2 , oldOffset + to / 2 ) , wpos + ImVec2 ( ty * 0.5 , oldOffset + to / 2 + th ) , labelColor ) ;
2018-04-20 20:45:29 +00:00
2019-02-23 00:14:08 +00:00
while ( msgit < msgend )
2017-10-14 13:03:28 +00:00
{
2019-02-23 00:14:08 +00:00
const auto next = std : : upper_bound ( msgit , v - > messages . end ( ) , ( * msgit ) - > time + MinVisSize * nspx , [ ] ( const auto & lhs , const auto & rhs ) { return lhs < rhs - > time ; } ) ;
const auto dist = std : : distance ( msgit , next ) ;
2018-04-20 20:45:29 +00:00
2019-02-23 00:14:08 +00:00
const auto px = ( ( * msgit ) - > time - m_zvStart ) * pxns ;
2019-06-21 12:25:51 +00:00
const bool isMsgHovered = hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 - 1 , oldOffset ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 + 1 , oldOffset + ty ) ) ;
unsigned int color = 0xFFDDDDDD ;
float animOff = 0 ;
2017-10-28 10:37:34 +00:00
if ( dist > 1 )
{
2018-10-05 18:39:42 +00:00
if ( m_msgHighlight & & m_msgHighlight - > thread = = v - > id )
{
const auto hTime = m_msgHighlight - > time ;
2019-02-23 00:14:08 +00:00
if ( ( * msgit ) - > time < = hTime & & ( next = = v - > messages . end ( ) | | ( * next ) - > time > hTime ) )
2018-10-05 18:39:42 +00:00
{
color = 0xFF4444FF ;
2019-06-21 12:25:51 +00:00
if ( ! isMsgHovered )
{
animOff = - fabs ( sin ( s_time * 8 ) ) * th ;
}
2018-10-05 18:39:42 +00:00
}
}
2019-06-21 12:25:51 +00:00
draw - > AddTriangleFilled ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 , animOff + oldOffset + to ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 , animOff + oldOffset + to ) , wpos + ImVec2 ( px , animOff + oldOffset + to + th ) , color ) ;
draw - > AddTriangle ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 , animOff + oldOffset + to ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 , animOff + oldOffset + to ) , wpos + ImVec2 ( px , animOff + oldOffset + to + th ) , color , 2.0f ) ;
2018-08-05 14:37:51 +00:00
}
else
{
2019-06-21 12:25:51 +00:00
if ( m_msgHighlight = = * msgit )
{
color = 0xFF4444FF ;
if ( ! isMsgHovered )
{
animOff = - fabs ( sin ( s_time * 8 ) ) * th ;
}
}
draw - > AddTriangle ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 , animOff + oldOffset + to ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 , animOff + oldOffset + to ) , wpos + ImVec2 ( px , animOff + oldOffset + to + th ) , color , 2.0f ) ;
2017-10-28 10:37:34 +00:00
}
2019-06-21 12:25:51 +00:00
if ( isMsgHovered )
2017-10-28 10:37:34 +00:00
{
2018-04-20 20:45:29 +00:00
ImGui : : BeginTooltip ( ) ;
if ( dist > 1 )
{
ImGui : : Text ( " %i messages " , ( int ) dist ) ;
}
else
{
2019-05-10 18:36:06 +00:00
TextFocused ( " Message at " , TimeToString ( ( * msgit ) - > time - m_worker . GetTimeBegin ( ) ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_Text , ( * msgit ) - > color ) ;
ImGui : : TextUnformatted ( m_worker . GetString ( ( * msgit ) - > ref ) ) ;
ImGui : : PopStyleColor ( ) ;
2018-04-20 20:45:29 +00:00
}
ImGui : : EndTooltip ( ) ;
2019-02-23 00:14:08 +00:00
m_msgHighlight = * msgit ;
2018-08-05 14:47:27 +00:00
2018-08-05 14:57:21 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_showMessages = true ;
2019-02-23 00:14:08 +00:00
m_msgToFocus = * msgit ;
2018-08-05 14:57:21 +00:00
}
2018-08-05 14:47:27 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
2019-02-23 00:14:08 +00:00
CenterAtTime ( ( * msgit ) - > time ) ;
2018-08-05 14:47:27 +00:00
}
2017-10-28 10:37:34 +00:00
}
2019-02-23 00:14:08 +00:00
msgit = next ;
2017-10-14 13:03:28 +00:00
}
2018-08-20 01:00:45 +00:00
if ( crash . thread = = v - > id & & crash . time > = m_zvStart & & crash . time < = m_zvEnd )
{
const auto px = ( crash . time - m_zvStart ) * pxns ;
2019-02-23 00:14:08 +00:00
draw - > AddTriangleFilled ( wpos + ImVec2 ( px - ( ty - to ) * 0.25f , oldOffset + to + th * 0.5f ) , wpos + ImVec2 ( px + ( ty - to ) * 0.25f , oldOffset + to + th * 0.5f ) , wpos + ImVec2 ( px , oldOffset + to + th ) , 0xFF2222FF ) ;
draw - > AddTriangle ( wpos + ImVec2 ( px - ( ty - to ) * 0.25f , oldOffset + to + th * 0.5f ) , wpos + ImVec2 ( px + ( ty - to ) * 0.25f , oldOffset + to + th * 0.5f ) , wpos + ImVec2 ( px , oldOffset + to + th ) , 0xFF2222FF , 2.0f ) ;
2018-08-20 01:00:45 +00:00
# ifdef TRACY_EXTENDED_FONT
const auto crashText = ICON_FA_SKULL " crash " ICON_FA_SKULL ;
# else
const auto crashText = " crash " ;
# endif
auto ctw = ImGui : : CalcTextSize ( crashText ) . x ;
2019-06-05 23:40:23 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( px - ctw * 0.5f , oldOffset + to + th * 0.5f - ty ) , 0xFF2222FF , crashText ) ;
2018-08-20 01:00:45 +00:00
2019-02-23 00:14:08 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 - 1 , oldOffset ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 + 1 , oldOffset + ty ) ) )
2018-08-20 01:00:45 +00:00
{
ImGui : : BeginTooltip ( ) ;
TextFocused ( " Time: " , TimeToString ( crash . time - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Reason: " , m_worker . GetString ( crash . message ) ) ;
ImGui : : EndTooltip ( ) ;
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_showInfo = true ;
}
2019-03-24 22:50:33 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
CenterAtTime ( crash . time ) ;
}
2018-08-20 01:00:45 +00:00
}
}
2017-10-14 13:03:28 +00:00
}
2018-04-20 20:45:29 +00:00
else
2017-11-18 00:03:40 +00:00
{
2019-02-23 00:14:08 +00:00
draw - > AddTriangle ( wpos + ImVec2 ( to / 2 , oldOffset + to / 2 ) , wpos + ImVec2 ( to / 2 , oldOffset + ty - to / 2 ) , wpos + ImVec2 ( to / 2 + th , oldOffset + ty * 0.5 ) , labelColor , 2.0f ) ;
2017-11-18 00:03:40 +00:00
}
2018-04-20 20:45:29 +00:00
const auto txt = m_worker . GetThreadString ( v - > id ) ;
const auto txtsz = ImGui : : CalcTextSize ( txt ) ;
if ( m_gpuThread = = v - > id )
2017-11-18 00:03:40 +00:00
{
2019-02-23 00:14:08 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , oldOffset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , oldOffset + ty ) , 0x448888DD ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , oldOffset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , oldOffset + ty ) , 0x888888DD ) ;
2017-11-18 00:03:40 +00:00
}
2018-04-20 20:45:29 +00:00
if ( m_gpuInfoWindow & & m_gpuInfoWindowThread = = v - > id )
{
2019-02-23 00:14:08 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , oldOffset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , oldOffset + ty ) , 0x4488DD88 ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , oldOffset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , oldOffset + ty ) , 0x8888DD88 ) ;
2018-04-20 20:45:29 +00:00
}
2019-06-05 23:40:23 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ty , oldOffset ) , labelColor , txt ) ;
2017-11-18 00:03:40 +00:00
2019-02-23 00:14:08 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , oldOffset ) , wpos + ImVec2 ( ty + txtsz . x , oldOffset + ty ) ) )
2018-04-20 20:45:29 +00:00
{
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetThreadString ( v - > id ) ) ;
2019-01-23 17:15:19 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIx64 " ) " , v - > id ) ;
2018-08-20 12:37:14 +00:00
if ( crash . thread = = v - > id )
{
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , ICON_FA_SKULL " Crashed " ) ;
2018-08-20 12:37:14 +00:00
# else
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , " Crashed " ) ;
2018-08-20 12:37:14 +00:00
# endif
}
2019-02-24 15:01:58 +00:00
ImGui : : Separator ( ) ;
int64_t first = std : : numeric_limits < int64_t > : : max ( ) ;
int64_t last = - 1 ;
if ( ! v - > timeline . empty ( ) )
{
first = v - > timeline . front ( ) - > start ;
last = m_worker . GetZoneEnd ( * v - > timeline . back ( ) ) ;
}
if ( ! v - > messages . empty ( ) )
{
first = std : : min ( first , v - > messages . front ( ) - > time ) ;
last = std : : max ( last , v - > messages . back ( ) - > time ) ;
}
2019-02-24 15:06:31 +00:00
size_t lockCnt = 0 ;
2019-02-24 15:01:58 +00:00
for ( const auto & lock : m_worker . GetLockMap ( ) )
{
2019-03-16 01:09:50 +00:00
const auto & lockmap = * lock . second ;
2019-02-24 15:01:58 +00:00
if ( ! lockmap . valid ) continue ;
auto it = lockmap . threadMap . find ( v - > id ) ;
if ( it = = lockmap . threadMap . end ( ) ) continue ;
2019-02-24 15:06:31 +00:00
lockCnt + + ;
2019-02-24 15:01:58 +00:00
const auto thread = it - > second ;
2019-02-24 16:30:18 +00:00
auto lptr = lockmap . timeline . data ( ) ;
auto eptr = lptr + lockmap . timeline . size ( ) - 1 ;
2019-03-16 13:18:43 +00:00
while ( lptr - > ptr - > thread ! = thread ) lptr + + ;
if ( lptr - > ptr - > time < first ) first = lptr - > ptr - > time ;
while ( eptr - > ptr - > thread ! = thread ) eptr - - ;
if ( eptr - > ptr - > time > last ) last = eptr - > ptr - > time ;
2019-02-24 15:01:58 +00:00
}
if ( last > = 0 )
{
const auto activity = last - first ;
const auto traceLen = m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ;
TextFocused ( " Appeared at " , TimeToString ( first - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Last event at " , TimeToString ( last - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Activity time: " , TimeToString ( activity ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , activity / double ( traceLen ) * 100 ) ;
}
2019-02-24 15:06:31 +00:00
ImGui : : Separator ( ) ;
2018-04-20 20:45:29 +00:00
if ( ! v - > timeline . empty ( ) )
{
2018-06-29 16:46:05 +00:00
TextFocused ( " Zone count: " , RealToString ( v - > count , true ) ) ;
TextFocused ( " Top-level zones: " , RealToString ( v - > timeline . size ( ) , true ) ) ;
2018-04-20 20:45:29 +00:00
}
2019-02-24 15:06:31 +00:00
if ( ! v - > messages . empty ( ) )
{
TextFocused ( " Messages: " , RealToString ( v - > messages . size ( ) , true ) ) ;
}
if ( lockCnt ! = 0 )
{
TextFocused ( " Locks: " , RealToString ( lockCnt , true ) ) ;
}
2018-04-20 20:45:29 +00:00
ImGui : : EndTooltip ( ) ;
2019-02-24 15:51:26 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2019-06-09 15:46:59 +00:00
Vis ( v ) . showFull = ! showFull ;
2019-02-24 15:51:26 +00:00
}
if ( last > = 0 & & ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToRange ( first , last ) ;
}
2018-04-20 20:45:29 +00:00
}
2017-10-12 17:47:56 +00:00
}
2019-06-09 15:51:37 +00:00
AdjustThreadHeight ( Vis ( v ) , oldOffset , offset ) ;
2019-02-21 20:18:41 +00:00
ImGui : : PopClipRect ( ) ;
2017-09-23 22:07:06 +00:00
}
2017-10-06 00:19:25 +00:00
m_lockHighlight = nextLockHighlight ;
2017-10-12 20:27:17 +00:00
2017-10-13 12:54:32 +00:00
if ( m_drawPlots )
{
2018-04-20 21:00:26 +00:00
offset = DrawPlots ( offset , pxns , wpos , hover , yMin , yMax ) ;
2017-10-13 12:54:32 +00:00
}
2017-10-12 20:27:17 +00:00
const auto scrollPos = ImGui : : GetScrollY ( ) ;
if ( scrollPos = = 0 & & m_zvScroll ! = 0 )
{
m_zvHeight = 0 ;
}
else
{
if ( offset > m_zvHeight ) m_zvHeight = offset ;
}
m_zvScroll = scrollPos ;
ImGui : : EndChild ( ) ;
2017-10-13 13:26:18 +00:00
2017-11-18 12:40:49 +00:00
if ( m_gpuStart ! = 0 & & m_gpuEnd ! = 0 )
2017-11-11 22:13:54 +00:00
{
const auto px0 = ( m_gpuStart - m_zvStart ) * pxns ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( px0 + std : : max ( 1.0 , pxns * 0.5 ) , ( m_gpuEnd - m_zvStart ) * pxns ) ;
2017-11-11 22:13:54 +00:00
draw - > AddRectFilled ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x228888DD ) ;
draw - > AddRect ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x448888DD ) ;
}
2017-11-12 00:32:21 +00:00
if ( m_gpuInfoWindow )
{
const auto px0 = ( m_gpuInfoWindow - > cpuStart - m_zvStart ) * pxns ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( px0 + std : : max ( 1.0 , pxns * 0.5 ) , ( m_gpuInfoWindow - > cpuEnd - m_zvStart ) * pxns ) ;
2017-11-12 00:32:21 +00:00
draw - > AddRectFilled ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x2288DD88 ) ;
draw - > AddRect ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x4488DD88 ) ;
}
2017-11-11 22:13:54 +00:00
2018-03-04 21:21:35 +00:00
if ( m_highlight . active & & m_highlight . start ! = m_highlight . end )
2017-10-15 14:42:56 +00:00
{
2018-03-04 21:21:35 +00:00
const auto s = std : : min ( m_highlight . start , m_highlight . end ) ;
const auto e = std : : max ( m_highlight . start , m_highlight . end ) ;
2017-10-15 14:42:56 +00:00
draw - > AddRectFilled ( ImVec2 ( wpos . x + ( s - m_zvStart ) * pxns , linepos . y ) , ImVec2 ( wpos . x + ( e - m_zvStart ) * pxns , linepos . y + lineh ) , 0x22DD8888 ) ;
draw - > AddRect ( ImVec2 ( wpos . x + ( s - m_zvStart ) * pxns , linepos . y ) , ImVec2 ( wpos . x + ( e - m_zvStart ) * pxns , linepos . y + lineh ) , 0x44DD8888 ) ;
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( TimeToString ( e - s ) ) ;
2017-10-15 14:42:56 +00:00
ImGui : : EndTooltip ( ) ;
}
else if ( drawMouseLine )
2017-10-13 13:26:18 +00:00
{
auto & io = ImGui : : GetIO ( ) ;
draw - > AddLine ( ImVec2 ( io . MousePos . x , linepos . y ) , ImVec2 ( io . MousePos . x , linepos . y + lineh ) , 0x33FFFFFF ) ;
}
2018-04-02 14:21:24 +00:00
2018-07-29 18:15:49 +00:00
if ( m_highlightZoom . active & & m_highlightZoom . start ! = m_highlightZoom . end )
{
const auto s = std : : min ( m_highlightZoom . start , m_highlightZoom . end ) ;
const auto e = std : : max ( m_highlightZoom . start , m_highlightZoom . end ) ;
draw - > AddRectFilled ( ImVec2 ( wpos . x + ( s - m_zvStart ) * pxns , linepos . y ) , ImVec2 ( wpos . x + ( e - m_zvStart ) * pxns , linepos . y + lineh ) , 0x1688DD88 ) ;
draw - > AddRect ( ImVec2 ( wpos . x + ( s - m_zvStart ) * pxns , linepos . y ) , ImVec2 ( wpos . x + ( e - m_zvStart ) * pxns , linepos . y + lineh ) , 0x2C88DD88 ) ;
}
2018-04-02 14:21:24 +00:00
if ( m_memInfo . show & & m_memInfo . restrictTime )
{
const auto zvMid = ( m_zvEnd - m_zvStart ) / 2 ;
draw - > AddLine ( ImVec2 ( wpos . x + zvMid * pxns , linepos . y ) , ImVec2 ( wpos . x + zvMid * pxns , linepos . y + lineh ) , 0x88FF44FF ) ;
}
2017-09-23 22:07:06 +00:00
}
2019-03-18 17:40:03 +00:00
int View : : DispatchZoneLevel ( const Vector < ZoneEvent * > & vec , bool hover , double pxns , int64_t nspx , const ImVec2 & wpos , int _offset , int depth , float yMin , float yMax )
2018-04-20 21:19:04 +00:00
{
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
const auto offset = _offset + ostep * depth ;
const auto yPos = wpos . y + offset ;
if ( yPos + ostep > = yMin & & yPos < = yMax )
{
2019-03-18 17:40:03 +00:00
return DrawZoneLevel ( vec , hover , pxns , nspx , wpos , _offset , depth , yMin , yMax ) ;
2018-04-20 21:19:04 +00:00
}
else
{
2019-03-18 17:40:03 +00:00
return SkipZoneLevel ( vec , hover , pxns , nspx , wpos , _offset , depth , yMin , yMax ) ;
2018-04-20 21:19:04 +00:00
}
}
2019-03-18 17:40:03 +00:00
int View : : DrawZoneLevel ( const Vector < ZoneEvent * > & vec , bool hover , double pxns , int64_t nspx , const ImVec2 & wpos , int _offset , int depth , float yMin , float yMax )
2017-09-23 22:07:06 +00:00
{
2018-02-13 13:57:47 +00:00
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
2017-10-28 20:20:39 +00:00
// cast to uint64_t, so that unended zones (end = -1) are still drawn
2018-02-13 13:57:47 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - delay , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > end < ( uint64_t ) r ; } ) ;
2017-10-12 17:14:03 +00:00
if ( it = = vec . end ( ) ) return depth ;
2018-02-13 13:57:47 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + resolution , [ ] ( const auto & l , const auto & r ) { return l - > start < r ; } ) ;
2017-10-12 17:14:03 +00:00
if ( it = = zitend ) return depth ;
2018-10-06 10:52:05 +00:00
if ( ( * it ) - > end < 0 & & m_worker . GetZoneEnd ( * * it ) < m_zvStart ) return depth ;
2017-10-12 17:14:03 +00:00
2017-10-12 20:27:17 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
2017-10-12 17:14:03 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
const auto offset = _offset + ostep * depth ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2018-02-13 13:57:47 +00:00
const auto dsz = delay * pxns ;
const auto rsz = resolution * pxns ;
2017-10-12 17:14:03 +00:00
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
2017-09-23 22:07:06 +00:00
{
2017-10-12 17:14:03 +00:00
auto & ev = * * it ;
2017-11-11 21:56:05 +00:00
const auto color = GetZoneColor ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-18 12:40:49 +00:00
const auto zsz = std : : max ( ( end - ev . start ) * pxns , pxns * 0.5 ) ;
2017-10-12 17:14:03 +00:00
if ( zsz < MinVisSize )
2017-09-21 00:16:01 +00:00
{
2019-03-18 17:24:27 +00:00
int num = 0 ;
2017-10-12 17:14:03 +00:00
const auto px0 = ( ev . start - m_zvStart ) * pxns ;
auto px1 = ( end - m_zvStart ) * pxns ;
auto rend = end ;
2019-03-18 18:39:37 +00:00
auto nextTime = end + MinVisSize ;
2017-10-12 17:14:03 +00:00
for ( ; ; )
2017-09-21 20:12:19 +00:00
{
2019-03-18 17:24:27 +00:00
const auto prevIt = it ;
2019-03-18 18:39:37 +00:00
it = std : : lower_bound ( it , zitend , nextTime , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > end < ( uint64_t ) r ; } ) ;
2019-03-18 17:24:27 +00:00
if ( it = = prevIt ) + + it ;
num + = std : : distance ( prevIt , it ) ;
2017-10-12 17:14:03 +00:00
if ( it = = zitend ) break ;
2018-02-13 13:57:47 +00:00
const auto nend = m_worker . GetZoneEnd ( * * it ) ;
2017-10-12 17:14:03 +00:00
const auto pxnext = ( nend - m_zvStart ) * pxns ;
if ( pxnext - px1 > = MinVisSize * 2 ) break ;
px1 = pxnext ;
rend = nend ;
2019-03-18 18:39:37 +00:00
nextTime = nend + nspx ;
2017-10-12 17:14:03 +00:00
}
2017-11-07 20:48:24 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) , color ) ;
2018-08-04 21:32:53 +00:00
DrawZigZag ( draw , wpos + ImVec2 ( 0 , offset + ty / 2 ) , std : : max ( px0 , - 10.0 ) , std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , ty / 4 , DarkenColor ( color ) ) ;
2017-10-28 14:14:52 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) ) )
2017-10-12 17:14:03 +00:00
{
2017-11-07 20:51:21 +00:00
if ( num > 1 )
{
ImGui : : BeginTooltip ( ) ;
2018-06-29 16:47:33 +00:00
TextFocused ( " Zones too small to display: " , RealToString ( num , true ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-06-29 16:47:33 +00:00
TextFocused ( " Execution time: " , TimeToString ( rend - ev . start ) ) ;
2017-11-07 20:51:21 +00:00
ImGui : : EndTooltip ( ) ;
2017-09-26 20:08:58 +00:00
2017-11-07 20:51:21 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - ev . start > 0 )
{
2017-11-27 21:12:26 +00:00
ZoomToRange ( ev . start , rend ) ;
2017-11-07 20:51:21 +00:00
}
}
else
2017-09-29 17:13:53 +00:00
{
2017-11-07 20:51:21 +00:00
ZoneTooltip ( ev ) ;
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - ev . start > 0 )
{
ZoomToZone ( ev ) ;
}
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2019-06-16 15:00:25 +00:00
if ( ImGui : : GetIO ( ) . KeyCtrl )
{
auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
m_findZone . ShowZone ( ev . srcloc , m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ) ;
}
else
{
ShowZoneInfo ( ev ) ;
}
2017-11-07 20:51:21 +00:00
}
2018-07-28 17:53:11 +00:00
m_zoneSrcLocHighlight = ev . srcloc ;
2019-06-16 15:05:56 +00:00
m_zoneHover = & ev ;
2017-09-29 17:13:53 +00:00
}
2017-09-23 22:07:06 +00:00
}
2018-07-15 23:24:43 +00:00
char tmp [ 64 ] ;
sprintf ( tmp , " %s " , RealToString ( num , true ) ) ;
2017-10-12 17:14:03 +00:00
const auto tsz = ImGui : : CalcTextSize ( tmp ) ;
if ( tsz . x < px1 - px0 )
{
const auto x = px0 + ( px1 - px0 - tsz . x ) / 2 ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFF4488DD , tmp ) ;
2017-10-12 17:14:03 +00:00
}
}
else
{
2018-06-29 13:14:20 +00:00
const char * zoneName = m_worker . GetZoneName ( ev ) ;
2017-11-14 22:31:24 +00:00
int dmul = ev . text . active ? 2 : 1 ;
2017-09-29 16:40:55 +00:00
2017-10-12 17:14:03 +00:00
bool migration = false ;
if ( m_lastCpu ! = ev . cpu_start )
{
2018-04-14 14:50:04 +00:00
if ( m_lastCpu > = 0 )
2017-10-01 17:58:53 +00:00
{
2017-10-12 17:14:03 +00:00
migration = true ;
2017-10-01 17:58:53 +00:00
}
2017-10-12 17:14:03 +00:00
m_lastCpu = ev . cpu_start ;
}
2017-10-01 17:58:53 +00:00
2018-07-22 14:05:50 +00:00
if ( ev . child > = 0 )
2017-10-12 17:14:03 +00:00
{
2019-03-18 17:40:03 +00:00
const auto d = DispatchZoneLevel ( m_worker . GetZoneChildren ( ev . child ) , hover , pxns , nspx , wpos , _offset , depth , yMin , yMax ) ;
2017-10-12 17:14:03 +00:00
if ( d > maxdepth ) maxdepth = d ;
}
2017-10-01 17:58:53 +00:00
2018-03-24 01:00:20 +00:00
if ( ev . end > = 0 & & m_lastCpu ! = ev . cpu_end )
2017-10-12 17:14:03 +00:00
{
m_lastCpu = ev . cpu_end ;
migration = true ;
}
2017-10-01 17:58:53 +00:00
2017-10-22 11:56:05 +00:00
auto tsz = ImGui : : CalcTextSize ( zoneName ) ;
if ( tsz . x > zsz )
{
zoneName = ShortenNamespace ( zoneName ) ;
tsz = ImGui : : CalcTextSize ( zoneName ) ;
}
2017-10-12 17:14:03 +00:00
const auto pr0 = ( ev . start - m_zvStart ) * pxns ;
const auto pr1 = ( end - m_zvStart ) * pxns ;
const auto px0 = std : : max ( pr0 , - 10.0 ) ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( { std : : min ( pr1 , double ( w + 10 ) ) , px0 + pxns * 0.5 , px0 + MinVisSize } ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , color ) ;
draw - > AddRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , GetZoneHighlight ( ev , migration ) , 0.f , - 1 , GetZoneThickness ( ev ) ) ;
2019-05-10 00:27:42 +00:00
if ( dsz * dmul > MinVisSize )
2017-10-12 17:14:03 +00:00
{
2019-05-10 00:27:42 +00:00
const auto diff = dsz * dmul - MinVisSize ;
uint32_t color ;
if ( diff < 1 )
{
color = ( uint32_t ( diff * 0x88 ) < < 24 ) | 0x2222DD ;
}
else
{
color = 0x882222DD ;
}
draw - > AddRectFilled ( wpos + ImVec2 ( pr0 , offset ) , wpos + ImVec2 ( std : : min ( pr0 + dsz * dmul , pr1 ) , offset + tsz . y ) , color ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( pr1 , offset ) , wpos + ImVec2 ( pr1 + dsz , offset + tsz . y ) , color ) ;
2017-10-12 17:14:03 +00:00
}
2019-05-10 00:27:42 +00:00
if ( rsz > MinVisSize )
2017-10-12 17:14:03 +00:00
{
2019-05-10 00:27:42 +00:00
const auto diff = rsz - MinVisSize ;
uint32_t color ;
if ( diff < 1 )
{
color = ( uint32_t ( diff * 0xAA ) < < 24 ) | 0xFFFFFF ;
}
else
{
color = 0xAAFFFFFF ;
}
draw - > AddLine ( wpos + ImVec2 ( pr0 + rsz , offset + round ( tsz . y / 2 ) ) , wpos + ImVec2 ( pr0 - rsz , offset + round ( tsz . y / 2 ) ) , color ) ;
draw - > AddLine ( wpos + ImVec2 ( pr0 + rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr0 + rsz , offset + round ( 3 * tsz . y / 4 ) ) , color ) ;
draw - > AddLine ( wpos + ImVec2 ( pr0 - rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr0 - rsz , offset + round ( 3 * tsz . y / 4 ) ) , color ) ;
2017-09-29 16:55:21 +00:00
2019-05-10 00:27:42 +00:00
draw - > AddLine ( wpos + ImVec2 ( pr1 + rsz , offset + round ( tsz . y / 2 ) ) , wpos + ImVec2 ( pr1 - rsz , offset + round ( tsz . y / 2 ) ) , color ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 + rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr1 + rsz , offset + round ( 3 * tsz . y / 4 ) ) , color ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 - rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr1 - rsz , offset + round ( 3 * tsz . y / 4 ) ) , color ) ;
2017-10-12 17:14:03 +00:00
}
if ( tsz . x < zsz )
{
const auto x = ( ev . start - m_zvStart ) * pxns + ( ( end - ev . start ) * pxns - tsz . x ) / 2 ;
if ( x < 0 | | x > w - tsz . x )
2017-09-24 14:25:07 +00:00
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( std : : max ( std : : max ( 0. , px0 ) , std : : min ( double ( w - tsz . x ) , x ) ) , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-10-12 17:14:03 +00:00
ImGui : : PopClipRect ( ) ;
2017-09-24 14:25:07 +00:00
}
2017-11-18 12:40:49 +00:00
else if ( ev . start = = ev . end )
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( px0 + ( px1 - px0 - tsz . x ) * 0.5 , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-18 12:40:49 +00:00
}
2017-09-24 14:25:07 +00:00
else
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-09-24 14:25:07 +00:00
}
2017-10-12 17:14:03 +00:00
}
else
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ( ev . start - m_zvStart ) * pxns , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-10-12 17:14:03 +00:00
ImGui : : PopClipRect ( ) ;
}
2017-09-21 00:16:01 +00:00
2017-11-18 12:40:49 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) ) )
2017-10-12 17:14:03 +00:00
{
ZoneTooltip ( ev ) ;
2017-09-26 19:49:50 +00:00
2017-11-27 21:41:30 +00:00
if ( ! m_zoomAnim . active & & ImGui : : IsMouseClicked ( 2 ) )
2017-10-12 17:14:03 +00:00
{
ZoomToZone ( ev ) ;
}
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2019-06-16 15:00:25 +00:00
if ( ImGui : : GetIO ( ) . KeyCtrl )
{
auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
m_findZone . ShowZone ( ev . srcloc , m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ) ;
}
else
{
ShowZoneInfo ( ev ) ;
}
2017-09-24 14:25:07 +00:00
}
2018-07-28 17:53:11 +00:00
m_zoneSrcLocHighlight = ev . srcloc ;
2019-06-16 15:05:56 +00:00
m_zoneHover = & ev ;
2017-09-24 14:25:07 +00:00
}
2017-10-12 17:14:03 +00:00
+ + it ;
2017-09-23 22:07:06 +00:00
}
2017-09-21 00:16:01 +00:00
}
2017-09-23 22:12:26 +00:00
return maxdepth ;
2017-09-20 22:57:26 +00:00
}
2019-03-18 17:40:03 +00:00
int View : : SkipZoneLevel ( const Vector < ZoneEvent * > & vec , bool hover , double pxns , int64_t nspx , const ImVec2 & wpos , int _offset , int depth , float yMin , float yMax )
2018-04-20 21:19:04 +00:00
{
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
// cast to uint64_t, so that unended zones (end = -1) are still drawn
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - delay , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > end < ( uint64_t ) r ; } ) ;
if ( it = = vec . end ( ) ) return depth ;
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + resolution , [ ] ( const auto & l , const auto & r ) { return l - > start < r ; } ) ;
if ( it = = zitend ) return depth ;
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
{
auto & ev = * * it ;
const auto end = m_worker . GetZoneEnd ( ev ) ;
const auto zsz = std : : max ( ( end - ev . start ) * pxns , pxns * 0.5 ) ;
if ( zsz < MinVisSize )
{
auto px1 = ( end - m_zvStart ) * pxns ;
2019-03-18 18:39:37 +00:00
auto nextTime = end + MinVisSize ;
2018-04-20 21:19:04 +00:00
for ( ; ; )
{
2019-03-18 17:42:58 +00:00
const auto prevIt = it ;
2019-03-18 18:39:37 +00:00
it = std : : lower_bound ( it , zitend , nextTime , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > end < ( uint64_t ) r ; } ) ;
2019-03-18 17:42:58 +00:00
if ( it = = prevIt ) + + it ;
2018-04-20 21:19:04 +00:00
if ( it = = zitend ) break ;
const auto nend = m_worker . GetZoneEnd ( * * it ) ;
const auto pxnext = ( nend - m_zvStart ) * pxns ;
if ( pxnext - px1 > = MinVisSize * 2 ) break ;
px1 = pxnext ;
2019-03-18 18:39:37 +00:00
nextTime = nend + nspx ;
2018-04-20 21:19:04 +00:00
}
}
else
{
m_lastCpu = ev . cpu_start ;
2018-07-22 14:05:50 +00:00
if ( ev . child > = 0 )
2018-04-20 21:19:04 +00:00
{
2019-03-18 17:40:03 +00:00
const auto d = DispatchZoneLevel ( m_worker . GetZoneChildren ( ev . child ) , hover , pxns , nspx , wpos , _offset , depth , yMin , yMax ) ;
2018-04-20 21:19:04 +00:00
if ( d > maxdepth ) maxdepth = d ;
}
if ( ev . end > = 0 & & m_lastCpu ! = ev . cpu_end )
{
m_lastCpu = ev . cpu_end ;
}
+ + it ;
}
}
return maxdepth ;
}
2019-03-18 17:40:03 +00:00
int View : : DispatchGpuZoneLevel ( const Vector < GpuEvent * > & vec , bool hover , double pxns , int64_t nspx , const ImVec2 & wpos , int _offset , int depth , uint64_t thread , float yMin , float yMax , int64_t begin , int drift )
2018-04-20 21:28:19 +00:00
{
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
const auto offset = _offset + ostep * depth ;
const auto yPos = wpos . y + offset ;
if ( yPos + ostep > = yMin & & yPos < = yMax )
{
2019-03-18 17:40:03 +00:00
return DrawGpuZoneLevel ( vec , hover , pxns , nspx , wpos , _offset , depth , thread , yMin , yMax , begin , drift ) ;
2018-04-20 21:28:19 +00:00
}
else
{
2019-03-18 17:40:03 +00:00
return SkipGpuZoneLevel ( vec , hover , pxns , nspx , wpos , _offset , depth , thread , yMin , yMax , begin , drift ) ;
2018-04-20 21:28:19 +00:00
}
}
2018-06-27 23:12:25 +00:00
static int64_t AdjustGpuTime ( int64_t time , int64_t begin , int drift )
{
const auto t = time - begin ;
return time + t / 1000000000 * drift ;
}
2019-03-18 17:40:03 +00:00
int View : : DrawGpuZoneLevel ( const Vector < GpuEvent * > & vec , bool hover , double pxns , int64_t nspx , const ImVec2 & wpos , int _offset , int depth , uint64_t thread , float yMin , float yMax , int64_t begin , int drift )
2017-11-11 21:56:05 +00:00
{
2018-02-13 13:57:47 +00:00
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
2017-11-11 21:56:05 +00:00
// cast to uint64_t, so that unended zones (end = -1) are still drawn
2018-06-27 23:12:25 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - delay , [ begin , drift ] ( const auto & l , const auto & r ) { return ( uint64_t ) AdjustGpuTime ( l - > gpuEnd , begin , drift ) < ( uint64_t ) r ; } ) ;
2017-11-11 21:56:05 +00:00
if ( it = = vec . end ( ) ) return depth ;
2018-06-27 23:12:25 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + resolution , [ begin , drift ] ( const auto & l , const auto & r ) { return AdjustGpuTime ( l - > gpuStart , begin , drift ) < r ; } ) ;
2017-11-11 21:56:05 +00:00
if ( it = = zitend ) return depth ;
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
const auto offset = _offset + ostep * depth ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
{
auto & ev = * * it ;
const auto color = GetZoneColor ( ev ) ;
2018-06-27 23:12:25 +00:00
auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-14 23:08:21 +00:00
if ( end = = std : : numeric_limits < int64_t > : : max ( ) ) break ;
2018-06-27 23:12:25 +00:00
const auto start = AdjustGpuTime ( ev . gpuStart , begin , drift ) ;
end = AdjustGpuTime ( end , begin , drift ) ;
const auto zsz = std : : max ( ( end - start ) * pxns , pxns * 0.5 ) ;
2017-11-11 21:56:05 +00:00
if ( zsz < MinVisSize )
{
2019-03-18 17:48:27 +00:00
int num = 0 ;
2018-06-27 23:12:25 +00:00
const auto px0 = ( start - m_zvStart ) * pxns ;
2017-11-11 21:56:05 +00:00
auto px1 = ( end - m_zvStart ) * pxns ;
auto rend = end ;
2019-03-18 18:39:37 +00:00
auto nextTime = end + MinVisSize ;
2017-11-11 21:56:05 +00:00
for ( ; ; )
{
2019-03-18 17:48:27 +00:00
const auto prevIt = it ;
2019-03-18 18:39:37 +00:00
it = std : : lower_bound ( it , zitend , nextTime , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > gpuEnd < ( uint64_t ) r ; } ) ;
2019-03-18 17:48:27 +00:00
if ( it = = prevIt ) + + it ;
num + = std : : distance ( prevIt , it ) ;
2017-11-11 21:56:05 +00:00
if ( it = = zitend ) break ;
2018-06-27 23:12:25 +00:00
const auto nend = AdjustGpuTime ( m_worker . GetZoneEnd ( * * it ) , begin , drift ) ;
2017-11-11 21:56:05 +00:00
const auto pxnext = ( nend - m_zvStart ) * pxns ;
if ( pxnext - px1 > = MinVisSize * 2 ) break ;
px1 = pxnext ;
rend = nend ;
2019-03-18 18:39:37 +00:00
nextTime = nend + nspx ;
2017-11-11 21:56:05 +00:00
}
draw - > AddRectFilled ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) , color ) ;
2018-08-04 21:32:53 +00:00
DrawZigZag ( draw , wpos + ImVec2 ( 0 , offset + ty / 2 ) , std : : max ( px0 , - 10.0 ) , std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , ty / 4 , DarkenColor ( color ) ) ;
2017-11-11 21:56:05 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) ) )
{
if ( num > 1 )
{
ImGui : : BeginTooltip ( ) ;
2018-06-29 16:47:33 +00:00
TextFocused ( " Zones too small to display: " , RealToString ( num , true ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-06-29 16:47:33 +00:00
TextFocused ( " Execution time: " , TimeToString ( rend - start ) ) ;
2017-11-11 21:56:05 +00:00
ImGui : : EndTooltip ( ) ;
2018-06-27 23:12:25 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - start > 0 )
2017-11-11 21:56:05 +00:00
{
2018-06-27 23:12:25 +00:00
ZoomToRange ( start , rend ) ;
2017-11-11 21:56:05 +00:00
}
}
else
{
ZoneTooltip ( ev ) ;
2018-06-27 23:12:25 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - start > 0 )
2017-11-11 21:56:05 +00:00
{
ZoomToZone ( ev ) ;
}
2017-11-12 00:25:44 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-05-02 17:23:46 +00:00
ShowZoneInfo ( ev , thread ) ;
2017-11-12 00:25:44 +00:00
}
2017-11-11 22:13:54 +00:00
2017-11-13 23:48:26 +00:00
m_gpuThread = thread ;
2017-11-11 22:13:54 +00:00
m_gpuStart = ev . cpuStart ;
m_gpuEnd = ev . cpuEnd ;
2017-11-11 21:56:05 +00:00
}
}
2018-07-15 23:24:43 +00:00
char tmp [ 64 ] ;
sprintf ( tmp , " %s " , RealToString ( num , true ) ) ;
2017-11-11 21:56:05 +00:00
const auto tsz = ImGui : : CalcTextSize ( tmp ) ;
if ( tsz . x < px1 - px0 )
{
const auto x = px0 + ( px1 - px0 - tsz . x ) / 2 ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFF4488DD , tmp ) ;
2017-11-11 21:56:05 +00:00
}
}
else
{
2018-07-22 17:47:01 +00:00
if ( ev . child > = 0 )
2017-11-11 21:56:05 +00:00
{
2019-03-18 17:40:03 +00:00
const auto d = DispatchGpuZoneLevel ( m_worker . GetGpuChildren ( ev . child ) , hover , pxns , nspx , wpos , _offset , depth , thread , yMin , yMax , begin , drift ) ;
2017-11-11 21:56:05 +00:00
if ( d > maxdepth ) maxdepth = d ;
}
2018-06-29 13:14:20 +00:00
const char * zoneName = m_worker . GetZoneName ( ev ) ;
2017-11-11 21:56:05 +00:00
auto tsz = ImGui : : CalcTextSize ( zoneName ) ;
2018-06-27 23:12:25 +00:00
const auto pr0 = ( start - m_zvStart ) * pxns ;
2017-11-11 21:56:05 +00:00
const auto pr1 = ( end - m_zvStart ) * pxns ;
const auto px0 = std : : max ( pr0 , - 10.0 ) ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( { std : : min ( pr1 , double ( w + 10 ) ) , px0 + pxns * 0.5 , px0 + MinVisSize } ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , color ) ;
draw - > AddRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , GetZoneHighlight ( ev ) , 0.f , - 1 , GetZoneThickness ( ev ) ) ;
2017-11-11 21:56:05 +00:00
if ( tsz . x < zsz )
{
2018-06-27 23:12:25 +00:00
const auto x = ( start - m_zvStart ) * pxns + ( ( end - start ) * pxns - tsz . x ) / 2 ;
2017-11-11 21:56:05 +00:00
if ( x < 0 | | x > w - tsz . x )
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( std : : max ( std : : max ( 0. , px0 ) , std : : min ( double ( w - tsz . x ) , x ) ) , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-11 21:56:05 +00:00
ImGui : : PopClipRect ( ) ;
}
2017-11-18 12:40:49 +00:00
else if ( ev . gpuStart = = ev . gpuEnd )
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( px0 + ( px1 - px0 - tsz . x ) * 0.5 , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-18 12:40:49 +00:00
}
2017-11-11 21:56:05 +00:00
else
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-11 21:56:05 +00:00
}
}
else
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2018-06-27 23:12:25 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ( start - m_zvStart ) * pxns , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-11 21:56:05 +00:00
ImGui : : PopClipRect ( ) ;
}
2017-11-18 12:40:49 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) ) )
2017-11-11 21:56:05 +00:00
{
ZoneTooltip ( ev ) ;
2017-11-27 21:41:30 +00:00
if ( ! m_zoomAnim . active & & ImGui : : IsMouseClicked ( 2 ) )
2017-11-11 21:56:05 +00:00
{
ZoomToZone ( ev ) ;
}
2017-11-12 00:25:44 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-05-02 17:23:46 +00:00
ShowZoneInfo ( ev , thread ) ;
2017-11-12 00:25:44 +00:00
}
2017-11-11 22:13:54 +00:00
2017-11-13 23:48:26 +00:00
m_gpuThread = thread ;
2017-11-11 22:13:54 +00:00
m_gpuStart = ev . cpuStart ;
m_gpuEnd = ev . cpuEnd ;
2017-11-11 21:56:05 +00:00
}
+ + it ;
}
}
return maxdepth ;
}
2019-03-18 17:40:03 +00:00
int View : : SkipGpuZoneLevel ( const Vector < GpuEvent * > & vec , bool hover , double pxns , int64_t nspx , const ImVec2 & wpos , int _offset , int depth , uint64_t thread , float yMin , float yMax , int64_t begin , int drift )
2018-04-20 21:28:19 +00:00
{
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
// cast to uint64_t, so that unended zones (end = -1) are still drawn
2018-06-27 23:12:25 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - delay , [ begin , drift ] ( const auto & l , const auto & r ) { return ( uint64_t ) AdjustGpuTime ( l - > gpuEnd , begin , drift ) < ( uint64_t ) r ; } ) ;
2018-04-20 21:28:19 +00:00
if ( it = = vec . end ( ) ) return depth ;
2018-06-27 23:12:25 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + resolution , [ begin , drift ] ( const auto & l , const auto & r ) { return AdjustGpuTime ( l - > gpuStart , begin , drift ) < r ; } ) ;
2018-04-20 21:28:19 +00:00
if ( it = = zitend ) return depth ;
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
{
auto & ev = * * it ;
2018-06-27 23:12:25 +00:00
auto end = m_worker . GetZoneEnd ( ev ) ;
2018-04-20 21:28:19 +00:00
if ( end = = std : : numeric_limits < int64_t > : : max ( ) ) break ;
2018-06-27 23:12:25 +00:00
const auto start = AdjustGpuTime ( ev . gpuStart , begin , drift ) ;
end = AdjustGpuTime ( end , begin , drift ) ;
const auto zsz = std : : max ( ( end - start ) * pxns , pxns * 0.5 ) ;
2018-04-20 21:28:19 +00:00
if ( zsz < MinVisSize )
{
auto px1 = ( end - m_zvStart ) * pxns ;
2019-03-18 18:39:37 +00:00
auto nextTime = end ;
2018-04-20 21:28:19 +00:00
for ( ; ; )
{
2019-03-18 17:48:27 +00:00
const auto prevIt = it ;
2019-03-18 18:39:37 +00:00
it = std : : lower_bound ( it , zitend , nextTime , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > gpuEnd < ( uint64_t ) r ; } ) ;
2019-03-18 17:48:27 +00:00
if ( it = = prevIt ) + + it ;
2018-04-20 21:28:19 +00:00
if ( it = = zitend ) break ;
2018-06-27 23:12:25 +00:00
const auto nend = AdjustGpuTime ( m_worker . GetZoneEnd ( * * it ) , begin , drift ) ;
2018-04-20 21:28:19 +00:00
const auto pxnext = ( nend - m_zvStart ) * pxns ;
if ( pxnext - px1 > = MinVisSize * 2 ) break ;
px1 = pxnext ;
2019-03-18 18:39:37 +00:00
nextTime = nend + nspx ;
2018-04-20 21:28:19 +00:00
}
}
else
{
2018-07-22 17:47:01 +00:00
if ( ev . child > = 0 )
2018-04-20 21:28:19 +00:00
{
2019-03-18 17:40:03 +00:00
const auto d = DispatchGpuZoneLevel ( m_worker . GetGpuChildren ( ev . child ) , hover , pxns , nspx , wpos , _offset , depth , thread , yMin , yMax , begin , drift ) ;
2018-04-20 21:28:19 +00:00
if ( d > maxdepth ) maxdepth = d ;
}
+ + it ;
}
}
return maxdepth ;
}
2017-10-28 11:44:46 +00:00
enum class LockState
{
2017-11-26 20:37:57 +00:00
Nothing ,
HasLock , // green
HasBlockingLock , // yellow
WaitLock // red
2017-10-28 11:44:46 +00:00
} ;
2019-03-16 13:18:43 +00:00
static Vector < LockEventPtr > : : const_iterator GetNextLockEvent ( const Vector < LockEventPtr > : : const_iterator & it , const Vector < LockEventPtr > : : const_iterator & end , LockState & nextState , uint64_t threadBit )
2017-10-04 19:27:06 +00:00
{
2017-10-28 11:44:46 +00:00
auto next = it ;
next + + ;
2017-12-17 17:00:15 +00:00
switch ( nextState )
{
case LockState : : Nothing :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
if ( next - > lockCount ! = 0 )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
if ( GetThreadBit ( next - > lockingThread ) = = threadBit )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
nextState = AreOtherWaiting ( next - > waitList , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
break ;
}
2019-03-16 13:18:43 +00:00
else if ( IsThreadWaiting ( next - > waitList , threadBit ) )
2017-12-17 17:00:15 +00:00
{
nextState = LockState : : WaitLock ;
break ;
}
}
next + + ;
}
break ;
case LockState : : HasLock :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
if ( next - > lockCount = = 0 )
2017-12-17 17:00:15 +00:00
{
nextState = LockState : : Nothing ;
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > waitList ! = 0 )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
if ( AreOtherWaiting ( next - > waitList , threadBit ) )
2017-12-17 17:00:15 +00:00
{
nextState = LockState : : HasBlockingLock ;
}
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > waitList ! = it - > waitList | | next - > lockCount ! = it - > lockCount )
2017-12-17 17:00:15 +00:00
{
break ;
}
next + + ;
}
break ;
case LockState : : HasBlockingLock :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
if ( next - > lockCount = = 0 )
2017-12-17 17:00:15 +00:00
{
nextState = LockState : : Nothing ;
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > waitList ! = it - > waitList | | next - > lockCount ! = it - > lockCount )
2017-12-17 17:00:15 +00:00
{
break ;
}
next + + ;
}
break ;
case LockState : : WaitLock :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
if ( GetThreadBit ( next - > lockingThread ) = = threadBit )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
nextState = AreOtherWaiting ( next - > waitList , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > lockingThread ! = it - > lockingThread )
2017-12-17 17:00:15 +00:00
{
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > lockCount = = 0 )
2017-12-17 17:00:15 +00:00
{
break ;
}
next + + ;
}
break ;
default :
assert ( false ) ;
break ;
}
return next ;
}
2019-03-16 13:18:43 +00:00
static Vector < LockEventPtr > : : const_iterator GetNextLockEventShared ( const Vector < LockEventPtr > : : const_iterator & it , const Vector < LockEventPtr > : : const_iterator & end , LockState & nextState , uint64_t threadBit )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
const auto itptr = ( const LockEventShared * ) it - > ptr ;
2017-12-17 17:00:15 +00:00
auto next = it ;
next + + ;
2017-12-09 18:28:12 +00:00
switch ( nextState )
2017-10-05 21:18:24 +00:00
{
2017-10-28 11:44:46 +00:00
case LockState : : Nothing :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
const auto ptr = ( const LockEventShared * ) next - > ptr ;
if ( next - > lockCount ! = 0 )
2017-10-28 11:44:46 +00:00
{
2019-03-16 13:18:43 +00:00
const auto wait = next - > waitList | ptr - > waitShared ;
if ( GetThreadBit ( next - > lockingThread ) = = threadBit )
2017-10-28 11:44:46 +00:00
{
2017-12-10 22:33:39 +00:00
nextState = AreOtherWaiting ( wait , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-10-28 11:44:46 +00:00
break ;
}
2017-12-10 22:33:39 +00:00
else if ( IsThreadWaiting ( wait , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : WaitLock ;
break ;
}
}
2017-12-17 17:44:31 +00:00
else if ( IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-12-10 22:30:13 +00:00
{
2019-03-16 13:18:43 +00:00
nextState = ( next - > waitList ! = 0 ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-10 22:30:13 +00:00
break ;
}
2019-03-16 13:18:43 +00:00
else if ( ptr - > sharedList ! = 0 & & IsThreadWaiting ( next - > waitList , threadBit ) )
2017-12-10 22:30:13 +00:00
{
nextState = LockState : : WaitLock ;
break ;
}
2017-10-28 11:44:46 +00:00
next + + ;
}
break ;
case LockState : : HasLock :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
const auto ptr = ( const LockEventShared * ) next - > ptr ;
if ( next - > lockCount = = 0 & & ! IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : Nothing ;
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > waitList ! = 0 )
2017-10-28 11:44:46 +00:00
{
2019-03-16 13:18:43 +00:00
if ( AreOtherWaiting ( next - > waitList , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : HasBlockingLock ;
}
break ;
}
2017-12-17 17:44:31 +00:00
else if ( ! IsThreadWaiting ( ptr - > sharedList , threadBit ) & & ptr - > waitShared ! = 0 )
2017-12-10 22:30:13 +00:00
{
nextState = LockState : : HasBlockingLock ;
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > waitList ! = it - > waitList | | ptr - > waitShared ! = itptr - > waitShared | | next - > lockCount ! = it - > lockCount | | ptr - > sharedList ! = itptr - > sharedList )
2017-10-28 11:44:46 +00:00
{
break ;
}
next + + ;
}
break ;
case LockState : : HasBlockingLock :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
const auto ptr = ( const LockEventShared * ) next - > ptr ;
if ( next - > lockCount = = 0 & & ! IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : Nothing ;
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > waitList ! = it - > waitList | | ptr - > waitShared ! = itptr - > waitShared | | next - > lockCount ! = it - > lockCount | | ptr - > sharedList ! = itptr - > sharedList )
2017-10-28 11:44:46 +00:00
{
break ;
}
next + + ;
}
break ;
case LockState : : WaitLock :
while ( next < end )
{
2019-03-16 13:18:43 +00:00
const auto ptr = ( const LockEventShared * ) next - > ptr ;
if ( GetThreadBit ( next - > lockingThread ) = = threadBit )
2017-10-28 11:44:46 +00:00
{
2019-03-16 13:18:43 +00:00
const auto wait = next - > waitList | ptr - > waitShared ;
2017-12-10 22:33:39 +00:00
nextState = AreOtherWaiting ( wait , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-10 22:30:13 +00:00
break ;
}
2017-12-17 17:44:31 +00:00
if ( IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-12-10 22:30:13 +00:00
{
2019-03-16 13:18:43 +00:00
nextState = ( next - > waitList ! = 0 ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-10-28 11:44:46 +00:00
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > lockingThread ! = it - > lockingThread )
2017-10-28 11:44:46 +00:00
{
break ;
}
2019-03-16 13:18:43 +00:00
if ( next - > lockCount = = 0 & & ! IsThreadWaiting ( ptr - > waitShared , threadBit ) )
2017-10-28 11:44:46 +00:00
{
break ;
}
next + + ;
}
break ;
default :
assert ( false ) ;
break ;
}
return next ;
}
2017-10-05 21:18:24 +00:00
2017-10-28 13:15:07 +00:00
static LockState CombineLockState ( LockState state , LockState next )
{
2017-11-26 20:37:57 +00:00
return ( LockState ) std : : max ( ( int ) state , ( int ) next ) ;
2017-10-28 13:15:07 +00:00
}
2019-02-24 16:30:58 +00:00
void View : : DrawLockHeader ( uint32_t id , const LockMap & lockmap , const SourceLocation & srcloc , bool hover , ImDrawList * draw , const ImVec2 & wpos , float w , float ty , float offset , uint8_t tid )
2019-02-17 15:49:03 +00:00
{
char buf [ 1024 ] ;
sprintf ( buf , " % " PRIu32 " : %s " , id , m_worker . GetString ( srcloc . function ) ) ;
DrawTextContrast ( draw , wpos + ImVec2 ( 0 , offset ) , 0xFF8888FF , buf ) ;
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) ) )
{
m_lockHoverHighlight = id ;
if ( ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + ImGui : : CalcTextSize ( buf ) . x , offset + ty ) ) )
{
2019-03-16 01:47:37 +00:00
const auto & range = lockmap . range [ tid ] ;
const auto activity = range . end - range . start ;
2019-02-24 16:44:44 +00:00
const auto traceLen = m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ;
int64_t timeAnnounce = lockmap . timeAnnounce ;
int64_t timeTerminate = lockmap . timeTerminate ;
if ( ! lockmap . timeline . empty ( ) )
{
if ( timeAnnounce = = 0 )
{
2019-03-16 13:18:43 +00:00
timeAnnounce = lockmap . timeline . front ( ) . ptr - > time ;
2019-02-24 16:44:44 +00:00
}
if ( timeTerminate = = 0 )
{
2019-03-16 13:18:43 +00:00
timeTerminate = lockmap . timeline . back ( ) . ptr - > time ;
2019-02-24 16:44:44 +00:00
}
}
const auto lockLen = timeTerminate - timeAnnounce ;
2019-02-17 15:49:03 +00:00
ImGui : : BeginTooltip ( ) ;
switch ( lockmap . type )
{
case LockType : : Lockable :
TextFocused ( " Type: " , " lockable " ) ;
break ;
case LockType : : SharedLockable :
TextFocused ( " Type: " , " shared lockable " ) ;
break ;
default :
assert ( false ) ;
break ;
}
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : Separator ( ) ;
2019-02-24 16:44:44 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-03-16 01:47:37 +00:00
TextFocused ( ICON_FA_RANDOM " Appeared at " , TimeToString ( range . start - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( ICON_FA_RANDOM " Last event at " , TimeToString ( range . end - m_worker . GetTimeBegin ( ) ) ) ;
2019-02-24 16:44:44 +00:00
TextFocused ( ICON_FA_RANDOM " Activity time: " , TimeToString ( activity ) ) ;
# else
ImGui : : TextUnformatted ( " This thread " ) ;
2019-03-16 01:47:37 +00:00
TextFocused ( " Appeared at " , TimeToString ( range . start - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Last event at " , TimeToString ( range . end - m_worker . GetTimeBegin ( ) ) ) ;
2019-02-24 16:44:44 +00:00
TextFocused ( " Activity time: " , TimeToString ( activity ) ) ;
# endif
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%% of lock lifetime) " , activity / double ( lockLen ) * 100 ) ;
ImGui : : Separator ( ) ;
TextFocused ( " Announce time: " , TimeToString ( timeAnnounce - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Terminate time: " , TimeToString ( timeTerminate - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Lifetime: " , TimeToString ( lockLen ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%% of trace time) " , lockLen / double ( traceLen ) * 100 ) ;
ImGui : : Separator ( ) ;
2019-02-17 15:49:03 +00:00
TextDisabledUnformatted ( " Thread list: " ) ;
ImGui : : Indent ( ty ) ;
for ( const auto & t : lockmap . threadList )
{
ImGui : : TextUnformatted ( m_worker . GetThreadString ( t ) ) ;
}
ImGui : : Unindent ( ty ) ;
ImGui : : Separator ( ) ;
TextFocused ( " Lock events: " , RealToString ( lockmap . timeline . size ( ) , true ) ) ;
ImGui : : EndTooltip ( ) ;
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_lockInfoWindow = id ;
}
2019-02-24 16:30:58 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
2019-03-16 01:47:37 +00:00
ZoomToRange ( range . start , range . end ) ;
2019-02-24 16:30:58 +00:00
}
2019-02-17 15:49:03 +00:00
}
}
}
2018-04-20 20:53:15 +00:00
int View : : DrawLocks ( uint64_t tid , bool hover , double pxns , const ImVec2 & wpos , int _offset , LockHighlight & highlight , float yMin , float yMax )
2017-10-28 11:44:46 +00:00
{
2018-02-13 13:57:47 +00:00
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
2019-03-01 00:20:20 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
2017-10-28 12:25:35 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2018-02-13 13:57:47 +00:00
const auto dsz = delay * pxns ;
const auto rsz = resolution * pxns ;
2017-10-28 12:25:35 +00:00
2017-10-04 19:27:06 +00:00
int cnt = 0 ;
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetLockMap ( ) )
2017-10-04 19:27:06 +00:00
{
2019-03-16 01:09:50 +00:00
const auto & lockmap = * v . second ;
2019-02-21 19:24:08 +00:00
if ( ! lockmap . valid | | ! Vis ( & lockmap ) . visible ) continue ;
2019-05-12 14:17:17 +00:00
if ( m_onlyContendedLocks & & ( lockmap . threadList . size ( ) = = 1 | | ! lockmap . isContended ) & & m_lockInfoWindow ! = v . first ) continue ;
2017-10-22 11:25:58 +00:00
2017-10-08 21:03:38 +00:00
auto it = lockmap . threadMap . find ( tid ) ;
if ( it = = lockmap . threadMap . end ( ) ) continue ;
2019-02-17 15:49:18 +00:00
const auto offset = _offset + ostep * cnt ;
2019-03-16 01:32:23 +00:00
const auto & range = lockmap . range [ it - > second ] ;
2018-02-13 13:57:47 +00:00
const auto & tl = lockmap . timeline ;
2017-10-05 21:18:24 +00:00
assert ( ! tl . empty ( ) ) ;
2019-03-16 01:32:23 +00:00
if ( range . start > m_zvEnd | | range . end < m_zvStart )
2019-02-17 15:49:18 +00:00
{
if ( m_lockInfoWindow = = v . first )
{
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) , 0x2288DD88 ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) , 0x4488DD88 ) ;
2019-02-24 16:30:58 +00:00
DrawLockHeader ( v . first , lockmap , m_worker . GetSourceLocation ( lockmap . srcloc ) , hover , draw , wpos , w , ty , offset , it - > second ) ;
2019-02-17 15:49:18 +00:00
cnt + + ;
}
continue ;
}
2017-10-08 21:03:38 +00:00
2017-12-17 17:00:15 +00:00
auto GetNextLockFunc = lockmap . type = = LockType : : Lockable ? GetNextLockEvent : GetNextLockEventShared ;
2017-10-08 21:03:38 +00:00
const auto thread = it - > second ;
2017-12-05 21:09:53 +00:00
const auto threadBit = GetThreadBit ( thread ) ;
2017-10-08 21:03:38 +00:00
2019-03-16 13:18:43 +00:00
auto vbegin = std : : lower_bound ( tl . begin ( ) , tl . end ( ) , std : : max ( range . start , m_zvStart - delay ) , [ ] ( const auto & l , const auto & r ) { return l . ptr - > time < r ; } ) ;
const auto vend = std : : lower_bound ( vbegin , tl . end ( ) , std : : min ( range . end , m_zvEnd + resolution ) , [ ] ( const auto & l , const auto & r ) { return l . ptr - > time < r ; } ) ;
2017-10-05 21:18:24 +00:00
if ( vbegin > tl . begin ( ) ) vbegin - - ;
2017-10-28 11:44:46 +00:00
LockState state = LockState : : Nothing ;
2017-12-17 17:00:15 +00:00
if ( lockmap . type = = LockType : : Lockable )
2017-10-08 21:03:38 +00:00
{
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockCount ! = 0 )
2017-10-08 21:03:38 +00:00
{
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockingThread = = thread )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
state = AreOtherWaiting ( vbegin - > waitList , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
}
2019-03-16 13:18:43 +00:00
else if ( IsThreadWaiting ( vbegin - > waitList , threadBit ) )
2017-12-17 17:00:15 +00:00
{
state = LockState : : WaitLock ;
}
2017-10-08 21:03:38 +00:00
}
2017-12-17 17:00:15 +00:00
}
else
{
2019-03-16 13:18:43 +00:00
auto ptr = ( const LockEventShared * ) vbegin - > ptr ;
if ( vbegin - > lockCount ! = 0 )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockingThread = = thread )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
state = ( AreOtherWaiting ( vbegin - > waitList , threadBit ) | | AreOtherWaiting ( ptr - > waitShared , threadBit ) ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
}
2019-03-16 13:18:43 +00:00
else if ( IsThreadWaiting ( vbegin - > waitList , threadBit ) | | IsThreadWaiting ( ptr - > waitShared , threadBit ) )
2017-12-17 17:00:15 +00:00
{
state = LockState : : WaitLock ;
}
}
2017-12-17 17:44:31 +00:00
else if ( IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-12-17 17:00:15 +00:00
{
2019-03-16 13:18:43 +00:00
state = vbegin - > waitList ! = 0 ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
}
2019-03-16 13:18:43 +00:00
else if ( ptr - > sharedList ! = 0 & & IsThreadWaiting ( vbegin - > waitList , threadBit ) )
2017-10-08 21:03:38 +00:00
{
2017-10-28 11:44:46 +00:00
state = LockState : : WaitLock ;
2017-10-08 21:03:38 +00:00
}
}
2018-04-20 20:53:15 +00:00
const auto yPos = wpos . y + offset ;
if ( yPos + ostep > = yMin & & yPos < = yMax )
2017-10-05 21:18:24 +00:00
{
2018-04-20 20:53:15 +00:00
bool drawn = false ;
const auto & srcloc = m_worker . GetSourceLocation ( lockmap . srcloc ) ;
2017-10-28 13:15:07 +00:00
2018-04-20 20:53:15 +00:00
double pxend = 0 ;
2017-10-28 13:15:07 +00:00
for ( ; ; )
{
2019-03-16 13:46:21 +00:00
if ( m_onlyContendedLocks )
2017-10-28 13:24:25 +00:00
{
2019-03-16 13:46:21 +00:00
while ( vbegin < vend & & ( state = = LockState : : Nothing | | state = = LockState : : HasLock ) )
{
vbegin = GetNextLockFunc ( vbegin , vend , state , threadBit ) ;
}
}
else
{
while ( vbegin < vend & & state = = LockState : : Nothing )
{
vbegin = GetNextLockFunc ( vbegin , vend , state , threadBit ) ;
}
2017-10-28 13:24:25 +00:00
}
2018-04-20 20:53:15 +00:00
if ( vbegin > = vend ) break ;
2017-10-28 12:08:10 +00:00
2018-04-20 20:53:15 +00:00
assert ( state ! = LockState : : Nothing & & ( ! m_onlyContendedLocks | | state ! = LockState : : HasLock ) ) ;
drawn = true ;
2017-10-28 20:44:41 +00:00
2018-04-20 20:53:15 +00:00
LockState drawState = state ;
auto next = GetNextLockFunc ( vbegin , vend , state , threadBit ) ;
2019-03-16 13:18:43 +00:00
const auto t0 = vbegin - > ptr - > time ;
int64_t t1 = next = = tl . end ( ) ? m_worker . GetLastTime ( ) : next - > ptr - > time ;
2018-04-20 20:53:15 +00:00
const auto px0 = std : : max ( pxend , ( t0 - m_zvStart ) * pxns ) ;
auto tx0 = px0 ;
double px1 = ( t1 - m_zvStart ) * pxns ;
uint64_t condensed = 0 ;
2019-03-16 13:46:21 +00:00
if ( m_onlyContendedLocks )
2017-10-05 21:35:21 +00:00
{
2019-03-16 13:46:21 +00:00
for ( ; ; )
2018-04-20 20:53:15 +00:00
{
2019-03-16 13:46:21 +00:00
if ( next > = vend | | px1 - tx0 > MinVisSize ) break ;
auto n = next ;
auto ns = state ;
while ( n < vend & & ( ns = = LockState : : Nothing | | ns = = LockState : : HasLock ) )
{
n = GetNextLockFunc ( n , vend , ns , threadBit ) ;
}
if ( n > = vend ) break ;
if ( n = = next )
{
n = GetNextLockFunc ( n , vend , ns , threadBit ) ;
}
drawState = CombineLockState ( drawState , state ) ;
condensed + + ;
const auto t2 = n = = tl . end ( ) ? m_worker . GetLastTime ( ) : n - > ptr - > time ;
const auto px2 = ( t2 - m_zvStart ) * pxns ;
if ( px2 - px1 > MinVisSize ) break ;
if ( drawState ! = ns & & px2 - px0 > MinVisSize & & ! ( ns = = LockState : : Nothing | | ns = = LockState : : HasLock ) ) break ;
t1 = t2 ;
tx0 = px1 ;
px1 = px2 ;
next = n ;
state = ns ;
2018-04-20 20:53:15 +00:00
}
2019-03-16 13:46:21 +00:00
}
else
{
for ( ; ; )
2018-04-20 20:53:15 +00:00
{
2019-03-16 13:46:21 +00:00
if ( next > = vend | | px1 - tx0 > MinVisSize ) break ;
auto n = next ;
auto ns = state ;
while ( n < vend & & ns = = LockState : : Nothing )
{
n = GetNextLockFunc ( n , vend , ns , threadBit ) ;
}
if ( n > = vend ) break ;
if ( n = = next )
{
n = GetNextLockFunc ( n , vend , ns , threadBit ) ;
}
drawState = CombineLockState ( drawState , state ) ;
condensed + + ;
const auto t2 = n = = tl . end ( ) ? m_worker . GetLastTime ( ) : n - > ptr - > time ;
const auto px2 = ( t2 - m_zvStart ) * pxns ;
if ( px2 - px1 > MinVisSize ) break ;
if ( drawState ! = ns & & px2 - px0 > MinVisSize & & ns ! = LockState : : Nothing ) break ;
t1 = t2 ;
tx0 = px1 ;
px1 = px2 ;
next = n ;
state = ns ;
2018-04-20 20:53:15 +00:00
}
2017-10-28 12:08:10 +00:00
}
2018-04-20 20:53:15 +00:00
pxend = std : : max ( { px1 , px0 + MinVisSize , px0 + pxns * 0.5 } ) ;
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 )
2017-10-28 12:08:10 +00:00
{
2018-12-16 19:01:40 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_lockInfoWindow = v . first ;
}
2018-12-16 19:04:45 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToRange ( t0 , t1 ) ;
}
2018-12-16 19:01:40 +00:00
2018-04-20 20:53:15 +00:00
if ( condensed > 1 )
2017-10-08 21:03:38 +00:00
{
2018-04-20 20:53:15 +00:00
ImGui : : BeginTooltip ( ) ;
2018-06-29 16:49:47 +00:00
TextFocused ( " Multiple lock events: " , RealToString ( condensed , true ) ) ;
2018-04-20 20:53:15 +00:00
ImGui : : EndTooltip ( ) ;
2017-10-08 21:03:38 +00:00
}
2017-10-28 13:33:34 +00:00
else
2017-10-08 21:03:38 +00:00
{
2018-04-20 20:53:15 +00:00
highlight . blocked = drawState = = LockState : : HasBlockingLock ;
if ( ! highlight . blocked )
2017-10-08 21:03:38 +00:00
{
2018-04-20 20:53:15 +00:00
highlight . id = v . first ;
highlight . begin = t0 ;
highlight . end = t1 ;
highlight . thread = thread ;
highlight . blocked = false ;
2017-10-08 21:03:38 +00:00
}
2018-04-20 20:53:15 +00:00
else
2017-10-08 21:03:38 +00:00
{
2018-04-20 20:53:15 +00:00
auto b = vbegin ;
while ( b ! = tl . begin ( ) )
2017-10-28 13:33:34 +00:00
{
2019-03-16 13:18:43 +00:00
if ( b - > lockingThread ! = vbegin - > lockingThread )
2018-04-20 20:53:15 +00:00
{
break ;
}
b - - ;
2017-10-28 13:33:34 +00:00
}
2018-04-20 20:53:15 +00:00
b + + ;
2019-03-16 13:18:43 +00:00
highlight . begin = b - > ptr - > time ;
2017-10-06 16:12:13 +00:00
2018-04-20 20:53:15 +00:00
auto e = next ;
while ( e ! = tl . end ( ) )
2017-10-28 13:33:34 +00:00
{
2019-03-16 13:18:43 +00:00
if ( e - > lockingThread ! = next - > lockingThread )
2018-04-20 20:53:15 +00:00
{
highlight . id = v . first ;
2019-03-16 13:18:43 +00:00
highlight . end = e - > ptr - > time ;
2018-04-20 20:53:15 +00:00
highlight . thread = thread ;
break ;
}
e + + ;
2017-10-28 13:33:34 +00:00
}
}
2018-04-20 20:53:15 +00:00
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Lock #% " PRIu32 " : %s " , v . first , m_worker . GetString ( srcloc . function ) ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-06-29 16:49:47 +00:00
TextFocused ( " Time: " , TimeToString ( t1 - t0 ) ) ;
2017-10-28 13:33:34 +00:00
ImGui : : Separator ( ) ;
2018-04-20 20:53:15 +00:00
uint32_t markloc = 0 ;
auto it = vbegin ;
for ( ; ; )
2017-10-28 13:33:34 +00:00
{
2019-03-16 13:18:43 +00:00
if ( it - > ptr - > thread = = thread )
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
if ( ( it - > lockingThread = = thread | | IsThreadWaiting ( it - > waitList , threadBit ) ) & & it - > ptr - > srcloc ! = 0 )
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
markloc = it - > ptr - > srcloc ;
2018-04-20 20:53:15 +00:00
break ;
2017-12-17 18:40:45 +00:00
}
}
2018-04-20 20:53:15 +00:00
if ( it = = tl . begin ( ) ) break ;
- - it ;
2017-10-28 13:33:34 +00:00
}
2018-04-20 20:53:15 +00:00
if ( markloc ! = 0 )
2017-10-28 13:33:34 +00:00
{
2018-04-20 20:53:15 +00:00
const auto & marklocdata = m_worker . GetSourceLocation ( markloc ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Lock event location: " ) ;
ImGui : : TextUnformatted ( m_worker . GetString ( marklocdata . function ) ) ;
2018-04-20 20:53:15 +00:00
ImGui : : Text ( " %s:%i " , m_worker . GetString ( marklocdata . file ) , marklocdata . line ) ;
ImGui : : Separator ( ) ;
2017-10-28 13:33:34 +00:00
}
2018-04-20 20:53:15 +00:00
2019-02-17 15:49:03 +00:00
if ( lockmap . type = = LockType : : Lockable )
2017-10-28 13:33:34 +00:00
{
2018-04-20 20:53:15 +00:00
switch ( drawState )
2017-12-17 18:40:45 +00:00
{
2018-04-20 20:53:15 +00:00
case LockState : : HasLock :
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockCount = = 1 )
2018-04-20 20:53:15 +00:00
{
ImGui : : Text ( " Thread \" %s \" has lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
}
else
{
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " Thread \" %s \" has %i locks. No other threads are waiting. " , m_worker . GetThreadString ( tid ) , vbegin - > lockCount ) ;
2018-04-20 20:53:15 +00:00
}
2019-03-16 13:18:43 +00:00
if ( vbegin - > waitList ! = 0 )
2018-04-20 20:53:15 +00:00
{
2019-03-16 19:36:06 +00:00
assert ( ! AreOtherWaiting ( next - > waitList , threadBit ) ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Recursive lock acquire in thread. " ) ;
2018-04-20 20:53:15 +00:00
}
break ;
case LockState : : HasBlockingLock :
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockCount = = 1 )
2018-04-20 20:53:15 +00:00
{
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " Thread \" %s \" has lock. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , TracyCountBits ( vbegin - > waitList ) ) ;
2018-04-20 20:53:15 +00:00
}
else
{
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " Thread \" %s \" has %i locks. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , vbegin - > lockCount , TracyCountBits ( vbegin - > waitList ) ) ;
2018-04-20 20:53:15 +00:00
}
2019-03-16 13:18:43 +00:00
auto waitList = vbegin - > waitList ;
2017-12-17 18:40:45 +00:00
int t = 0 ;
ImGui : : Indent ( ty ) ;
2018-04-20 20:53:15 +00:00
while ( waitList ! = 0 )
2017-12-17 18:40:45 +00:00
{
2018-04-20 20:53:15 +00:00
if ( waitList & 0x1 )
2017-12-17 18:40:45 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
waitList > > = 1 ;
2017-12-17 18:40:45 +00:00
t + + ;
}
ImGui : : Unindent ( ty ) ;
2018-04-20 20:53:15 +00:00
break ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
case LockState : : WaitLock :
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockCount > 0 )
2018-04-20 20:53:15 +00:00
{
ImGui : : Text ( " Thread \" %s \" is blocked by other thread: " , m_worker . GetThreadString ( tid ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" waits to obtain lock after release by thread: " , m_worker . GetThreadString ( tid ) ) ;
}
ImGui : : Indent ( ty ) ;
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ vbegin - > lockingThread ] ) ) ;
2018-04-20 20:53:15 +00:00
ImGui : : Unindent ( ty ) ;
break ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
default :
assert ( false ) ;
break ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
}
else
{
2019-03-16 13:18:43 +00:00
const auto ptr = ( const LockEventShared * ) vbegin - > ptr ;
2018-04-20 20:53:15 +00:00
switch ( drawState )
2017-10-28 13:33:34 +00:00
{
2018-04-20 20:53:15 +00:00
case LockState : : HasLock :
2019-03-16 19:36:06 +00:00
assert ( vbegin - > waitList = = 0 ) ;
2018-04-20 20:53:15 +00:00
if ( ptr - > sharedList = = 0 )
{
2019-03-16 13:18:43 +00:00
assert ( vbegin - > lockCount = = 1 ) ;
2018-04-20 20:53:15 +00:00
ImGui : : Text ( " Thread \" %s \" has lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
}
else if ( TracyCountBits ( ptr - > sharedList ) = = 1 )
{
ImGui : : Text ( " Thread \" %s \" has a sole shared lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" has shared lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
ImGui : : Text ( " Threads sharing the lock (%i): " , TracyCountBits ( ptr - > sharedList ) - 1 ) ;
auto sharedList = ptr - > sharedList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 & & t ! = thread )
{
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
sharedList > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
}
break ;
case LockState : : HasBlockingLock :
{
if ( ptr - > sharedList = = 0 )
{
2019-03-16 13:18:43 +00:00
assert ( vbegin - > lockCount = = 1 ) ;
ImGui : : Text ( " Thread \" %s \" has lock. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , TracyCountBits ( vbegin - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
2018-04-20 20:53:15 +00:00
}
else if ( TracyCountBits ( ptr - > sharedList ) = = 1 )
{
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " Thread \" %s \" has a sole shared lock. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , TracyCountBits ( vbegin - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
2018-04-20 20:53:15 +00:00
}
else
{
ImGui : : Text ( " Thread \" %s \" has shared lock. " , m_worker . GetThreadString ( tid ) ) ;
ImGui : : Text ( " Threads sharing the lock (%i): " , TracyCountBits ( ptr - > sharedList ) - 1 ) ;
auto sharedList = ptr - > sharedList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 & & t ! = thread )
{
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
sharedList > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " Blocked threads (%i): " , TracyCountBits ( vbegin - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
2018-04-20 20:53:15 +00:00
}
2019-03-16 13:18:43 +00:00
auto waitList = vbegin - > waitList ;
2017-12-17 18:40:45 +00:00
int t = 0 ;
ImGui : : Indent ( ty ) ;
2018-04-20 20:53:15 +00:00
while ( waitList ! = 0 )
2017-12-17 18:40:45 +00:00
{
2018-04-20 20:53:15 +00:00
if ( waitList & 0x1 )
2017-12-17 18:40:45 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
waitList > > = 1 ;
t + + ;
}
auto waitShared = ptr - > waitShared ;
t = 0 ;
while ( waitShared ! = 0 )
{
if ( waitShared & 0x1 )
{
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
waitShared > > = 1 ;
2017-12-17 18:40:45 +00:00
t + + ;
}
ImGui : : Unindent ( ty ) ;
2018-04-20 20:53:15 +00:00
break ;
2017-10-28 13:33:34 +00:00
}
2018-04-20 20:53:15 +00:00
case LockState : : WaitLock :
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
assert ( vbegin - > lockCount = = 0 | | vbegin - > lockCount = = 1 ) ;
if ( vbegin - > lockCount ! = 0 | | ptr - > sharedList ! = 0 )
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " Thread \" %s \" is blocked by other threads (%i): " , m_worker . GetThreadString ( tid ) , vbegin - > lockCount + TracyCountBits ( ptr - > sharedList ) ) ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
else
2017-12-17 18:40:45 +00:00
{
2018-04-20 20:53:15 +00:00
ImGui : : Text ( " Thread \" %s \" waits to obtain lock after release by thread: " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
ImGui : : Indent ( ty ) ;
2019-03-16 13:18:43 +00:00
if ( vbegin - > lockCount ! = 0 )
2017-12-17 18:40:45 +00:00
{
2019-03-16 13:18:43 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ vbegin - > lockingThread ] ) ) ;
2018-04-20 20:53:15 +00:00
}
auto sharedList = ptr - > sharedList ;
int t = 0 ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 )
{
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
sharedList > > = 1 ;
t + + ;
2017-12-17 18:40:45 +00:00
}
2018-04-20 20:53:15 +00:00
ImGui : : Unindent ( ty ) ;
break ;
}
default :
assert ( false ) ;
break ;
2017-12-17 18:40:45 +00:00
}
2017-12-10 19:53:20 +00:00
}
2018-04-20 20:53:15 +00:00
ImGui : : EndTooltip ( ) ;
2017-10-05 21:35:21 +00:00
}
2017-10-06 16:25:30 +00:00
}
2018-04-20 20:53:15 +00:00
const auto cfilled = drawState = = LockState : : HasLock ? 0xFF228A22 : ( drawState = = LockState : : HasBlockingLock ? 0xFF228A8A : 0xFF2222BD ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( pxend , double ( w + 10 ) ) , offset + ty ) , cfilled ) ;
2019-03-16 13:18:43 +00:00
if ( m_lockHighlight . thread ! = thread & & ( drawState = = LockState : : HasBlockingLock ) ! = m_lockHighlight . blocked & & next ! = tl . end ( ) & & m_lockHighlight . id = = int64_t ( v . first ) & & m_lockHighlight . begin < = vbegin - > ptr - > time & & m_lockHighlight . end > = next - > ptr - > time )
2018-04-20 20:53:15 +00:00
{
const auto t = uint8_t ( ( sin ( std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) * 0.01 ) * 0.5 + 0.5 ) * 255 ) ;
draw - > AddRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( pxend , double ( w + 10 ) ) , offset + ty ) , 0x00FFFFFF | ( t < < 24 ) , 0.f , - 1 , 2.f ) ;
}
else if ( condensed = = 0 )
{
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 ) ;
}
2018-12-16 19:18:29 +00:00
else if ( condensed > 1 )
{
DrawZigZag ( draw , wpos + ImVec2 ( 0 , offset + round ( ty / 2 ) ) , px0 , pxend , ty / 4 , DarkenColor ( cfilled ) ) ;
}
2017-11-07 00:51:30 +00:00
2018-04-20 20:53:15 +00:00
const auto rx0 = ( t0 - m_zvStart ) * pxns ;
if ( dsz > = MinVisSize )
{
draw - > AddRectFilled ( wpos + ImVec2 ( rx0 , offset ) , wpos + ImVec2 ( std : : min ( rx0 + dsz , px1 ) , offset + ty ) , 0x882222DD ) ;
}
if ( rsz > = MinVisSize )
{
draw - > AddLine ( wpos + ImVec2 ( rx0 + rsz , offset + round ( ty / 2 ) ) , wpos + ImVec2 ( rx0 - rsz , offset + round ( ty / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( rx0 + rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( rx0 + rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( rx0 - rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( rx0 - rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
2017-10-28 12:08:10 +00:00
2018-04-20 20:53:15 +00:00
draw - > AddLine ( wpos + ImVec2 ( px1 + rsz , offset + round ( ty / 2 ) ) , wpos + ImVec2 ( px1 - rsz , offset + round ( ty / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( px1 + rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( px1 + rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( px1 - rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( px1 - rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
}
2017-10-05 21:18:24 +00:00
2018-04-20 20:53:15 +00:00
vbegin = next ;
}
2017-10-05 21:18:24 +00:00
2019-02-17 15:20:56 +00:00
if ( drawn | | m_lockInfoWindow = = v . first )
2017-10-25 22:42:16 +00:00
{
2019-02-17 15:57:52 +00:00
if ( m_lockInfoWindow = = v . first )
{
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) , 0x2288DD88 ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) , 0x4488DD88 ) ;
}
else if ( m_lockHoverHighlight = = v . first )
{
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) , 0x228888DD ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + ty ) , 0x448888DD ) ;
}
2019-02-24 16:30:58 +00:00
DrawLockHeader ( v . first , lockmap , srcloc , hover , draw , wpos , w , ty , offset , it - > second ) ;
2018-04-20 20:53:15 +00:00
cnt + + ;
}
}
else
{
while ( vbegin < vend & & ( state = = LockState : : Nothing | | ( m_onlyContendedLocks & & state = = LockState : : HasLock ) ) )
{
vbegin = GetNextLockFunc ( vbegin , vend , state , threadBit ) ;
2017-10-25 22:42:16 +00:00
}
2018-04-20 20:53:15 +00:00
if ( vbegin < vend ) cnt + + ;
2017-10-04 19:27:06 +00:00
}
}
return cnt ;
}
2019-02-21 22:07:32 +00:00
static const char * FormatPlotValue ( double val , PlotType type )
{
static char buf [ 64 ] ;
switch ( type )
{
case PlotType : : User :
return RealToString ( val , true ) ;
break ;
case PlotType : : Memory :
return MemSizeToString ( val ) ;
break ;
case PlotType : : SysTime :
sprintf ( buf , " %.2f%% " , val ) ;
break ;
default :
assert ( false ) ;
break ;
}
return buf ;
}
2018-04-20 21:00:26 +00:00
int View : : DrawPlots ( int offset , double pxns , const ImVec2 & wpos , bool hover , float yMin , float yMax )
2017-10-13 13:15:57 +00:00
{
2018-06-28 22:38:56 +00:00
const auto PlotHeight = 100 * ImGui : : GetTextLineHeight ( ) / 15.f ;
2019-03-22 19:11:10 +00:00
enum { MaxPoints = 128 } ;
2017-11-26 16:27:51 +00:00
float tmpvec [ MaxPoints * 2 ] ;
2017-10-13 12:54:32 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
const auto ty = ImGui : : GetFontSize ( ) ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-13 13:41:20 +00:00
const auto to = 9.f ;
const auto th = ( ty - to ) * sqrt ( 3 ) * 0.5 ;
2017-10-18 20:29:59 +00:00
const auto nspx = 1.0 / pxns ;
2017-10-13 12:54:32 +00:00
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetPlots ( ) )
2017-10-13 12:54:32 +00:00
{
2019-02-21 19:24:08 +00:00
auto & vis = Vis ( v ) ;
2019-02-21 20:18:41 +00:00
if ( ! vis . visible )
{
vis . height = 0 ;
vis . offset = 0 ;
continue ;
}
2017-10-13 13:36:16 +00:00
assert ( ! v - > data . empty ( ) ) ;
2019-02-21 19:24:08 +00:00
bool & showFull = vis . showFull ;
2017-10-13 12:54:32 +00:00
2019-01-29 22:18:13 +00:00
float txtx = 0 ;
2019-02-21 20:18:41 +00:00
const auto yPos = AdjustThreadPosition ( vis , wpos . y , offset ) ;
const auto oldOffset = offset ;
2019-03-17 16:21:30 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( w , offset + vis . height ) , true ) ;
2018-04-20 21:00:26 +00:00
if ( yPos + ty > = yMin & & yPos < = yMax )
2017-10-13 13:41:20 +00:00
{
2018-04-20 21:00:26 +00:00
if ( showFull )
2017-10-13 13:44:24 +00:00
{
2018-04-20 21:00:26 +00:00
draw - > AddTriangleFilled ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty - to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty * 0.5 , offset + to / 2 + th ) , 0xFF44DDDD ) ;
2017-10-13 13:44:24 +00:00
}
2018-04-20 21:00:26 +00:00
else
{
2019-01-19 13:22:45 +00:00
draw - > AddTriangle ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( to / 2 , offset + ty - to / 2 ) , wpos + ImVec2 ( to / 2 + th , offset + ty * 0.5 ) , 0xFF226E6E , 2.0f ) ;
2018-04-20 21:00:26 +00:00
}
2018-04-28 13:49:51 +00:00
const auto txt = GetPlotName ( v ) ;
2018-04-28 14:44:36 +00:00
txtx = ImGui : : CalcTextSize ( txt ) . x ;
2019-06-05 23:40:23 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ty , offset ) , showFull ? 0xFF44DDDD : 0xFF226E6E , txt ) ;
2018-04-20 21:00:26 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ty - 1 ) , wpos + ImVec2 ( w , offset + ty - 1 ) , 0x8844DDDD ) ;
2017-10-13 13:44:24 +00:00
2018-04-28 14:44:36 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + txtx , offset + ty ) ) )
2018-04-20 21:00:26 +00:00
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Plot \" %s \" " , txt ) ;
ImGui : : Separator ( ) ;
2019-02-24 15:59:45 +00:00
const auto first = v - > data . front ( ) . time ;
const auto last = v - > data . back ( ) . time ;
const auto activity = last - first ;
const auto traceLen = m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ;
TextFocused ( " Appeared at " , TimeToString ( first - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Last event at " , TimeToString ( last - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Activity time: " , TimeToString ( activity ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , activity / double ( traceLen ) * 100 ) ;
ImGui : : Separator ( ) ;
2018-06-29 16:52:28 +00:00
TextFocused ( " Data points: " , RealToString ( v - > data . size ( ) , true ) ) ;
2019-02-21 22:07:32 +00:00
TextFocused ( " Data range: " , FormatPlotValue ( v - > max - v - > min , v - > type ) ) ;
TextFocused ( " Min value: " , FormatPlotValue ( v - > min , v - > type ) ) ;
TextFocused ( " Max value: " , FormatPlotValue ( v - > max , v - > type ) ) ;
2019-02-24 15:59:45 +00:00
TextFocused ( " Data/second: " , RealToString ( double ( v - > data . size ( ) ) / activity * 1000000000ll , true ) ) ;
2018-04-20 21:00:26 +00:00
2019-02-24 15:59:45 +00:00
const auto it = std : : lower_bound ( v - > data . begin ( ) , v - > data . end ( ) , last - 1000000000ll * 10 , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
const auto tr10 = last - it - > time ;
2018-04-20 21:00:26 +00:00
if ( tr10 ! = 0 )
{
2018-06-29 16:52:28 +00:00
TextFocused ( " D/s (10s): " , RealToString ( double ( std : : distance ( it , v - > data . end ( ) ) ) / tr10 * 1000000000ll , true ) ) ;
2018-04-20 21:00:26 +00:00
}
ImGui : : EndTooltip ( ) ;
2019-02-24 15:59:45 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
showFull = ! showFull ;
}
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToRange ( first , last ) ;
}
2018-04-20 21:00:26 +00:00
}
2017-10-13 13:41:20 +00:00
}
2017-10-13 12:54:32 +00:00
2017-10-13 13:41:20 +00:00
offset + = ty ;
2017-10-13 12:54:32 +00:00
2018-02-13 13:57:47 +00:00
if ( showFull )
2017-10-13 12:54:32 +00:00
{
2018-04-20 21:00:26 +00:00
auto yPos = wpos . y + offset ;
if ( yPos + PlotHeight > = yMin & & yPos < = yMax )
{
const auto & vec = v - > data ;
2018-07-17 22:21:16 +00:00
2018-07-19 13:43:45 +00:00
if ( v - > type = = PlotType : : Memory )
2018-07-17 22:21:16 +00:00
{
const auto & mem = m_worker . GetMemData ( ) ;
2018-07-19 13:43:45 +00:00
if ( m_memoryAllocInfoWindow > = 0 )
{
const auto & ev = mem . data [ m_memoryAllocInfoWindow ] ;
const auto tStart = ev . timeAlloc ;
const auto tEnd = ev . timeFree < 0 ? m_worker . GetLastTime ( ) : ev . timeFree ;
const auto px0 = ( tStart - m_zvStart ) * pxns ;
const auto px1 = std : : max ( px0 + std : : max ( 1.0 , pxns * 0.5 ) , ( tEnd - m_zvStart ) * pxns ) ;
draw - > AddRectFilled ( ImVec2 ( wpos . x + px0 , yPos ) , ImVec2 ( wpos . x + px1 , yPos + PlotHeight ) , 0x2288DD88 ) ;
draw - > AddRect ( ImVec2 ( wpos . x + px0 , yPos ) , ImVec2 ( wpos . x + px1 , yPos + PlotHeight ) , 0x4488DD88 ) ;
}
if ( m_memoryAllocHover > = 0 & & m_memoryAllocHover ! = m_memoryAllocInfoWindow )
{
const auto & ev = mem . data [ m_memoryAllocHover ] ;
const auto tStart = ev . timeAlloc ;
const auto tEnd = ev . timeFree < 0 ? m_worker . GetLastTime ( ) : ev . timeFree ;
const auto px0 = ( tStart - m_zvStart ) * pxns ;
const auto px1 = std : : max ( px0 + std : : max ( 1.0 , pxns * 0.5 ) , ( tEnd - m_zvStart ) * pxns ) ;
draw - > AddRectFilled ( ImVec2 ( wpos . x + px0 , yPos ) , ImVec2 ( wpos . x + px1 , yPos + PlotHeight ) , 0x228888DD ) ;
draw - > AddRect ( ImVec2 ( wpos . x + px0 , yPos ) , ImVec2 ( wpos . x + px1 , yPos + PlotHeight ) , 0x448888DD ) ;
2018-07-17 22:21:16 +00:00
2018-07-19 13:43:45 +00:00
if ( m_memoryAllocHoverWait > 0 )
{
m_memoryAllocHoverWait - - ;
}
else
{
m_memoryAllocHover = - 1 ;
}
}
2018-07-17 22:21:16 +00:00
}
2018-04-20 21:00:26 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - m_worker . GetDelay ( ) , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
auto end = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + m_worker . GetResolution ( ) , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
2017-10-13 13:41:20 +00:00
2018-04-20 21:00:26 +00:00
if ( end ! = vec . end ( ) ) end + + ;
if ( it ! = vec . begin ( ) ) it - - ;
2017-10-13 13:41:20 +00:00
2018-04-20 21:00:26 +00:00
double min = it - > val ;
double max = it - > val ;
2019-04-23 15:17:25 +00:00
const auto num = std : : distance ( it , end ) ;
if ( num > 1000000 )
2017-10-13 13:41:20 +00:00
{
2018-04-20 21:00:26 +00:00
min = v - > min ;
max = v - > max ;
}
else
{
auto tmp = it ;
+ + tmp ;
const auto sz = end - tmp ;
for ( ptrdiff_t i = 0 ; i < sz ; i + + )
{
min = tmp [ i ] . val < min ? tmp [ i ] . val : min ;
max = tmp [ i ] . val > max ? tmp [ i ] . val : max ;
}
2017-10-13 13:41:20 +00:00
}
2019-06-02 23:19:01 +00:00
if ( min = = max )
{
min - - ;
max + + ;
}
2017-10-13 12:54:32 +00:00
2019-03-17 16:21:30 +00:00
auto pvit = m_plotView . find ( v ) ;
if ( pvit = = m_plotView . end ( ) )
{
pvit = m_plotView . emplace ( v , PlotView { min , max } ) . first ;
}
auto & pv = pvit - > second ;
if ( pv . min ! = min | | pv . max ! = max )
{
const auto dt = ImGui : : GetIO ( ) . DeltaTime ;
const auto minDiff = min - pv . min ;
const auto maxDiff = max - pv . max ;
pv . min + = minDiff * 15.0 * dt ;
pv . max + = maxDiff * 15.0 * dt ;
const auto minDiffNew = min - pv . min ;
const auto maxDiffNew = max - pv . max ;
if ( minDiff * minDiffNew < 0 ) pv . min = min ;
if ( maxDiff * maxDiffNew < 0 ) pv . max = max ;
min = pv . min ;
max = pv . max ;
}
2018-04-20 21:00:26 +00:00
const auto revrange = 1.0 / ( max - min ) ;
2017-10-19 19:04:57 +00:00
2018-04-20 21:00:26 +00:00
if ( it = = vec . begin ( ) )
2017-10-18 20:29:59 +00:00
{
2018-04-20 21:00:26 +00:00
const auto x = ( it - > time - m_zvStart ) * pxns ;
const auto y = PlotHeight - ( it - > val - min ) * revrange * PlotHeight ;
2018-06-28 22:38:56 +00:00
DrawPlotPoint ( wpos , x , y , offset , 0xFF44DDDD , hover , false , it , 0 , false , v - > type , PlotHeight ) ;
2017-10-18 20:29:59 +00:00
}
2018-04-20 21:00:26 +00:00
auto prevx = it ;
auto prevy = it ;
+ + it ;
ptrdiff_t skip = 0 ;
while ( it < end )
2017-10-18 20:29:59 +00:00
{
2018-04-20 21:00:26 +00:00
const auto x0 = ( prevx - > time - m_zvStart ) * pxns ;
const auto x1 = ( it - > time - m_zvStart ) * pxns ;
const auto y0 = PlotHeight - ( prevy - > val - min ) * revrange * PlotHeight ;
const auto y1 = PlotHeight - ( it - > val - min ) * revrange * PlotHeight ;
2017-10-18 20:29:59 +00:00
2018-04-20 21:00:26 +00:00
draw - > AddLine ( wpos + ImVec2 ( x0 , offset + y0 ) , wpos + ImVec2 ( x1 , offset + y1 ) , 0xFF44DDDD ) ;
2017-10-19 17:43:27 +00:00
2018-04-20 21:00:26 +00:00
const auto rx = skip = = 0 ? 2.0 : ( skip = = 1 ? 2.5 : 4.0 ) ;
auto range = std : : upper_bound ( it , end , int64_t ( it - > time + nspx * rx ) , [ ] ( const auto & l , const auto & r ) { return l < r . time ; } ) ;
assert ( range > it ) ;
const auto rsz = std : : distance ( it , range ) ;
if ( rsz = = 1 )
2017-10-18 20:29:59 +00:00
{
2018-06-28 22:38:56 +00:00
DrawPlotPoint ( wpos , x1 , y1 , offset , 0xFF44DDDD , hover , true , it , prevy - > val , false , v - > type , PlotHeight ) ;
2018-04-20 21:00:26 +00:00
prevx = it ;
prevy = it ;
+ + it ;
2017-10-18 20:29:59 +00:00
}
2018-04-20 21:00:26 +00:00
else
{
prevx = it ;
2017-10-18 20:29:59 +00:00
2018-04-20 21:00:26 +00:00
skip = rsz / MaxPoints ;
const auto skip1 = std : : max < ptrdiff_t > ( 1 , skip ) ;
const auto sz = rsz / skip1 + 1 ;
assert ( sz < = MaxPoints * 2 ) ;
2017-10-18 20:29:59 +00:00
2018-04-20 21:00:26 +00:00
auto dst = tmpvec ;
for ( ; ; )
2017-10-18 20:29:59 +00:00
{
2018-04-20 21:00:26 +00:00
* dst + + = float ( it - > val ) ;
if ( std : : distance ( it , range ) > skip1 )
{
it + = skip1 ;
}
else
{
break ;
}
2017-10-18 20:29:59 +00:00
}
2018-04-20 21:00:26 +00:00
pdqsort_branchless ( tmpvec , dst ) ;
2019-03-22 19:11:24 +00:00
if ( rsz > MaxPoints )
2017-10-18 20:29:59 +00:00
{
2019-03-22 19:11:24 +00:00
draw - > AddLine ( wpos + ImVec2 ( x1 , offset + PlotHeight - ( tmpvec [ 0 ] - min ) * revrange * PlotHeight ) , wpos + ImVec2 ( x1 , offset + PlotHeight - ( dst [ - 1 ] - min ) * revrange * PlotHeight ) , 0xFF44DDDD , 4.f ) ;
2019-03-23 01:24:45 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( x1 - 2 , offset ) , wpos + ImVec2 ( x1 + 2 , offset + PlotHeight ) ) )
{
ImGui : : BeginTooltip ( ) ;
TextFocused ( " Number of values: " , RealToString ( rsz , true ) ) ;
TextDisabledUnformatted ( " Estimated range: " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s " , FormatPlotValue ( tmpvec [ 0 ] , v - > type ) , FormatPlotValue ( dst [ - 1 ] , v - > type ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , FormatPlotValue ( dst [ - 1 ] - tmpvec [ 0 ] , v - > type ) ) ;
ImGui : : EndTooltip ( ) ;
}
2019-03-22 19:11:24 +00:00
}
else
{
draw - > AddLine ( wpos + ImVec2 ( x1 , offset + PlotHeight - ( tmpvec [ 0 ] - min ) * revrange * PlotHeight ) , wpos + ImVec2 ( x1 , offset + PlotHeight - ( dst [ - 1 ] - min ) * revrange * PlotHeight ) , 0xFF44DDDD ) ;
auto vit = tmpvec ;
while ( vit ! = dst )
2018-04-20 21:00:26 +00:00
{
2019-03-22 19:11:24 +00:00
auto vrange = std : : upper_bound ( vit , dst , * vit + 3.0 / ( revrange * PlotHeight ) , [ ] ( const auto & l , const auto & r ) { return l < r ; } ) ;
assert ( vrange > vit ) ;
if ( std : : distance ( vit , vrange ) = = 1 )
{
DrawPlotPoint ( wpos , x1 , PlotHeight - ( * vit - min ) * revrange * PlotHeight , offset , 0xFF44DDDD , hover , false , * vit , 0 , false , v - > type , PlotHeight ) ;
}
else
{
DrawPlotPoint ( wpos , x1 , PlotHeight - ( * vit - min ) * revrange * PlotHeight , offset , 0xFF44DDDD , hover , false , * vit , 0 , true , v - > type , PlotHeight ) ;
}
vit = vrange ;
2018-04-20 21:00:26 +00:00
}
2017-10-18 20:29:59 +00:00
}
2018-04-20 21:00:26 +00:00
prevy = it - 1 ;
}
2017-10-18 20:29:59 +00:00
}
2017-10-13 12:54:32 +00:00
2018-04-20 21:00:26 +00:00
char tmp [ 64 ] ;
2018-04-28 14:44:36 +00:00
if ( yPos + ty > = yMin & & yPos < = yMax )
{
2019-04-23 15:17:25 +00:00
sprintf ( tmp , " (y-range: %s, visible data points: %s) " , FormatPlotValue ( max - min , v - > type ) , RealToString ( num , true ) ) ;
2018-04-28 14:44:36 +00:00
draw - > AddText ( wpos + ImVec2 ( ty * 1.5f + txtx , offset - ty ) , 0x8844DDDD , tmp ) ;
}
2019-02-21 22:07:32 +00:00
sprintf ( tmp , " %s " , FormatPlotValue ( max , v - > type ) ) ;
2018-04-20 21:00:26 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( 0 , offset ) , 0x8844DDDD , tmp ) ;
offset + = PlotHeight - ty ;
2019-02-21 22:07:32 +00:00
sprintf ( tmp , " %s " , FormatPlotValue ( min , v - > type ) ) ;
2018-04-20 21:00:26 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( 0 , offset ) , 0x8844DDDD , tmp ) ;
2017-11-26 01:31:48 +00:00
2018-04-20 21:00:26 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ty - 1 ) , wpos + ImVec2 ( w , offset + ty - 1 ) , 0x8844DDDD ) ;
offset + = ty ;
}
else
{
offset + = PlotHeight ;
}
2017-10-13 12:54:32 +00:00
}
2017-10-13 13:41:20 +00:00
offset + = 0.2 * ty ;
2019-02-21 20:18:41 +00:00
AdjustThreadHeight ( vis , oldOffset , offset ) ;
ImGui : : PopClipRect ( ) ;
2017-10-13 12:54:32 +00:00
}
return offset ;
}
2019-02-21 22:07:32 +00:00
void View : : DrawPlotPoint ( const ImVec2 & wpos , float x , float y , int offset , uint32_t color , bool hover , bool hasPrev , double val , double prev , bool merged , PlotType type , float PlotHeight )
2017-10-13 13:09:01 +00:00
{
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-18 20:29:59 +00:00
if ( merged )
{
draw - > AddRectFilled ( wpos + ImVec2 ( x - 1.5f , offset + y - 1.5f ) , wpos + ImVec2 ( x + 2.5f , offset + y + 2.5f ) , color ) ;
}
else
{
draw - > AddRect ( wpos + ImVec2 ( x - 1.5f , offset + y - 1.5f ) , wpos + ImVec2 ( x + 2.5f , offset + y + 2.5f ) , color ) ;
}
2017-10-13 13:15:57 +00:00
2017-10-21 11:47:32 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( x - 2 , offset ) , wpos + ImVec2 ( x + 2 , offset + PlotHeight ) ) )
2017-10-13 13:15:57 +00:00
{
ImGui : : BeginTooltip ( ) ;
2019-02-21 22:07:32 +00:00
TextFocused ( " Value: " , FormatPlotValue ( val , type ) ) ;
2017-10-13 13:15:57 +00:00
if ( hasPrev )
{
2019-02-21 22:07:32 +00:00
TextFocused ( " Change: " , FormatPlotValue ( val - prev , type ) ) ;
2017-10-13 13:15:57 +00:00
}
ImGui : : EndTooltip ( ) ;
}
2017-10-13 13:09:01 +00:00
}
2018-06-28 22:38:56 +00:00
void View : : DrawPlotPoint ( const ImVec2 & wpos , float x , float y , int offset , uint32_t color , bool hover , bool hasPrev , const PlotItem * item , double prev , bool merged , PlotType type , float PlotHeight )
2018-05-27 17:51:45 +00:00
{
auto draw = ImGui : : GetWindowDrawList ( ) ;
if ( merged )
{
draw - > AddRectFilled ( wpos + ImVec2 ( x - 1.5f , offset + y - 1.5f ) , wpos + ImVec2 ( x + 2.5f , offset + y + 2.5f ) , color ) ;
}
else
{
draw - > AddRect ( wpos + ImVec2 ( x - 1.5f , offset + y - 1.5f ) , wpos + ImVec2 ( x + 2.5f , offset + y + 2.5f ) , color ) ;
}
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( x - 2 , offset ) , wpos + ImVec2 ( x + 2 , offset + PlotHeight ) ) )
{
ImGui : : BeginTooltip ( ) ;
2018-08-08 18:38:43 +00:00
if ( type = = PlotType : : Memory )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Value: " ) ;
2018-08-08 18:38:43 +00:00
ImGui : : SameLine ( ) ;
if ( item - > val < 10000ll )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( MemSizeToString ( item - > val ) ) ;
2018-08-08 18:38:43 +00:00
}
else
{
ImGui : : Text ( " %s (%s) " , MemSizeToString ( item - > val ) , RealToString ( item - > val , true ) ) ;
}
}
else
{
2019-02-21 22:07:32 +00:00
TextFocused ( " Value: " , FormatPlotValue ( item - > val , type ) ) ;
2018-08-08 18:38:43 +00:00
}
2018-05-27 17:51:45 +00:00
if ( hasPrev )
{
2018-05-27 18:11:33 +00:00
const auto change = item - > val - prev ;
2019-02-21 22:07:32 +00:00
TextFocused ( " Change: " , FormatPlotValue ( change , type ) ) ;
2018-05-27 18:11:33 +00:00
if ( type = = PlotType : : Memory )
{
auto & mem = m_worker . GetMemData ( ) ;
const MemEvent * ev = nullptr ;
if ( change > 0 )
{
auto it = std : : lower_bound ( mem . data . begin ( ) , mem . data . end ( ) , item - > time , [ ] ( const auto & lhs , const auto & rhs ) { return lhs . timeAlloc < rhs ; } ) ;
if ( it ! = mem . data . end ( ) & & it - > timeAlloc = = item - > time )
{
ev = it ;
}
}
else
{
const auto & data = mem . data ;
auto it = std : : lower_bound ( mem . frees . begin ( ) , mem . frees . end ( ) , item - > time , [ & data ] ( const auto & lhs , const auto & rhs ) { return data [ lhs ] . timeFree < rhs ; } ) ;
if ( it ! = mem . frees . end ( ) & & data [ * it ] . timeFree = = item - > time )
{
ev = & data [ * it ] ;
}
}
if ( ev )
{
ImGui : : Separator ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Address: " ) ;
2018-06-29 16:52:28 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " 0x% " PRIx64 , ev - > ptr ) ;
2018-08-04 17:51:50 +00:00
TextFocused ( " Appeared at " , TimeToString ( ev - > timeAlloc - m_worker . GetTimeBegin ( ) ) ) ;
2018-05-27 18:11:33 +00:00
if ( change > 0 )
{
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (this event) " ) ;
}
if ( ev - > timeFree < 0 )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Allocation still active " ) ;
2018-05-27 18:11:33 +00:00
}
else
{
2018-08-04 17:51:50 +00:00
TextFocused ( " Freed at " , TimeToString ( ev - > timeFree - m_worker . GetTimeBegin ( ) ) ) ;
2018-05-27 18:11:33 +00:00
if ( change < 0 )
{
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " (this event) " ) ;
2018-05-27 18:11:33 +00:00
}
2018-06-29 16:52:28 +00:00
TextFocused ( " Duration: " , TimeToString ( ev - > timeFree - ev - > timeAlloc ) ) ;
2018-05-27 18:11:33 +00:00
}
2018-06-29 16:54:19 +00:00
uint64_t tid ;
2018-05-27 18:11:33 +00:00
if ( change > 0 )
{
2018-06-29 16:54:19 +00:00
tid = m_worker . DecompressThread ( ev - > threadAlloc ) ;
2018-05-27 18:11:33 +00:00
}
else
{
2018-06-29 16:54:19 +00:00
tid = m_worker . DecompressThread ( ev - > threadFree ) ;
2018-05-27 18:11:33 +00:00
}
2018-06-29 16:54:19 +00:00
TextFocused ( " Thread: " , m_worker . GetThreadString ( tid ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2018-05-27 18:17:20 +00:00
2018-07-19 13:43:45 +00:00
m_memoryAllocHover = std : : distance ( mem . data . begin ( ) , ev ) ;
m_memoryAllocHoverWait = 2 ;
2018-05-27 18:17:20 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-07-19 13:43:45 +00:00
m_memoryAllocInfoWindow = m_memoryAllocHover ;
2018-05-27 18:17:20 +00:00
}
2018-05-27 18:11:33 +00:00
}
}
2018-05-27 17:51:45 +00:00
}
ImGui : : EndTooltip ( ) ;
}
}
2017-11-12 00:25:44 +00:00
void View : : DrawInfoWindow ( )
2017-09-29 19:49:14 +00:00
{
2017-11-12 00:25:44 +00:00
if ( m_zoneInfoWindow )
{
DrawZoneInfoWindow ( ) ;
}
else if ( m_gpuInfoWindow )
{
DrawGpuInfoWindow ( ) ;
}
}
2017-09-29 20:06:31 +00:00
2018-06-24 13:54:36 +00:00
template < typename T >
2019-02-27 20:12:56 +00:00
void DrawZoneTrace ( T zone , const std : : vector < T > & trace , const Worker & worker , BuzzAnim < const void * > & anim , View & view , bool & showUnknownFrames , std : : function < void ( T , int & ) > showZone )
2018-06-24 13:54:36 +00:00
{
bool expand = ImGui : : TreeNode ( " Zone trace " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( trace . size ( ) , true ) ) ;
if ( ! expand ) return ;
2018-12-21 20:10:29 +00:00
ImGui : : SameLine ( ) ;
2019-03-08 17:39:41 +00:00
SmallCheckbox ( " Show unknown frames " , & showUnknownFrames ) ;
2018-12-21 20:10:29 +00:00
2019-02-27 20:12:56 +00:00
int fidx = 1 ;
TextDisabledUnformatted ( " 0. " ) ;
ImGui : : SameLine ( ) ;
TextDisabledUnformatted ( " [this zone] " ) ;
2018-06-24 14:57:57 +00:00
if ( ! trace . empty ( ) )
2018-06-24 13:54:36 +00:00
{
2018-06-24 14:57:57 +00:00
T prev = zone ;
const auto sz = trace . size ( ) ;
for ( size_t i = 0 ; i < sz ; i + + )
{
auto curr = trace [ i ] ;
if ( prev - > callstack = = 0 | | curr - > callstack = = 0 )
{
2018-12-21 20:10:29 +00:00
if ( showUnknownFrames )
{
2019-02-27 20:12:56 +00:00
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " [unknown frames] " ) ;
2018-12-21 20:10:29 +00:00
}
2018-06-24 14:57:57 +00:00
}
else if ( prev - > callstack ! = curr - > callstack )
{
auto & prevCs = worker . GetCallstack ( prev - > callstack ) ;
auto & currCs = worker . GetCallstack ( curr - > callstack ) ;
2018-06-24 15:38:32 +00:00
const auto psz = int8_t ( prevCs . size ( ) ) ;
int8_t idx ;
2018-06-24 14:57:57 +00:00
for ( idx = 0 ; idx < psz ; idx + + )
{
auto pf = prevCs [ idx ] ;
bool found = false ;
for ( auto & cf : currCs )
{
2019-03-03 15:50:18 +00:00
if ( cf . data = = pf . data )
2018-06-24 14:57:57 +00:00
{
2018-06-24 15:38:32 +00:00
idx - - ;
2018-06-24 14:57:57 +00:00
found = true ;
break ;
}
}
if ( found ) break ;
}
2018-06-24 15:38:32 +00:00
for ( int8_t j = 1 ; j < idx ; j + + )
2018-06-24 14:57:57 +00:00
{
2019-01-20 18:11:48 +00:00
auto frameData = worker . GetCallstackFrame ( prevCs [ j ] ) ;
2019-02-06 13:17:18 +00:00
auto frame = frameData - > data + frameData - > size - 1 ;
2019-02-27 20:12:56 +00:00
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( worker . GetString ( frame - > name ) ) ;
2018-06-24 14:57:57 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
2018-08-18 12:26:10 +00:00
if ( anim . Match ( frame ) )
{
const auto time = anim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
const auto fileName = worker . GetString ( frame - > file ) ;
2018-06-24 14:57:57 +00:00
if ( frame - > line = = 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( fileName ) ;
2018-06-24 14:57:57 +00:00
}
else
{
2018-08-18 12:26:10 +00:00
ImGui : : TextDisabled ( " %s:%i " , fileName , frame - > line ) ;
}
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( frame - > line ! = 0 & & FileExists ( fileName ) )
{
view . SetTextEditorFile ( fileName , frame - > line ) ;
}
else
{
anim . Enable ( frame , 0.5f ) ;
}
2018-06-24 14:57:57 +00:00
}
}
}
2019-02-27 20:12:56 +00:00
showZone ( curr , fidx ) ;
2018-06-24 14:57:57 +00:00
prev = curr ;
}
}
auto last = trace . empty ( ) ? zone : trace . back ( ) ;
if ( last - > callstack = = 0 )
{
2018-12-21 20:10:29 +00:00
if ( showUnknownFrames )
{
2019-02-27 20:12:56 +00:00
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " [unknown frames] " ) ;
2018-12-21 20:10:29 +00:00
}
2018-06-24 14:57:57 +00:00
}
else
{
auto & cs = worker . GetCallstack ( last - > callstack ) ;
const auto csz = cs . size ( ) ;
for ( uint8_t i = 1 ; i < csz ; i + + )
{
2019-01-20 18:11:48 +00:00
auto frameData = worker . GetCallstackFrame ( cs [ i ] ) ;
2019-02-06 13:17:18 +00:00
auto frame = frameData - > data + frameData - > size - 1 ;
2019-02-27 20:12:56 +00:00
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( worker . GetString ( frame - > name ) ) ;
2018-06-24 14:57:57 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
2018-08-18 12:26:10 +00:00
if ( anim . Match ( frame ) )
{
const auto time = anim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
const auto fileName = worker . GetString ( frame - > file ) ;
2018-06-24 14:57:57 +00:00
if ( frame - > line = = 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( fileName ) ;
2018-06-24 14:57:57 +00:00
}
else
{
2018-08-18 12:26:10 +00:00
ImGui : : TextDisabled ( " %s:%i " , fileName , frame - > line ) ;
}
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( frame - > line ! = 0 & & FileExists ( fileName ) )
{
view . SetTextEditorFile ( fileName , frame - > line ) ;
}
else
{
anim . Enable ( frame , 0.5f ) ;
}
2018-06-24 14:57:57 +00:00
}
}
2018-06-24 13:54:36 +00:00
}
ImGui : : TreePop ( ) ;
}
2017-11-12 00:25:44 +00:00
void View : : DrawZoneInfoWindow ( )
{
2017-09-29 19:49:14 +00:00
auto & ev = * m_zoneInfoWindow ;
2017-09-29 20:06:31 +00:00
int dmul = 1 ;
2018-04-05 17:31:04 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 500 , 400 ) , ImGuiCond_FirstUseEver ) ;
2017-09-29 19:49:14 +00:00
bool show = true ;
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Zone info " , & show ) ;
2017-09-29 20:13:22 +00:00
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_MICROSCOPE " Zoom to zone " ) )
# else
2017-09-29 20:01:30 +00:00
if ( ImGui : : Button ( " Zoom to zone " ) )
2018-08-17 21:47:01 +00:00
# endif
2017-09-29 20:01:30 +00:00
{
ZoomToZone ( ev ) ;
}
2018-08-18 00:12:34 +00:00
auto parent = GetZoneParent ( ev ) ;
if ( parent )
{
ImGui : : SameLine ( ) ;
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-08-18 00:12:34 +00:00
if ( ImGui : : Button ( ICON_FA_ARROW_UP " Go to parent " ) )
2018-08-17 21:47:01 +00:00
# else
2018-08-18 00:12:34 +00:00
if ( ImGui : : Button ( " Go to parent " ) )
2018-08-17 21:47:01 +00:00
# endif
2017-09-30 11:41:03 +00:00
{
2018-05-02 17:23:46 +00:00
ShowZoneInfo ( * parent ) ;
2017-09-30 11:41:03 +00:00
}
}
2018-04-05 17:31:04 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_CHART_BAR " Statistics " ) )
# else
2018-04-05 17:31:04 +00:00
if ( ImGui : : Button ( " Statistics " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-04-05 17:31:04 +00:00
{
m_findZone . ShowZone ( ev . srcloc , m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ) ;
}
2018-06-21 23:21:51 +00:00
if ( ev . callstack ! = 0 )
{
ImGui : : SameLine ( ) ;
2018-06-22 00:24:36 +00:00
bool hilite = m_callstackInfoWindow = = ev . callstack ;
if ( hilite )
{
2018-12-18 15:28:09 +00:00
SetButtonHighlightColor ( ) ;
2018-06-22 00:24:36 +00:00
}
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_ALIGN_JUSTIFY " Call stack " ) )
# else
2018-08-17 20:00:35 +00:00
if ( ImGui : : Button ( " Call stack " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-06-21 23:21:51 +00:00
{
m_callstackInfoWindow = ev . callstack ;
}
2018-06-22 00:24:36 +00:00
if ( hilite )
{
ImGui : : PopStyleColor ( 3 ) ;
}
2018-06-21 23:21:51 +00:00
}
2018-08-18 18:38:14 +00:00
const auto fileName = m_worker . GetString ( srcloc . file ) ;
if ( FileExists ( fileName ) )
2018-08-17 12:54:28 +00:00
{
ImGui : : SameLine ( ) ;
2018-08-17 22:28:36 +00:00
bool hilite = m_textEditorFile = = fileName ;
if ( hilite )
{
2018-12-18 15:28:09 +00:00
SetButtonHighlightColor ( ) ;
2018-08-17 22:28:36 +00:00
}
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_FILE_ALT " Source " ) )
# else
2018-08-17 12:54:28 +00:00
if ( ImGui : : Button ( " Source " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-08-17 12:54:28 +00:00
{
2018-08-17 22:28:36 +00:00
SetTextEditorFile ( fileName , srcloc . line ) ;
}
if ( hilite )
{
ImGui : : PopStyleColor ( 3 ) ;
2018-08-17 12:54:28 +00:00
}
}
2018-05-02 17:25:52 +00:00
if ( ! m_zoneInfoStack . empty ( ) )
{
ImGui : : SameLine ( ) ;
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_ARROW_LEFT " Go back " ) )
# else
2018-05-02 17:25:52 +00:00
if ( ImGui : : Button ( " Go back " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-05-02 17:25:52 +00:00
{
m_zoneInfoWindow = m_zoneInfoStack . back_and_pop ( ) ;
}
}
2017-09-29 20:06:31 +00:00
ImGui : : Separator ( ) ;
2019-03-17 15:33:18 +00:00
auto threadData = GetZoneThreadData ( ev ) ;
assert ( threadData ) ;
const auto tid = threadData - > id ;
2018-06-29 14:14:31 +00:00
if ( ev . name . active )
{
2018-06-29 16:27:34 +00:00
TextFocused ( " Zone name: " , m_worker . GetString ( ev . name ) ) ;
2018-06-29 14:14:31 +00:00
}
2017-11-14 22:31:24 +00:00
if ( srcloc . name . active )
2017-09-29 19:49:14 +00:00
{
2018-06-29 16:27:34 +00:00
TextFocused ( " Zone name: " , m_worker . GetString ( srcloc . name ) ) ;
2017-09-29 19:49:14 +00:00
}
2018-06-29 16:27:34 +00:00
TextFocused ( " Function: " , m_worker . GetString ( srcloc . function ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Location: " ) ;
2018-06-29 16:27:34 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
TextFocused ( " Thread: " , m_worker . GetThreadString ( tid ) ) ;
2018-03-19 01:22:08 +00:00
ImGui : : SameLine ( ) ;
2019-02-22 23:34:01 +00:00
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2017-11-14 22:31:24 +00:00
if ( ev . text . active )
2017-09-29 19:49:14 +00:00
{
2018-06-29 16:27:34 +00:00
TextFocused ( " User text: " , m_worker . GetString ( ev . text ) ) ;
2017-09-29 20:06:31 +00:00
dmul + + ;
2017-09-29 19:49:14 +00:00
}
2017-09-29 20:06:31 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-09-29 20:13:22 +00:00
const auto ztime = end - ev . start ;
2019-03-29 23:52:25 +00:00
const auto selftime = GetZoneSelfTime ( ev ) ;
2018-08-04 17:51:50 +00:00
TextFocused ( " Time from start of program: " , TimeToString ( ev . start - m_worker . GetTimeBegin ( ) ) ) ;
2018-06-29 16:27:34 +00:00
TextFocused ( " Execution time: " , TimeToString ( ztime ) ) ;
2019-06-22 11:22:13 +00:00
# ifndef TRACY_NO_STATISTICS
auto & zoneData = m_worker . GetZonesForSourceLocation ( ev . srcloc ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%% of average time) " , float ( ztime ) / zoneData . total * zoneData . zones . size ( ) * 100 ) ;
# endif
2019-01-23 17:04:31 +00:00
TextFocused ( " Self time: " , TimeToString ( selftime ) ) ;
2019-06-22 20:42:57 +00:00
if ( ztime ! = 0 )
{
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , 100.f * selftime / ztime ) ;
}
2017-09-29 20:13:22 +00:00
2018-05-02 15:46:09 +00:00
auto & mem = m_worker . GetMemData ( ) ;
2019-03-06 23:57:32 +00:00
if ( ! mem . data . empty ( ) )
2018-05-02 15:46:09 +00:00
{
ImGui : : Separator ( ) ;
2019-03-06 23:57:32 +00:00
if ( ! mem . plot )
2018-05-02 15:46:09 +00:00
{
2019-03-06 23:57:32 +00:00
ImGui : : Text ( " Please wait, computing data... " ) ;
DrawWaitingDots ( s_time ) ;
2018-05-02 15:46:09 +00:00
}
else
{
2019-03-06 23:57:32 +00:00
const auto thread = m_worker . CompressThread ( tid ) ;
2018-05-02 16:06:27 +00:00
2019-03-06 23:57:32 +00:00
auto ait = std : : lower_bound ( mem . data . begin ( ) , mem . data . end ( ) , ev . start , [ ] ( const auto & l , const auto & r ) { return l . timeAlloc < r ; } ) ;
const auto aend = std : : upper_bound ( mem . data . begin ( ) , mem . data . end ( ) , end , [ ] ( const auto & l , const auto & r ) { return l < r . timeAlloc ; } ) ;
2018-05-02 17:03:34 +00:00
2019-03-06 23:57:32 +00:00
auto fit = std : : lower_bound ( mem . frees . begin ( ) , mem . frees . end ( ) , ev . start , [ & mem ] ( const auto & l , const auto & r ) { return mem . data [ l ] . timeFree < r ; } ) ;
const auto fend = std : : upper_bound ( mem . frees . begin ( ) , mem . frees . end ( ) , end , [ & mem ] ( const auto & l , const auto & r ) { return l < mem . data [ r ] . timeFree ; } ) ;
2018-05-02 15:46:09 +00:00
2019-03-06 23:57:32 +00:00
const auto aDist = std : : distance ( ait , aend ) ;
const auto fDist = std : : distance ( fit , fend ) ;
if ( aDist = = 0 & & fDist = = 0 )
2018-05-02 16:13:13 +00:00
{
2019-03-17 01:56:26 +00:00
TextDisabledUnformatted ( " No memory events. " ) ;
2018-05-02 16:13:13 +00:00
}
else
{
2019-03-06 23:57:32 +00:00
int64_t cAlloc = 0 ;
int64_t cFree = 0 ;
int64_t nAlloc = 0 ;
int64_t nFree = 0 ;
auto ait2 = ait ;
auto fit2 = fit ;
2018-05-02 17:03:34 +00:00
2019-03-06 23:57:32 +00:00
while ( ait ! = aend )
2018-05-02 17:03:34 +00:00
{
2019-03-06 23:57:32 +00:00
if ( ait - > threadAlloc = = thread )
{
cAlloc + = ait - > size ;
nAlloc + + ;
}
ait + + ;
}
while ( fit ! = fend )
{
if ( mem . data [ * fit ] . threadFree = = thread )
{
cFree + = mem . data [ * fit ] . size ;
nFree + + ;
}
fit + + ;
}
if ( nAlloc = = 0 & & nFree = = 0 )
{
2019-03-17 01:56:26 +00:00
TextDisabledUnformatted ( " No memory events. " ) ;
2019-03-06 23:57:32 +00:00
}
else
{
ImGui : : TextUnformatted ( RealToString ( nAlloc + nFree , true ) ) ;
ImGui : : SameLine ( ) ;
TextDisabledUnformatted ( " memory events. " ) ;
ImGui : : TextUnformatted ( RealToString ( nAlloc , true ) ) ;
ImGui : : SameLine ( ) ;
TextDisabledUnformatted ( " allocs, " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( RealToString ( nFree , true ) ) ;
ImGui : : SameLine ( ) ;
TextDisabledUnformatted ( " frees. " ) ;
TextFocused ( " Memory allocated: " , MemSizeToString ( cAlloc ) ) ;
TextFocused ( " Memory freed: " , MemSizeToString ( cFree ) ) ;
TextFocused ( " Overall change: " , MemSizeToString ( cAlloc - cFree ) ) ;
2018-05-02 17:03:34 +00:00
2019-03-06 23:57:32 +00:00
if ( ImGui : : TreeNode ( " Allocations list " ) )
2018-05-02 17:03:34 +00:00
{
2019-03-17 15:53:09 +00:00
SmallCheckbox ( " Allocation times relative to zone start " , & m_allocTimeRelativeToZone ) ;
2019-03-06 23:57:32 +00:00
std : : vector < const MemEvent * > v ;
v . reserve ( nAlloc + nFree ) ;
auto it = ait2 ;
while ( it ! = aend )
2018-05-02 17:03:34 +00:00
{
2019-03-06 23:57:32 +00:00
if ( it - > threadAlloc = = thread )
{
v . emplace_back ( it ) ;
}
it + + ;
2018-05-02 17:03:34 +00:00
}
2019-03-06 23:57:32 +00:00
while ( fit2 ! = fend )
2018-05-02 17:03:34 +00:00
{
2019-03-06 23:57:32 +00:00
const auto ptr = & mem . data [ * fit2 + + ] ;
if ( ptr - > threadFree = = thread )
2018-05-02 17:03:34 +00:00
{
2019-03-06 23:57:32 +00:00
if ( ptr < ait2 | | ptr > = aend )
{
v . emplace_back ( ptr ) ;
}
2018-05-02 17:03:34 +00:00
}
}
2019-03-06 23:57:32 +00:00
pdqsort_branchless ( v . begin ( ) , v . end ( ) , [ ] ( const auto & l , const auto & r ) { return l - > timeAlloc < r - > timeAlloc ; } ) ;
2018-05-02 17:03:34 +00:00
2019-03-06 23:57:32 +00:00
ListMemData < decltype ( v . begin ( ) ) > ( v . begin ( ) , v . end ( ) , [ ] ( auto & v ) {
ImGui : : Text ( " 0x% " PRIx64 , ( * v ) - > ptr ) ;
2019-03-17 15:53:09 +00:00
} , nullptr , m_allocTimeRelativeToZone ? ev . start : - 1 ) ;
2019-03-06 23:57:32 +00:00
ImGui : : TreePop ( ) ;
}
2018-05-02 17:03:34 +00:00
}
2018-05-02 16:13:13 +00:00
}
2018-05-02 15:46:09 +00:00
}
}
2019-03-17 15:33:18 +00:00
ImGui : : Separator ( ) ;
{
if ( threadData - > messages . empty ( ) )
{
TextDisabledUnformatted ( " No messages " ) ;
}
else
{
auto msgit = std : : lower_bound ( threadData - > messages . begin ( ) , threadData - > messages . end ( ) , ev . start , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
auto msgend = std : : lower_bound ( msgit , threadData - > messages . end ( ) , end + 1 , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
const auto dist = std : : distance ( msgit , msgend ) ;
if ( dist = = 0 )
{
TextDisabledUnformatted ( " No messages " ) ;
}
else
{
bool expand = ImGui : : TreeNode ( " Messages " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( dist , true ) ) ;
if ( expand )
{
static bool widthSet = false ;
ImGui : : Columns ( 2 ) ;
if ( ! widthSet )
{
widthSet = true ;
const auto w = ImGui : : GetWindowWidth ( ) ;
ImGui : : SetColumnWidth ( 0 , w * 0.2f ) ;
ImGui : : SetColumnWidth ( 1 , w * 0.8f ) ;
}
TextDisabledUnformatted ( " Time " ) ;
ImGui : : NextColumn ( ) ;
TextDisabledUnformatted ( " Message " ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
do
{
ImGui : : PushID ( * msgit ) ;
if ( ImGui : : Selectable ( TimeToString ( ( * msgit ) - > time - ev . start ) , m_msgHighlight = = * msgit , ImGuiSelectableFlags_SpanAllColumns ) )
{
CenterAtTime ( ( * msgit ) - > time ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_msgHighlight = * msgit ;
}
ImGui : : PopID ( ) ;
ImGui : : NextColumn ( ) ;
2019-05-10 18:25:57 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , ( * msgit ) - > color ) ;
2019-03-17 15:33:18 +00:00
ImGui : : TextWrapped ( " %s " , m_worker . GetString ( ( * msgit ) - > ref ) ) ;
2019-05-10 18:25:57 +00:00
ImGui : : PopStyleColor ( ) ;
2019-03-17 15:33:18 +00:00
ImGui : : NextColumn ( ) ;
}
while ( + + msgit ! = msgend ) ;
ImGui : : EndColumns ( ) ;
ImGui : : TreePop ( ) ;
ImGui : : Spacing ( ) ;
}
}
}
}
2018-03-27 23:47:28 +00:00
ImGui : : Separator ( ) ;
std : : vector < const ZoneEvent * > zoneTrace ;
while ( parent )
{
zoneTrace . emplace_back ( parent ) ;
parent = GetZoneParent ( * parent ) ;
}
2018-06-24 13:54:36 +00:00
int idx = 0 ;
2019-02-27 20:12:56 +00:00
DrawZoneTrace < const ZoneEvent * > ( & ev , zoneTrace , m_worker , m_zoneinfoBuzzAnim , * this , m_showUnknownFrames , [ & idx , this ] ( const ZoneEvent * v , int & fidx ) {
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2018-06-24 13:54:36 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( v - > srcloc ) ;
2018-06-29 13:14:20 +00:00
const auto txt = m_worker . GetZoneName ( * v , srcloc ) ;
2018-06-24 13:54:36 +00:00
ImGui : : PushID ( idx + + ) ;
auto sel = ImGui : : Selectable ( txt , false ) ;
auto hover = ImGui : : IsItemHovered ( ) ;
2018-08-18 12:26:10 +00:00
const auto fileName = m_worker . GetString ( srcloc . file ) ;
if ( m_zoneinfoBuzzAnim . Match ( v ) )
{
const auto time = m_zoneinfoBuzzAnim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
ImGui : : TextDisabled ( " (%s) %s:%i " , TimeToString ( m_worker . GetZoneEnd ( * v ) - v - > start ) , fileName , srcloc . line ) ;
2018-06-24 13:54:36 +00:00
ImGui : : PopID ( ) ;
2018-08-18 12:26:10 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( fileName ) )
{
SetTextEditorFile ( fileName , srcloc . line ) ;
}
else
{
m_zoneinfoBuzzAnim . Enable ( v , 0.5f ) ;
}
}
2018-06-24 13:54:36 +00:00
if ( sel )
{
ShowZoneInfo ( * v ) ;
}
if ( hover )
2018-03-27 23:47:28 +00:00
{
2018-06-24 13:54:36 +00:00
m_zoneHighlight = v ;
if ( ImGui : : IsMouseClicked ( 2 ) )
2018-03-27 23:47:28 +00:00
{
2018-06-24 13:54:36 +00:00
ZoomToZone ( * v ) ;
2018-03-27 23:47:28 +00:00
}
2018-06-24 13:54:36 +00:00
ZoneTooltip ( * v ) ;
2018-03-27 23:47:28 +00:00
}
2018-06-24 13:54:36 +00:00
} ) ;
2018-03-27 23:47:28 +00:00
2018-07-22 14:05:50 +00:00
if ( ev . child > = 0 )
2017-09-29 20:32:03 +00:00
{
2018-07-22 14:05:50 +00:00
const auto & children = m_worker . GetZoneChildren ( ev . child ) ;
2018-03-27 23:47:20 +00:00
bool expand = ImGui : : TreeNode ( " Child zones " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : SameLine ( ) ;
2018-07-22 14:05:50 +00:00
ImGui : : TextDisabled ( " (%s) " , RealToString ( children . size ( ) , true ) ) ;
2018-03-27 23:34:12 +00:00
if ( expand )
2017-09-29 20:32:03 +00:00
{
2019-02-10 16:21:01 +00:00
const auto rztime = 1.0 / ztime ;
const auto ty = ImGui : : GetTextLineHeight ( ) ;
2019-02-10 15:14:13 +00:00
ImGui : : SameLine ( ) ;
2019-03-08 17:39:41 +00:00
SmallCheckbox ( " Group children locations " , & m_groupChildrenLocations ) ;
2019-02-10 15:14:13 +00:00
2019-02-10 16:21:01 +00:00
if ( m_groupChildrenLocations )
2018-05-02 15:23:32 +00:00
{
2019-02-10 16:21:01 +00:00
struct ChildGroup
{
int32_t srcloc ;
uint64_t t ;
Vector < uint32_t > v ;
} ;
uint64_t ctime = 0 ;
flat_hash_map < int32_t , ChildGroup , nohash < int32_t > > cmap ;
cmap . reserve ( 128 ) ;
for ( size_t i = 0 ; i < children . size ( ) ; i + + )
{
const auto & child = * children [ i ] ;
const auto cend = m_worker . GetZoneEnd ( child ) ;
const auto ct = cend - child . start ;
const auto srcloc = child . srcloc ;
ctime + = ct ;
2018-05-02 15:23:32 +00:00
2019-02-10 16:21:01 +00:00
auto it = cmap . find ( srcloc ) ;
if ( it = = cmap . end ( ) ) it = cmap . emplace ( srcloc , ChildGroup { srcloc } ) . first ;
2018-05-02 15:23:32 +00:00
2019-02-10 16:21:01 +00:00
it - > second . t + = ct ;
it - > second . v . push_back ( i ) ;
}
auto msz = cmap . size ( ) ;
Vector < ChildGroup * > cgvec ;
2019-02-15 00:43:30 +00:00
cgvec . reserve_and_use ( msz ) ;
2019-02-10 16:21:01 +00:00
size_t idx = 0 ;
for ( auto & it : cmap )
2017-09-29 20:38:38 +00:00
{
2019-02-10 16:21:01 +00:00
cgvec [ idx + + ] = & it . second ;
2017-09-29 20:38:38 +00:00
}
2019-02-10 16:21:01 +00:00
pdqsort_branchless ( cgvec . begin ( ) , cgvec . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > t > rhs - > t ; } ) ;
ImGui : : Columns ( 2 ) ;
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.0f , 1.0f , 0.4f , 1.0f ) , " Self time " ) ;
2019-02-10 16:21:01 +00:00
ImGui : : NextColumn ( ) ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : ProgressBar ( double ( ztime - ctime ) * rztime , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
for ( size_t i = 0 ; i < msz ; i + + )
2018-03-27 23:34:12 +00:00
{
2019-02-10 16:21:01 +00:00
bool expandGroup = false ;
const auto & cgr = * cgvec [ i ] ;
const auto & srcloc = m_worker . GetSourceLocation ( cgr . srcloc ) ;
const auto txt = m_worker . GetZoneName ( srcloc ) ;
if ( cgr . v . size ( ) = = 1 )
{
auto & cev = * children [ cgr . v . front ( ) ] ;
const auto txt = m_worker . GetZoneName ( cev ) ;
bool b = false ;
ImGui : : PushID ( ( int ) cgr . v . front ( ) ) ;
if ( ImGui : : Selectable ( txt , & b , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( cev ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_zoneHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
ImGui : : PopID ( ) ;
}
else
{
ImGui : : PushID ( cgr . srcloc ) ;
expandGroup = ImGui : : TreeNode ( txt ) ;
ImGui : : PopID ( ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
if ( srcloc . name . active )
{
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . name ) ) ;
}
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . function ) ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : EndTooltip ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " ( \xc3 \x97 %s) " , RealToString ( cgr . v . size ( ) , true ) ) ;
}
ImGui : : NextColumn ( ) ;
const auto part = double ( cgr . t ) * rztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( cgr . t ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
if ( expandGroup )
2018-03-27 23:34:12 +00:00
{
2019-02-10 16:21:01 +00:00
auto ctt = std : : make_unique < uint64_t [ ] > ( cgr . v . size ( ) ) ;
auto cti = std : : make_unique < uint32_t [ ] > ( cgr . v . size ( ) ) ;
for ( size_t i = 0 ; i < cgr . v . size ( ) ; i + + )
{
const auto & child = * children [ cgr . v [ i ] ] ;
const auto cend = m_worker . GetZoneEnd ( child ) ;
const auto ct = cend - child . start ;
ctt [ i ] = ct ;
cti [ i ] = uint32_t ( i ) ;
}
pdqsort_branchless ( cti . get ( ) , cti . get ( ) + cgr . v . size ( ) , [ & ctt ] ( const auto & lhs , const auto & rhs ) { return ctt [ lhs ] > ctt [ rhs ] ; } ) ;
for ( size_t i = 0 ; i < cgr . v . size ( ) ; i + + )
{
auto & cev = * children [ cgr . v [ cti [ i ] ] ] ;
const auto txt = m_worker . GetZoneName ( cev ) ;
bool b = false ;
ImGui : : Indent ( ) ;
ImGui : : PushID ( ( int ) cgr . v [ cti [ i ] ] ) ;
if ( ImGui : : Selectable ( txt , & b , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( cev ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_zoneHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
ImGui : : PopID ( ) ;
ImGui : : Unindent ( ) ;
ImGui : : NextColumn ( ) ;
const auto part = double ( ctt [ cti [ i ] ] ) * rztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
}
ImGui : : TreePop ( ) ;
2018-03-27 23:34:12 +00:00
}
}
2019-02-10 16:21:01 +00:00
ImGui : : EndColumns ( ) ;
}
else
{
auto ctt = std : : make_unique < uint64_t [ ] > ( children . size ( ) ) ;
auto cti = std : : make_unique < uint32_t [ ] > ( children . size ( ) ) ;
uint64_t ctime = 0 ;
for ( size_t i = 0 ; i < children . size ( ) ; i + + )
{
const auto & child = * children [ i ] ;
const auto cend = m_worker . GetZoneEnd ( child ) ;
const auto ct = cend - child . start ;
ctime + = ct ;
ctt [ i ] = ct ;
cti [ i ] = uint32_t ( i ) ;
}
pdqsort_branchless ( cti . get ( ) , cti . get ( ) + children . size ( ) , [ & ctt ] ( const auto & lhs , const auto & rhs ) { return ctt [ lhs ] > ctt [ rhs ] ; } ) ;
ImGui : : Columns ( 2 ) ;
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.0f , 1.0f , 0.4f , 1.0f ) , " Self time " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
char buf [ 128 ] ;
2019-02-10 16:21:01 +00:00
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : ProgressBar ( double ( ztime - ctime ) * rztime , ImVec2 ( - 1 , ty ) , buf ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 16:21:01 +00:00
for ( size_t i = 0 ; i < children . size ( ) ; i + + )
{
auto & cev = * children [ cti [ i ] ] ;
const auto txt = m_worker . GetZoneName ( cev ) ;
bool b = false ;
ImGui : : PushID ( ( int ) i ) ;
if ( ImGui : : Selectable ( txt , & b , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( cev ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_zoneHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
ImGui : : PopID ( ) ;
ImGui : : NextColumn ( ) ;
const auto part = double ( ctt [ cti [ i ] ] ) * rztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
}
ImGui : : EndColumns ( ) ;
2017-09-29 20:38:38 +00:00
}
2018-03-27 23:34:12 +00:00
ImGui : : TreePop ( ) ;
2017-09-29 20:32:03 +00:00
}
}
2017-09-29 19:49:14 +00:00
ImGui : : End ( ) ;
2017-09-29 20:06:31 +00:00
2018-05-02 17:23:46 +00:00
if ( ! show )
{
m_zoneInfoWindow = nullptr ;
m_zoneInfoStack . clear ( ) ;
}
2017-09-29 19:49:14 +00:00
}
2017-11-12 00:25:44 +00:00
void View : : DrawGpuInfoWindow ( )
{
auto & ev = * m_gpuInfoWindow ;
2018-08-17 12:54:28 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-12 00:25:44 +00:00
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 500 , 400 ) , ImGuiCond_FirstUseEver ) ;
2017-11-12 00:25:44 +00:00
bool show = true ;
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Zone info " , & show ) ;
2017-11-12 00:25:44 +00:00
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_MICROSCOPE " Zoom to zone " ) )
# else
2017-11-12 00:25:44 +00:00
if ( ImGui : : Button ( " Zoom to zone " ) )
2018-08-17 21:47:01 +00:00
# endif
2017-11-12 00:25:44 +00:00
{
ZoomToZone ( ev ) ;
}
2018-08-18 00:12:34 +00:00
auto parent = GetZoneParent ( ev ) ;
if ( parent )
{
ImGui : : SameLine ( ) ;
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-08-18 00:12:34 +00:00
if ( ImGui : : Button ( ICON_FA_ARROW_UP " Go to parent " ) )
2018-08-17 21:47:01 +00:00
# else
2018-08-18 00:12:34 +00:00
if ( ImGui : : Button ( " Go to parent " ) )
2018-08-17 21:47:01 +00:00
# endif
2017-11-12 00:25:44 +00:00
{
2018-05-02 17:23:46 +00:00
ShowZoneInfo ( * parent , m_gpuInfoWindowThread ) ;
2017-11-12 00:25:44 +00:00
}
}
2018-06-21 23:58:14 +00:00
if ( ev . callstack ! = 0 )
{
ImGui : : SameLine ( ) ;
2018-06-22 00:24:36 +00:00
bool hilite = m_callstackInfoWindow = = ev . callstack ;
if ( hilite )
{
2018-12-18 15:28:09 +00:00
SetButtonHighlightColor ( ) ;
2018-06-22 00:24:36 +00:00
}
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_ALIGN_JUSTIFY " Call stack " ) )
# else
2018-08-17 20:00:35 +00:00
if ( ImGui : : Button ( " Call stack " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-06-21 23:58:14 +00:00
{
m_callstackInfoWindow = ev . callstack ;
}
2018-06-22 00:24:36 +00:00
if ( hilite )
{
ImGui : : PopStyleColor ( 3 ) ;
}
2018-06-21 23:58:14 +00:00
}
2018-08-18 18:38:14 +00:00
const auto fileName = m_worker . GetString ( srcloc . file ) ;
if ( FileExists ( fileName ) )
2018-08-17 12:54:28 +00:00
{
ImGui : : SameLine ( ) ;
2018-08-17 22:28:36 +00:00
bool hilite = m_textEditorFile = = fileName ;
if ( hilite )
{
2018-12-18 15:28:09 +00:00
SetButtonHighlightColor ( ) ;
2018-08-17 22:28:36 +00:00
}
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_FILE_ALT " Source " ) )
# else
2018-08-17 12:54:28 +00:00
if ( ImGui : : Button ( " Source " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-08-17 12:54:28 +00:00
{
2018-08-17 22:28:36 +00:00
SetTextEditorFile ( fileName , srcloc . line ) ;
}
if ( hilite )
{
ImGui : : PopStyleColor ( 3 ) ;
2018-08-17 12:54:28 +00:00
}
}
2018-05-02 17:25:52 +00:00
if ( ! m_gpuInfoStack . empty ( ) )
{
ImGui : : SameLine ( ) ;
2018-08-17 21:47:01 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_ARROW_LEFT " Go back " ) )
# else
2018-05-02 17:25:52 +00:00
if ( ImGui : : Button ( " Go back " ) )
2018-08-17 21:47:01 +00:00
# endif
2018-05-02 17:25:52 +00:00
{
m_gpuInfoWindow = m_gpuInfoStack . back_and_pop ( ) ;
}
}
2017-11-12 00:25:44 +00:00
ImGui : : Separator ( ) ;
2018-03-19 15:11:44 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-06-29 16:27:34 +00:00
TextFocused ( " Zone name: " , m_worker . GetString ( srcloc . name ) ) ;
TextFocused ( " Function: " , m_worker . GetString ( srcloc . function ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Location: " ) ;
2018-06-29 16:27:34 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
TextFocused ( " Thread: " , m_worker . GetThreadString ( tid ) ) ;
2018-03-19 01:22:08 +00:00
ImGui : : SameLine ( ) ;
2019-02-22 23:34:01 +00:00
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2017-11-12 00:25:44 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-12 00:25:44 +00:00
const auto ztime = end - ev . gpuStart ;
2019-03-29 23:52:25 +00:00
const auto selftime = GetZoneSelfTime ( ev ) ;
2018-08-04 17:51:50 +00:00
TextFocused ( " Time from start of program: " , TimeToString ( ev . gpuStart - m_worker . GetTimeBegin ( ) ) ) ;
2018-06-29 16:27:34 +00:00
TextFocused ( " GPU execution time: " , TimeToString ( ztime ) ) ;
2019-02-14 00:31:06 +00:00
TextFocused ( " GPU self time: " , TimeToString ( selftime ) ) ;
2019-06-22 20:42:57 +00:00
if ( ztime ! = 0 )
{
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , 100.f * selftime / ztime ) ;
}
2018-06-29 16:27:34 +00:00
TextFocused ( " CPU command setup time: " , TimeToString ( ev . cpuEnd - ev . cpuStart ) ) ;
2018-06-27 23:12:25 +00:00
auto ctx = GetZoneCtx ( ev ) ;
if ( ! ctx )
{
2018-06-29 16:27:34 +00:00
TextFocused ( " Delay to execution: " , TimeToString ( ev . gpuStart - ev . cpuStart ) ) ;
2018-06-27 23:12:25 +00:00
}
else
{
const auto begin = ctx - > timeline . front ( ) - > gpuStart ;
const auto drift = GpuDrift ( ctx ) ;
2018-06-29 16:27:34 +00:00
TextFocused ( " Delay to execution: " , TimeToString ( AdjustGpuTime ( ev . gpuStart , begin , drift ) - ev . cpuStart ) ) ;
2018-06-27 23:12:25 +00:00
}
2017-11-12 00:25:44 +00:00
2018-03-27 23:47:28 +00:00
ImGui : : Separator ( ) ;
std : : vector < const GpuEvent * > zoneTrace ;
while ( parent )
{
zoneTrace . emplace_back ( parent ) ;
parent = GetZoneParent ( * parent ) ;
}
2018-06-24 13:54:36 +00:00
int idx = 0 ;
2019-02-27 20:12:56 +00:00
DrawZoneTrace < const GpuEvent * > ( & ev , zoneTrace , m_worker , m_zoneinfoBuzzAnim , * this , m_showUnknownFrames , [ & idx , this ] ( const GpuEvent * v , int & fidx ) {
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2018-06-24 13:54:36 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( v - > srcloc ) ;
2018-06-29 13:14:20 +00:00
const auto txt = m_worker . GetZoneName ( * v , srcloc ) ;
2018-06-24 13:54:36 +00:00
ImGui : : PushID ( idx + + ) ;
auto sel = ImGui : : Selectable ( txt , false ) ;
auto hover = ImGui : : IsItemHovered ( ) ;
2018-08-18 12:26:10 +00:00
const auto fileName = m_worker . GetString ( srcloc . file ) ;
if ( m_zoneinfoBuzzAnim . Match ( v ) )
{
const auto time = m_zoneinfoBuzzAnim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
ImGui : : TextDisabled ( " (%s) %s:%i " , TimeToString ( m_worker . GetZoneEnd ( * v ) - v - > gpuStart ) , fileName , srcloc . line ) ;
2018-06-24 13:54:36 +00:00
ImGui : : PopID ( ) ;
2018-08-18 12:26:10 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( fileName ) )
{
SetTextEditorFile ( fileName , srcloc . line ) ;
}
else
{
m_zoneinfoBuzzAnim . Enable ( v , 0.5f ) ;
}
}
2018-06-24 13:54:36 +00:00
if ( sel )
{
ShowZoneInfo ( * v , m_gpuInfoWindowThread ) ;
}
if ( hover )
2018-03-27 23:47:28 +00:00
{
2018-06-24 13:54:36 +00:00
m_gpuHighlight = v ;
if ( ImGui : : IsMouseClicked ( 2 ) )
2018-03-27 23:47:28 +00:00
{
2018-06-24 13:54:36 +00:00
ZoomToZone ( * v ) ;
2018-03-27 23:47:28 +00:00
}
2018-06-24 13:54:36 +00:00
ZoneTooltip ( * v ) ;
2018-03-27 23:47:28 +00:00
}
2018-06-24 13:54:36 +00:00
} ) ;
2018-03-27 23:47:28 +00:00
2018-07-22 17:47:01 +00:00
if ( ev . child > = 0 )
2017-11-12 00:25:44 +00:00
{
2018-07-22 17:47:01 +00:00
const auto & children = m_worker . GetGpuChildren ( ev . child ) ;
2018-03-27 23:47:20 +00:00
bool expand = ImGui : : TreeNode ( " Child zones " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : SameLine ( ) ;
2018-07-22 17:47:01 +00:00
ImGui : : TextDisabled ( " (%s) " , RealToString ( children . size ( ) , true ) ) ;
2018-03-27 23:34:12 +00:00
if ( expand )
2017-11-12 00:25:44 +00:00
{
2019-02-14 00:38:34 +00:00
const auto rztime = 1.0 / ztime ;
const auto ty = ImGui : : GetTextLineHeight ( ) ;
2018-05-02 15:23:32 +00:00
2019-02-14 00:38:34 +00:00
ImGui : : SameLine ( ) ;
2019-03-08 17:39:41 +00:00
SmallCheckbox ( " Group children locations " , & m_groupChildrenLocations ) ;
2018-05-02 15:23:32 +00:00
2019-02-14 00:38:34 +00:00
if ( m_groupChildrenLocations )
2017-11-12 00:25:44 +00:00
{
2019-02-14 00:38:34 +00:00
struct ChildGroup
2017-11-12 00:25:44 +00:00
{
2019-02-14 00:38:34 +00:00
int32_t srcloc ;
uint64_t t ;
Vector < uint32_t > v ;
} ;
uint64_t ctime = 0 ;
flat_hash_map < int32_t , ChildGroup , nohash < int32_t > > cmap ;
cmap . reserve ( 128 ) ;
for ( size_t i = 0 ; i < children . size ( ) ; i + + )
{
const auto & child = * children [ i ] ;
const auto cend = m_worker . GetZoneEnd ( child ) ;
const auto ct = cend - child . gpuStart ;
const auto srcloc = child . srcloc ;
ctime + = ct ;
auto it = cmap . find ( srcloc ) ;
if ( it = = cmap . end ( ) ) it = cmap . emplace ( srcloc , ChildGroup { srcloc } ) . first ;
it - > second . t + = ct ;
it - > second . v . push_back ( i ) ;
2017-11-12 00:25:44 +00:00
}
2019-02-14 00:38:34 +00:00
auto msz = cmap . size ( ) ;
Vector < ChildGroup * > cgvec ;
2019-02-15 00:43:30 +00:00
cgvec . reserve_and_use ( msz ) ;
2019-02-14 00:38:34 +00:00
size_t idx = 0 ;
for ( auto & it : cmap )
2018-03-27 23:34:12 +00:00
{
2019-02-14 00:38:34 +00:00
cgvec [ idx + + ] = & it . second ;
}
pdqsort_branchless ( cgvec . begin ( ) , cgvec . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > t > rhs - > t ; } ) ;
ImGui : : Columns ( 2 ) ;
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.0f , 1.0f , 0.4f , 1.0f ) , " Self time " ) ;
2019-02-14 00:38:34 +00:00
ImGui : : NextColumn ( ) ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : ProgressBar ( double ( ztime - ctime ) * rztime , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
for ( size_t i = 0 ; i < msz ; i + + )
{
bool expandGroup = false ;
const auto & cgr = * cgvec [ i ] ;
const auto & srcloc = m_worker . GetSourceLocation ( cgr . srcloc ) ;
const auto txt = m_worker . GetZoneName ( srcloc ) ;
if ( cgr . v . size ( ) = = 1 )
{
auto & cev = * children [ cgr . v . front ( ) ] ;
const auto txt = m_worker . GetZoneName ( cev ) ;
bool b = false ;
ImGui : : PushID ( ( int ) cgr . v . front ( ) ) ;
if ( ImGui : : Selectable ( txt , & b , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( cev , m_gpuInfoWindowThread ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_gpuHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
ImGui : : PopID ( ) ;
}
else
{
ImGui : : PushID ( cgr . srcloc ) ;
expandGroup = ImGui : : TreeNode ( txt ) ;
ImGui : : PopID ( ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
if ( srcloc . name . active )
{
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . name ) ) ;
}
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . function ) ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : EndTooltip ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " ( \xc3 \x97 %s) " , RealToString ( cgr . v . size ( ) , true ) ) ;
}
ImGui : : NextColumn ( ) ;
const auto part = double ( cgr . t ) * rztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( cgr . t ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
if ( expandGroup )
2018-03-27 23:34:12 +00:00
{
2019-02-14 00:38:34 +00:00
auto ctt = std : : make_unique < uint64_t [ ] > ( cgr . v . size ( ) ) ;
auto cti = std : : make_unique < uint32_t [ ] > ( cgr . v . size ( ) ) ;
for ( size_t i = 0 ; i < cgr . v . size ( ) ; i + + )
{
const auto & child = * children [ cgr . v [ i ] ] ;
const auto cend = m_worker . GetZoneEnd ( child ) ;
const auto ct = cend - child . gpuStart ;
ctt [ i ] = ct ;
cti [ i ] = uint32_t ( i ) ;
}
pdqsort_branchless ( cti . get ( ) , cti . get ( ) + cgr . v . size ( ) , [ & ctt ] ( const auto & lhs , const auto & rhs ) { return ctt [ lhs ] > ctt [ rhs ] ; } ) ;
for ( size_t i = 0 ; i < cgr . v . size ( ) ; i + + )
{
auto & cev = * children [ cgr . v [ cti [ i ] ] ] ;
const auto txt = m_worker . GetZoneName ( cev ) ;
bool b = false ;
ImGui : : Indent ( ) ;
ImGui : : PushID ( ( int ) cgr . v [ cti [ i ] ] ) ;
if ( ImGui : : Selectable ( txt , & b , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( cev , m_gpuInfoWindowThread ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_gpuHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
ImGui : : PopID ( ) ;
ImGui : : Unindent ( ) ;
ImGui : : NextColumn ( ) ;
const auto part = double ( ctt [ cti [ i ] ] ) * rztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
}
ImGui : : TreePop ( ) ;
2018-03-27 23:34:12 +00:00
}
}
2019-02-14 00:38:34 +00:00
ImGui : : EndColumns ( ) ;
}
else
{
auto ctt = std : : make_unique < uint64_t [ ] > ( children . size ( ) ) ;
auto cti = std : : make_unique < uint32_t [ ] > ( children . size ( ) ) ;
uint64_t ctime = 0 ;
for ( size_t i = 0 ; i < children . size ( ) ; i + + )
{
const auto & child = * children [ i ] ;
const auto cend = m_worker . GetZoneEnd ( child ) ;
const auto ct = cend - child . gpuStart ;
ctime + = ct ;
ctt [ i ] = ct ;
cti [ i ] = uint32_t ( i ) ;
}
pdqsort_branchless ( cti . get ( ) , cti . get ( ) + children . size ( ) , [ & ctt ] ( const auto & lhs , const auto & rhs ) { return ctt [ lhs ] > ctt [ rhs ] ; } ) ;
const auto ty = ImGui : : GetTextLineHeight ( ) ;
ImGui : : Columns ( 2 ) ;
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.0f , 1.0f , 0.4f , 1.0f ) , " Self time " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
char buf [ 128 ] ;
2019-02-14 00:38:34 +00:00
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : ProgressBar ( double ( ztime - ctime ) / ztime , ImVec2 ( - 1 , ty ) , buf ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
2019-02-14 00:38:34 +00:00
for ( size_t i = 0 ; i < children . size ( ) ; i + + )
{
auto & cev = * children [ cti [ i ] ] ;
bool b = false ;
ImGui : : PushID ( ( int ) i ) ;
if ( ImGui : : Selectable ( m_worker . GetZoneName ( cev ) , & b , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( cev , m_gpuInfoWindowThread ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_gpuHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
ImGui : : PopID ( ) ;
ImGui : : NextColumn ( ) ;
const auto part = double ( ctt [ cti [ i ] ] ) / ztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
}
ImGui : : EndColumns ( ) ;
ImGui : : TreePop ( ) ;
2017-11-12 00:25:44 +00:00
}
}
}
ImGui : : End ( ) ;
2018-05-02 17:23:46 +00:00
if ( ! show )
{
m_gpuInfoWindow = nullptr ;
m_gpuInfoStack . clear ( ) ;
}
2017-11-12 00:25:44 +00:00
}
2017-10-13 11:32:23 +00:00
void View : : DrawOptions ( )
{
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Options " , & m_showOptions , ImGuiWindowFlags_AlwaysAutoResize ) ;
2018-03-15 22:33:05 +00:00
2019-02-23 00:14:08 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_EXPAND " Draw empty labels " , & m_drawEmptyLabels ) ;
# else
ImGui : : Checkbox ( " Draw empty labels " , & m_drawEmptyLabels ) ;
# endif
ImGui : : Separator ( ) ;
2018-06-17 23:08:56 +00:00
const auto & gpuData = m_worker . GetGpuData ( ) ;
if ( ! gpuData . empty ( ) )
2017-11-30 14:34:52 +00:00
{
2018-08-17 22:21:01 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_EYE " Draw GPU zones " , & m_drawGpuZones ) ;
# else
2018-03-15 22:33:05 +00:00
ImGui : : Checkbox ( " Draw GPU zones " , & m_drawGpuZones ) ;
2018-08-17 22:21:01 +00:00
# endif
2018-03-15 22:33:05 +00:00
const auto expand = ImGui : : TreeNode ( " GPU zones " ) ;
ImGui : : SameLine ( ) ;
2018-06-17 23:08:56 +00:00
ImGui : : TextDisabled ( " (%zu) " , gpuData . size ( ) ) ;
2018-03-15 22:33:05 +00:00
if ( expand )
{
2018-06-17 23:08:56 +00:00
for ( size_t i = 0 ; i < gpuData . size ( ) ; i + + )
2018-03-15 22:33:05 +00:00
{
2018-06-17 23:08:56 +00:00
const bool isVulkan = gpuData [ i ] - > thread = = 0 ;
2018-03-15 22:33:05 +00:00
char buf [ 1024 ] ;
2018-06-17 23:08:56 +00:00
if ( isVulkan )
{
sprintf ( buf , " Vulkan context %zu " , i ) ;
}
else
{
sprintf ( buf , " OpenGL context %zu " , i ) ;
}
2019-06-21 12:15:46 +00:00
SmallCheckbox ( buf , & Vis ( gpuData [ i ] ) . visible ) ;
2018-08-04 13:09:52 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " %s top level zones " , RealToString ( gpuData [ i ] - > timeline . size ( ) , true ) ) ;
2018-06-27 23:12:25 +00:00
ImGui : : TreePush ( ) ;
auto & drift = GpuDrift ( gpuData [ i ] ) ;
ImGui : : InputInt ( " Drift (ns/s) " , & drift ) ;
ImGui : : TreePop ( ) ;
2018-03-15 22:33:05 +00:00
}
ImGui : : TreePop ( ) ;
}
2017-11-30 14:34:52 +00:00
}
2018-03-15 22:33:05 +00:00
2018-08-17 22:21:01 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_MICROCHIP " Draw CPU zones " , & m_drawZones ) ;
# else
2017-11-11 21:56:05 +00:00
ImGui : : Checkbox ( " Draw CPU zones " , & m_drawZones ) ;
2018-08-17 22:21:01 +00:00
# endif
2017-10-22 11:56:05 +00:00
int ns = ( int ) m_namespace ;
2017-10-22 13:27:07 +00:00
ImGui : : Combo ( " Namespaces " , & ns , " Full \0 Shortened \0 None \0 " ) ;
2017-10-22 11:56:05 +00:00
m_namespace = ( Namespace ) ns ;
2018-03-15 22:33:05 +00:00
if ( ! m_worker . GetLockMap ( ) . empty ( ) )
2017-10-22 11:25:58 +00:00
{
2019-02-17 16:19:17 +00:00
size_t lockCnt = 0 ;
size_t singleCnt = 0 ;
2019-05-12 14:26:19 +00:00
size_t multiCntCont = 0 ;
size_t multiCntUncont = 0 ;
2019-02-17 16:19:17 +00:00
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-03-16 01:09:50 +00:00
if ( l . second - > valid & & ! l . second - > timeline . empty ( ) )
2019-02-17 16:19:17 +00:00
{
lockCnt + + ;
2019-03-16 01:09:50 +00:00
if ( l . second - > threadList . size ( ) = = 1 )
2019-02-17 16:19:17 +00:00
{
singleCnt + + ;
}
2019-05-12 14:26:19 +00:00
else if ( l . second - > isContended )
{
multiCntCont + + ;
}
2019-02-17 16:19:17 +00:00
else
{
2019-05-12 14:26:19 +00:00
multiCntUncont + + ;
2019-02-17 16:19:17 +00:00
}
}
}
2018-03-15 22:33:05 +00:00
ImGui : : Separator ( ) ;
2018-08-17 22:21:01 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_LOCK " Draw locks " , & m_drawLocks ) ;
# else
2018-03-15 22:33:05 +00:00
ImGui : : Checkbox ( " Draw locks " , & m_drawLocks ) ;
2018-08-17 22:21:01 +00:00
# endif
2018-03-15 22:33:05 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Only contended " , & m_onlyContendedLocks ) ;
const auto expand = ImGui : : TreeNode ( " Locks " ) ;
ImGui : : SameLine ( ) ;
2019-02-17 16:19:17 +00:00
ImGui : : TextDisabled ( " (%zu) " , lockCnt ) ;
2018-03-15 22:33:05 +00:00
if ( ImGui : : IsItemHovered ( ) )
2017-12-10 20:37:39 +00:00
{
2018-03-15 22:33:05 +00:00
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Locks with no recorded events are counted, but not listed. " ) ;
2018-03-15 22:33:05 +00:00
ImGui : : EndTooltip ( ) ;
}
if ( expand )
{
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2018-04-09 14:15:40 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-03-16 01:09:50 +00:00
Vis ( l . second ) . visible = true ;
2018-04-09 14:15:40 +00:00
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-03-16 01:09:50 +00:00
Vis ( l . second ) . visible = false ;
2018-04-09 14:15:40 +00:00
}
}
2018-12-16 20:14:15 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Right click on lock name to open lock information window. " ) ;
2018-04-09 14:15:40 +00:00
2019-05-12 14:26:19 +00:00
const bool multiExpand = ImGui : : TreeNodeEx ( " Contended locks present in multiple threads " , ImGuiTreeNodeFlags_DefaultOpen ) ;
2019-02-17 16:19:17 +00:00
ImGui : : SameLine ( ) ;
2019-05-12 14:26:19 +00:00
ImGui : : TextDisabled ( " (%zu) " , multiCntCont ) ;
2019-02-17 16:19:17 +00:00
if ( multiExpand )
2018-03-15 22:33:05 +00:00
{
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2019-02-17 16:06:39 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
2018-03-15 22:33:05 +00:00
{
2019-02-17 16:06:39 +00:00
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-05-12 14:26:19 +00:00
if ( l . second - > threadList . size ( ) ! = 1 & & l . second - > isContended ) Vis ( l . second ) . visible = true ;
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
{
if ( l . second - > threadList . size ( ) ! = 1 & & l . second - > isContended ) Vis ( l . second ) . visible = false ;
}
}
for ( const auto & l : m_worker . GetLockMap ( ) )
{
if ( l . second - > valid & & ! l . second - > timeline . empty ( ) & & l . second - > threadList . size ( ) ! = 1 & & l . second - > isContended )
{
auto & sl = m_worker . GetSourceLocation ( l . second - > srcloc ) ;
auto fileName = m_worker . GetString ( sl . file ) ;
char buf [ 1024 ] ;
sprintf ( buf , " % " PRIu32 " : %s " , l . first , m_worker . GetString ( m_worker . GetSourceLocation ( l . second - > srcloc ) . function ) ) ;
2019-06-21 12:15:46 +00:00
SmallCheckbox ( buf , & Vis ( l . second ) . visible ) ;
2019-05-12 14:26:19 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
m_lockHoverHighlight = l . first ;
if ( ImGui : : IsItemClicked ( 1 ) )
{
m_lockInfoWindow = l . first ;
}
}
if ( m_optionsLockBuzzAnim . Match ( l . second - > srcloc ) )
{
const auto time = m_optionsLockBuzzAnim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
ImGui : : TextDisabled ( " (%s) %s:%i " , RealToString ( l . second - > timeline . size ( ) , true ) , fileName , sl . line ) ;
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( fileName ) )
{
SetTextEditorFile ( fileName , sl . line ) ;
}
else
{
m_optionsLockBuzzAnim . Enable ( l . second - > srcloc , 0.5f ) ;
}
}
}
}
ImGui : : TreePop ( ) ;
}
const bool multiUncontExpand = ImGui : : TreeNodeEx ( " Uncontended locks present in multiple threads " , 0 ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , multiCntUncont ) ;
if ( multiUncontExpand )
{
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2019-05-12 14:26:19 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
{
if ( l . second - > threadList . size ( ) ! = 1 & & ! l . second - > isContended ) Vis ( l . second ) . visible = true ;
2019-02-17 16:06:39 +00:00
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-05-12 14:26:19 +00:00
if ( l . second - > threadList . size ( ) ! = 1 & & ! l . second - > isContended ) Vis ( l . second ) . visible = false ;
2019-02-17 16:06:39 +00:00
}
}
2018-09-18 14:14:32 +00:00
2019-02-17 16:06:39 +00:00
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-05-12 14:26:19 +00:00
if ( l . second - > valid & & ! l . second - > timeline . empty ( ) & & l . second - > threadList . size ( ) ! = 1 & & ! l . second - > isContended )
2018-12-16 20:14:15 +00:00
{
2019-03-16 01:09:50 +00:00
auto & sl = m_worker . GetSourceLocation ( l . second - > srcloc ) ;
2019-02-17 16:06:39 +00:00
auto fileName = m_worker . GetString ( sl . file ) ;
char buf [ 1024 ] ;
2019-03-16 01:09:50 +00:00
sprintf ( buf , " % " PRIu32 " : %s " , l . first , m_worker . GetString ( m_worker . GetSourceLocation ( l . second - > srcloc ) . function ) ) ;
2019-06-21 12:15:46 +00:00
SmallCheckbox ( buf , & Vis ( l . second ) . visible ) ;
2019-02-17 16:06:39 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
m_lockHoverHighlight = l . first ;
2019-02-17 15:53:33 +00:00
2019-02-17 16:06:39 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
m_lockInfoWindow = l . first ;
}
}
2019-03-16 01:09:50 +00:00
if ( m_optionsLockBuzzAnim . Match ( l . second - > srcloc ) )
2019-02-17 16:06:39 +00:00
{
const auto time = m_optionsLockBuzzAnim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
2019-03-16 01:09:50 +00:00
ImGui : : TextDisabled ( " (%s) %s:%i " , RealToString ( l . second - > timeline . size ( ) , true ) , fileName , sl . line ) ;
2019-02-17 15:53:33 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
2019-02-17 16:06:39 +00:00
if ( FileExists ( fileName ) )
{
SetTextEditorFile ( fileName , sl . line ) ;
}
else
{
2019-03-16 01:09:50 +00:00
m_optionsLockBuzzAnim . Enable ( l . second - > srcloc , 0.5f ) ;
2019-02-17 16:06:39 +00:00
}
2019-02-17 15:53:33 +00:00
}
2018-12-16 20:14:15 +00:00
}
2019-02-17 16:06:39 +00:00
}
ImGui : : TreePop ( ) ;
}
2019-05-12 14:26:19 +00:00
const auto singleExpand = ImGui : : TreeNodeEx ( " Locks present in a single thread " , 0 ) ;
2019-02-17 16:19:17 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , singleCnt ) ;
if ( singleExpand )
2019-02-17 16:06:39 +00:00
{
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2019-02-17 16:06:39 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
2018-09-18 14:14:32 +00:00
{
2019-03-16 01:09:50 +00:00
if ( l . second - > threadList . size ( ) = = 1 ) Vis ( l . second ) . visible = true ;
2018-09-18 14:14:32 +00:00
}
2019-02-17 16:06:39 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
2018-09-18 14:14:32 +00:00
{
2019-03-16 01:09:50 +00:00
if ( l . second - > threadList . size ( ) = = 1 ) Vis ( l . second ) . visible = false ;
2018-09-18 14:14:32 +00:00
}
2019-02-17 16:06:39 +00:00
}
for ( const auto & l : m_worker . GetLockMap ( ) )
{
2019-03-16 01:09:50 +00:00
if ( l . second - > valid & & ! l . second - > timeline . empty ( ) & & l . second - > threadList . size ( ) = = 1 )
2018-09-18 14:14:32 +00:00
{
2019-03-16 01:09:50 +00:00
auto & sl = m_worker . GetSourceLocation ( l . second - > srcloc ) ;
2019-02-17 16:06:39 +00:00
auto fileName = m_worker . GetString ( sl . file ) ;
char buf [ 1024 ] ;
2019-03-16 01:09:50 +00:00
sprintf ( buf , " % " PRIu32 " : %s " , l . first , m_worker . GetString ( m_worker . GetSourceLocation ( l . second - > srcloc ) . function ) ) ;
2019-06-21 12:15:46 +00:00
SmallCheckbox ( buf , & Vis ( l . second ) . visible ) ;
2019-02-17 16:06:39 +00:00
if ( ImGui : : IsItemHovered ( ) )
2018-09-18 14:14:32 +00:00
{
2019-02-17 16:06:39 +00:00
m_lockHoverHighlight = l . first ;
if ( ImGui : : IsItemClicked ( 1 ) )
{
m_lockInfoWindow = l . first ;
}
}
2019-03-16 01:09:50 +00:00
if ( m_optionsLockBuzzAnim . Match ( l . second - > srcloc ) )
2019-02-17 16:06:39 +00:00
{
const auto time = m_optionsLockBuzzAnim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
2018-09-18 14:14:32 +00:00
}
else
{
2019-02-17 16:06:39 +00:00
ImGui : : SameLine ( ) ;
}
2019-03-16 01:09:50 +00:00
ImGui : : TextDisabled ( " (%s) %s:%i " , RealToString ( l . second - > timeline . size ( ) , true ) , fileName , sl . line ) ;
2019-02-17 16:06:39 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( fileName ) )
{
SetTextEditorFile ( fileName , sl . line ) ;
}
else
{
2019-03-16 01:09:50 +00:00
m_optionsLockBuzzAnim . Enable ( l . second - > srcloc , 0.5f ) ;
2019-02-17 16:06:39 +00:00
}
2018-09-18 14:14:32 +00:00
}
}
2018-03-15 22:33:05 +00:00
}
2019-02-17 16:06:39 +00:00
ImGui : : TreePop ( ) ;
2018-03-15 22:33:05 +00:00
}
ImGui : : TreePop ( ) ;
2017-12-10 20:37:39 +00:00
}
2017-10-22 11:25:58 +00:00
}
2018-03-15 22:33:05 +00:00
if ( ! m_worker . GetPlots ( ) . empty ( ) )
2017-10-22 11:17:34 +00:00
{
2018-03-15 22:33:05 +00:00
ImGui : : Separator ( ) ;
2018-08-17 22:21:01 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_SIGNATURE " Draw plots " , & m_drawPlots ) ;
# else
2018-03-15 22:33:05 +00:00
ImGui : : Checkbox ( " Draw plots " , & m_drawPlots ) ;
2018-08-17 22:21:01 +00:00
# endif
2018-03-15 22:33:05 +00:00
const auto expand = ImGui : : TreeNode ( " Plots " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_worker . GetPlots ( ) . size ( ) ) ;
if ( expand )
{
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2018-07-13 22:10:38 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
for ( const auto & p : m_worker . GetPlots ( ) )
{
2019-02-21 19:24:08 +00:00
Vis ( p ) . visible = true ;
2018-07-13 22:10:38 +00:00
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
for ( const auto & p : m_worker . GetPlots ( ) )
{
2019-02-21 19:24:08 +00:00
Vis ( p ) . visible = false ;
2018-07-13 22:10:38 +00:00
}
}
2018-03-15 22:33:05 +00:00
for ( const auto & p : m_worker . GetPlots ( ) )
{
2019-06-21 12:15:46 +00:00
SmallCheckbox ( GetPlotName ( p ) , & Vis ( p ) . visible ) ;
2018-08-04 13:09:52 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " %s data points " , RealToString ( p - > data . size ( ) , true ) ) ;
2018-03-15 22:33:05 +00:00
}
ImGui : : TreePop ( ) ;
}
2017-10-22 11:17:34 +00:00
}
2018-03-15 22:33:05 +00:00
2017-10-22 11:13:26 +00:00
ImGui : : Separator ( ) ;
2018-08-17 22:21:01 +00:00
# ifdef TRACY_EXTENDED_FONT
auto expand = ImGui : : TreeNode ( ICON_FA_RANDOM " Visible threads: " ) ;
# else
2018-08-04 19:26:01 +00:00
auto expand = ImGui : : TreeNode ( " Visible threads: " ) ;
2018-08-17 22:21:01 +00:00
# endif
2018-03-15 22:33:05 +00:00
ImGui : : SameLine ( ) ;
2019-03-24 12:41:02 +00:00
ImGui : : TextDisabled ( " (%zu) " , m_threadOrder . size ( ) ) ;
2018-03-15 22:33:05 +00:00
if ( expand )
2017-10-22 11:13:26 +00:00
{
2018-08-20 00:41:11 +00:00
auto & crash = m_worker . GetCrashEvent ( ) ;
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2018-07-13 22:08:37 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
2019-03-24 12:41:02 +00:00
for ( const auto & t : m_threadOrder )
2018-07-13 22:08:37 +00:00
{
2019-02-21 19:24:08 +00:00
Vis ( t ) . visible = true ;
2018-07-13 22:08:37 +00:00
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
2019-03-24 12:41:02 +00:00
for ( const auto & t : m_threadOrder )
2018-07-13 22:08:37 +00:00
{
2019-02-21 19:24:08 +00:00
Vis ( t ) . visible = false ;
2018-07-13 22:08:37 +00:00
}
}
2019-03-24 12:54:36 +00:00
int idIdx = 0 ;
2018-03-15 22:33:05 +00:00
int idx = 0 ;
2019-03-24 12:54:36 +00:00
int upIdx = - 1 ;
int downIdx = - 1 ;
2019-03-24 12:41:02 +00:00
for ( const auto & t : m_threadOrder )
2018-03-15 22:33:05 +00:00
{
2019-03-24 12:54:36 +00:00
ImGui : : PushID ( idIdx + + ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-21 12:15:46 +00:00
if ( ImGui : : SmallButton ( ICON_FA_CARET_UP ) )
2019-03-24 12:54:36 +00:00
# else
2019-06-21 12:15:46 +00:00
if ( ImGui : : SmallButton ( " ^ " ) )
2019-03-24 12:54:36 +00:00
# endif
{
upIdx = idx ;
}
ImGui : : PopID ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushID ( idIdx + + ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-21 12:15:46 +00:00
if ( ImGui : : SmallButton ( ICON_FA_CARET_DOWN ) )
2019-03-24 12:54:36 +00:00
# else
2019-06-21 12:15:46 +00:00
if ( ImGui : : SmallButton ( " v " ) )
2019-03-24 12:54:36 +00:00
# endif
{
downIdx = idx ;
}
ImGui : : PopID ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : PushID ( idIdx + + ) ;
2019-06-21 12:15:46 +00:00
SmallCheckbox ( m_worker . GetThreadString ( t - > id ) , & Vis ( t ) . visible ) ;
2018-03-15 22:33:05 +00:00
ImGui : : PopID ( ) ;
2018-08-20 00:41:11 +00:00
if ( crash . thread = = t - > id )
{
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , ICON_FA_SKULL ) ;
2019-01-09 19:08:18 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Crashed " ) ;
2019-01-09 19:08:18 +00:00
ImGui : : EndTooltip ( ) ;
2019-03-24 22:52:36 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_showInfo = true ;
}
if ( ImGui : : IsMouseClicked ( 2 ) )
{
CenterAtTime ( crash . time ) ;
}
2019-01-09 19:08:18 +00:00
}
2018-08-20 00:41:11 +00:00
# else
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , " Crashed " ) ;
2018-08-20 00:41:11 +00:00
# endif
}
2019-01-09 19:08:18 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " %s top level zones " , RealToString ( t - > timeline . size ( ) , true ) ) ;
2019-03-24 12:54:36 +00:00
idx + + ;
}
if ( upIdx > 0 )
{
std : : swap ( m_threadOrder [ upIdx ] , m_threadOrder [ upIdx - 1 ] ) ;
}
2019-06-22 12:15:25 +00:00
if ( downIdx > = 0 & & ( size_t ) downIdx < m_threadOrder . size ( ) - 1 )
2019-03-24 12:54:36 +00:00
{
std : : swap ( m_threadOrder [ downIdx ] , m_threadOrder [ downIdx + 1 ] ) ;
2018-03-15 22:33:05 +00:00
}
ImGui : : TreePop ( ) ;
2017-10-22 11:13:26 +00:00
}
2018-08-04 19:26:01 +00:00
ImGui : : Separator ( ) ;
2018-08-17 22:21:01 +00:00
# ifdef TRACY_EXTENDED_FONT
expand = ImGui : : TreeNode ( ICON_FA_IMAGES " Visible frame sets: " ) ;
# else
2018-08-04 19:26:01 +00:00
expand = ImGui : : TreeNode ( " Visible frame sets: " ) ;
2018-08-17 22:21:01 +00:00
# endif
2018-08-04 19:26:01 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_worker . GetFrames ( ) . size ( ) ) ;
if ( expand )
{
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2018-08-04 19:26:01 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
for ( const auto & fd : m_worker . GetFrames ( ) )
{
2019-02-21 19:24:08 +00:00
Vis ( fd ) . visible = true ;
2018-08-04 19:26:01 +00:00
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
for ( const auto & fd : m_worker . GetFrames ( ) )
{
2019-02-21 19:24:08 +00:00
Vis ( fd ) . visible = false ;
2018-08-04 19:26:01 +00:00
}
}
int idx = 0 ;
for ( const auto & fd : m_worker . GetFrames ( ) )
{
ImGui : : PushID ( idx + + ) ;
2019-06-21 12:15:46 +00:00
SmallCheckbox ( fd - > name = = 0 ? " Frames " : m_worker . GetString ( fd - > name ) , & Vis ( fd ) . visible ) ;
2018-08-04 19:26:01 +00:00
ImGui : : PopID ( ) ;
ImGui : : SameLine ( ) ;
2018-08-05 00:30:41 +00:00
ImGui : : TextDisabled ( " %s %sframes " , RealToString ( fd - > frames . size ( ) , true ) , fd - > continuous ? " " : " discontinuous " ) ;
2018-08-04 19:26:01 +00:00
}
ImGui : : TreePop ( ) ;
}
2017-10-13 11:32:23 +00:00
ImGui : : End ( ) ;
}
2017-10-14 12:36:30 +00:00
void View : : DrawMessages ( )
{
2019-03-08 23:37:58 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 1200 , 600 ) , ImGuiCond_FirstUseEver ) ;
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Messages " , & m_showMessages ) ;
2018-08-18 17:57:36 +00:00
2019-02-22 19:55:55 +00:00
size_t tsz = 0 ;
2019-03-24 12:41:14 +00:00
for ( const auto & t : m_threadOrder ) if ( ! t - > messages . empty ( ) ) tsz + + ;
2019-02-22 19:55:55 +00:00
2018-08-18 17:57:36 +00:00
# ifdef TRACY_EXTENDED_FONT
auto expand = ImGui : : TreeNode ( ICON_FA_RANDOM " Visible threads: " ) ;
# else
auto expand = ImGui : : TreeNode ( " Visible threads: " ) ;
# endif
ImGui : : SameLine ( ) ;
2019-02-22 19:55:55 +00:00
ImGui : : TextDisabled ( " (%zu) " , tsz ) ;
2018-08-18 17:57:36 +00:00
if ( expand )
{
2018-08-20 00:41:11 +00:00
auto & crash = m_worker . GetCrashEvent ( ) ;
2019-06-22 12:43:58 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 17:57:36 +00:00
if ( ImGui : : SmallButton ( " Select all " ) )
{
2019-03-24 12:41:14 +00:00
for ( const auto & t : m_threadOrder )
2018-08-18 17:57:36 +00:00
{
VisibleMsgThread ( t - > id ) = true ;
}
}
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( " Unselect all " ) )
{
2019-03-24 12:41:14 +00:00
for ( const auto & t : m_threadOrder )
2018-08-18 17:57:36 +00:00
{
VisibleMsgThread ( t - > id ) = false ;
}
}
int idx = 0 ;
2019-03-24 12:41:14 +00:00
for ( const auto & t : m_threadOrder )
2018-08-18 17:57:36 +00:00
{
2019-02-22 19:55:55 +00:00
if ( t - > messages . empty ( ) ) continue ;
2018-08-18 17:57:36 +00:00
ImGui : : PushID ( idx + + ) ;
2019-06-21 12:15:46 +00:00
SmallCheckbox ( m_worker . GetThreadString ( t - > id ) , & VisibleMsgThread ( t - > id ) ) ;
2018-08-18 17:57:36 +00:00
ImGui : : PopID ( ) ;
2019-02-22 19:55:46 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( t - > messages . size ( ) , true ) ) ;
2018-08-20 00:41:11 +00:00
if ( crash . thread = = t - > id )
{
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , ICON_FA_SKULL " Crashed " ) ;
2018-08-20 00:41:11 +00:00
# else
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , " Crashed " ) ;
2018-08-20 00:41:11 +00:00
# endif
}
2018-08-18 17:57:36 +00:00
}
ImGui : : TreePop ( ) ;
}
ImGui : : Separator ( ) ;
2019-03-08 23:37:58 +00:00
const auto w = ImGui : : GetWindowWidth ( ) ;
static bool widthSet = false ;
2018-05-25 19:13:56 +00:00
ImGui : : Columns ( 3 ) ;
2019-03-08 23:37:58 +00:00
if ( ! widthSet )
{
widthSet = true ;
ImGui : : SetColumnWidth ( 0 , w * 0.07f ) ;
ImGui : : SetColumnWidth ( 1 , w * 0.13f ) ;
ImGui : : SetColumnWidth ( 2 , w * 0.8f ) ;
}
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Time " ) ;
2018-06-22 18:23:56 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Click on message to center timeline on it. " ) ;
2018-05-25 18:53:26 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Thread " ) ;
2018-05-25 19:13:56 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Message " ) ;
2018-05-25 18:53:26 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetMessages ( ) )
2017-10-14 12:36:30 +00:00
{
2018-08-18 17:57:36 +00:00
if ( VisibleMsgThread ( v - > thread ) )
2018-08-05 14:57:21 +00:00
{
2018-08-18 17:57:36 +00:00
ImGui : : PushID ( v ) ;
if ( ImGui : : Selectable ( TimeToString ( v - > time - m_worker . GetTimeBegin ( ) ) , m_msgHighlight = = v , ImGuiSelectableFlags_SpanAllColumns ) )
{
CenterAtTime ( v - > time ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_msgHighlight = v ;
}
if ( m_msgToFocus = = v )
{
2019-03-15 00:00:43 +00:00
ImGui : : SetScrollHereY ( ) ;
2018-08-18 17:57:36 +00:00
m_msgToFocus = nullptr ;
}
ImGui : : PopID ( ) ;
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetThreadString ( v - > thread ) ) ;
2018-08-18 17:57:36 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , v - > thread ) ;
ImGui : : NextColumn ( ) ;
2019-05-10 18:25:57 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , v - > color ) ;
2018-08-18 17:57:36 +00:00
ImGui : : TextWrapped ( " %s " , m_worker . GetString ( v - > ref ) ) ;
2019-05-10 18:25:57 +00:00
ImGui : : PopStyleColor ( ) ;
2018-08-18 17:57:36 +00:00
ImGui : : NextColumn ( ) ;
2018-08-05 14:57:21 +00:00
}
2017-10-14 12:36:30 +00:00
}
2018-05-25 18:53:26 +00:00
ImGui : : EndColumns ( ) ;
2017-10-14 12:36:30 +00:00
ImGui : : End ( ) ;
}
2018-07-21 18:26:13 +00:00
uint64_t View : : GetSelectionTarget ( const Worker : : ZoneThreadData & ev , FindZone : : GroupBy groupBy ) const
{
switch ( groupBy )
{
case FindZone : : GroupBy : : Thread :
return ev . thread ;
case FindZone : : GroupBy : : UserText :
return ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ;
case FindZone : : GroupBy : : Callstack :
return ev . zone - > callstack ;
default :
assert ( false ) ;
return 0 ;
}
}
2018-01-17 11:49:50 +00:00
void View : : DrawFindZone ( )
{
2018-12-22 16:39:22 +00:00
if ( m_shortcut = = ShortcutAction : : OpenFind ) ImGui : : SetNextWindowFocus ( ) ;
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 520 , 800 ) , ImGuiCond_FirstUseEver ) ;
2018-08-08 16:40:20 +00:00
ImGui : : Begin ( " Find zone " , & m_findZone . show ) ;
2018-03-18 11:55:54 +00:00
# ifdef TRACY_NO_STATISTICS
ImGui : : TextWrapped ( " Collection of statistical data is disabled in this build. " ) ;
ImGui : : TextWrapped ( " Rebuild without the TRACY_NO_STATISTICS macro to enable zone search. " ) ;
# else
2018-04-30 01:54:09 +00:00
if ( ! m_worker . AreSourceLocationZonesReady ( ) )
{
ImGui : : TextWrapped ( " Please wait, computing data... " ) ;
2019-03-06 17:25:39 +00:00
DrawWaitingDots ( s_time ) ;
2018-04-30 01:54:09 +00:00
ImGui : : End ( ) ;
return ;
}
2018-12-18 15:40:23 +00:00
bool findClicked = false ;
2018-12-18 15:38:55 +00:00
ImGui : : PushItemWidth ( - 0.01f ) ;
2018-12-22 16:39:22 +00:00
if ( m_shortcut = = ShortcutAction : : OpenFind )
{
ImGui : : SetKeyboardFocusHere ( ) ;
m_shortcut = ShortcutAction : : None ;
}
2019-03-15 00:47:07 +00:00
findClicked | = ImGui : : InputTextWithHint ( " ###findzone " , " Enter zone name to search for " , m_findZone . pattern , 1024 , ImGuiInputTextFlags_EnterReturnsTrue ) ;
2018-12-18 15:38:55 +00:00
ImGui : : PopItemWidth ( ) ;
2018-01-17 11:49:50 +00:00
2018-08-17 21:52:03 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:40:23 +00:00
findClicked | = ImGui : : Button ( ICON_FA_SEARCH " Find " ) ;
2018-08-17 21:52:03 +00:00
# else
2018-12-18 15:40:23 +00:00
findClicked | = ImGui : : Button ( " Find " ) ;
2018-08-17 21:52:03 +00:00
# endif
2018-01-17 11:49:50 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 21:52:03 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_BAN " Clear " ) )
# else
2018-01-17 11:49:50 +00:00
if ( ImGui : : Button ( " Clear " ) )
2018-08-17 21:52:03 +00:00
# endif
2018-01-17 11:49:50 +00:00
{
2018-03-04 21:52:36 +00:00
m_findZone . Reset ( ) ;
2018-01-17 11:49:50 +00:00
}
2018-12-18 15:38:55 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Ignore case " , & m_findZone . ignoreCase ) ;
2018-01-17 11:49:50 +00:00
2018-02-15 15:24:01 +00:00
if ( findClicked )
2018-01-17 11:49:50 +00:00
{
2018-03-04 21:52:36 +00:00
m_findZone . Reset ( ) ;
2018-01-17 11:49:50 +00:00
FindZones ( ) ;
}
2018-03-04 20:10:10 +00:00
if ( ! m_findZone . match . empty ( ) )
{
ImGui : : Separator ( ) ;
2018-03-24 01:45:24 +00:00
bool expand = ImGui : : TreeNodeEx ( " Matched source locations " , ImGuiTreeNodeFlags_DefaultOpen ) ;
2018-03-20 19:18:23 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_findZone . match . size ( ) ) ;
if ( expand )
2018-03-04 20:10:10 +00:00
{
2018-03-18 15:41:58 +00:00
auto prev = m_findZone . selMatch ;
2018-03-04 21:11:50 +00:00
int idx = 0 ;
for ( auto & v : m_findZone . match )
2018-03-04 20:10:10 +00:00
{
2018-03-18 15:07:07 +00:00
auto & srcloc = m_worker . GetSourceLocation ( v ) ;
2018-03-18 19:20:24 +00:00
auto & zones = m_worker . GetZonesForSourceLocation ( v ) . zones ;
2018-03-18 15:07:07 +00:00
ImGui : : PushID ( idx ) ;
ImGui : : RadioButton ( m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) , & m_findZone . selMatch , idx + + ) ;
2018-08-18 18:35:25 +00:00
if ( m_findZoneBuzzAnim . Match ( idx ) )
{
const auto time = m_findZoneBuzzAnim . Time ( ) ;
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
{
ImGui : : SameLine ( ) ;
}
const auto fileName = m_worker . GetString ( srcloc . file ) ;
ImGui : : TextColored ( ImVec4 ( 0.5 , 0.5 , 0.5 , 1 ) , " (%s) %s:%i " , RealToString ( zones . size ( ) , true ) , fileName , srcloc . line ) ;
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( fileName ) )
{
SetTextEditorFile ( fileName , srcloc . line ) ;
}
else
{
m_findZoneBuzzAnim . Enable ( idx , 0.5f ) ;
}
}
2018-03-04 20:10:10 +00:00
ImGui : : PopID ( ) ;
}
ImGui : : TreePop ( ) ;
2018-03-18 15:41:58 +00:00
if ( m_findZone . selMatch ! = prev )
{
2018-09-02 11:25:17 +00:00
m_findZone . ResetMatch ( ) ;
2018-03-18 15:41:58 +00:00
}
2018-03-04 20:10:10 +00:00
}
2019-01-23 13:25:28 +00:00
if ( m_findZone . scheduleResetMatch )
{
m_findZone . scheduleResetMatch = false ;
m_findZone . ResetMatch ( ) ;
}
2018-03-04 20:10:10 +00:00
2018-02-15 16:25:16 +00:00
ImGui : : Separator ( ) ;
2018-02-15 15:17:16 +00:00
2019-02-27 19:37:38 +00:00
auto & zoneData = m_worker . GetZonesForSourceLocation ( m_findZone . match [ m_findZone . selMatch ] ) ;
2018-03-24 01:45:24 +00:00
if ( ImGui : : TreeNodeEx ( " Histogram " , ImGuiTreeNodeFlags_DefaultOpen ) )
2018-01-17 11:49:50 +00:00
{
2018-02-20 15:01:33 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
2018-03-18 19:20:24 +00:00
auto & zones = zoneData . zones ;
2019-06-15 23:58:15 +00:00
auto tmin = m_findZone . selfTime ? zoneData . selfMin : zoneData . min ;
auto tmax = m_findZone . selfTime ? zoneData . selfMax : zoneData . max ;
auto timeTotal = m_findZone . selfTime ? zoneData . selfTotal : zoneData . total ;
2018-02-15 16:25:16 +00:00
2018-09-01 22:19:15 +00:00
const auto zsz = zones . size ( ) ;
if ( m_findZone . sortedNum ! = zsz )
{
auto & vec = m_findZone . sorted ;
vec . reserve ( zsz ) ;
2018-09-01 22:28:57 +00:00
int64_t total = m_findZone . total ;
2018-09-01 22:19:15 +00:00
size_t i ;
2019-01-23 13:25:45 +00:00
if ( m_findZone . selfTime )
2018-09-01 22:19:15 +00:00
{
2019-01-23 13:25:45 +00:00
for ( i = m_findZone . sortedNum ; i < zsz ; i + + )
{
auto & zone = * zones [ i ] . zone ;
if ( zone . end < 0 ) break ;
const auto t = zone . end - zone . start - GetZoneChildTimeFast ( zone ) ;
vec . emplace_back ( t ) ;
total + = t ;
}
}
else
{
for ( i = m_findZone . sortedNum ; i < zsz ; i + + )
{
auto & zone = * zones [ i ] . zone ;
if ( zone . end < 0 ) break ;
const auto t = zone . end - zone . start ;
vec . emplace_back ( t ) ;
total + = t ;
}
2018-09-01 22:19:15 +00:00
}
auto mid = vec . begin ( ) + m_findZone . sortedNum ;
pdqsort_branchless ( mid , vec . end ( ) ) ;
std : : inplace_merge ( vec . begin ( ) , mid , vec . end ( ) ) ;
2018-09-01 22:28:57 +00:00
m_findZone . average = float ( total ) / i ;
m_findZone . median = vec [ i / 2 ] ;
m_findZone . total = total ;
2018-09-01 22:19:15 +00:00
m_findZone . sortedNum = i ;
}
2018-09-02 01:17:05 +00:00
if ( m_findZone . selGroup ! = m_findZone . Unselected )
{
if ( m_findZone . selSortNum ! = m_findZone . sortedNum )
{
const auto selGroup = m_findZone . selGroup ;
const auto groupBy = m_findZone . groupBy ;
auto & vec = m_findZone . selSort ;
vec . reserve ( zsz ) ;
auto act = m_findZone . selSortActive ;
2018-09-02 10:48:04 +00:00
int64_t total = m_findZone . selTotal ;
2019-01-23 13:25:45 +00:00
if ( m_findZone . selfTime )
{
for ( size_t i = m_findZone . selSortNum ; i < m_findZone . sortedNum ; i + + )
{
auto & ev = zones [ i ] ;
if ( selGroup = = GetSelectionTarget ( ev , groupBy ) )
{
const auto t = ev . zone - > end - ev . zone - > start - GetZoneChildTimeFast ( * ev . zone ) ;
vec . emplace_back ( t ) ;
act + + ;
total + = t ;
}
}
}
else
2018-09-02 01:17:05 +00:00
{
2019-01-23 13:25:45 +00:00
for ( size_t i = m_findZone . selSortNum ; i < m_findZone . sortedNum ; i + + )
2018-09-02 01:17:05 +00:00
{
2019-01-23 13:25:45 +00:00
auto & ev = zones [ i ] ;
if ( selGroup = = GetSelectionTarget ( ev , groupBy ) )
{
const auto t = ev . zone - > end - ev . zone - > start ;
vec . emplace_back ( t ) ;
act + + ;
total + = t ;
}
2018-09-02 01:17:05 +00:00
}
}
auto mid = vec . begin ( ) + m_findZone . selSortActive ;
pdqsort_branchless ( mid , vec . end ( ) ) ;
std : : inplace_merge ( vec . begin ( ) , mid , vec . end ( ) ) ;
2018-09-02 10:48:04 +00:00
m_findZone . selAverage = float ( total ) / act ;
m_findZone . selMedian = vec [ act / 2 ] ;
m_findZone . selTotal = total ;
2018-09-02 01:17:05 +00:00
m_findZone . selSortNum = m_findZone . sortedNum ;
m_findZone . selSortActive = act ;
}
}
2018-03-18 01:43:17 +00:00
if ( tmin ! = std : : numeric_limits < int64_t > : : max ( ) )
2018-03-05 19:15:18 +00:00
{
2018-03-18 01:43:17 +00:00
ImGui : : Checkbox ( " Log values " , & m_findZone . logVal ) ;
ImGui : : SameLine ( ) ;
2019-06-16 23:05:46 +00:00
if ( ImGui : : Checkbox ( " Log time " , & m_findZone . logTime ) )
{
m_findZone . binCache . numBins = - 1 ;
}
2018-03-18 01:43:17 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Cumulate time " , & m_findZone . cumulateTime ) ;
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Show total time taken by calls in each bin instead of call counts. " ) ;
2019-01-23 13:25:28 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Checkbox ( " Self time " , & m_findZone . selfTime ) )
{
m_findZone . scheduleResetMatch = true ;
}
2019-01-23 17:11:47 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , 100.f * zoneData . selfTotal / zoneData . total ) ;
2018-02-16 12:28:40 +00:00
2019-06-15 23:29:09 +00:00
TextDisabledUnformatted ( " Minimum values in bin: " ) ;
2018-06-29 16:33:01 +00:00
ImGui : : SameLine ( ) ;
2019-06-15 23:29:09 +00:00
ImGui : : SetNextItemWidth ( ImGui : : CalcTextSize ( " 123456890123456 " ) . x ) ;
ImGui : : InputInt ( " ##minBinVal " , & m_findZone . minBinVal ) ;
if ( m_findZone . minBinVal < 1 ) m_findZone . minBinVal = 1 ;
2019-06-16 23:12:24 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Reset " ) ) m_findZone . minBinVal = 1 ;
2018-01-17 11:49:50 +00:00
2018-03-20 15:28:55 +00:00
const auto cumulateTime = m_findZone . cumulateTime ;
2018-02-15 16:25:16 +00:00
2019-06-15 23:58:15 +00:00
if ( tmax - tmin > 0 )
2018-02-16 12:09:24 +00:00
{
2018-03-18 01:43:17 +00:00
const auto w = ImGui : : GetContentRegionAvail ( ) . x ;
2018-02-16 13:42:16 +00:00
2018-03-18 01:43:17 +00:00
const auto numBins = int64_t ( w - 4 ) ;
if ( numBins > 1 )
2018-02-15 16:25:16 +00:00
{
2018-03-18 01:43:17 +00:00
int64_t selectionTime = 0 ;
2018-09-01 23:31:09 +00:00
const auto s = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto e = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
2018-03-18 01:43:17 +00:00
2018-09-02 00:30:06 +00:00
const auto & sorted = m_findZone . sorted ;
2019-06-15 23:28:36 +00:00
auto sortedBegin = sorted . begin ( ) ;
auto sortedEnd = sorted . end ( ) ;
while ( sortedBegin ! = sortedEnd & & * sortedBegin = = 0 ) + + sortedBegin ;
2019-06-15 23:58:15 +00:00
if ( m_findZone . minBinVal > 1 )
{
if ( m_findZone . logTime )
{
const auto tMinLog = log10 ( tmin ) ;
const auto zmax = ( log10 ( tmax ) - tMinLog ) / numBins ;
int64_t i ;
for ( i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
auto nit = std : : lower_bound ( sortedBegin , sortedEnd , nextBinVal ) ;
const auto distance = std : : distance ( sortedBegin , nit ) ;
if ( distance > = m_findZone . minBinVal ) break ;
sortedBegin = nit ;
}
for ( int64_t j = numBins - 1 ; j > i ; j - - )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( j - 1 ) * zmax ) ) ;
auto nit = std : : lower_bound ( sortedBegin , sortedEnd , nextBinVal ) ;
const auto distance = std : : distance ( nit , sortedEnd ) ;
if ( distance > = m_findZone . minBinVal ) break ;
sortedEnd = nit ;
}
}
else
{
const auto zmax = tmax - tmin ;
int64_t i ;
for ( i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
auto nit = std : : lower_bound ( sortedBegin , sortedEnd , nextBinVal ) ;
const auto distance = std : : distance ( sortedBegin , nit ) ;
if ( distance > = m_findZone . minBinVal ) break ;
sortedBegin = nit ;
}
for ( int64_t j = numBins - 1 ; j > i ; j - - )
{
const auto nextBinVal = tmin + ( j - 1 ) * zmax / numBins ;
auto nit = std : : lower_bound ( sortedBegin , sortedEnd , nextBinVal ) ;
const auto distance = std : : distance ( nit , sortedEnd ) ;
if ( distance > = m_findZone . minBinVal ) break ;
sortedEnd = nit ;
}
}
tmin = * sortedBegin ;
tmax = * ( sortedEnd - 1 ) ;
timeTotal = tmax - tmin ;
}
2019-06-16 14:29:18 +00:00
if ( numBins > m_findZone . numBins )
{
m_findZone . numBins = numBins ;
m_findZone . bins = std : : make_unique < int64_t [ ] > ( numBins ) ;
m_findZone . binTime = std : : make_unique < int64_t [ ] > ( numBins ) ;
m_findZone . selBin = std : : make_unique < int64_t [ ] > ( numBins ) ;
2019-06-16 14:41:52 +00:00
m_findZone . binCache . numBins = - 1 ;
2019-06-16 14:29:18 +00:00
}
const auto & bins = m_findZone . bins ;
const auto & binTime = m_findZone . binTime ;
const auto & selBin = m_findZone . selBin ;
2019-06-16 14:41:52 +00:00
const auto distBegin = std : : distance ( sorted . begin ( ) , sortedBegin ) ;
const auto distEnd = std : : distance ( sorted . begin ( ) , sortedEnd ) ;
if ( m_findZone . binCache . numBins ! = numBins | |
m_findZone . binCache . distBegin ! = distBegin | |
m_findZone . binCache . distEnd ! = distEnd )
2018-09-01 23:31:09 +00:00
{
2019-06-16 14:41:52 +00:00
m_findZone . binCache . numBins = numBins ;
m_findZone . binCache . distBegin = distBegin ;
m_findZone . binCache . distEnd = distEnd ;
memset ( bins . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
memset ( binTime . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
memset ( selBin . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
if ( m_findZone . logTime )
2018-03-05 19:23:58 +00:00
{
2019-06-16 14:41:52 +00:00
const auto tMinLog = log10 ( tmin ) ;
const auto zmax = ( log10 ( tmax ) - tMinLog ) / numBins ;
{
auto zit = sortedBegin ;
for ( int64_t i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
auto nit = std : : lower_bound ( zit , sortedEnd , nextBinVal ) ;
const auto distance = std : : distance ( zit , nit ) ;
const auto timeSum = std : : accumulate ( zit , nit , int64_t ( 0 ) ) ;
bins [ i ] = distance ;
binTime [ i ] = timeSum ;
if ( m_findZone . highlight . active )
{
auto end = nit = = zit ? zit : nit - 1 ;
if ( * zit > = s & & * end < = e ) selectionTime + = timeSum ;
}
zit = nit ;
}
const auto timeSum = std : : accumulate ( zit , sortedEnd , int64_t ( 0 ) ) ;
bins [ numBins - 1 ] + = std : : distance ( zit , sortedEnd ) ;
binTime [ numBins - 1 ] + = timeSum ;
if ( m_findZone . highlight . active & & * zit > = s & & * ( sortedEnd - 1 ) < = e ) selectionTime + = timeSum ;
}
if ( m_findZone . selGroup ! = m_findZone . Unselected )
{
auto zit = m_findZone . selSort . begin ( ) ;
while ( zit ! = m_findZone . selSort . end ( ) & & * zit = = 0 ) + + zit ;
for ( int64_t i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
auto nit = std : : lower_bound ( zit , m_findZone . selSort . end ( ) , nextBinVal ) ;
if ( cumulateTime )
{
selBin [ i ] = std : : accumulate ( zit , nit , int64_t ( 0 ) ) ;
}
else
{
selBin [ i ] = std : : distance ( zit , nit ) ;
}
zit = nit ;
}
}
}
else
{
const auto zmax = tmax - tmin ;
2019-06-15 23:28:36 +00:00
auto zit = sortedBegin ;
2018-09-02 01:17:05 +00:00
for ( int64_t i = 0 ; i < numBins ; i + + )
2018-03-20 13:37:58 +00:00
{
2019-06-16 14:41:52 +00:00
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
2019-06-15 23:28:36 +00:00
auto nit = std : : lower_bound ( zit , sortedEnd , nextBinVal ) ;
2018-09-02 01:17:05 +00:00
const auto distance = std : : distance ( zit , nit ) ;
const auto timeSum = std : : accumulate ( zit , nit , int64_t ( 0 ) ) ;
bins [ i ] = distance ;
binTime [ i ] = timeSum ;
if ( m_findZone . highlight . active )
{
auto end = nit = = zit ? zit : nit - 1 ;
if ( * zit > = s & & * end < = e ) selectionTime + = timeSum ;
}
zit = nit ;
2018-09-02 00:30:06 +00:00
}
2019-06-15 23:28:36 +00:00
const auto timeSum = std : : accumulate ( zit , sortedEnd , int64_t ( 0 ) ) ;
bins [ numBins - 1 ] + = std : : distance ( zit , sortedEnd ) ;
2018-09-02 01:17:05 +00:00
binTime [ numBins - 1 ] + = timeSum ;
2019-06-15 23:28:36 +00:00
if ( m_findZone . highlight . active & & * zit > = s & & * ( sortedEnd - 1 ) < = e ) selectionTime + = timeSum ;
2018-09-02 00:30:06 +00:00
2019-06-16 14:41:52 +00:00
if ( m_findZone . selGroup ! = m_findZone . Unselected )
2018-03-05 19:23:58 +00:00
{
2019-06-16 14:41:52 +00:00
auto zit = m_findZone . selSort . begin ( ) ;
while ( zit ! = m_findZone . selSort . end ( ) & & * zit = = 0 ) + + zit ;
for ( int64_t i = 0 ; i < numBins ; i + + )
2018-03-18 01:43:17 +00:00
{
2019-06-16 14:41:52 +00:00
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
auto nit = std : : lower_bound ( zit , m_findZone . selSort . end ( ) , nextBinVal ) ;
if ( cumulateTime )
{
selBin [ i ] = std : : accumulate ( zit , nit , int64_t ( 0 ) ) ;
}
else
{
selBin [ i ] = std : : distance ( zit , nit ) ;
}
zit = nit ;
2018-03-18 01:43:17 +00:00
}
2018-03-05 19:23:58 +00:00
}
2018-02-16 14:34:22 +00:00
}
2018-02-16 12:09:24 +00:00
}
2018-01-17 11:49:50 +00:00
2018-03-18 01:43:17 +00:00
int64_t maxVal ;
2018-03-20 15:28:55 +00:00
if ( cumulateTime )
2018-03-05 19:15:18 +00:00
{
2018-03-18 01:43:17 +00:00
maxVal = binTime [ 0 ] ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( maxVal , binTime [ i ] ) ;
}
2018-03-05 19:15:18 +00:00
}
2018-03-18 01:43:17 +00:00
else
2018-03-05 19:15:18 +00:00
{
2018-03-18 01:43:17 +00:00
maxVal = bins [ 0 ] ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( maxVal , bins [ i ] ) ;
}
2018-03-05 19:15:18 +00:00
}
2018-02-15 16:25:16 +00:00
2019-06-15 23:29:09 +00:00
TextDisabledUnformatted ( " Time range: " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s (%s) " , TimeToString ( tmin ) , TimeToString ( tmax ) , TimeToString ( tmax - tmin ) ) ;
2018-06-29 16:33:01 +00:00
TextFocused ( " Total time: " , TimeToString ( timeTotal ) ) ;
2018-03-18 01:43:17 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
2018-06-29 16:33:01 +00:00
TextFocused ( " Max counts: " , cumulateTime ? TimeToString ( maxVal ) : RealToString ( maxVal , true ) ) ;
2018-09-01 22:28:57 +00:00
TextFocused ( " Average time: " , TimeToString ( m_findZone . average ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
TextFocused ( " Median time: " , TimeToString ( m_findZone . median ) ) ;
2019-03-14 00:14:06 +00:00
if ( m_findZone . sorted . size ( ) > 1 )
{
2019-03-14 00:23:37 +00:00
const auto sz = m_findZone . sorted . size ( ) ;
2019-03-14 00:14:06 +00:00
const auto avg = m_findZone . average ;
2019-03-14 00:23:37 +00:00
const auto ss = zoneData . sumSq - 2. * zoneData . total * avg + avg * avg * sz ;
const auto sd = sqrt ( ss / ( sz - 1 ) ) ;
2019-03-14 00:14:06 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
TextFocused ( " \xcf \x83 : " , TimeToString ( sd ) ) ;
# else
TextFocused ( " s: " , TimeToString ( sd ) ) ;
# endif
2019-03-14 00:34:43 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Standard deviation " ) ;
ImGui : : EndTooltip ( ) ;
}
2019-03-14 00:14:06 +00:00
}
2018-02-16 15:19:31 +00:00
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Selection range: " ) ;
2018-06-29 16:33:01 +00:00
ImGui : : SameLine ( ) ;
2018-03-18 01:43:17 +00:00
if ( m_findZone . highlight . active )
{
const auto s = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto e = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
2018-06-29 16:33:01 +00:00
ImGui : : Text ( " %s - %s (%s) " , TimeToString ( s ) , TimeToString ( e ) , TimeToString ( e - s ) ) ;
2018-03-18 01:43:17 +00:00
}
else
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " none " ) ;
2018-03-18 01:43:17 +00:00
}
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Left draw on histogram to select range. Right click to clear selection. " ) ;
2018-03-18 01:43:17 +00:00
if ( m_findZone . highlight . active )
{
2018-06-29 16:33:01 +00:00
TextFocused ( " Selection time: " , TimeToString ( selectionTime ) ) ;
2018-03-18 01:43:17 +00:00
}
else
{
2018-06-29 16:33:01 +00:00
TextFocused ( " Selection time: " , " none " ) ;
2018-03-18 01:43:17 +00:00
}
2018-09-02 01:17:05 +00:00
if ( m_findZone . selGroup ! = m_findZone . Unselected )
2018-03-20 15:56:11 +00:00
{
2018-09-02 01:17:05 +00:00
TextFocused ( " Zone group time: " , TimeToString ( m_findZone . groups [ m_findZone . selGroup ] . time ) ) ;
2018-09-02 10:48:15 +00:00
TextFocused ( " Group average: " , TimeToString ( m_findZone . selAverage ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
TextFocused ( " Group median: " , TimeToString ( m_findZone . selMedian ) ) ;
2018-03-20 15:56:11 +00:00
}
else
{
2018-06-29 16:33:01 +00:00
TextFocused ( " Zone group time: " , " none " ) ;
2018-09-02 10:48:15 +00:00
TextFocused ( " Group average: " , " none " ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
TextFocused ( " Group median: " , " none " ) ;
2018-03-20 15:56:11 +00:00
}
2018-03-05 19:23:58 +00:00
2019-06-21 12:15:46 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
2018-09-02 11:06:09 +00:00
ImGui : : Checkbox ( " ###draw1 " , & m_findZone . drawAvgMed ) ;
ImGui : : SameLine ( ) ;
2018-09-01 22:28:57 +00:00
ImGui : : ColorButton ( " c1 " , ImVec4 ( 0xFF / 255.f , 0x44 / 255.f , 0x44 / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Average time " ) ;
2018-09-01 22:28:57 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
2018-09-02 10:56:38 +00:00
ImGui : : ColorButton ( " c2 " , ImVec4 ( 0x44 / 255.f , 0xAA / 255.f , 0xFF / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
2018-09-01 22:28:57 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Median time " ) ;
2018-09-02 11:06:09 +00:00
ImGui : : Checkbox ( " ###draw2 " , & m_findZone . drawSelAvgMed ) ;
2018-09-02 10:56:38 +00:00
ImGui : : SameLine ( ) ;
ImGui : : ColorButton ( " c3 " , ImVec4 ( 0xFF / 255.f , 0xAA / 255.f , 0x44 / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
ImGui : : SameLine ( ) ;
2018-09-03 18:36:40 +00:00
if ( m_findZone . selGroup ! = m_findZone . Unselected )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Group average " ) ;
2018-09-03 18:36:40 +00:00
}
else
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Group average " ) ;
2018-09-03 18:36:40 +00:00
}
2018-09-02 10:56:38 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : ColorButton ( " c4 " , ImVec4 ( 0x44 / 255.f , 0xDD / 255.f , 0x44 / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
ImGui : : SameLine ( ) ;
2018-09-03 18:36:40 +00:00
if ( m_findZone . selGroup ! = m_findZone . Unselected )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Group median " ) ;
2018-09-03 18:36:40 +00:00
}
else
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Group median " ) ;
2018-09-03 18:36:40 +00:00
}
2019-06-21 12:15:46 +00:00
ImGui : : PopStyleVar ( ) ;
2018-09-01 22:28:57 +00:00
2018-06-28 22:44:05 +00:00
const auto Height = 200 * ImGui : : GetTextLineHeight ( ) / 15.f ;
2018-03-18 01:43:17 +00:00
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
ImGui : : InvisibleButton ( " ##histogram " , ImVec2 ( w , Height + round ( ty * 1.5 ) ) ) ;
const bool hover = ImGui : : IsItemHovered ( ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
auto draw = ImGui : : GetWindowDrawList ( ) ;
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( w , Height ) , 0x22FFFFFF ) ;
draw - > AddRect ( wpos , wpos + ImVec2 ( w , Height ) , 0x88FFFFFF ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
if ( m_findZone . logVal )
2018-02-16 12:28:40 +00:00
{
2018-09-08 17:01:51 +00:00
const auto hAdj = double ( Height - 4 ) / log10 ( maxVal + 1 ) ;
2018-03-18 01:43:17 +00:00
for ( int i = 0 ; i < numBins ; i + + )
2018-02-16 12:28:40 +00:00
{
2018-03-20 15:28:55 +00:00
const auto val = cumulateTime ? binTime [ i ] : bins [ i ] ;
2018-03-18 01:43:17 +00:00
if ( val > 0 )
{
2018-09-08 17:01:51 +00:00
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val + 1 ) * hAdj ) , 0xFF22DDDD ) ;
2018-03-20 13:37:58 +00:00
if ( selBin [ i ] > 0 )
{
2018-09-08 17:01:51 +00:00
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( selBin [ i ] + 1 ) * hAdj ) , 0xFFDD7777 ) ;
2018-03-20 13:37:58 +00:00
}
2018-03-18 01:43:17 +00:00
}
2018-02-16 12:28:40 +00:00
}
}
2018-03-18 01:43:17 +00:00
else
2018-02-16 12:09:24 +00:00
{
2018-03-18 01:43:17 +00:00
const auto hAdj = double ( Height - 4 ) / maxVal ;
for ( int i = 0 ; i < numBins ; i + + )
2018-02-16 12:28:40 +00:00
{
2018-03-20 15:28:55 +00:00
const auto val = cumulateTime ? binTime [ i ] : bins [ i ] ;
2018-03-18 01:43:17 +00:00
if ( val > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - val * hAdj ) , 0xFF22DDDD ) ;
2018-03-20 13:37:58 +00:00
if ( selBin [ i ] > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - selBin [ i ] * hAdj ) , 0xFFDD7777 ) ;
}
2018-03-18 01:43:17 +00:00
}
2018-02-16 12:28:40 +00:00
}
2018-02-16 12:09:24 +00:00
}
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
const auto xoff = 2 ;
const auto yoff = Height + 1 ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
if ( m_findZone . logTime )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-03-18 01:43:17 +00:00
const auto start = int ( floor ( ltmin ) ) ;
const auto end = int ( ceil ( ltmax ) ) ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
const auto range = ltmax - ltmin ;
const auto step = w / range ;
auto offset = start - ltmin ;
int tw = 0 ;
int tx = 0 ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
auto tt = int64_t ( pow ( 10 , start ) ) ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
static const double logticks [ ] = { log10 ( 2 ) , log10 ( 3 ) , log10 ( 4 ) , log10 ( 5 ) , log10 ( 6 ) , log10 ( 7 ) , log10 ( 8 ) , log10 ( 9 ) } ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
for ( int i = start ; i < = end ; i + + )
2018-02-28 14:20:52 +00:00
{
2018-03-18 01:43:17 +00:00
const auto x = ( i - start + offset ) * step ;
if ( x > = 0 )
2018-02-28 14:20:52 +00:00
{
2018-03-18 01:43:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( x , yoff ) , wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF ) ;
if ( tw = = 0 | | x > tx + tw + ty * 1.1 )
{
tx = x ;
2019-02-10 00:14:34 +00:00
auto txt = TimeToString ( tt ) ;
2018-03-18 01:43:17 +00:00
draw - > AddText ( wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
2018-02-28 14:20:52 +00:00
}
2018-03-18 01:43:17 +00:00
for ( int j = 0 ; j < 8 ; j + + )
2018-02-28 14:20:52 +00:00
{
2018-03-18 01:43:17 +00:00
const auto xoff = x + logticks [ j ] * step ;
if ( xoff > = 0 )
{
draw - > AddLine ( wpos + ImVec2 ( xoff , yoff ) , wpos + ImVec2 ( xoff , yoff + round ( ty * 0.25 ) ) , 0x66FFFFFF ) ;
}
2018-02-28 14:20:52 +00:00
}
2018-03-18 01:43:17 +00:00
tt * = 10 ;
}
2018-02-28 14:20:52 +00:00
}
2018-03-18 01:43:17 +00:00
else
{
2019-06-15 23:58:15 +00:00
const auto pxns = numBins / double ( tmax - tmin ) ;
2018-03-18 01:43:17 +00:00
const auto nspx = 1.0 / pxns ;
2018-09-08 17:01:51 +00:00
const auto scale = std : : max < float > ( 0.0f , round ( log10 ( nspx ) + 2 ) ) ;
2018-03-18 01:43:17 +00:00
const auto step = pow ( 10 , scale ) ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
const auto dx = step * pxns ;
double x = 0 ;
int tw = 0 ;
int tx = 0 ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
const auto sstep = step / 10.0 ;
const auto sdx = dx / 10.0 ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
static const double linelen [ ] = { 0.5 , 0.25 , 0.25 , 0.25 , 0.25 , 0.375 , 0.25 , 0.25 , 0.25 , 0.25 } ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
int64_t tt = int64_t ( ceil ( tmin / sstep ) * sstep ) ;
const auto diff = tmin / sstep - int64_t ( tmin / sstep ) ;
const auto xo = ( diff = = 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff ;
int iter = int ( ceil ( ( tmin - int64_t ( tmin / step ) * step ) / sstep ) ) ;
2018-02-21 14:18:30 +00:00
2018-03-18 01:43:17 +00:00
while ( x < numBins )
2018-02-20 15:01:33 +00:00
{
2018-03-18 01:43:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( xo + x , yoff ) , wpos + ImVec2 ( xo + x , yoff + round ( ty * linelen [ iter ] ) ) , 0x66FFFFFF ) ;
if ( iter = = 0 & & ( tw = = 0 | | x > tx + tw + ty * 1.1 ) )
{
tx = x ;
2019-02-10 00:14:34 +00:00
auto txt = TimeToString ( tt ) ;
2018-03-18 01:43:17 +00:00
draw - > AddText ( wpos + ImVec2 ( xo + x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
iter = ( iter + 1 ) % 10 ;
x + = sdx ;
tt + = sstep ;
}
2018-02-20 15:01:33 +00:00
}
2018-09-02 10:56:38 +00:00
float ta , tm , tga , tgm ;
2018-09-01 22:28:57 +00:00
if ( m_findZone . logTime )
{
2018-09-02 10:56:38 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-09-01 22:28:57 +00:00
2018-09-02 10:56:38 +00:00
ta = ( log10 ( m_findZone . average ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
tm = ( log10 ( m_findZone . median ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
tga = ( log10 ( m_findZone . selAverage ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
tgm = ( log10 ( m_findZone . selMedian ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
2018-09-01 22:28:57 +00:00
}
else
{
ta = ( m_findZone . average - tmin ) / float ( tmax - tmin ) * numBins ;
tm = ( m_findZone . median - tmin ) / float ( tmax - tmin ) * numBins ;
2018-09-02 10:56:38 +00:00
tga = ( m_findZone . selAverage - tmin ) / float ( tmax - tmin ) * numBins ;
tgm = ( m_findZone . selMedian - tmin ) / float ( tmax - tmin ) * numBins ;
2018-09-01 22:28:57 +00:00
}
ta = round ( ta ) ;
tm = round ( tm ) ;
2018-09-02 10:56:38 +00:00
tga = round ( tga ) ;
tgm = round ( tgm ) ;
2018-09-01 22:28:57 +00:00
2018-09-02 11:06:09 +00:00
if ( m_findZone . drawAvgMed )
2018-09-01 22:28:57 +00:00
{
2018-09-02 11:06:09 +00:00
if ( ta = = tm )
{
draw - > AddLine ( ImVec2 ( wpos . x + ta , wpos . y ) , ImVec2 ( wpos . x + ta , wpos . y + Height - 2 ) , 0xFFFF88FF ) ;
}
else
{
draw - > AddLine ( ImVec2 ( wpos . x + ta , wpos . y ) , ImVec2 ( wpos . x + ta , wpos . y + Height - 2 ) , 0xFF4444FF ) ;
draw - > AddLine ( ImVec2 ( wpos . x + tm , wpos . y ) , ImVec2 ( wpos . x + tm , wpos . y + Height - 2 ) , 0xFFFFAA44 ) ;
}
2018-09-02 10:56:38 +00:00
}
2018-09-02 11:06:09 +00:00
if ( m_findZone . drawSelAvgMed & & m_findZone . selGroup ! = m_findZone . Unselected )
2018-09-02 10:56:38 +00:00
{
draw - > AddLine ( ImVec2 ( wpos . x + tga , wpos . y ) , ImVec2 ( wpos . x + tga , wpos . y + Height - 2 ) , 0xFF44AAFF ) ;
draw - > AddLine ( ImVec2 ( wpos . x + tgm , wpos . y ) , ImVec2 ( wpos . x + tgm , wpos . y + Height - 2 ) , 0xFF44DD44 ) ;
2018-09-01 22:28:57 +00:00
}
2018-03-18 01:43:17 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 2 , 2 ) , wpos + ImVec2 ( w - 2 , Height + round ( ty * 1.5 ) ) ) )
{
2018-09-02 00:30:06 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-03-05 12:20:24 +00:00
2018-03-18 01:43:17 +00:00
auto & io = ImGui : : GetIO ( ) ;
draw - > AddLine ( ImVec2 ( io . MousePos . x , wpos . y ) , ImVec2 ( io . MousePos . x , wpos . y + Height - 2 ) , 0x33FFFFFF ) ;
2018-02-16 13:31:57 +00:00
2018-03-18 01:43:17 +00:00
const auto bin = double ( io . MousePos . x - wpos . x - 2 ) ;
int64_t t0 , t1 ;
if ( m_findZone . logTime )
{
t0 = int64_t ( pow ( 10 , ltmin + bin / numBins * ( ltmax - ltmin ) ) ) ;
2018-06-06 21:36:21 +00:00
// Hackfix for inability to select data in last bin.
// A proper solution would be nice.
if ( bin + 1 = = numBins )
{
t1 = tmax ;
}
else
{
t1 = int64_t ( pow ( 10 , ltmin + ( bin + 1 ) / numBins * ( ltmax - ltmin ) ) ) ;
}
2018-03-18 01:43:17 +00:00
}
else
{
t0 = int64_t ( tmin + bin / numBins * ( tmax - tmin ) ) ;
t1 = int64_t ( tmin + ( bin + 1 ) / numBins * ( tmax - tmin ) ) ;
}
2018-02-16 13:31:57 +00:00
2018-03-18 01:43:17 +00:00
int64_t tBefore = 0 ;
for ( int i = 0 ; i < bin ; i + + )
{
tBefore + = binTime [ i ] ;
}
2018-02-16 13:42:16 +00:00
2018-03-18 01:43:17 +00:00
int64_t tAfter = 0 ;
for ( int i = bin + 1 ; i < numBins ; i + + )
{
tAfter + = binTime [ i ] ;
}
2018-02-16 13:42:16 +00:00
2018-03-18 01:43:17 +00:00
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time range: " ) ;
2018-06-29 16:33:01 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s " , TimeToString ( t0 ) , TimeToString ( t1 ) ) ;
2019-03-26 19:18:20 +00:00
TextFocused ( " Count: " , RealToString ( bins [ bin ] , true ) ) ;
2018-06-29 16:33:01 +00:00
TextFocused ( " Time spent in bin: " , TimeToString ( binTime [ bin ] ) ) ;
TextFocused ( " Time spent in the left bins: " , TimeToString ( tBefore ) ) ;
TextFocused ( " Time spent in the right bins: " , TimeToString ( tAfter ) ) ;
2018-03-18 01:43:17 +00:00
ImGui : : EndTooltip ( ) ;
2018-03-04 21:52:36 +00:00
2018-03-18 01:43:17 +00:00
if ( ImGui : : IsMouseClicked ( 1 ) )
{
m_findZone . highlight . active = false ;
2018-07-21 21:41:50 +00:00
m_findZone . ResetGroups ( ) ;
2018-03-18 01:43:17 +00:00
}
else if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_findZone . highlight . active = true ;
m_findZone . highlight . start = t0 ;
m_findZone . highlight . end = t1 ;
2018-09-02 00:09:29 +00:00
m_findZone . hlOrig_t0 = t0 ;
m_findZone . hlOrig_t1 = t1 ;
2018-03-18 01:43:17 +00:00
}
else if ( ImGui : : IsMouseDragging ( 0 , 0 ) )
{
2018-09-02 00:09:29 +00:00
if ( t0 < m_findZone . hlOrig_t0 )
{
m_findZone . highlight . start = t0 ;
m_findZone . highlight . end = m_findZone . hlOrig_t1 ;
}
else
{
m_findZone . highlight . start = m_findZone . hlOrig_t0 ;
m_findZone . highlight . end = t1 ;
}
2018-07-21 21:41:50 +00:00
m_findZone . ResetGroups ( ) ;
2018-03-18 01:43:17 +00:00
}
2018-03-04 21:52:36 +00:00
}
2018-03-18 01:43:17 +00:00
if ( m_findZone . highlight . active & & m_findZone . highlight . start ! = m_findZone . highlight . end )
2018-03-04 21:52:36 +00:00
{
2018-03-18 01:43:17 +00:00
const auto s = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto e = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
2018-03-04 21:52:36 +00:00
2018-03-18 01:43:17 +00:00
float t0 , t1 ;
if ( m_findZone . logTime )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-03-04 21:52:36 +00:00
2018-09-08 17:01:51 +00:00
t0 = ( log10 ( s ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
t1 = ( log10 ( e ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
2018-03-18 01:43:17 +00:00
}
else
{
t0 = ( s - tmin ) / float ( tmax - tmin ) * numBins ;
t1 = ( e - tmin ) / float ( tmax - tmin ) * numBins ;
}
2018-03-05 12:20:24 +00:00
2019-06-16 14:23:24 +00:00
draw - > PushClipRect ( wpos , wpos + ImVec2 ( w , Height ) , true ) ;
2018-03-18 01:43:17 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( 2 + t0 , 1 ) , wpos + ImVec2 ( 2 + t1 , Height - 1 ) , 0x22DD8888 ) ;
draw - > AddRect ( wpos + ImVec2 ( 2 + t0 , 1 ) , wpos + ImVec2 ( 2 + t1 , Height - 1 ) , 0x44DD8888 ) ;
2019-06-16 14:23:24 +00:00
draw - > PopClipRect ( ) ;
2018-03-04 21:52:36 +00:00
}
2019-06-16 15:14:47 +00:00
if ( m_zoneHover & & m_findZone . match [ m_findZone . selMatch ] = = m_zoneHover - > srcloc )
{
const auto zoneTime = m_worker . GetZoneEnd ( * m_zoneHover ) - m_zoneHover - > start ;
float zonePos ;
if ( m_findZone . logTime )
{
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
zonePos = round ( ( log10 ( zoneTime ) - ltmin ) / float ( ltmax - ltmin ) * numBins ) ;
}
else
{
zonePos = round ( ( zoneTime - tmin ) / float ( tmax - tmin ) * numBins ) ;
}
2019-06-19 18:01:41 +00:00
const auto c = uint32_t ( ( sin ( s_time * 10 ) * 0.25 + 0.75 ) * 255 ) ;
const auto color = 0xFF000000 | ( c < < 16 ) | ( c < < 8 ) | c ;
draw - > AddLine ( ImVec2 ( wpos . x + zonePos , wpos . y ) , ImVec2 ( wpos . x + zonePos , wpos . y + Height - 2 ) , color ) ;
2019-06-16 15:14:47 +00:00
}
2018-02-16 13:31:57 +00:00
}
2018-02-15 16:25:16 +00:00
}
}
ImGui : : TreePop ( ) ;
}
ImGui : : Separator ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Found zones: " ) ;
2018-03-19 15:01:36 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Left click to highlight entry. Right click to clear selection. " ) ;
2018-03-04 17:44:33 +00:00
2018-07-21 22:04:41 +00:00
bool groupChanged = false ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Group by: " ) ;
2018-07-21 22:04:41 +00:00
ImGui : : SameLine ( ) ;
groupChanged | = ImGui : : RadioButton ( " Thread " , ( int * ) ( & m_findZone . groupBy ) , ( int ) FindZone : : GroupBy : : Thread ) ;
ImGui : : SameLine ( ) ;
groupChanged | = ImGui : : RadioButton ( " User text " , ( int * ) ( & m_findZone . groupBy ) , ( int ) FindZone : : GroupBy : : UserText ) ;
ImGui : : SameLine ( ) ;
2018-08-17 20:00:35 +00:00
groupChanged | = ImGui : : RadioButton ( " Call stacks " , ( int * ) ( & m_findZone . groupBy ) , ( int ) FindZone : : GroupBy : : Callstack ) ;
2018-07-21 22:04:41 +00:00
if ( groupChanged )
2018-07-21 18:26:13 +00:00
{
2018-07-21 21:41:50 +00:00
m_findZone . selGroup = m_findZone . Unselected ;
m_findZone . ResetGroups ( ) ;
2018-07-21 18:26:13 +00:00
}
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Sort by: " ) ;
2018-07-21 22:04:41 +00:00
ImGui : : SameLine ( ) ;
ImGui : : RadioButton ( " Order " , ( int * ) ( & m_findZone . sortBy ) , ( int ) FindZone : : SortBy : : Order ) ;
ImGui : : SameLine ( ) ;
ImGui : : RadioButton ( " Count " , ( int * ) ( & m_findZone . sortBy ) , ( int ) FindZone : : SortBy : : Count ) ;
ImGui : : SameLine ( ) ;
ImGui : : RadioButton ( " Time " , ( int * ) ( & m_findZone . sortBy ) , ( int ) FindZone : : SortBy : : Time ) ;
2019-01-30 00:54:18 +00:00
ImGui : : SameLine ( ) ;
ImGui : : RadioButton ( " MTPC " , ( int * ) ( & m_findZone . sortBy ) , ( int ) FindZone : : SortBy : : Mtpc ) ;
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Mean time per call " ) ;
2018-07-21 21:58:50 +00:00
2018-03-18 19:20:24 +00:00
auto & zones = m_worker . GetZonesForSourceLocation ( m_findZone . match [ m_findZone . selMatch ] ) . zones ;
2018-03-18 15:41:58 +00:00
auto sz = zones . size ( ) ;
2018-03-18 20:03:36 +00:00
auto processed = m_findZone . processed ;
2018-03-20 15:28:55 +00:00
const auto hmin = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto hmax = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
2018-07-21 18:26:13 +00:00
const auto groupBy = m_findZone . groupBy ;
2018-03-20 15:28:55 +00:00
const auto highlightActive = m_findZone . highlight . active ;
2018-03-18 20:03:36 +00:00
while ( processed < sz )
2018-02-15 16:25:16 +00:00
{
2018-03-18 20:03:36 +00:00
auto & ev = zones [ processed ] ;
2018-03-24 01:00:20 +00:00
if ( ev . zone - > end < 0 ) break ;
2018-03-18 15:41:58 +00:00
2018-03-18 19:45:49 +00:00
const auto end = m_worker . GetZoneEndDirect ( * ev . zone ) ;
2019-01-23 13:25:45 +00:00
auto timespan = end - ev . zone - > start ;
2018-03-18 20:03:36 +00:00
if ( timespan = = 0 )
{
processed + + ;
continue ;
}
2019-01-23 13:25:45 +00:00
if ( m_findZone . selfTime ) timespan - = GetZoneChildTimeFast ( * ev . zone ) ;
2018-03-18 15:41:58 +00:00
2018-03-20 15:28:55 +00:00
if ( highlightActive )
2018-03-18 15:41:58 +00:00
{
2018-03-20 15:28:55 +00:00
if ( timespan < hmin | | timespan > hmax )
2018-03-18 20:03:36 +00:00
{
processed + + ;
continue ;
}
2018-03-18 15:41:58 +00:00
}
2018-03-04 22:17:36 +00:00
2018-03-18 20:03:36 +00:00
processed + + ;
2018-07-21 21:53:11 +00:00
FindZone : : Group * group ;
2018-07-21 19:35:35 +00:00
switch ( groupBy )
2018-03-19 15:01:36 +00:00
{
2018-07-21 18:26:13 +00:00
case FindZone : : GroupBy : : Thread :
2018-07-21 21:53:11 +00:00
group = & m_findZone . groups [ ev . thread ] ;
2018-07-21 18:26:13 +00:00
break ;
case FindZone : : GroupBy : : UserText :
2018-07-21 21:53:11 +00:00
group = & m_findZone . groups [ ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ] ;
2018-07-21 18:26:13 +00:00
break ;
case FindZone : : GroupBy : : Callstack :
2018-07-21 21:53:11 +00:00
group = & m_findZone . groups [ ev . zone - > callstack ] ;
2018-07-21 18:26:13 +00:00
break ;
default :
2018-07-21 21:53:11 +00:00
group = nullptr ;
2018-07-21 18:26:13 +00:00
assert ( false ) ;
break ;
2018-03-19 15:01:36 +00:00
}
2018-07-21 21:53:11 +00:00
group - > time + = timespan ;
group - > zones . push_back ( ev . zone ) ;
2018-03-18 15:41:58 +00:00
}
2018-03-18 20:03:36 +00:00
m_findZone . processed = processed ;
2018-03-18 15:41:58 +00:00
2018-07-21 21:41:50 +00:00
Vector < decltype ( m_findZone . groups ) : : iterator > groups ;
groups . reserve_and_use ( m_findZone . groups . size ( ) ) ;
2018-03-18 15:41:58 +00:00
int idx = 0 ;
2018-07-21 21:41:50 +00:00
for ( auto it = m_findZone . groups . begin ( ) ; it ! = m_findZone . groups . end ( ) ; + + it )
2018-03-20 16:19:48 +00:00
{
2018-07-21 21:41:50 +00:00
groups [ idx + + ] = it ;
2018-03-20 16:19:48 +00:00
}
2018-07-21 21:58:50 +00:00
switch ( m_findZone . sortBy )
2018-03-20 16:19:48 +00:00
{
2018-07-21 21:58:50 +00:00
case FindZone : : SortBy : : Order :
break ;
case FindZone : : SortBy : : Count :
2018-07-21 21:53:11 +00:00
pdqsort_branchless ( groups . begin ( ) , groups . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . zones . size ( ) > rhs - > second . zones . size ( ) ; } ) ;
2018-07-21 21:58:50 +00:00
break ;
case FindZone : : SortBy : : Time :
pdqsort_branchless ( groups . begin ( ) , groups . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . time > rhs - > second . time ; } ) ;
break ;
2019-01-30 00:54:18 +00:00
case FindZone : : SortBy : : Mtpc :
pdqsort_branchless ( groups . begin ( ) , groups . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return double ( lhs - > second . time ) / lhs - > second . zones . size ( ) > double ( rhs - > second . time ) / rhs - > second . zones . size ( ) ; } ) ;
break ;
2018-07-21 21:58:50 +00:00
default :
assert ( false ) ;
break ;
2018-03-20 16:19:48 +00:00
}
ImGui : : BeginChild ( " ##zonesScroll " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) , std : : max ( 200.f , ImGui : : GetContentRegionAvail ( ) . y ) ) ) ;
2018-07-21 18:26:13 +00:00
idx = 0 ;
2019-02-27 19:37:38 +00:00
if ( groupBy = = FindZone : : GroupBy : : Callstack )
2018-03-18 15:41:58 +00:00
{
2019-06-22 12:15:25 +00:00
const auto gsz = ( int ) groups . size ( ) ;
2019-02-27 19:37:38 +00:00
if ( gsz > 0 )
2018-03-19 15:01:36 +00:00
{
2019-02-27 19:37:38 +00:00
if ( m_findZone . selCs > gsz ) m_findZone . selCs = gsz ;
const auto group = groups [ m_findZone . selCs ] ;
const bool selHilite = m_findZone . selGroup = = group - > first ;
if ( selHilite ) SetButtonHighlightColor ( ) ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : SmallButton ( " " ICON_FA_CHECK " " ) )
# else
if ( ImGui : : SmallButton ( " Select " ) )
# endif
2018-07-21 18:26:13 +00:00
{
2019-02-27 19:37:38 +00:00
m_findZone . selGroup = group - > first ;
m_findZone . ResetSelection ( ) ;
2018-07-21 18:26:13 +00:00
}
2019-02-27 19:37:38 +00:00
if ( selHilite ) ImGui : : PopStyleColor ( 3 ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : SmallButton ( " " ICON_FA_CARET_LEFT " " ) )
# else
if ( ImGui : : SmallButton ( " < " ) )
# endif
2018-07-21 18:26:13 +00:00
{
2019-02-27 19:37:38 +00:00
m_findZone . selCs = std : : max ( m_findZone . selCs - 1 , 0 ) ;
2018-07-21 18:26:13 +00:00
}
ImGui : : SameLine ( ) ;
2019-02-27 19:37:38 +00:00
ImGui : : Text ( " %s / %s " , RealToString ( m_findZone . selCs + 1 , true ) , RealToString ( gsz , true ) ) ;
2018-06-29 14:20:24 +00:00
ImGui : : SameLine ( ) ;
2019-02-27 19:37:38 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : SmallButton ( " " ICON_FA_CARET_RIGHT " " ) )
# else
if ( ImGui : : SmallButton ( " > " ) )
# endif
{
m_findZone . selCs = std : : min < int > ( m_findZone . selCs + 1 , gsz - 1 ) ;
}
2018-02-15 16:25:16 +00:00
2019-02-27 19:37:38 +00:00
ImGui : : SameLine ( ) ;
TextFocused ( " Count: " , RealToString ( group - > second . zones . size ( ) , true ) ) ;
ImGui : : SameLine ( ) ;
TextFocused ( " Time: " , TimeToString ( group - > second . time ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , group - > second . time * 100.f / zoneData . total ) ;
2019-02-07 11:25:03 +00:00
2019-02-27 19:37:38 +00:00
if ( group - > first ! = 0 )
2019-02-07 11:25:03 +00:00
{
2019-02-27 19:37:38 +00:00
ImGui : : SameLine ( ) ;
2019-02-27 19:55:58 +00:00
int idx = 0 ;
2019-02-27 19:37:38 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-02-27 19:55:58 +00:00
SmallCallstackButton ( " " ICON_FA_ALIGN_JUSTIFY " " , group - > first , idx , false ) ;
2019-02-27 19:37:38 +00:00
# else
2019-02-27 19:55:58 +00:00
SmallCallstackButton ( " Call stack " , group - > first , idx , false ) ;
2019-02-27 19:37:38 +00:00
# endif
2019-02-07 11:25:03 +00:00
2019-02-27 19:55:58 +00:00
int fidx = 0 ;
2019-02-27 19:37:38 +00:00
ImGui : : Spacing ( ) ;
ImGui : : Indent ( ) ;
auto & csdata = m_worker . GetCallstack ( group - > first ) ;
for ( auto & entry : csdata )
2019-02-07 13:51:34 +00:00
{
2019-02-27 19:55:58 +00:00
auto frameData = m_worker . GetCallstackFrame ( entry ) ;
if ( ! frameData )
2019-02-08 01:29:24 +00:00
{
2019-02-27 19:55:58 +00:00
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2019-03-03 15:50:18 +00:00
ImGui : : Text ( " %p " , ( void * ) m_worker . GetCanonicalPointer ( entry ) ) ;
2019-02-08 01:29:24 +00:00
}
2019-02-07 13:51:34 +00:00
else
2019-02-08 01:29:24 +00:00
{
2019-02-27 19:55:58 +00:00
const auto fsz = frameData - > size ;
for ( uint8_t f = 0 ; f < fsz ; f + + )
{
const auto & frame = frameData - > data [ f ] ;
auto txt = m_worker . GetString ( frame . name ) ;
if ( fidx = = 0 & & f ! = fsz - 1 )
{
auto test = s_tracyStackFrames ;
bool match = false ;
do
{
if ( strcmp ( txt , * test ) = = 0 )
{
match = true ;
break ;
}
}
while ( * + + test ) ;
if ( match ) continue ;
}
if ( f = = fsz - 1 )
{
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
}
else
{
TextDisabledUnformatted ( " -- " ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( txt ) ;
}
2019-02-08 01:29:24 +00:00
}
2019-02-07 13:51:34 +00:00
}
2019-02-27 19:37:38 +00:00
ImGui : : Unindent ( ) ;
2019-02-07 13:51:34 +00:00
}
2019-02-27 19:37:38 +00:00
else
2018-02-15 16:25:16 +00:00
{
2019-02-27 19:37:38 +00:00
ImGui : : Text ( " No call stack " ) ;
}
2018-03-04 22:07:38 +00:00
2019-02-27 19:37:38 +00:00
ImGui : : Spacing ( ) ;
if ( ImGui : : TreeNodeEx ( " Zone list " ) )
{
DrawZoneList ( group - > second . zones ) ;
}
}
}
else
{
for ( auto & v : groups )
{
const char * hdrString ;
switch ( groupBy )
{
case FindZone : : GroupBy : : Thread :
hdrString = m_worker . GetThreadString ( m_worker . DecompressThread ( v - > first ) ) ;
break ;
case FindZone : : GroupBy : : UserText :
hdrString = v - > first = = std : : numeric_limits < uint64_t > : : max ( ) ? " No user text " : m_worker . GetString ( StringIdx ( v - > first ) ) ;
break ;
case FindZone : : GroupBy : : Callstack :
if ( v - > first = = 0 )
2018-02-15 16:25:16 +00:00
{
2019-02-27 19:37:38 +00:00
hdrString = " No callstack " ;
2018-02-15 16:25:16 +00:00
}
2019-02-27 19:37:38 +00:00
else
2018-06-29 14:20:24 +00:00
{
2019-02-27 19:37:38 +00:00
auto & callstack = m_worker . GetCallstack ( v - > first ) ;
auto & frameData = * m_worker . GetCallstackFrame ( * callstack . begin ( ) ) ;
hdrString = m_worker . GetString ( frameData . data [ frameData . size - 1 ] . name ) ;
2018-06-29 14:20:24 +00:00
}
2019-02-27 19:37:38 +00:00
break ;
default :
hdrString = nullptr ;
assert ( false ) ;
break ;
}
ImGui : : PushID ( v - > first ) ;
const bool expand = ImGui : : TreeNodeEx ( hdrString , ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ( v - > first = = m_findZone . selGroup ? ImGuiTreeNodeFlags_Selected : 0 ) ) ;
if ( ImGui : : IsItemClicked ( ) )
{
m_findZone . selGroup = v - > first ;
m_findZone . ResetSelection ( ) ;
}
ImGui : : PopID ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextColored ( ImVec4 ( 0.5f , 0.5f , 0.5f , 1.0f ) , " (%s) %s " , RealToString ( v - > second . zones . size ( ) , true ) , TimeToString ( v - > second . time ) ) ;
if ( expand )
{
DrawZoneList ( v - > second . zones ) ;
2018-02-15 16:25:16 +00:00
}
2018-01-17 11:49:50 +00:00
}
}
2018-03-20 11:56:26 +00:00
ImGui : : EndChild ( ) ;
2018-04-14 13:21:22 +00:00
if ( ImGui : : IsItemHovered ( ) & & ImGui : : IsMouseClicked ( 1 ) )
{
2018-07-21 21:41:50 +00:00
m_findZone . selGroup = m_findZone . Unselected ;
2018-09-02 01:17:05 +00:00
m_findZone . ResetSelection ( ) ;
2018-04-14 13:21:22 +00:00
}
2018-01-17 11:49:50 +00:00
}
2018-03-18 11:55:54 +00:00
# endif
2018-01-17 11:49:50 +00:00
ImGui : : End ( ) ;
}
2019-02-27 19:37:38 +00:00
void View : : DrawZoneList ( const Vector < ZoneEvent * > & zones )
{
ImGui : : Columns ( 3 ) ;
ImGui : : Separator ( ) ;
if ( ImGui : : SmallButton ( " Time from start " ) ) m_findZone . tableSortBy = FindZone : : TableSortBy : : Starttime ;
ImGui : : NextColumn ( ) ;
if ( ImGui : : SmallButton ( " Execution time " ) ) m_findZone . tableSortBy = FindZone : : TableSortBy : : Runtime ;
ImGui : : NextColumn ( ) ;
if ( ImGui : : SmallButton ( " Name " ) ) m_findZone . tableSortBy = FindZone : : TableSortBy : : Name ;
ImGui : : SameLine ( ) ;
DrawHelpMarker ( " Only displayed if custom zone name is set. " ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
const Vector < ZoneEvent * > * zonesToIterate = & zones ;
Vector < ZoneEvent * > sortedZones ;
if ( m_findZone . tableSortBy ! = FindZone : : TableSortBy : : Starttime )
{
zonesToIterate = & sortedZones ;
sortedZones . reserve_and_use ( zones . size ( ) ) ;
memcpy ( sortedZones . data ( ) , zones . data ( ) , zones . size ( ) * sizeof ( ZoneEvent * ) ) ;
switch ( m_findZone . tableSortBy )
{
case FindZone : : TableSortBy : : Runtime :
if ( m_findZone . selfTime )
{
pdqsort_branchless ( sortedZones . begin ( ) , sortedZones . end ( ) , [ this ] ( const auto & lhs , const auto & rhs ) {
return m_worker . GetZoneEndDirect ( * lhs ) - lhs - > start - this - > GetZoneChildTimeFast ( * lhs ) >
m_worker . GetZoneEndDirect ( * rhs ) - rhs - > start - this - > GetZoneChildTimeFast ( * rhs ) ;
} ) ;
}
else
{
pdqsort_branchless ( sortedZones . begin ( ) , sortedZones . end ( ) , [ this ] ( const auto & lhs , const auto & rhs ) {
return m_worker . GetZoneEndDirect ( * lhs ) - lhs - > start > m_worker . GetZoneEndDirect ( * rhs ) - rhs - > start ;
} ) ;
}
break ;
case FindZone : : TableSortBy : : Name :
pdqsort_branchless ( sortedZones . begin ( ) , sortedZones . end ( ) , [ this ] ( const auto & lhs , const auto & rhs ) {
if ( lhs - > name . active ! = rhs - > name . active ) return lhs - > name . active > rhs - > name . active ;
return strcmp ( m_worker . GetString ( lhs - > name ) , m_worker . GetString ( rhs - > name ) ) < 0 ;
} ) ;
break ;
default :
assert ( false ) ;
break ;
}
}
for ( auto & ev : * zonesToIterate )
{
const auto end = m_worker . GetZoneEndDirect ( * ev ) ;
auto timespan = end - ev - > start ;
if ( m_findZone . selfTime ) timespan - = GetZoneChildTimeFast ( * ev ) ;
ImGui : : PushID ( ev ) ;
if ( ImGui : : Selectable ( TimeToString ( ev - > start - m_worker . GetTimeBegin ( ) ) , m_zoneInfoWindow = = ev , ImGuiSelectableFlags_SpanAllColumns ) )
{
ShowZoneInfo ( * ev ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
m_zoneHighlight = ev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * ev ) ;
}
ZoneTooltip ( * ev ) ;
}
ImGui : : NextColumn ( ) ;
ImGui : : TextUnformatted ( TimeToString ( timespan ) ) ;
ImGui : : NextColumn ( ) ;
if ( ev - > name . active )
{
ImGui : : TextUnformatted ( m_worker . GetString ( ev - > name ) ) ;
}
ImGui : : NextColumn ( ) ;
ImGui : : PopID ( ) ;
}
ImGui : : Columns ( 1 ) ;
ImGui : : Separator ( ) ;
ImGui : : TreePop ( ) ;
}
2018-04-21 22:52:33 +00:00
void View : : DrawCompare ( )
{
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 590 , 800 ) , ImGuiCond_FirstUseEver ) ;
2018-04-21 22:52:33 +00:00
ImGui : : Begin ( " Compare traces " , & m_compare . show ) ;
# ifdef TRACY_NO_STATISTICS
ImGui : : TextWrapped ( " Collection of statistical data is disabled in this build. " ) ;
ImGui : : TextWrapped ( " Rebuild without the TRACY_NO_STATISTICS macro to enable trace comparison. " ) ;
# elif !defined TRACY_FILESELECTOR
ImGui : : TextWrapped ( " File selector is disabled in this build. " ) ;
ImGui : : TextWrapped ( " Rebuild with the TRACY_FILESELECTOR macro to enable trace comparison. " ) ;
# else
if ( ! m_compare . second )
{
ImGui : : TextWrapped ( " Please load a second trace to compare results. " ) ;
2018-08-17 21:54:40 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_FOLDER_OPEN " Open second trace " ) & & ! m_compare . loadThread . joinable ( ) )
# else
2018-07-28 16:47:33 +00:00
if ( ImGui : : Button ( " Open second trace " ) & & ! m_compare . loadThread . joinable ( ) )
2018-08-17 21:54:40 +00:00
# endif
2018-04-21 22:52:33 +00:00
{
nfdchar_t * fn ;
auto res = NFD_OpenDialog ( " tracy " , nullptr , & fn ) ;
if ( res = = NFD_OKAY )
{
try
{
2018-07-28 16:47:33 +00:00
auto f = std : : shared_ptr < tracy : : FileRead > ( tracy : : FileRead : : Open ( fn ) ) ;
2018-04-21 22:52:33 +00:00
if ( f )
{
2018-07-28 16:47:33 +00:00
m_compare . loadThread = std : : thread ( [ this , f ] {
try
{
m_compare . second = std : : make_unique < Worker > ( * f , EventType : : None ) ;
}
catch ( const tracy : : UnsupportedVersion & e )
{
m_compare . badVer = e . version ;
}
} ) ;
2018-04-21 22:52:33 +00:00
}
}
2019-06-22 11:41:24 +00:00
catch ( const tracy : : NotTracyDump & )
2018-04-21 22:52:33 +00:00
{
m_compare . badVer = - 1 ;
}
}
}
tracy : : BadVersion ( m_compare . badVer ) ;
ImGui : : End ( ) ;
return ;
}
2018-07-28 16:47:33 +00:00
if ( m_compare . loadThread . joinable ( ) ) m_compare . loadThread . join ( ) ;
2018-04-30 01:54:09 +00:00
if ( ! m_worker . AreSourceLocationZonesReady ( ) | | ! m_compare . second - > AreSourceLocationZonesReady ( ) )
{
ImGui : : TextWrapped ( " Please wait, computing data... " ) ;
2019-03-06 23:59:02 +00:00
DrawWaitingDots ( s_time ) ;
2018-04-30 01:54:09 +00:00
ImGui : : End ( ) ;
return ;
}
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 255.f , 0xDD / 255.f , 0x22 / 255.f , 1.f ) , ICON_FA_LEMON ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " This trace: " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetCaptureName ( ) . c_str ( ) ) ;
2018-04-21 22:52:33 +00:00
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) , ICON_FA_GEM ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " External trace: " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_compare . second - > GetCaptureName ( ) . c_str ( ) ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 21:54:40 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : SmallButton ( ICON_FA_TRASH_ALT " Unload " ) )
# else
2018-04-21 22:52:33 +00:00
if ( ImGui : : SmallButton ( " Unload " ) )
2018-08-17 21:54:40 +00:00
# endif
2018-04-21 22:52:33 +00:00
{
m_compare . Reset ( ) ;
m_compare . second . reset ( ) ;
ImGui : : End ( ) ;
return ;
}
2018-12-18 15:56:19 +00:00
bool findClicked = false ;
ImGui : : PushItemWidth ( - 0.01f ) ;
2019-03-15 00:47:07 +00:00
findClicked | = ImGui : : InputTextWithHint ( " ###compare " , " Enter zone name to search for " , m_compare . pattern , 1024 , ImGuiInputTextFlags_EnterReturnsTrue ) ;
2018-12-18 15:56:19 +00:00
ImGui : : PopItemWidth ( ) ;
2018-04-21 22:52:33 +00:00
2018-08-17 21:54:40 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-12-18 15:56:19 +00:00
findClicked | = ImGui : : Button ( ICON_FA_SEARCH " Find " ) ;
2018-08-17 21:54:40 +00:00
# else
2018-12-18 15:56:19 +00:00
findClicked | = ImGui : : Button ( " Find " ) ;
2018-08-17 21:54:40 +00:00
# endif
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 21:54:40 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_BAN " Clear " ) )
# else
2018-04-21 22:52:33 +00:00
if ( ImGui : : Button ( " Clear " ) )
2018-08-17 21:54:40 +00:00
# endif
2018-04-21 22:52:33 +00:00
{
m_compare . Reset ( ) ;
}
2018-12-18 15:56:19 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Ignore case " , & m_compare . ignoreCase ) ;
2018-04-21 22:52:33 +00:00
if ( findClicked )
{
m_compare . Reset ( ) ;
FindZonesCompare ( ) ;
}
if ( m_compare . match [ 0 ] . empty ( ) & & m_compare . match [ 1 ] . empty ( ) )
{
ImGui : : End ( ) ;
return ;
}
if ( ImGui : : TreeNodeEx ( " Matched source locations " , ImGuiTreeNodeFlags_DefaultOpen ) )
{
2019-06-02 13:40:19 +00:00
ImGui : : SameLine ( ) ;
SmallCheckbox ( " Link selection " , & m_compare . link ) ;
2018-04-21 22:52:33 +00:00
ImGui : : Separator ( ) ;
ImGui : : Columns ( 2 ) ;
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 255.f , 0xDD / 255.f , 0x22 / 255.f , 1.f ) , ICON_FA_LEMON ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " This trace " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_compare . match [ 0 ] . size ( ) ) ;
ImGui : : NextColumn ( ) ;
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) , ICON_FA_GEM ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " External trace " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_compare . match [ 1 ] . size ( ) ) ;
ImGui : : Separator ( ) ;
ImGui : : NextColumn ( ) ;
2018-09-03 18:34:07 +00:00
const auto prev0 = m_compare . selMatch [ 0 ] ;
2018-04-21 22:52:33 +00:00
int idx = 0 ;
for ( auto & v : m_compare . match [ 0 ] )
{
auto & srcloc = m_worker . GetSourceLocation ( v ) ;
auto & zones = m_worker . GetZonesForSourceLocation ( v ) . zones ;
ImGui : : PushID ( idx ) ;
ImGui : : RadioButton ( m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) , & m_compare . selMatch [ 0 ] , idx + + ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextColored ( ImVec4 ( 0.5 , 0.5 , 0.5 , 1 ) , " (%s) %s:%i " , RealToString ( zones . size ( ) , true ) , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : PopID ( ) ;
}
ImGui : : NextColumn ( ) ;
2018-09-03 18:34:07 +00:00
const auto prev1 = m_compare . selMatch [ 1 ] ;
2018-04-21 22:52:33 +00:00
idx = 0 ;
for ( auto & v : m_compare . match [ 1 ] )
{
auto & srcloc = m_compare . second - > GetSourceLocation ( v ) ;
auto & zones = m_compare . second - > GetZonesForSourceLocation ( v ) . zones ;
ImGui : : PushID ( - 1 - idx ) ;
ImGui : : RadioButton ( m_compare . second - > GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) , & m_compare . selMatch [ 1 ] , idx + + ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextColored ( ImVec4 ( 0.5 , 0.5 , 0.5 , 1 ) , " (%s) %s:%i " , RealToString ( zones . size ( ) , true ) , m_compare . second - > GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : PopID ( ) ;
}
ImGui : : NextColumn ( ) ;
ImGui : : EndColumns ( ) ;
ImGui : : TreePop ( ) ;
2018-09-03 18:34:07 +00:00
if ( prev0 ! = m_compare . selMatch [ 0 ] | | prev1 ! = m_compare . selMatch [ 1 ] )
{
m_compare . ResetSelection ( ) ;
2019-06-02 13:40:19 +00:00
if ( m_compare . link )
{
auto & srcloc0 = m_worker . GetSourceLocation ( m_compare . match [ 0 ] [ m_compare . selMatch [ 0 ] ] ) ;
auto & srcloc1 = m_compare . second - > GetSourceLocation ( m_compare . match [ 1 ] [ m_compare . selMatch [ 1 ] ] ) ;
auto string0 = m_worker . GetString ( srcloc0 . name . active ? srcloc0 . name : srcloc0 . function ) ;
auto string1 = m_compare . second - > GetString ( srcloc1 . name . active ? srcloc1 . name : srcloc1 . function ) ;
if ( strcmp ( string0 , string1 ) ! = 0 )
{
idx = 0 ;
if ( prev0 ! = m_compare . selMatch [ 0 ] )
{
for ( auto & v : m_compare . match [ 1 ] )
{
auto & srcloc = m_compare . second - > GetSourceLocation ( v ) ;
auto string = m_compare . second - > GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ;
if ( strcmp ( string0 , string ) = = 0 )
{
m_compare . selMatch [ 1 ] = idx ;
break ;
}
idx + + ;
}
}
else
{
assert ( prev1 ! = m_compare . selMatch [ 1 ] ) ;
for ( auto & v : m_compare . match [ 0 ] )
{
auto & srcloc = m_worker . GetSourceLocation ( v ) ;
auto string = m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ;
if ( strcmp ( string1 , string ) = = 0 )
{
m_compare . selMatch [ 0 ] = idx ;
break ;
}
idx + + ;
}
}
}
}
2018-09-03 18:34:07 +00:00
}
2018-04-21 22:52:33 +00:00
}
ImGui : : Separator ( ) ;
if ( m_compare . match [ 0 ] . empty ( ) | | m_compare . match [ 1 ] . empty ( ) )
{
ImGui : : TextWrapped ( " Both traces must have matches. " ) ;
ImGui : : End ( ) ;
return ;
}
if ( ImGui : : TreeNodeEx ( " Histogram " , ImGuiTreeNodeFlags_DefaultOpen ) )
{
const auto ty = ImGui : : GetFontSize ( ) ;
auto & zoneData0 = m_worker . GetZonesForSourceLocation ( m_compare . match [ 0 ] [ m_compare . selMatch [ 0 ] ] ) ;
auto & zoneData1 = m_compare . second - > GetZonesForSourceLocation ( m_compare . match [ 1 ] [ m_compare . selMatch [ 1 ] ] ) ;
auto & zones0 = zoneData0 . zones ;
auto & zones1 = zoneData1 . zones ;
auto tmin = std : : min ( zoneData0 . min , zoneData1 . min ) ;
2019-06-18 20:27:25 +00:00
auto tmax = std : : max ( zoneData0 . max , zoneData1 . max ) ;
2018-04-21 22:52:33 +00:00
2018-09-03 18:34:07 +00:00
const size_t zsz [ 2 ] = { zones0 . size ( ) , zones1 . size ( ) } ;
for ( int k = 0 ; k < 2 ; k + + )
{
if ( m_compare . sortedNum [ k ] ! = zsz [ k ] )
{
auto & zones = k = = 0 ? zones0 : zones1 ;
auto & vec = m_compare . sorted [ k ] ;
vec . reserve ( zsz [ k ] ) ;
int64_t total = m_compare . total [ k ] ;
size_t i ;
for ( i = m_compare . sortedNum [ k ] ; i < zsz [ k ] ; i + + )
{
auto & zone = * zones [ i ] . zone ;
if ( zone . end < 0 ) break ;
const auto t = zone . end - zone . start ;
vec . emplace_back ( t ) ;
total + = t ;
}
auto mid = vec . begin ( ) + m_compare . sortedNum [ k ] ;
pdqsort_branchless ( mid , vec . end ( ) ) ;
std : : inplace_merge ( vec . begin ( ) , mid , vec . end ( ) ) ;
m_compare . average [ k ] = float ( total ) / i ;
m_compare . median [ k ] = vec [ i / 2 ] ;
m_compare . total [ k ] = total ;
m_compare . sortedNum [ k ] = i ;
}
}
2018-04-21 22:52:33 +00:00
if ( tmin ! = std : : numeric_limits < int64_t > : : max ( ) )
{
ImGui : : Checkbox ( " Log values " , & m_compare . logVal ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Log time " , & m_compare . logTime ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Cumulate time " , & m_compare . cumulateTime ) ;
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Show total time taken by calls in each bin instead of call counts. " ) ;
2018-04-22 00:19:22 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Normalize values " , & m_compare . normalize ) ;
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Normalization will fudge reported data values! " ) ;
2018-04-21 22:52:33 +00:00
2019-06-18 20:27:25 +00:00
TextDisabledUnformatted ( " Minimum values in bin: " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( ImGui : : CalcTextSize ( " 123456890123456 " ) . x ) ;
ImGui : : InputInt ( " ##minBinVal " , & m_compare . minBinVal ) ;
if ( m_compare . minBinVal < 1 ) m_compare . minBinVal = 1 ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Reset " ) ) m_compare . minBinVal = 1 ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time range: " ) ;
2018-06-29 16:35:40 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s (%s) " , TimeToString ( tmin ) , TimeToString ( tmax ) , TimeToString ( tmax - tmin ) ) ;
2018-04-21 22:52:33 +00:00
const auto cumulateTime = m_compare . cumulateTime ;
2019-06-18 20:27:25 +00:00
if ( tmax - tmin > 0 )
2018-04-21 22:52:33 +00:00
{
const auto w = ImGui : : GetContentRegionAvail ( ) . x ;
const auto numBins = int64_t ( w - 4 ) ;
if ( numBins > 1 )
{
2019-06-15 22:25:22 +00:00
if ( numBins > m_compare . numBins )
2018-06-06 21:09:46 +00:00
{
m_compare . numBins = numBins ;
m_compare . bins = std : : make_unique < CompVal [ ] > ( numBins ) ;
m_compare . binTime = std : : make_unique < CompVal [ ] > ( numBins ) ;
}
2018-04-21 22:52:33 +00:00
2018-06-06 21:09:46 +00:00
const auto & bins = m_compare . bins ;
const auto & binTime = m_compare . binTime ;
memset ( bins . get ( ) , 0 , sizeof ( CompVal ) * numBins ) ;
2018-04-21 22:52:33 +00:00
memset ( binTime . get ( ) , 0 , sizeof ( CompVal ) * numBins ) ;
2018-06-06 21:17:13 +00:00
double adj0 = 1 ;
double adj1 = 1 ;
2018-04-22 00:19:22 +00:00
if ( m_compare . normalize )
2018-04-21 22:52:33 +00:00
{
2018-04-22 00:19:22 +00:00
if ( zones0 . size ( ) > zones1 . size ( ) )
{
adj1 = double ( zones0 . size ( ) ) / zones1 . size ( ) ;
}
else
{
adj0 = double ( zones1 . size ( ) ) / zones0 . size ( ) ;
}
2018-09-03 19:26:50 +00:00
}
2018-04-22 00:19:22 +00:00
2018-09-03 19:26:50 +00:00
const auto & sorted = m_compare . sorted ;
2019-06-18 20:27:25 +00:00
auto sBegin0 = sorted [ 0 ] . begin ( ) ;
auto sBegin1 = sorted [ 1 ] . begin ( ) ;
auto sEnd0 = sorted [ 0 ] . end ( ) ;
auto sEnd1 = sorted [ 1 ] . end ( ) ;
if ( m_compare . minBinVal > 1 )
{
if ( m_compare . logTime )
{
const auto tMinLog = log10 ( tmin ) ;
const auto zmax = ( log10 ( tmax ) - tMinLog ) / numBins ;
int64_t i ;
for ( i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
auto nit0 = std : : lower_bound ( sBegin0 , sEnd0 , nextBinVal ) ;
auto nit1 = std : : lower_bound ( sBegin1 , sEnd1 , nextBinVal ) ;
const auto distance0 = std : : distance ( sBegin0 , nit0 ) ;
const auto distance1 = std : : distance ( sBegin1 , nit1 ) ;
if ( distance0 > = m_compare . minBinVal | | distance1 > = m_compare . minBinVal ) break ;
sBegin0 = nit0 ;
sBegin1 = nit1 ;
}
for ( int64_t j = numBins - 1 ; j > i ; j - - )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( j - 1 ) * zmax ) ) ;
auto nit0 = std : : lower_bound ( sBegin0 , sEnd0 , nextBinVal ) ;
auto nit1 = std : : lower_bound ( sBegin1 , sEnd1 , nextBinVal ) ;
const auto distance0 = std : : distance ( nit0 , sEnd0 ) ;
const auto distance1 = std : : distance ( nit1 , sEnd1 ) ;
if ( distance0 > = m_compare . minBinVal | | distance1 > = m_compare . minBinVal ) break ;
sEnd0 = nit0 ;
sEnd1 = nit1 ;
}
}
else
{
const auto zmax = tmax - tmin ;
int64_t i ;
for ( i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
auto nit0 = std : : lower_bound ( sBegin0 , sEnd0 , nextBinVal ) ;
auto nit1 = std : : lower_bound ( sBegin1 , sEnd1 , nextBinVal ) ;
const auto distance0 = std : : distance ( sBegin0 , nit0 ) ;
const auto distance1 = std : : distance ( sBegin1 , nit1 ) ;
if ( distance0 > = m_compare . minBinVal | | distance1 > = m_compare . minBinVal ) break ;
sBegin0 = nit0 ;
sBegin1 = nit1 ;
}
for ( int64_t j = numBins - 1 ; j > i ; j - - )
{
const auto nextBinVal = tmin + ( j - 1 ) * zmax / numBins ;
auto nit0 = std : : lower_bound ( sBegin0 , sEnd0 , nextBinVal ) ;
auto nit1 = std : : lower_bound ( sBegin1 , sEnd1 , nextBinVal ) ;
const auto distance0 = std : : distance ( nit0 , sEnd0 ) ;
const auto distance1 = std : : distance ( nit1 , sEnd1 ) ;
if ( distance0 > = m_compare . minBinVal | | distance1 > = m_compare . minBinVal ) break ;
sEnd0 = nit0 ;
sEnd1 = nit1 ;
}
}
tmin = std : : min ( * sBegin0 , * sBegin1 ) ;
tmax = std : : max ( * ( sEnd0 - 1 ) , * ( sEnd1 - 1 ) ) ;
}
auto zit0 = sBegin0 ;
auto zit1 = sBegin1 ;
2018-09-03 19:26:50 +00:00
if ( m_compare . logTime )
{
const auto tMinLog = log10 ( tmin ) ;
const auto zmax = ( log10 ( tmax ) - tMinLog ) / numBins ;
for ( int64_t i = 0 ; i < numBins ; i + + )
2018-04-21 22:52:33 +00:00
{
2018-09-03 19:26:50 +00:00
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
2019-06-18 20:27:25 +00:00
auto nit0 = std : : lower_bound ( zit0 , sEnd0 , nextBinVal ) ;
auto nit1 = std : : lower_bound ( zit1 , sEnd1 , nextBinVal ) ;
2018-09-03 19:26:50 +00:00
bins [ i ] . v0 + = adj0 * std : : distance ( zit0 , nit0 ) ;
bins [ i ] . v1 + = adj1 * std : : distance ( zit1 , nit1 ) ;
binTime [ i ] . v0 + = adj0 * std : : accumulate ( zit0 , nit0 , int64_t ( 0 ) ) ;
binTime [ i ] . v1 + = adj1 * std : : accumulate ( zit1 , nit1 , int64_t ( 0 ) ) ;
zit0 = nit0 ;
zit1 = nit1 ;
2018-04-21 22:52:33 +00:00
}
}
else
{
2018-09-03 19:26:50 +00:00
const auto zmax = tmax - tmin ;
for ( int64_t i = 0 ; i < numBins ; i + + )
2018-04-21 22:52:33 +00:00
{
2019-01-24 15:02:36 +00:00
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
2019-06-18 20:27:25 +00:00
auto nit0 = std : : lower_bound ( zit0 , sEnd0 , nextBinVal ) ;
auto nit1 = std : : lower_bound ( zit1 , sEnd1 , nextBinVal ) ;
2018-09-03 19:26:50 +00:00
bins [ i ] . v0 + = adj0 * std : : distance ( zit0 , nit0 ) ;
bins [ i ] . v1 + = adj1 * std : : distance ( zit1 , nit1 ) ;
binTime [ i ] . v0 + = adj0 * std : : accumulate ( zit0 , nit0 , int64_t ( 0 ) ) ;
binTime [ i ] . v1 + = adj1 * std : : accumulate ( zit1 , nit1 , int64_t ( 0 ) ) ;
zit0 = nit0 ;
zit1 = nit1 ;
2018-04-21 22:52:33 +00:00
}
}
2018-04-22 00:19:22 +00:00
double maxVal ;
2018-04-21 22:52:33 +00:00
if ( cumulateTime )
{
maxVal = std : : max ( binTime [ 0 ] . v0 , binTime [ 0 ] . v1 ) ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( { maxVal , binTime [ i ] . v0 , binTime [ i ] . v1 } ) ;
}
}
else
{
maxVal = std : : max ( bins [ 0 ] . v0 , bins [ 0 ] . v1 ) ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( { maxVal , bins [ i ] . v0 , bins [ i ] . v1 } ) ;
}
}
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0xDD / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_LEMON ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2018-06-29 16:35:40 +00:00
TextFocused ( " Total time (this): " , TimeToString ( zoneData0 . total * adj0 ) ) ;
2018-09-03 18:39:34 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0x22 / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_GEM ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2018-09-03 18:45:51 +00:00
TextFocused ( " Total time (ext.): " , TimeToString ( zoneData1 . total * adj1 ) ) ;
2018-09-08 18:23:49 +00:00
TextFocused ( " Savings: " , TimeToString ( zoneData1 . total * adj1 - zoneData0 . total * adj0 ) ) ;
2019-01-20 02:16:32 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , ( zoneData0 . total * adj0 ) / ( zoneData1 . total * adj1 ) * 100 ) ;
2018-06-29 16:35:40 +00:00
TextFocused ( " Max counts: " , cumulateTime ? TimeToString ( maxVal ) : RealToString ( floor ( maxVal ) , true ) ) ;
2018-04-21 22:52:33 +00:00
2018-09-03 18:45:51 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0xDD / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_LEMON ) ;
2018-09-03 18:45:51 +00:00
ImGui : : SameLine ( ) ;
# endif
TextFocused ( " Average time (this): " , TimeToString ( m_compare . average [ 0 ] ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0xDD / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_LEMON ) ;
2018-09-03 18:45:51 +00:00
ImGui : : SameLine ( ) ;
# endif
TextFocused ( " Median time (this): " , TimeToString ( m_compare . median [ 0 ] ) ) ;
2019-03-14 00:32:50 +00:00
if ( sorted [ 0 ] . size ( ) > 1 )
{
const auto sz = sorted [ 0 ] . size ( ) ;
const auto avg = m_compare . average [ 0 ] ;
const auto ss = zoneData0 . sumSq - 2. * zoneData0 . total * avg + avg * avg * sz ;
const auto sd = sqrt ( ss / ( sz - 1 ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0xDD / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_LEMON ) ;
2019-03-14 00:32:50 +00:00
ImGui : : SameLine ( ) ;
TextFocused ( " \xcf \x83 (this): " , TimeToString ( sd ) ) ;
# else
TextFocused ( " s (this): " , TimeToString ( sd ) ) ;
# endif
2019-03-14 00:34:43 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Standard deviation " ) ;
ImGui : : EndTooltip ( ) ;
}
2019-03-14 00:32:50 +00:00
}
2018-09-03 18:45:51 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0x22 / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_GEM ) ;
2018-09-03 18:45:51 +00:00
ImGui : : SameLine ( ) ;
# endif
TextFocused ( " Average time (ext.): " , TimeToString ( m_compare . average [ 1 ] ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0x22 / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_GEM ) ;
2018-09-03 18:45:51 +00:00
ImGui : : SameLine ( ) ;
# endif
TextFocused ( " Median time (ext.): " , TimeToString ( m_compare . median [ 1 ] ) ) ;
2019-03-14 00:32:50 +00:00
if ( sorted [ 1 ] . size ( ) > 1 )
{
const auto sz = sorted [ 1 ] . size ( ) ;
const auto avg = m_compare . average [ 1 ] ;
const auto ss = zoneData1 . sumSq - 2. * zoneData1 . total * avg + avg * avg * sz ;
const auto sd = sqrt ( ss / ( sz - 1 ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0x22 / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_GEM ) ;
2019-03-14 00:32:50 +00:00
ImGui : : SameLine ( ) ;
TextFocused ( " \xcf \x83 (ext.): " , TimeToString ( sd ) ) ;
# else
TextFocused ( " s (ext.): " , TimeToString ( sd ) ) ;
# endif
2019-03-14 00:34:43 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Standard deviation " ) ;
ImGui : : EndTooltip ( ) ;
}
2019-03-14 00:32:50 +00:00
}
2018-09-03 18:45:51 +00:00
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-08-18 12:02:20 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , ImVec4 ( 0xDD / 511.f , 0xDD / 511.f , 0x22 / 511.f , 1.f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0xDD / 255.f , 0xDD / 255.f , 0x22 / 255.f , 1.f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_ButtonHovered , ImVec4 ( 0xDD / 255.f , 0xDD / 255.f , 0x22 / 255.f , 1.f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_ButtonActive , ImVec4 ( 0xDD / 255.f , 0xDD / 255.f , 0x22 / 255.f , 1.f ) ) ;
ImGui : : Button ( ICON_FA_LEMON ) ;
ImGui : : PopStyleColor ( 4 ) ;
2018-08-18 14:32:26 +00:00
# else
ImGui : : ColorButton ( " c1 " , ImVec4 ( 0xDD / 255.f , 0xDD / 255.f , 0x22 / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
# endif
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " This trace " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-08-18 12:02:20 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , ImVec4 ( 0xDD / 511.f , 0x22 / 511.f , 0x22 / 511.f , 1.f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_ButtonHovered , ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_ButtonActive , ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) ) ;
ImGui : : Button ( ICON_FA_GEM ) ;
ImGui : : PopStyleColor ( 4 ) ;
2018-08-18 14:32:26 +00:00
# else
ImGui : : ColorButton ( " c2 " , ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
# endif
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " External trace " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : ColorButton ( " c3 " , ImVec4 ( 0x44 / 255.f , 0xBB / 255.f , 0xBB / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Overlap " ) ;
2018-04-21 22:52:33 +00:00
2018-06-28 22:44:05 +00:00
const auto Height = 200 * ImGui : : GetTextLineHeight ( ) / 15.f ;
2018-04-21 22:52:33 +00:00
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
ImGui : : InvisibleButton ( " ##histogram " , ImVec2 ( w , Height + round ( ty * 1.5 ) ) ) ;
const bool hover = ImGui : : IsItemHovered ( ) ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( w , Height ) , 0x22FFFFFF ) ;
draw - > AddRect ( wpos , wpos + ImVec2 ( w , Height ) , 0x88FFFFFF ) ;
if ( m_compare . logVal )
{
2018-09-08 17:01:51 +00:00
const auto hAdj = double ( Height - 4 ) / log10 ( maxVal + 1 ) ;
2018-04-21 22:52:33 +00:00
for ( int i = 0 ; i < numBins ; i + + )
{
const auto val0 = cumulateTime ? binTime [ i ] . v0 : bins [ i ] . v0 ;
const auto val1 = cumulateTime ? binTime [ i ] . v1 : bins [ i ] . v1 ;
if ( val0 > 0 | | val1 > 0 )
{
const auto val = std : : min ( val0 , val1 ) ;
if ( val > 0 )
{
2018-09-08 17:01:51 +00:00
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val + 1 ) * hAdj ) , 0xFFBBBB44 ) ;
2018-04-21 22:52:33 +00:00
}
if ( val1 = = val )
{
2018-09-08 17:01:51 +00:00
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val + 1 ) * hAdj ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val0 + 1 ) * hAdj ) , 0xFF22DDDD ) ;
2018-04-21 22:52:33 +00:00
}
else
{
2018-09-08 17:01:51 +00:00
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val + 1 ) * hAdj ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val1 + 1 ) * hAdj ) , 0xFF2222DD ) ;
2018-04-21 22:52:33 +00:00
}
}
}
}
else
{
const auto hAdj = double ( Height - 4 ) / maxVal ;
for ( int i = 0 ; i < numBins ; i + + )
{
const auto val0 = cumulateTime ? binTime [ i ] . v0 : bins [ i ] . v0 ;
const auto val1 = cumulateTime ? binTime [ i ] . v1 : bins [ i ] . v1 ;
if ( val0 > 0 | | val1 > 0 )
{
const auto val = std : : min ( val0 , val1 ) ;
if ( val > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - val * hAdj ) , 0xFFBBBB44 ) ;
}
if ( val1 = = val )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 - val * hAdj ) , wpos + ImVec2 ( 2 + i , Height - 3 - val0 * hAdj ) , 0xFF22DDDD ) ;
}
else
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 - val * hAdj ) , wpos + ImVec2 ( 2 + i , Height - 3 - val1 * hAdj ) , 0xFF2222DD ) ;
}
}
}
}
const auto xoff = 2 ;
const auto yoff = Height + 1 ;
if ( m_compare . logTime )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-04-21 22:52:33 +00:00
const auto start = int ( floor ( ltmin ) ) ;
const auto end = int ( ceil ( ltmax ) ) ;
const auto range = ltmax - ltmin ;
const auto step = w / range ;
auto offset = start - ltmin ;
int tw = 0 ;
int tx = 0 ;
auto tt = int64_t ( pow ( 10 , start ) ) ;
static const double logticks [ ] = { log10 ( 2 ) , log10 ( 3 ) , log10 ( 4 ) , log10 ( 5 ) , log10 ( 6 ) , log10 ( 7 ) , log10 ( 8 ) , log10 ( 9 ) } ;
for ( int i = start ; i < = end ; i + + )
{
const auto x = ( i - start + offset ) * step ;
if ( x > = 0 )
{
draw - > AddLine ( wpos + ImVec2 ( x , yoff ) , wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF ) ;
if ( tw = = 0 | | x > tx + tw + ty * 1.1 )
{
tx = x ;
2019-02-10 00:14:34 +00:00
auto txt = TimeToString ( tt ) ;
2018-04-21 22:52:33 +00:00
draw - > AddText ( wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
}
for ( int j = 0 ; j < 8 ; j + + )
{
const auto xoff = x + logticks [ j ] * step ;
if ( xoff > = 0 )
{
draw - > AddLine ( wpos + ImVec2 ( xoff , yoff ) , wpos + ImVec2 ( xoff , yoff + round ( ty * 0.25 ) ) , 0x66FFFFFF ) ;
}
}
tt * = 10 ;
}
}
else
{
2019-06-18 20:27:25 +00:00
const auto pxns = numBins / double ( tmax - tmin ) ;
2018-04-21 22:52:33 +00:00
const auto nspx = 1.0 / pxns ;
2018-09-08 17:01:51 +00:00
const auto scale = std : : max < float > ( 0.0f , round ( log10 ( nspx ) + 2 ) ) ;
2018-04-21 22:52:33 +00:00
const auto step = pow ( 10 , scale ) ;
const auto dx = step * pxns ;
double x = 0 ;
int tw = 0 ;
int tx = 0 ;
const auto sstep = step / 10.0 ;
const auto sdx = dx / 10.0 ;
static const double linelen [ ] = { 0.5 , 0.25 , 0.25 , 0.25 , 0.25 , 0.375 , 0.25 , 0.25 , 0.25 , 0.25 } ;
int64_t tt = int64_t ( ceil ( tmin / sstep ) * sstep ) ;
const auto diff = tmin / sstep - int64_t ( tmin / sstep ) ;
const auto xo = ( diff = = 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff ;
int iter = int ( ceil ( ( tmin - int64_t ( tmin / step ) * step ) / sstep ) ) ;
while ( x < numBins )
{
draw - > AddLine ( wpos + ImVec2 ( xo + x , yoff ) , wpos + ImVec2 ( xo + x , yoff + round ( ty * linelen [ iter ] ) ) , 0x66FFFFFF ) ;
if ( iter = = 0 & & ( tw = = 0 | | x > tx + tw + ty * 1.1 ) )
{
tx = x ;
2019-02-10 00:14:34 +00:00
auto txt = TimeToString ( tt ) ;
2018-04-21 22:52:33 +00:00
draw - > AddText ( wpos + ImVec2 ( xo + x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
iter = ( iter + 1 ) % 10 ;
x + = sdx ;
tt + = sstep ;
}
}
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 2 , 2 ) , wpos + ImVec2 ( w - 2 , Height + round ( ty * 1.5 ) ) ) )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-04-21 22:52:33 +00:00
auto & io = ImGui : : GetIO ( ) ;
draw - > AddLine ( ImVec2 ( io . MousePos . x , wpos . y ) , ImVec2 ( io . MousePos . x , wpos . y + Height - 2 ) , 0x33FFFFFF ) ;
const auto bin = double ( io . MousePos . x - wpos . x - 2 ) ;
int64_t t0 , t1 ;
if ( m_compare . logTime )
{
t0 = int64_t ( pow ( 10 , ltmin + bin / numBins * ( ltmax - ltmin ) ) ) ;
t1 = int64_t ( pow ( 10 , ltmin + ( bin + 1 ) / numBins * ( ltmax - ltmin ) ) ) ;
}
else
{
t0 = int64_t ( tmin + bin / numBins * ( tmax - tmin ) ) ;
t1 = int64_t ( tmin + ( bin + 1 ) / numBins * ( tmax - tmin ) ) ;
}
int64_t tBefore [ 2 ] = { 0 , 0 } ;
for ( int i = 0 ; i < bin ; i + + )
{
tBefore [ 0 ] + = binTime [ i ] . v0 ;
tBefore [ 1 ] + = binTime [ i ] . v1 ;
}
int64_t tAfter [ 2 ] = { 0 , 0 } ;
for ( int i = bin + 1 ; i < numBins ; i + + )
{
tAfter [ 0 ] + = binTime [ i ] . v0 ;
tAfter [ 1 ] + = binTime [ i ] . v1 ;
}
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time range: " ) ;
2018-06-29 16:57:49 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s " , TimeToString ( t0 ) , TimeToString ( t1 ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Count: " ) ;
2018-06-29 16:57:49 +00:00
ImGui : : SameLine ( ) ;
2019-03-26 19:27:28 +00:00
ImGui : : Text ( " %s / %s " , RealToString ( floor ( bins [ bin ] . v0 ) , true ) , RealToString ( floor ( bins [ bin ] . v1 ) , true ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time spent in bin: " ) ;
2018-06-29 16:57:49 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s / %s " , TimeToString ( binTime [ bin ] . v0 ) , TimeToString ( binTime [ bin ] . v1 ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time spent in the left bins: " ) ;
2018-06-29 16:57:49 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s / %s " , TimeToString ( tBefore [ 0 ] ) , TimeToString ( tBefore [ 1 ] ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time spent in the right bins: " ) ;
2018-06-29 16:57:49 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s / %s " , TimeToString ( tAfter [ 0 ] ) , TimeToString ( tAfter [ 1 ] ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " (Data is displayed as: " ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0xDD / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_LEMON ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " [this trace] / " ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xDD / 511.f , 0x22 / 511.f , 0x22 / 511.f , 1.f ) , ICON_FA_GEM ) ;
2018-08-18 12:02:20 +00:00
ImGui : : SameLine ( ) ;
2018-08-18 14:32:26 +00:00
# endif
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " [external trace]) " ) ;
2018-04-21 22:52:33 +00:00
ImGui : : EndTooltip ( ) ;
}
}
}
}
2018-04-21 23:28:55 +00:00
ImGui : : TreePop ( ) ;
2018-04-21 22:52:33 +00:00
}
# endif
ImGui : : End ( ) ;
}
2018-03-24 13:40:48 +00:00
void View : : DrawStatistics ( )
{
2019-03-08 23:30:53 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 1000 , 600 ) , ImGuiCond_FirstUseEver ) ;
2018-03-24 13:40:48 +00:00
ImGui : : Begin ( " Statistics " , & m_showStatistics ) ;
# ifdef TRACY_NO_STATISTICS
ImGui : : TextWrapped ( " Collection of statistical data is disabled in this build. " ) ;
ImGui : : TextWrapped ( " Rebuild without the TRACY_NO_STATISTICS macro to enable statistics view. " ) ;
# else
2018-04-30 01:54:09 +00:00
if ( ! m_worker . AreSourceLocationZonesReady ( ) )
{
ImGui : : TextWrapped ( " Please wait, computing data... " ) ;
2019-03-06 23:59:43 +00:00
DrawWaitingDots ( s_time ) ;
2018-04-30 01:54:09 +00:00
ImGui : : End ( ) ;
return ;
}
2018-08-17 22:09:23 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_CLOCK " Show self times " , & m_statSelf ) ;
# else
2018-06-05 22:47:16 +00:00
ImGui : : Checkbox ( " Show self times " , & m_statSelf ) ;
2018-08-17 22:09:23 +00:00
# endif
2018-06-05 22:47:16 +00:00
2018-03-24 14:16:43 +00:00
auto & slz = m_worker . GetSourceLocationZones ( ) ;
Vector < decltype ( slz . begin ( ) ) > srcloc ;
srcloc . reserve ( slz . size ( ) ) ;
for ( auto it = slz . begin ( ) ; it ! = slz . end ( ) ; + + it )
{
if ( it - > second . total ! = 0 )
{
srcloc . push_back_no_space_check ( it ) ;
}
}
2018-06-05 22:47:16 +00:00
2018-03-24 16:28:10 +00:00
switch ( m_statSort )
{
case 0 :
2018-06-05 22:47:16 +00:00
if ( m_statSelf )
{
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . selfTotal > rhs - > second . selfTotal ; } ) ;
}
else
{
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . total > rhs - > second . total ; } ) ;
}
2018-03-24 16:28:10 +00:00
break ;
case 1 :
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . zones . size ( ) > rhs - > second . zones . size ( ) ; } ) ;
break ;
case 2 :
2018-06-05 22:47:16 +00:00
if ( m_statSelf )
{
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . selfTotal / lhs - > second . zones . size ( ) > rhs - > second . selfTotal / rhs - > second . zones . size ( ) ; } ) ;
}
else
{
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . total / lhs - > second . zones . size ( ) > rhs - > second . total / rhs - > second . zones . size ( ) ; } ) ;
}
2018-03-24 16:28:10 +00:00
break ;
default :
assert ( false ) ;
break ;
}
2018-03-24 14:16:43 +00:00
2018-08-18 18:01:57 +00:00
TextFocused ( " Recorded source locations: " , RealToString ( srcloc . size ( ) , true ) ) ;
2018-03-24 14:16:43 +00:00
2019-03-08 23:30:53 +00:00
const auto w = ImGui : : GetWindowWidth ( ) ;
static bool widthSet = false ;
2018-03-24 14:16:43 +00:00
ImGui : : Columns ( 5 ) ;
2019-03-08 23:30:53 +00:00
if ( ! widthSet )
{
widthSet = true ;
ImGui : : SetColumnWidth ( 0 , w * 0.3f ) ;
ImGui : : SetColumnWidth ( 1 , w * 0.4f ) ;
ImGui : : SetColumnWidth ( 2 , w * 0.1f ) ;
ImGui : : SetColumnWidth ( 3 , w * 0.1f ) ;
ImGui : : SetColumnWidth ( 4 , w * 0.1f ) ;
}
2018-03-24 14:16:43 +00:00
ImGui : : Separator ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Name " ) ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Location " ) ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2018-04-21 12:17:42 +00:00
if ( ImGui : : SmallButton ( " Total time " ) ) m_statSort = 0 ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2018-04-21 12:17:42 +00:00
if ( ImGui : : SmallButton ( " Counts " ) ) m_statSort = 1 ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2018-04-21 12:17:42 +00:00
if ( ImGui : : SmallButton ( " MTPC " ) ) m_statSort = 2 ;
2018-03-24 14:16:43 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Mean time per call " ) ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
for ( auto & v : srcloc )
{
ImGui : : PushID ( v - > first ) ;
auto & srcloc = m_worker . GetSourceLocation ( v - > first ) ;
2018-03-24 14:20:39 +00:00
auto name = m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ;
2018-03-24 16:32:27 +00:00
if ( ImGui : : Selectable ( name , m_findZone . show & & ! m_findZone . match . empty ( ) & & m_findZone . match [ m_findZone . selMatch ] = = v - > first , ImGuiSelectableFlags_SpanAllColumns ) )
2018-03-24 14:16:43 +00:00
{
2018-04-05 17:30:32 +00:00
m_findZone . ShowZone ( v - > first , name ) ;
2018-03-24 14:16:43 +00:00
}
ImGui : : NextColumn ( ) ;
2019-03-08 23:15:23 +00:00
float indentVal = 0.f ;
if ( m_statBuzzAnim . Match ( v - > first ) )
{
const auto time = m_statBuzzAnim . Time ( ) ;
indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : Indent ( indentVal ) ;
}
const auto file = m_worker . GetString ( srcloc . file ) ;
ImGui : : TextDisabled ( " %s:%i " , file , srcloc . line ) ;
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( file ) )
{
SetTextEditorFile ( file , srcloc . line ) ;
}
else
{
m_statBuzzAnim . Enable ( v - > first , 0.5f ) ;
}
}
if ( indentVal ! = 0.f )
{
ImGui : : Unindent ( indentVal ) ;
}
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( TimeToString ( m_statSelf ? v - > second . selfTotal : v - > second . total ) ) ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( RealToString ( v - > second . zones . size ( ) , true ) ) ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( TimeToString ( ( m_statSelf ? v - > second . selfTotal : v - > second . total ) / v - > second . zones . size ( ) ) ) ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : PopID ( ) ;
}
2018-06-20 12:37:55 +00:00
ImGui : : EndColumns ( ) ;
2018-03-24 13:40:48 +00:00
# endif
ImGui : : End ( ) ;
}
2018-06-20 11:23:08 +00:00
void View : : DrawCallstackWindow ( )
{
bool show = true ;
2019-03-08 23:34:04 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 1200 , 500 ) , ImGuiCond_FirstUseEver ) ;
2018-08-17 20:00:35 +00:00
ImGui : : Begin ( " Call stack " , & show ) ;
2018-06-20 11:23:08 +00:00
2018-08-21 15:55:59 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_AT " Show frame addresses " , & m_showCallstackFrameAddress ) ;
# else
ImGui : : Checkbox ( " Show frame addresses " , & m_showCallstackFrameAddress ) ;
# endif
2018-06-20 11:23:08 +00:00
auto & cs = m_worker . GetCallstack ( m_callstackInfoWindow ) ;
2019-03-08 23:34:04 +00:00
const auto w = ImGui : : GetWindowWidth ( ) ;
static bool widthSet = false ;
2018-06-20 12:41:00 +00:00
ImGui : : Columns ( 3 ) ;
2019-03-08 23:34:04 +00:00
if ( ! widthSet )
{
widthSet = true ;
ImGui : : SetColumnWidth ( 0 , w * 0.05f ) ;
ImGui : : SetColumnWidth ( 1 , w * 0.475f ) ;
ImGui : : SetColumnWidth ( 2 , w * 0.475f ) ;
}
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Frame " ) ;
2018-06-20 12:41:00 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Function " ) ;
2018-06-22 18:44:57 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Click on entry to copy it to clipboard. " ) ;
2018-06-20 12:41:00 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Location " ) ;
2018-06-22 18:44:57 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Click on entry to copy it to clipboard. \n Right click on entry to try to open source file. " ) ;
2019-02-10 12:38:14 +00:00
ImGui : : NextColumn ( ) ;
2018-06-20 12:41:00 +00:00
2018-06-20 11:23:08 +00:00
int fidx = 0 ;
2019-01-20 18:11:48 +00:00
int bidx = 0 ;
2018-06-20 11:23:08 +00:00
for ( auto & entry : cs )
{
2019-01-20 18:11:48 +00:00
auto frameData = m_worker . GetCallstackFrame ( entry ) ;
if ( ! frameData )
2018-06-20 11:23:08 +00:00
{
2019-02-19 15:37:34 +00:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " %i " , fidx + + ) ;
ImGui : : NextColumn ( ) ;
2018-06-22 18:44:57 +00:00
char buf [ 32 ] ;
2019-03-03 15:50:18 +00:00
sprintf ( buf , " %p " , ( void * ) m_worker . GetCanonicalPointer ( entry ) ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( buf ) ;
2018-06-22 18:44:57 +00:00
if ( ImGui : : IsItemClicked ( ) )
{
ImGui : : SetClipboardText ( buf ) ;
}
2018-06-20 12:41:00 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : NextColumn ( ) ;
2018-06-20 11:23:08 +00:00
}
else
{
2019-01-21 16:12:01 +00:00
const auto fsz = frameData - > size ;
for ( uint8_t f = 0 ; f < fsz ; f + + )
2018-06-21 11:26:04 +00:00
{
2019-01-20 18:11:48 +00:00
const auto & frame = frameData - > data [ f ] ;
2019-02-04 01:27:13 +00:00
auto txt = m_worker . GetString ( frame . name ) ;
if ( fidx = = 0 & & f ! = fsz - 1 )
{
2019-02-06 20:07:41 +00:00
auto test = s_tracyStackFrames ;
bool match = false ;
do
2019-02-04 01:27:13 +00:00
{
2019-02-06 20:07:41 +00:00
if ( strcmp ( txt , * test ) = = 0 )
{
match = true ;
break ;
}
2019-02-04 01:27:13 +00:00
}
2019-02-06 20:07:41 +00:00
while ( * + + test ) ;
if ( match ) continue ;
2019-02-04 01:27:13 +00:00
}
2019-01-20 18:11:48 +00:00
bidx + + ;
ImGui : : Separator ( ) ;
2019-01-21 16:12:01 +00:00
if ( f = = fsz - 1 )
2018-08-21 15:55:59 +00:00
{
2019-01-20 18:11:48 +00:00
ImGui : : Text ( " %i " , fidx + + ) ;
2018-08-21 15:55:59 +00:00
}
else
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " inline " ) ;
2018-08-21 15:55:59 +00:00
}
2019-01-20 18:11:48 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : TextWrapped ( " %s " , txt ) ;
2018-08-21 15:55:59 +00:00
if ( ImGui : : IsItemClicked ( ) )
{
ImGui : : SetClipboardText ( txt ) ;
}
2019-01-20 18:11:48 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : PushTextWrapPos ( 0.0f ) ;
float indentVal = 0.f ;
if ( m_callstackBuzzAnim . Match ( bidx ) )
2018-08-17 20:06:59 +00:00
{
2019-01-20 18:11:48 +00:00
const auto time = m_callstackBuzzAnim . Time ( ) ;
indentVal = sin ( time * 60.f ) * 10.f * time ;
ImGui : : Indent ( indentVal ) ;
}
txt = m_worker . GetString ( frame . file ) ;
if ( m_showCallstackFrameAddress )
{
2019-03-03 17:20:55 +00:00
if ( entry . sel = = 0 )
{
ImGui : : TextDisabled ( " 0x% " PRIx64 , entry . idx ) ;
if ( ImGui : : IsItemClicked ( ) )
{
char tmp [ 32 ] ;
sprintf ( tmp , " 0x% " PRIx64 , entry . idx ) ;
ImGui : : SetClipboardText ( tmp ) ;
}
}
else
2019-01-20 18:11:48 +00:00
{
2019-03-03 17:20:55 +00:00
ImGui : : TextDisabled ( " Custom #% " PRIu64 , entry . idx ) ;
2019-01-20 18:11:48 +00:00
}
2018-08-17 20:06:59 +00:00
}
2018-08-17 20:23:16 +00:00
else
{
2019-01-20 18:11:48 +00:00
if ( frame . line = = 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( txt ) ;
2019-01-20 18:11:48 +00:00
}
else
{
ImGui : : TextDisabled ( " %s:%i " , txt , frame . line ) ;
}
if ( ImGui : : IsItemClicked ( ) )
{
ImGui : : SetClipboardText ( txt ) ;
}
2018-08-17 20:23:16 +00:00
}
2019-01-20 18:11:48 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
if ( FileExists ( txt ) )
{
SetTextEditorFile ( txt , frame . line ) ;
}
else
{
m_callstackBuzzAnim . Enable ( bidx , 0.5f ) ;
}
}
if ( indentVal ! = 0.f )
{
ImGui : : Unindent ( indentVal ) ;
}
ImGui : : PopTextWrapPos ( ) ;
ImGui : : NextColumn ( ) ;
2018-08-17 20:23:16 +00:00
}
2018-06-20 11:23:08 +00:00
}
}
2018-06-20 12:41:00 +00:00
ImGui : : EndColumns ( ) ;
2018-06-20 11:23:08 +00:00
ImGui : : End ( ) ;
if ( ! show )
{
m_callstackInfoWindow = 0 ;
}
}
2018-07-17 21:03:03 +00:00
void View : : DrawMemoryAllocWindow ( )
{
2018-07-17 22:25:02 +00:00
bool show = true ;
2019-03-17 15:39:27 +00:00
ImGui : : Begin ( " Memory allocation " , & show , ImGuiWindowFlags_AlwaysAutoResize ) ;
2018-07-17 21:03:03 +00:00
const auto & mem = m_worker . GetMemData ( ) ;
const auto & ev = mem . data [ m_memoryAllocInfoWindow ] ;
const auto tidAlloc = m_worker . DecompressThread ( ev . threadAlloc ) ;
const auto tidFree = m_worker . DecompressThread ( ev . threadFree ) ;
int idx = 0 ;
2018-09-28 09:40:22 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_MICROSCOPE " Zoom to allocation " ) )
# else
if ( ImGui : : Button ( " Zoom to allocation " ) )
# endif
{
ZoomToRange ( ev . timeAlloc , ev . timeFree > = 0 ? ev . timeFree : m_worker . GetLastTime ( ) ) ;
}
2018-07-17 21:03:03 +00:00
char buf [ 64 ] ;
sprintf ( buf , " 0x% " PRIx64 , ev . ptr ) ;
TextFocused ( " Address: " , buf ) ;
2018-08-08 18:38:43 +00:00
TextFocused ( " Size: " , MemSizeToString ( ev . size ) ) ;
2018-08-09 00:27:55 +00:00
if ( ev . size > = 10000ll )
{
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s bytes) " , RealToString ( ev . size , true ) ) ;
}
2018-07-17 21:03:03 +00:00
ImGui : : Separator ( ) ;
2018-08-04 17:51:50 +00:00
TextFocused ( " Appeared at " , TimeToString ( ev . timeAlloc - m_worker . GetTimeBegin ( ) ) ) ;
2018-07-17 21:03:03 +00:00
if ( ImGui : : IsItemClicked ( ) ) CenterAtTime ( ev . timeAlloc ) ;
ImGui : : SameLine ( ) ; ImGui : : Spacing ( ) ; ImGui : : SameLine ( ) ;
TextFocused ( " Thread: " , m_worker . GetThreadString ( tidAlloc ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tidAlloc ) ;
if ( ev . csAlloc ! = 0 )
{
ImGui : : SameLine ( ) ; ImGui : : Spacing ( ) ; ImGui : : SameLine ( ) ;
2018-08-17 20:00:35 +00:00
SmallCallstackButton ( " Call stack " , ev . csAlloc , idx ) ;
2018-07-17 21:03:03 +00:00
}
if ( ev . timeFree < 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Allocation still active " ) ;
2018-07-17 21:03:03 +00:00
}
else
{
2018-08-04 17:51:50 +00:00
TextFocused ( " Freed at " , TimeToString ( ev . timeFree - m_worker . GetTimeBegin ( ) ) ) ;
2018-07-17 21:03:03 +00:00
if ( ImGui : : IsItemClicked ( ) ) CenterAtTime ( ev . timeFree ) ;
ImGui : : SameLine ( ) ; ImGui : : Spacing ( ) ; ImGui : : SameLine ( ) ;
TextFocused ( " Thread: " , m_worker . GetThreadString ( tidFree ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tidFree ) ;
if ( ev . csFree ! = 0 )
{
ImGui : : SameLine ( ) ; ImGui : : Spacing ( ) ; ImGui : : SameLine ( ) ;
2018-08-17 20:00:35 +00:00
SmallCallstackButton ( " Call stack " , ev . csFree , idx ) ;
2018-07-17 21:03:03 +00:00
}
TextFocused ( " Duration: " , TimeToString ( ev . timeFree - ev . timeAlloc ) ) ;
}
ImGui : : Separator ( ) ;
auto zoneAlloc = FindZoneAtTime ( tidAlloc , ev . timeAlloc ) ;
if ( zoneAlloc )
{
const auto & srcloc = m_worker . GetSourceLocation ( zoneAlloc - > srcloc ) ;
const auto txt = srcloc . name . active ? m_worker . GetString ( srcloc . name ) : m_worker . GetString ( srcloc . function ) ;
ImGui : : PushID ( idx + + ) ;
TextFocused ( " Zone alloc: " , txt ) ;
auto hover = ImGui : : IsItemHovered ( ) ;
ImGui : : PopID ( ) ;
if ( ImGui : : IsItemClicked ( ) )
{
ShowZoneInfo ( * zoneAlloc ) ;
}
if ( hover )
{
m_zoneHighlight = zoneAlloc ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * zoneAlloc ) ;
}
ZoneTooltip ( * zoneAlloc ) ;
}
}
if ( ev . timeFree > = 0 )
{
auto zoneFree = FindZoneAtTime ( tidFree , ev . timeFree ) ;
if ( zoneFree )
{
const auto & srcloc = m_worker . GetSourceLocation ( zoneFree - > srcloc ) ;
const auto txt = srcloc . name . active ? m_worker . GetString ( srcloc . name ) : m_worker . GetString ( srcloc . function ) ;
TextFocused ( " Zone free: " , txt ) ;
auto hover = ImGui : : IsItemHovered ( ) ;
if ( ImGui : : IsItemClicked ( ) )
{
ShowZoneInfo ( * zoneFree ) ;
}
if ( hover )
{
m_zoneHighlight = zoneFree ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * zoneFree ) ;
}
ZoneTooltip ( * zoneFree ) ;
}
}
2018-07-17 21:32:29 +00:00
if ( zoneAlloc ! = 0 & & zoneAlloc = = zoneFree )
2018-07-17 21:03:03 +00:00
{
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " (same zone) " ) ;
2018-07-17 21:03:03 +00:00
}
}
ImGui : : End ( ) ;
2018-07-19 13:43:45 +00:00
if ( ! show ) m_memoryAllocInfoWindow = - 1 ;
2018-07-17 21:03:03 +00:00
}
2018-08-08 17:25:13 +00:00
void View : : DrawInfo ( )
{
2018-08-28 23:00:29 +00:00
char dtmp [ 64 ] ;
time_t date = m_worker . GetCaptureTime ( ) ;
auto lt = localtime ( & date ) ;
strftime ( dtmp , 64 , " %F %T " , lt ) ;
2018-08-08 18:53:01 +00:00
const auto & io = ImGui : : GetIO ( ) ;
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 400 , 650 ) , ImGuiCond_FirstUseEver ) ;
2018-08-08 17:25:13 +00:00
ImGui : : Begin ( " Trace information " , & m_showInfo ) ;
2018-08-08 18:53:01 +00:00
TextFocused ( " Profiler memory usage: " , MemSizeToString ( memUsage . load ( std : : memory_order_relaxed ) ) ) ;
TextFocused ( " Profiler FPS: " , RealToString ( int ( io . Framerate ) , true ) ) ;
ImGui : : Separator ( ) ;
2018-08-28 23:00:29 +00:00
TextFocused ( " Captured program: " , m_worker . GetCaptureProgram ( ) . c_str ( ) ) ;
TextFocused ( " Capture time: " , dtmp ) ;
2019-03-01 00:47:36 +00:00
ImGui : : TextDisabled ( " Trace version: " ) ;
ImGui : : SameLine ( ) ;
const auto version = m_worker . GetTraceVersion ( ) ;
ImGui : : Text ( " %i.%i.%i " , version > > 16 , ( version > > 8 ) & 0xFF , version & 0xFF ) ;
2018-08-28 23:00:29 +00:00
ImGui : : Separator ( ) ;
2018-08-08 17:25:13 +00:00
TextFocused ( " Queue delay: " , TimeToString ( m_worker . GetDelay ( ) ) ) ;
TextFocused ( " Timer resolution: " , TimeToString ( m_worker . GetResolution ( ) ) ) ;
ImGui : : Separator ( ) ;
TextFocused ( " Zones: " , RealToString ( m_worker . GetZoneCount ( ) , true ) ) ;
TextFocused ( " Lock events: " , RealToString ( m_worker . GetLockCount ( ) , true ) ) ;
TextFocused ( " Plot data points: " , RealToString ( m_worker . GetPlotCount ( ) , true ) ) ;
TextFocused ( " Memory allocations: " , RealToString ( m_worker . GetMemData ( ) . data . size ( ) , true ) ) ;
2018-08-14 14:36:25 +00:00
TextFocused ( " Source locations: " , RealToString ( m_worker . GetSrcLocCount ( ) , true ) ) ;
2018-08-17 20:00:35 +00:00
TextFocused ( " Call stacks: " , RealToString ( m_worker . GetCallstackPayloadCount ( ) , true ) ) ;
TextFocused ( " Call stack frames: " , RealToString ( m_worker . GetCallstackFrameCount ( ) , true ) ) ;
2019-06-11 23:26:49 +00:00
const auto ficnt = m_worker . GetFrameImageCount ( ) ;
TextFocused ( " Frame images: " , RealToString ( ficnt , true ) ) ;
if ( ficnt ! = 0 )
{
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_PLAY " Playback " ) )
# else
if ( ImGui : : Button ( " Playback " ) )
# endif
{
m_showPlayback = true ;
}
}
2018-09-01 00:07:52 +00:00
2018-09-01 10:38:12 +00:00
const auto fsz = m_worker . GetFullFrameCount ( * m_frames ) ;
2018-09-01 00:07:52 +00:00
if ( fsz ! = 0 )
2018-08-31 13:32:30 +00:00
{
ImGui : : Separator ( ) ;
TextFocused ( " Frame set: " , m_frames - > name = = 0 ? " Frames " : m_worker . GetString ( m_frames - > name ) ) ;
2018-09-01 12:04:23 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , m_frames - > continuous ? " continuous " : " discontinuous " ) ;
2019-04-26 20:47:30 +00:00
ImGui : : SameLine ( ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
if ( ImGui : : BeginCombo ( " ##frameCombo " , nullptr , ImGuiComboFlags_NoPreview ) )
{
auto & frames = m_worker . GetFrames ( ) ;
for ( auto & fd : frames )
{
bool isSelected = m_frames = = fd ;
if ( ImGui : : Selectable ( fd - > name = = 0 ? " Frames " : m_worker . GetString ( fd - > name ) , isSelected ) )
{
m_frames = fd ;
}
if ( isSelected )
{
ImGui : : SetItemDefaultFocus ( ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( fd - > frames . size ( ) , true ) ) ;
}
ImGui : : EndCombo ( ) ;
}
ImGui : : PopStyleVar ( ) ;
2019-04-26 21:19:31 +00:00
ImGui : : SameLine ( ) ;
SmallCheckbox ( " Limit to view " , & m_frameSortData . limitToView ) ;
const auto frameRange = m_worker . GetFrameRange ( * m_frames , m_zvStart , m_zvEnd ) ;
2019-05-12 13:48:25 +00:00
if ( m_frameSortData . frameSet ! = m_frames | | ( m_frameSortData . limitToView & & m_frameSortData . limitRange ! = frameRange ) | | ( ! m_frameSortData . limitToView & & m_frameSortData . limitRange . first ! = - 1 ) )
2019-04-26 21:19:31 +00:00
{
m_frameSortData . frameSet = m_frames ;
m_frameSortData . frameNum = 0 ;
m_frameSortData . data . clear ( ) ;
m_frameSortData . total = 0 ;
}
bool recalc = false ;
int64_t total = 0 ;
if ( ! m_frameSortData . limitToView )
{
if ( m_frameSortData . frameNum ! = fsz | | m_frameSortData . limitRange . first ! = - 1 )
{
auto & vec = m_frameSortData . data ;
vec . reserve ( fsz ) ;
const auto midSz = vec . size ( ) ;
total = m_frameSortData . total ;
for ( size_t i = m_frameSortData . frameNum ; i < fsz ; i + + )
{
const auto t = m_worker . GetFrameTime ( * m_frames , i ) ;
if ( t > 0 )
{
vec . emplace_back ( t ) ;
total + = t ;
}
}
auto mid = vec . begin ( ) + midSz ;
pdqsort_branchless ( mid , vec . end ( ) ) ;
std : : inplace_merge ( vec . begin ( ) , mid , vec . end ( ) ) ;
recalc = true ;
m_frameSortData . limitRange . first = - 1 ;
}
}
else
{
if ( m_frameSortData . limitRange ! = frameRange )
{
auto & vec = m_frameSortData . data ;
assert ( vec . empty ( ) ) ;
vec . reserve ( frameRange . second - frameRange . first ) ;
for ( int i = frameRange . first ; i < frameRange . second ; i + + )
{
const auto t = m_worker . GetFrameTime ( * m_frames , i ) ;
if ( t > 0 )
{
vec . emplace_back ( t ) ;
total + = t ;
}
}
pdqsort_branchless ( vec . begin ( ) , vec . end ( ) ) ;
recalc = true ;
m_frameSortData . limitRange = frameRange ;
}
}
if ( recalc )
{
auto & vec = m_frameSortData . data ;
const auto vsz = vec . size ( ) ;
m_frameSortData . average = float ( total ) / vsz ;
m_frameSortData . median = vec [ vsz / 2 ] ;
m_frameSortData . total = total ;
m_frameSortData . frameNum = fsz ;
}
const auto profileSpan = m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ;
2018-08-31 13:32:30 +00:00
TextFocused ( " Count: " , RealToString ( fsz , true ) ) ;
2018-08-31 23:12:04 +00:00
TextFocused ( " Total time: " , TimeToString ( m_frameSortData . total ) ) ;
2018-08-31 23:15:37 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%% of profile time span) " , m_frameSortData . total / float ( profileSpan ) * 100.f ) ;
2018-08-31 16:51:00 +00:00
TextFocused ( " Average frame time: " , TimeToString ( m_frameSortData . average ) ) ;
2018-08-31 16:43:25 +00:00
ImGui : : SameLine ( ) ;
2018-08-31 16:51:00 +00:00
ImGui : : TextDisabled ( " (%s FPS) " , RealToString ( round ( 1000000000.0 / m_frameSortData . average ) , true ) ) ;
2018-08-31 16:58:39 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s FPS " , RealToString ( 1000000000.0 / m_frameSortData . average , true ) ) ;
ImGui : : EndTooltip ( ) ;
}
2018-08-31 16:51:00 +00:00
TextFocused ( " Median frame time: " , TimeToString ( m_frameSortData . median ) ) ;
2018-08-31 16:43:25 +00:00
ImGui : : SameLine ( ) ;
2018-08-31 16:51:00 +00:00
ImGui : : TextDisabled ( " (%s FPS) " , RealToString ( round ( 1000000000.0 / m_frameSortData . median ) , true ) ) ;
2018-08-31 16:58:39 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s FPS " , RealToString ( 1000000000.0 / m_frameSortData . median , true ) ) ;
ImGui : : EndTooltip ( ) ;
}
2018-08-31 23:12:16 +00:00
if ( ImGui : : TreeNode ( " Histogram " ) )
{
const auto ty = ImGui : : GetFontSize ( ) ;
auto & frames = m_frameSortData . data ;
2019-06-16 22:44:34 +00:00
auto tmin = frames . front ( ) ;
auto tmax = frames . back ( ) ;
2018-08-31 23:12:16 +00:00
if ( tmin ! = std : : numeric_limits < int64_t > : : max ( ) )
{
ImGui : : Checkbox ( " Log values " , & m_frameSortData . logVal ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Log time " , & m_frameSortData . logTime ) ;
2019-06-16 22:44:34 +00:00
TextDisabledUnformatted ( " Minimum values in bin: " ) ;
ImGui : : SameLine ( ) ;
ImGui : : SetNextItemWidth ( ImGui : : CalcTextSize ( " 123456890123456 " ) . x ) ;
ImGui : : InputInt ( " ##minBinVal " , & m_frameSortData . minBinVal ) ;
if ( m_frameSortData . minBinVal < 1 ) m_frameSortData . minBinVal = 1 ;
2019-06-16 23:12:24 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Reset " ) ) m_frameSortData . minBinVal = 1 ;
2019-06-16 22:44:34 +00:00
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time range: " ) ;
2018-08-31 23:12:16 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s (%s) " , TimeToString ( tmin ) , TimeToString ( tmax ) , TimeToString ( tmax - tmin ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " FPS range: " ) ;
2018-08-31 23:39:29 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s FPS - %s FPS " , RealToString ( round ( 1000000000.0 / tmin ) , true ) , RealToString ( round ( 1000000000.0 / tmax ) , true ) ) ;
2019-06-16 22:44:34 +00:00
if ( tmax - tmin > 0 )
2018-08-31 23:12:16 +00:00
{
const auto w = ImGui : : GetContentRegionAvail ( ) . x ;
const auto numBins = int64_t ( w - 4 ) ;
if ( numBins > 1 )
{
2019-06-15 22:25:22 +00:00
if ( numBins > m_frameSortData . numBins )
2018-08-31 23:12:16 +00:00
{
m_frameSortData . numBins = numBins ;
m_frameSortData . bins = std : : make_unique < int64_t [ ] > ( numBins ) ;
}
const auto & bins = m_frameSortData . bins ;
memset ( bins . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
2019-06-16 22:44:34 +00:00
auto framesBegin = frames . begin ( ) ;
auto framesEnd = frames . end ( ) ;
while ( framesBegin ! = framesEnd & & * framesBegin = = 0 ) + + framesBegin ;
if ( m_frameSortData . minBinVal > 1 )
{
if ( m_frameSortData . logTime )
{
const auto tMinLog = log10 ( tmin ) ;
const auto zmax = ( log10 ( tmax ) - tMinLog ) / numBins ;
int64_t i ;
for ( i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
auto nit = std : : lower_bound ( framesBegin , framesEnd , nextBinVal ) ;
const auto distance = std : : distance ( framesBegin , nit ) ;
if ( distance > = m_frameSortData . minBinVal ) break ;
framesBegin = nit ;
}
for ( int64_t j = numBins - 1 ; j > i ; j - - )
{
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( j - 1 ) * zmax ) ) ;
auto nit = std : : lower_bound ( framesBegin , framesEnd , nextBinVal ) ;
const auto distance = std : : distance ( nit , framesEnd ) ;
if ( distance > = m_frameSortData . minBinVal ) break ;
framesEnd = nit ;
}
}
else
{
const auto zmax = tmax - tmin ;
int64_t i ;
for ( i = 0 ; i < numBins ; i + + )
{
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
auto nit = std : : lower_bound ( framesBegin , framesEnd , nextBinVal ) ;
const auto distance = std : : distance ( framesBegin , nit ) ;
if ( distance > = m_frameSortData . minBinVal ) break ;
framesBegin = nit ;
}
for ( int64_t j = numBins - 1 ; j > i ; j - - )
{
const auto nextBinVal = tmin + ( j - 1 ) * zmax / numBins ;
auto nit = std : : lower_bound ( framesBegin , framesEnd , nextBinVal ) ;
const auto distance = std : : distance ( nit , framesEnd ) ;
if ( distance > = m_frameSortData . minBinVal ) break ;
framesEnd = nit ;
}
}
tmin = * framesBegin ;
tmax = * ( framesEnd - 1 ) ;
}
2018-08-31 23:12:16 +00:00
if ( m_frameSortData . logTime )
{
2018-09-01 12:50:38 +00:00
const auto tMinLog = log10 ( tmin ) ;
const auto zmax = ( log10 ( tmax ) - tMinLog ) / numBins ;
2019-06-16 22:44:34 +00:00
auto fit = framesBegin ;
2018-09-01 12:50:38 +00:00
for ( int64_t i = 0 ; i < numBins ; i + + )
2018-08-31 23:12:16 +00:00
{
2018-09-01 12:50:38 +00:00
const auto nextBinVal = int64_t ( pow ( 10.0 , tMinLog + ( i + 1 ) * zmax ) ) ;
2019-06-16 22:44:34 +00:00
auto nit = std : : lower_bound ( fit , framesEnd , nextBinVal ) ;
2018-09-01 12:50:38 +00:00
bins [ i ] = std : : distance ( fit , nit ) ;
fit = nit ;
2018-08-31 23:12:16 +00:00
}
2019-06-16 22:44:34 +00:00
bins [ numBins - 1 ] + = std : : distance ( fit , framesEnd ) ;
2018-08-31 23:12:16 +00:00
}
else
{
2018-09-01 12:50:38 +00:00
const auto zmax = tmax - tmin ;
2019-06-16 22:44:34 +00:00
auto fit = framesBegin ;
2018-09-01 12:50:38 +00:00
for ( int64_t i = 0 ; i < numBins ; i + + )
2018-08-31 23:12:16 +00:00
{
2019-01-24 15:02:36 +00:00
const auto nextBinVal = tmin + ( i + 1 ) * zmax / numBins ;
2019-06-16 22:44:34 +00:00
auto nit = std : : lower_bound ( fit , framesEnd , nextBinVal ) ;
2018-09-01 12:50:38 +00:00
bins [ i ] = std : : distance ( fit , nit ) ;
fit = nit ;
2018-08-31 23:12:16 +00:00
}
2019-06-16 22:44:34 +00:00
bins [ numBins - 1 ] + = std : : distance ( fit , framesEnd ) ;
2018-08-31 23:12:16 +00:00
}
int64_t maxVal = bins [ 0 ] ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( maxVal , bins [ i ] ) ;
}
TextFocused ( " Max counts: " , RealToString ( maxVal , true ) ) ;
2019-06-21 12:15:46 +00:00
ImGui : : PushStyleVar ( ImGuiStyleVar_FramePadding , ImVec2 ( 0 , 0 ) ) ;
2018-09-02 11:37:36 +00:00
ImGui : : Checkbox ( " ###draw1 " , & m_frameSortData . drawAvgMed ) ;
ImGui : : SameLine ( ) ;
2018-08-31 23:34:08 +00:00
ImGui : : ColorButton ( " c1 " , ImVec4 ( 0xFF / 255.f , 0x44 / 255.f , 0x44 / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Average time " ) ;
2018-08-31 23:34:08 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
ImGui : : ColorButton ( " c2 " , ImVec4 ( 0x44 / 255.f , 0x88 / 255.f , 0xFF / 255.f , 1.f ) , ImGuiColorEditFlags_NoTooltip ) ;
ImGui : : SameLine ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Median time " ) ;
2019-06-21 12:15:46 +00:00
ImGui : : PopStyleVar ( ) ;
2018-08-31 23:34:08 +00:00
2018-08-31 23:12:16 +00:00
const auto Height = 200 * ImGui : : GetTextLineHeight ( ) / 15.f ;
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
ImGui : : InvisibleButton ( " ##histogram " , ImVec2 ( w , Height + round ( ty * 1.5 ) ) ) ;
const bool hover = ImGui : : IsItemHovered ( ) ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( w , Height ) , 0x22FFFFFF ) ;
draw - > AddRect ( wpos , wpos + ImVec2 ( w , Height ) , 0x88FFFFFF ) ;
if ( m_frameSortData . logVal )
{
2018-09-08 17:01:51 +00:00
const auto hAdj = double ( Height - 4 ) / log10 ( maxVal + 1 ) ;
2018-08-31 23:12:16 +00:00
for ( int i = 0 ; i < numBins ; i + + )
{
const auto val = bins [ i ] ;
if ( val > 0 )
{
2018-09-08 17:01:51 +00:00
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val + 1 ) * hAdj ) , 0xFF22DDDD ) ;
2018-08-31 23:12:16 +00:00
}
}
}
else
{
const auto hAdj = double ( Height - 4 ) / maxVal ;
for ( int i = 0 ; i < numBins ; i + + )
{
const auto val = bins [ i ] ;
if ( val > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - val * hAdj ) , 0xFF22DDDD ) ;
}
}
}
const auto xoff = 2 ;
const auto yoff = Height + 1 ;
if ( m_frameSortData . logTime )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-08-31 23:12:16 +00:00
const auto start = int ( floor ( ltmin ) ) ;
const auto end = int ( ceil ( ltmax ) ) ;
const auto range = ltmax - ltmin ;
const auto step = w / range ;
auto offset = start - ltmin ;
int tw = 0 ;
int tx = 0 ;
auto tt = int64_t ( pow ( 10 , start ) ) ;
static const double logticks [ ] = { log10 ( 2 ) , log10 ( 3 ) , log10 ( 4 ) , log10 ( 5 ) , log10 ( 6 ) , log10 ( 7 ) , log10 ( 8 ) , log10 ( 9 ) } ;
for ( int i = start ; i < = end ; i + + )
{
const auto x = ( i - start + offset ) * step ;
if ( x > = 0 )
{
draw - > AddLine ( wpos + ImVec2 ( x , yoff ) , wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF ) ;
if ( tw = = 0 | | x > tx + tw + ty * 1.1 )
{
tx = x ;
2019-02-10 00:14:34 +00:00
auto txt = TimeToString ( tt ) ;
2018-08-31 23:12:16 +00:00
draw - > AddText ( wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
}
for ( int j = 0 ; j < 8 ; j + + )
{
const auto xoff = x + logticks [ j ] * step ;
if ( xoff > = 0 )
{
draw - > AddLine ( wpos + ImVec2 ( xoff , yoff ) , wpos + ImVec2 ( xoff , yoff + round ( ty * 0.25 ) ) , 0x66FFFFFF ) ;
}
}
tt * = 10 ;
}
}
else
{
2019-06-16 23:09:25 +00:00
const auto pxns = numBins / double ( tmax - tmin ) ;
2018-08-31 23:12:16 +00:00
const auto nspx = 1.0 / pxns ;
2018-09-08 17:01:51 +00:00
const auto scale = std : : max < float > ( 0.0f , round ( log10 ( nspx ) + 2 ) ) ;
2018-08-31 23:12:16 +00:00
const auto step = pow ( 10 , scale ) ;
const auto dx = step * pxns ;
double x = 0 ;
int tw = 0 ;
int tx = 0 ;
const auto sstep = step / 10.0 ;
const auto sdx = dx / 10.0 ;
static const double linelen [ ] = { 0.5 , 0.25 , 0.25 , 0.25 , 0.25 , 0.375 , 0.25 , 0.25 , 0.25 , 0.25 } ;
int64_t tt = int64_t ( ceil ( tmin / sstep ) * sstep ) ;
const auto diff = tmin / sstep - int64_t ( tmin / sstep ) ;
const auto xo = ( diff = = 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff ;
int iter = int ( ceil ( ( tmin - int64_t ( tmin / step ) * step ) / sstep ) ) ;
while ( x < numBins )
{
draw - > AddLine ( wpos + ImVec2 ( xo + x , yoff ) , wpos + ImVec2 ( xo + x , yoff + round ( ty * linelen [ iter ] ) ) , 0x66FFFFFF ) ;
if ( iter = = 0 & & ( tw = = 0 | | x > tx + tw + ty * 1.1 ) )
{
tx = x ;
2019-02-10 00:14:34 +00:00
auto txt = TimeToString ( tt ) ;
2018-08-31 23:12:16 +00:00
draw - > AddText ( wpos + ImVec2 ( xo + x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
iter = ( iter + 1 ) % 10 ;
x + = sdx ;
tt + = sstep ;
}
}
2018-09-02 11:37:36 +00:00
if ( m_frameSortData . drawAvgMed )
2018-08-31 23:34:08 +00:00
{
2018-09-02 11:37:36 +00:00
float ta , tm ;
if ( m_frameSortData . logTime )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-08-31 23:34:08 +00:00
2018-09-08 17:01:51 +00:00
ta = ( log10 ( m_frameSortData . average ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
tm = ( log10 ( m_frameSortData . median ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
2018-09-02 11:37:36 +00:00
}
else
{
ta = ( m_frameSortData . average - tmin ) / float ( tmax - tmin ) * numBins ;
tm = ( m_frameSortData . median - tmin ) / float ( tmax - tmin ) * numBins ;
}
ta = round ( ta ) ;
tm = round ( tm ) ;
2018-08-31 23:34:08 +00:00
2018-09-02 11:37:36 +00:00
if ( ta = = tm )
{
draw - > AddLine ( ImVec2 ( wpos . x + ta , wpos . y ) , ImVec2 ( wpos . x + ta , wpos . y + Height - 2 ) , 0xFFFF88FF ) ;
}
else
{
draw - > AddLine ( ImVec2 ( wpos . x + ta , wpos . y ) , ImVec2 ( wpos . x + ta , wpos . y + Height - 2 ) , 0xFF4444FF ) ;
draw - > AddLine ( ImVec2 ( wpos . x + tm , wpos . y ) , ImVec2 ( wpos . x + tm , wpos . y + Height - 2 ) , 0xFFFF8844 ) ;
}
2018-08-31 23:44:03 +00:00
}
2018-08-31 23:34:08 +00:00
2018-08-31 23:12:16 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 2 , 2 ) , wpos + ImVec2 ( w - 2 , Height + round ( ty * 1.5 ) ) ) )
{
2018-09-08 17:01:51 +00:00
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-08-31 23:12:16 +00:00
auto & io = ImGui : : GetIO ( ) ;
draw - > AddLine ( ImVec2 ( io . MousePos . x , wpos . y ) , ImVec2 ( io . MousePos . x , wpos . y + Height - 2 ) , 0x33FFFFFF ) ;
const auto bin = double ( io . MousePos . x - wpos . x - 2 ) ;
int64_t t0 , t1 ;
if ( m_frameSortData . logTime )
{
t0 = int64_t ( pow ( 10 , ltmin + bin / numBins * ( ltmax - ltmin ) ) ) ;
// Hackfix for inability to select data in last bin.
// A proper solution would be nice.
if ( bin + 1 = = numBins )
{
t1 = tmax ;
}
else
{
t1 = int64_t ( pow ( 10 , ltmin + ( bin + 1 ) / numBins * ( ltmax - ltmin ) ) ) ;
}
}
else
{
t0 = int64_t ( tmin + bin / numBins * ( tmax - tmin ) ) ;
t1 = int64_t ( tmin + ( bin + 1 ) / numBins * ( tmax - tmin ) ) ;
}
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Time range: " ) ;
2018-08-31 23:12:16 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Text ( " %s - %s " , TimeToString ( t0 ) , TimeToString ( t1 ) ) ;
2018-08-31 23:39:29 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s FPS - %s FPS) " , RealToString ( round ( 1000000000.0 / t0 ) , true ) , RealToString ( round ( 1000000000.0 / t1 ) , true ) ) ;
2019-03-26 19:19:56 +00:00
TextFocused ( " Count: " , RealToString ( bins [ bin ] , true ) ) ;
2018-08-31 23:12:16 +00:00
ImGui : : EndTooltip ( ) ;
}
2019-06-16 22:59:16 +00:00
if ( m_frameHover ! = - 1 )
{
const auto frameTime = m_worker . GetFrameTime ( * m_frames , m_frameHover ) ;
float framePos ;
if ( m_frameSortData . logTime )
{
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
framePos = round ( ( log10 ( frameTime ) - ltmin ) / float ( ltmax - ltmin ) * numBins ) ;
}
else
{
framePos = round ( ( frameTime - tmin ) / float ( tmax - tmin ) * numBins ) ;
}
2019-06-19 18:01:41 +00:00
const auto c = uint32_t ( ( sin ( s_time * 10 ) * 0.25 + 0.75 ) * 255 ) ;
const auto color = 0xFF000000 | ( c < < 16 ) | ( c < < 8 ) | c ;
draw - > AddLine ( ImVec2 ( wpos . x + framePos , wpos . y ) , ImVec2 ( wpos . x + framePos , wpos . y + Height - 2 ) , color ) ;
2019-06-16 22:59:16 +00:00
}
2018-08-31 23:12:16 +00:00
}
}
}
ImGui : : TreePop ( ) ;
}
2018-08-31 13:32:30 +00:00
}
2018-08-19 16:24:43 +00:00
ImGui : : Separator ( ) ;
TextFocused ( " Host info: " , m_worker . GetHostInfo ( ) . c_str ( ) ) ;
2018-08-20 00:23:29 +00:00
auto & crash = m_worker . GetCrashEvent ( ) ;
if ( crash . thread ! = 0 )
{
ImGui : : Separator ( ) ;
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , ICON_FA_SKULL " Application has crashed. " ICON_FA_SKULL ) ;
2018-08-20 00:23:29 +00:00
# else
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.2f , 0.2f , 1.f ) , " Application has crashed. " ) ;
2018-08-20 00:23:29 +00:00
# endif
TextFocused ( " Time of crash: " , TimeToString ( crash . time - m_worker . GetTimeBegin ( ) ) ) ;
TextFocused ( " Thread: " , m_worker . GetThreadString ( crash . thread ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , crash . thread ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Reason: " ) ;
2018-08-20 00:23:29 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextWrapped ( " %s " , m_worker . GetString ( crash . message ) ) ;
2019-03-24 22:55:38 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_MICROSCOPE " Focus " ) )
# else
if ( ImGui : : Button ( " Focus " ) )
# endif
{
CenterAtTime ( crash . time ) ;
}
2018-08-20 00:23:29 +00:00
if ( crash . callstack ! = 0 )
{
2019-03-24 22:55:38 +00:00
ImGui : : SameLine ( ) ;
2018-08-20 00:23:29 +00:00
bool hilite = m_callstackInfoWindow = = crash . callstack ;
if ( hilite )
{
2018-12-18 15:28:09 +00:00
SetButtonHighlightColor ( ) ;
2018-08-20 00:23:29 +00:00
}
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_ALIGN_JUSTIFY " Call stack " ) )
# else
if ( ImGui : : Button ( " Call stack " ) )
# endif
{
m_callstackInfoWindow = crash . callstack ;
}
if ( hilite )
{
ImGui : : PopStyleColor ( 3 ) ;
}
if ( ImGui : : IsItemHovered ( ) )
{
CallstackTooltip ( crash . callstack ) ;
}
}
}
2018-08-08 17:25:13 +00:00
ImGui : : End ( ) ;
}
2018-08-17 13:33:12 +00:00
void View : : DrawTextEditor ( )
{
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 700 , 800 ) , ImGuiCond_FirstUseEver ) ;
2018-08-17 13:33:12 +00:00
bool show = true ;
ImGui : : Begin ( " Source view " , & show ) ;
2018-08-17 15:57:13 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 1.f , 0.2f , 1.f ) , ICON_FA_EXCLAMATION_TRIANGLE ) ;
2018-08-17 15:57:13 +00:00
# else
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 1.f , 0.2f , 1.f ) , " /! \\ " ) ;
2018-08-17 15:57:13 +00:00
# endif
2018-08-17 15:08:16 +00:00
ImGui : : SameLine ( ) ;
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 0.3f , 0.3f , 1.f ) , " The source file contents might not reflect the actual profiled code! " ) ;
2018-08-17 15:08:16 +00:00
ImGui : : SameLine ( ) ;
2018-08-17 15:57:13 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 1.f , 0.2f , 1.f ) , ICON_FA_EXCLAMATION_TRIANGLE ) ;
2018-08-17 15:57:13 +00:00
# else
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 1.f , 1.f , 0.2f , 1.f ) , " /! \\ " ) ;
2018-08-17 15:57:13 +00:00
# endif
2018-08-17 13:33:12 +00:00
TextFocused ( " File: " , m_textEditorFile ) ;
2019-06-22 12:55:01 +00:00
if ( SmallCheckbox ( " Show whitespace " , & m_textEditorWhitespace ) )
2019-06-22 12:24:39 +00:00
{
m_textEditor - > SetShowWhitespaces ( m_textEditorWhitespace ) ;
}
2018-08-17 13:33:12 +00:00
if ( m_textEditorFont ) ImGui : : PushFont ( m_textEditorFont ) ;
m_textEditor - > Render ( m_textEditorFile , ImVec2 ( ) , true ) ;
if ( m_textEditorFont ) ImGui : : PopFont ( ) ;
ImGui : : End ( ) ;
if ( ! show ) m_textEditorFile = nullptr ;
}
2018-10-21 15:36:27 +00:00
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 ) ) ;
2019-06-16 23:13:32 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_CROSSHAIRS " Go to " ) )
# else
2018-10-21 15:36:27 +00:00
if ( ImGui : : Button ( " Go to " ) )
2019-06-16 23:13:32 +00:00
# endif
2018-10-21 15:36:27 +00:00
{
ZoomToRange ( m_worker . GetFrameBegin ( * m_frames , frameNum - frameOffset ) , m_worker . GetFrameEnd ( * m_frames , frameNum - frameOffset ) ) ;
}
ImGui : : End ( ) ;
}
2018-12-16 18:58:11 +00:00
void View : : DrawLockInfoWindow ( )
{
auto it = m_worker . GetLockMap ( ) . find ( m_lockInfoWindow ) ;
assert ( it ! = m_worker . GetLockMap ( ) . end ( ) ) ;
2019-03-16 01:09:50 +00:00
const auto & lock = * it - > second ;
2018-12-16 18:58:11 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( lock . srcloc ) ;
auto fileName = m_worker . GetString ( srcloc . file ) ;
2018-12-16 20:01:46 +00:00
int64_t timeAnnounce = lock . timeAnnounce ;
int64_t timeTerminate = lock . timeTerminate ;
if ( ! lock . timeline . empty ( ) )
{
if ( timeAnnounce = = 0 )
{
2019-03-16 13:18:43 +00:00
timeAnnounce = lock . timeline . front ( ) . ptr - > time ;
2018-12-16 20:01:46 +00:00
}
if ( timeTerminate = = 0 )
{
2019-03-16 13:18:43 +00:00
timeTerminate = lock . timeline . back ( ) . ptr - > time ;
2018-12-16 20:01:46 +00:00
}
}
2018-12-19 17:28:48 +00:00
bool waitState = false ;
bool holdState = false ;
int64_t waitStartTime = 0 ;
int64_t holdStartTime = 0 ;
int64_t waitTotalTime = 0 ;
int64_t holdTotalTime = 0 ;
2018-12-19 17:34:53 +00:00
uint32_t maxWaitingThreads = 0 ;
2018-12-19 17:28:48 +00:00
for ( auto & v : lock . timeline )
{
if ( holdState )
{
2019-03-16 13:18:43 +00:00
if ( v . lockCount = = 0 )
2018-12-19 17:28:48 +00:00
{
2019-03-16 13:18:43 +00:00
holdTotalTime + = v . ptr - > time - holdStartTime ;
2018-12-19 17:28:48 +00:00
holdState = false ;
}
}
else
{
2019-03-16 13:18:43 +00:00
if ( v . lockCount ! = 0 )
2018-12-19 17:28:48 +00:00
{
2019-03-16 13:18:43 +00:00
holdStartTime = v . ptr - > time ;
2018-12-19 17:28:48 +00:00
holdState = true ;
}
}
if ( waitState )
{
2019-03-16 13:18:43 +00:00
if ( v . waitList = = 0 )
2018-12-19 17:28:48 +00:00
{
2019-03-16 13:18:43 +00:00
waitTotalTime + = v . ptr - > time - waitStartTime ;
2018-12-19 17:28:48 +00:00
waitState = false ;
}
2018-12-19 17:34:53 +00:00
else
{
2019-03-16 13:18:43 +00:00
maxWaitingThreads = std : : max < uint32_t > ( maxWaitingThreads , TracyCountBits ( v . waitList ) ) ;
2018-12-19 17:34:53 +00:00
}
2018-12-19 17:28:48 +00:00
}
else
{
2019-03-16 13:18:43 +00:00
if ( v . waitList ! = 0 )
2018-12-19 17:28:48 +00:00
{
2019-03-16 13:18:43 +00:00
waitStartTime = v . ptr - > time ;
2018-12-19 17:28:48 +00:00
waitState = true ;
2019-03-16 13:18:43 +00:00
maxWaitingThreads = std : : max < uint32_t > ( maxWaitingThreads , TracyCountBits ( v . waitList ) ) ;
2018-12-19 17:28:48 +00:00
}
}
}
2018-12-16 18:58:11 +00:00
bool visible = true ;
ImGui : : Begin ( " Lock info " , & visible , ImGuiWindowFlags_AlwaysAutoResize ) ;
ImGui : : Text ( " Lock #% " PRIu32 " : %s " , m_lockInfoWindow , m_worker . GetString ( srcloc . function ) ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Location: " ) ;
2018-12-16 18:58:11 +00:00
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 ) ;
}
}
2018-12-16 20:01:46 +00:00
ImGui : : Separator ( ) ;
2018-12-19 17:28:48 +00:00
2018-12-16 18:58:11 +00:00
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 ( ) ;
2018-12-19 17:28:48 +00:00
const auto announce = timeAnnounce - m_worker . GetTimeBegin ( ) ;
const auto terminate = timeTerminate - m_worker . GetTimeBegin ( ) ;
const auto lifetime = timeTerminate - timeAnnounce ;
2019-02-24 16:44:44 +00:00
const auto traceLen = m_worker . GetLastTime ( ) - m_worker . GetTimeBegin ( ) ;
2018-12-19 17:28:48 +00:00
TextFocused ( " Announce time: " , TimeToString ( announce ) ) ;
TextFocused ( " Terminate time: " , TimeToString ( terminate ) ) ;
TextFocused ( " Lifetime: " , TimeToString ( lifetime ) ) ;
2019-02-24 16:44:44 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%% of trace time) " , lifetime / double ( traceLen ) * 100 ) ;
2018-12-19 17:28:48 +00:00
ImGui : : Separator ( ) ;
TextFocused ( " Lock hold time: " , TimeToString ( holdTotalTime ) ) ;
ImGui : : SameLine ( ) ;
2019-02-24 16:44:44 +00:00
ImGui : : TextDisabled ( " (%.2f%% of lock lifetime) " , holdTotalTime / float ( lifetime ) * 100.f ) ;
2018-12-19 17:28:48 +00:00
TextFocused ( " Lock wait time: " , TimeToString ( waitTotalTime ) ) ;
ImGui : : SameLine ( ) ;
2019-02-24 16:44:44 +00:00
ImGui : : TextDisabled ( " (%.2f%% of lock lifetime) " , waitTotalTime / float ( lifetime ) * 100.f ) ;
2018-12-19 17:34:53 +00:00
TextFocused ( " Max waiting threads: " , RealToString ( maxWaitingThreads , true ) ) ;
2018-12-19 17:28:48 +00:00
ImGui : : Separator ( ) ;
2018-12-16 18:58:11 +00:00
const auto threadList = ImGui : : TreeNode ( " Thread list " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , lock . threadList . size ( ) ) ;
if ( threadList )
{
for ( const auto & t : lock . threadList )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetThreadString ( t ) ) ;
2018-12-16 18:58:11 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , t ) ;
}
ImGui : : TreePop ( ) ;
}
ImGui : : End ( ) ;
if ( ! visible ) m_lockInfoWindow = InvalidId ;
}
2019-06-12 22:12:06 +00:00
void View : : SetPlaybackFrame ( uint32_t idx )
{
const auto frameSet = m_worker . GetFramesBase ( ) ;
const auto & frameImages = m_worker . GetFrameImages ( ) ;
assert ( idx < frameImages . size ( ) ) ;
m_playback . frame = idx ;
if ( idx = = frameImages . size ( ) - 1 )
{
m_playback . pause = true ;
}
else
{
const auto t0 = m_worker . GetFrameBegin ( * frameSet , frameImages [ idx ] - > frameRef ) ;
const auto t1 = m_worker . GetFrameBegin ( * frameSet , frameImages [ idx + 1 ] - > frameRef ) ;
m_playback . timeLeft = ( t1 - t0 ) / 1000000000.f ;
}
}
2019-06-11 23:26:49 +00:00
static const char * PlaybackWindowButtons [ ] = {
# ifdef TRACY_EXTENDED_FONT
ICON_FA_PLAY " Play " ,
ICON_FA_PAUSE " Pause " ,
# else
" Play " ,
" Pause " ,
# endif
} ;
enum { PlaybackWindowButtonsCount = sizeof ( PlaybackWindowButtons ) / sizeof ( * PlaybackWindowButtons ) } ;
void View : : DrawPlayback ( )
{
const auto frameSet = m_worker . GetFramesBase ( ) ;
const auto & frameImages = m_worker . GetFrameImages ( ) ;
const auto fi = frameImages [ m_playback . frame ] ;
const auto ficnt = m_worker . GetFrameImageCount ( ) ;
const auto tstart = m_worker . GetFrameBegin ( * frameSet , fi - > frameRef ) ;
if ( ! m_playback . texture )
{
m_playback . texture = MakeTexture ( ) ;
}
if ( m_playback . currFrame ! = m_playback . frame )
{
m_playback . currFrame = m_playback . frame ;
UpdateTexture ( m_playback . texture , m_worker . UnpackFrameImage ( * fi ) , fi - > w , fi - > h ) ;
if ( m_playback . sync )
{
const auto end = m_worker . GetFrameEnd ( * frameSet , fi - > frameRef ) ;
2019-06-12 11:25:45 +00:00
m_zoomAnim . active = false ;
m_zvStart = tstart ;
m_zvEnd = end ;
2019-06-11 23:26:49 +00:00
}
}
2019-06-12 22:12:06 +00:00
if ( ! m_playback . pause )
2019-06-11 23:26:49 +00:00
{
2019-06-12 22:12:06 +00:00
auto time = ImGui : : GetIO ( ) . DeltaTime * m_playback . speed ;
while ( ! m_playback . pause & & time > 0 )
2019-06-11 23:26:49 +00:00
{
2019-06-12 22:12:06 +00:00
const auto dt = std : : min ( time , m_playback . timeLeft ) ;
time - = dt ;
m_playback . timeLeft - = dt ;
if ( m_playback . timeLeft = = 0 )
{
SetPlaybackFrame ( m_playback . frame + 1 ) ;
}
2019-06-11 23:26:49 +00:00
}
}
ImGui : : Begin ( " Playback " , & m_showPlayback , ImGuiWindowFlags_AlwaysAutoResize ) ;
2019-06-12 13:30:08 +00:00
if ( fi - > flip )
{
ImGui : : Image ( m_playback . texture , ImVec2 ( fi - > w , fi - > h ) , ImVec2 ( 0 , 1 ) , ImVec2 ( 1 , 0 ) ) ;
}
else
{
ImGui : : Image ( m_playback . texture , ImVec2 ( fi - > w , fi - > h ) ) ;
}
2019-06-11 23:26:49 +00:00
int tmp = m_playback . frame + 1 ;
if ( ImGui : : SliderInt ( " Frame image " , & tmp , 1 , ficnt , " %d " ) )
{
if ( tmp < 1 ) tmp = 1 ;
2019-06-22 12:15:25 +00:00
else if ( ( uint32_t ) tmp > ficnt ) tmp = ficnt ;
SetPlaybackFrame ( uint32_t ( tmp - 1 ) ) ;
2019-06-11 23:26:49 +00:00
}
2019-06-12 22:12:06 +00:00
ImGui : : SliderFloat ( " Playback speed " , & m_playback . speed , 0.1f , 4 , " %.2f " ) ;
2019-06-11 23:26:49 +00:00
const auto th = ImGui : : GetTextLineHeight ( ) ;
float bw = 0 ;
for ( int i = 0 ; i < PlaybackWindowButtonsCount ; i + + )
{
bw = std : : max ( bw , ImGui : : CalcTextSize ( PlaybackWindowButtons [ i ] ) . x ) ;
}
bw + = th ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( " " ICON_FA_CARET_LEFT " " ) )
# else
if ( ImGui : : Button ( " < " ) )
# endif
{
if ( m_playback . frame > 0 )
{
2019-06-12 22:12:06 +00:00
SetPlaybackFrame ( m_playback . frame - 1 ) ;
2019-06-11 23:26:49 +00:00
m_playback . pause = true ;
}
}
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( " " ICON_FA_CARET_RIGHT " " ) )
# else
if ( ImGui : : Button ( " > " ) )
# endif
{
if ( m_playback . frame < ficnt - 1 )
{
2019-06-12 22:12:06 +00:00
SetPlaybackFrame ( m_playback . frame + 1 ) ;
2019-06-11 23:26:49 +00:00
m_playback . pause = true ;
}
}
ImGui : : SameLine ( ) ;
if ( m_playback . pause )
{
2019-06-12 22:12:06 +00:00
if ( ImGui : : Button ( PlaybackWindowButtons [ 0 ] , ImVec2 ( bw , 0 ) ) & & m_playback . frame ! = frameImages . size ( ) - 1 )
2019-06-11 23:26:49 +00:00
{
m_playback . pause = false ;
}
}
else
{
if ( ImGui : : Button ( PlaybackWindowButtons [ 1 ] , ImVec2 ( bw , 0 ) ) )
{
m_playback . pause = true ;
}
}
ImGui : : SameLine ( ) ;
2019-06-12 21:46:14 +00:00
if ( ImGui : : Checkbox ( " Sync timeline " , & m_playback . sync ) )
2019-06-11 23:26:49 +00:00
{
if ( m_playback . sync )
{
2019-06-21 11:08:41 +00:00
m_zvStart = m_worker . GetFrameBegin ( * frameSet , fi - > frameRef ) ;
m_zvEnd = m_worker . GetFrameEnd ( * frameSet , fi - > frameRef ) ;
2019-06-11 23:26:49 +00:00
}
}
TextFocused ( " Timestamp: " , TimeToString ( tstart - m_worker . GetTimeBegin ( ) ) ) ;
ImGui : : End ( ) ;
}
2018-04-02 00:19:46 +00:00
template < class T >
2019-03-17 15:47:44 +00:00
void View : : ListMemData ( T ptr , T end , std : : function < void ( T & ) > DrawAddress , const char * id , int64_t startTime )
2018-04-02 00:19:46 +00:00
{
2019-03-17 15:47:44 +00:00
if ( startTime = = - 1 ) startTime = m_worker . GetTimeBegin ( ) ;
2018-05-02 17:40:35 +00:00
const auto & style = ImGui : : GetStyle ( ) ;
const auto dist = std : : distance ( ptr , end ) + 1 ;
const auto ty = ImGui : : GetTextLineHeight ( ) + style . ItemSpacing . y ;
2018-06-21 22:10:00 +00:00
ImGui : : BeginChild ( id ? id : " ##memScroll " , ImVec2 ( 0 , std : : max ( ty * std : : min < int64_t > ( dist , 5 ) , std : : min ( ty * dist , ImGui : : GetContentRegionAvail ( ) . y ) ) ) ) ;
2018-06-19 20:19:33 +00:00
ImGui : : Columns ( 8 ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Address " ) ;
2018-07-17 21:08:10 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Click on address to display memory allocation info window. \n Middle click to zoom to allocation range. " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Size " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Appeared at " ) ;
2018-06-22 18:32:38 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Click on entry to center timeline at the memory allocation time. " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Duration " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Active allocations are displayed using green color. \n Click on entry to center timeline at the memory release time. " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Thread " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Shows one thread if alloc and free was performed on the same thread. \n Otherwise two threads are displayed in order: alloc, free. " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Zone alloc " ) ;
2018-04-02 12:29:56 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Zone free " ) ;
2018-04-02 12:36:07 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " If alloc and free is performed in the same zone, it is displayed in yellow color. " ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Call stack " ) ;
2018-06-19 20:19:33 +00:00
ImGui : : NextColumn ( ) ;
2018-04-02 00:19:46 +00:00
ImGui : : Separator ( ) ;
2018-07-17 21:08:10 +00:00
const auto & mem = m_worker . GetMemData ( ) ;
2018-04-02 00:19:46 +00:00
int idx = 0 ;
while ( ptr ! = end )
{
2018-07-17 21:13:56 +00:00
auto v = * ptr ;
2018-07-17 21:17:46 +00:00
const auto arrIdx = std : : distance ( mem . data . begin ( ) , v ) ;
if ( m_memoryAllocInfoWindow = = arrIdx )
{
ImGui : : PushStyleColor ( ImGuiCol_Text , ImVec4 ( 1.f , 0.f , 0.f , 1.f ) ) ;
DrawAddress ( ptr ) ;
ImGui : : PopStyleColor ( ) ;
}
else
2018-07-17 21:08:10 +00:00
{
2018-07-17 21:17:46 +00:00
DrawAddress ( ptr ) ;
if ( ImGui : : IsItemClicked ( ) )
{
m_memoryAllocInfoWindow = arrIdx ;
}
2018-10-05 19:13:31 +00:00
}
if ( ImGui : : IsItemClicked ( 2 ) )
{
ZoomToRange ( v - > timeAlloc , v - > timeFree > = 0 ? v - > timeFree : m_worker . GetLastTime ( ) ) ;
2018-07-17 21:08:10 +00:00
}
2018-07-19 13:55:15 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
m_memoryAllocHover = arrIdx ;
m_memoryAllocHoverWait = 2 ;
}
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( MemSizeToString ( v - > size ) ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2018-06-22 18:32:38 +00:00
ImGui : : PushID ( idx + + ) ;
2019-03-17 15:47:44 +00:00
if ( ImGui : : Selectable ( TimeToString ( v - > timeAlloc - startTime ) ) )
2018-06-22 18:32:38 +00:00
{
CenterAtTime ( v - > timeAlloc ) ;
}
ImGui : : PopID ( ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
if ( v - > timeFree < 0 )
{
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0.6f , 1.f , 0.6f , 1.f ) , TimeToString ( m_worker . GetLastTime ( ) - v - > timeAlloc ) ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetThreadString ( m_worker . DecompressThread ( v - > threadAlloc ) ) ) ;
2018-04-02 00:19:46 +00:00
}
else
{
2018-06-22 18:32:38 +00:00
ImGui : : PushID ( idx + + ) ;
if ( ImGui : : Selectable ( TimeToString ( v - > timeFree - v - > timeAlloc ) ) )
{
CenterAtTime ( v - > timeFree ) ;
}
ImGui : : PopID ( ) ;
2018-04-02 00:19:46 +00:00
ImGui : : NextColumn ( ) ;
2018-05-02 17:07:34 +00:00
if ( v - > threadAlloc = = v - > threadFree )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetThreadString ( m_worker . DecompressThread ( v - > threadAlloc ) ) ) ;
2018-05-02 17:07:34 +00:00
}
else
2018-04-02 00:19:46 +00:00
{
2018-05-02 17:07:34 +00:00
ImGui : : Text ( " %s / %s " , m_worker . GetThreadString ( m_worker . DecompressThread ( v - > threadAlloc ) ) , m_worker . GetThreadString ( m_worker . DecompressThread ( v - > threadFree ) ) ) ;
2018-04-02 00:19:46 +00:00
}
}
ImGui : : NextColumn ( ) ;
auto zone = FindZoneAtTime ( m_worker . DecompressThread ( v - > threadAlloc ) , v - > timeAlloc ) ;
if ( ! zone )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " - " ) ;
2018-04-02 00:19:46 +00:00
}
else
{
const auto & srcloc = m_worker . GetSourceLocation ( zone - > srcloc ) ;
const auto txt = srcloc . name . active ? m_worker . GetString ( srcloc . name ) : m_worker . GetString ( srcloc . function ) ;
ImGui : : PushID ( idx + + ) ;
2018-04-02 12:38:08 +00:00
auto sel = ImGui : : Selectable ( txt , m_zoneInfoWindow = = zone ) ;
2018-04-02 00:19:46 +00:00
auto hover = ImGui : : IsItemHovered ( ) ;
ImGui : : PopID ( ) ;
if ( sel )
{
2018-05-02 17:23:46 +00:00
ShowZoneInfo ( * zone ) ;
2018-04-02 00:19:46 +00:00
}
if ( hover )
{
m_zoneHighlight = zone ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * zone ) ;
}
ZoneTooltip ( * zone ) ;
}
}
ImGui : : NextColumn ( ) ;
2018-04-02 12:29:56 +00:00
if ( v - > timeFree < 0 )
{
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0.6f , 1.f , 0.6f , 1.f ) , " active " ) ;
2018-04-02 12:29:56 +00:00
}
else
{
2018-04-02 12:36:07 +00:00
auto zoneFree = FindZoneAtTime ( m_worker . DecompressThread ( v - > threadFree ) , v - > timeFree ) ;
if ( ! zoneFree )
2018-04-02 12:29:56 +00:00
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " - " ) ;
2018-04-02 12:29:56 +00:00
}
else
{
2018-04-02 12:36:07 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( zoneFree - > srcloc ) ;
2018-04-02 12:29:56 +00:00
const auto txt = srcloc . name . active ? m_worker . GetString ( srcloc . name ) : m_worker . GetString ( srcloc . function ) ;
ImGui : : PushID ( idx + + ) ;
2018-04-02 12:36:07 +00:00
bool sel ;
if ( zoneFree = = zone )
{
2018-06-20 12:44:24 +00:00
ImGui : : PushStyleColor ( ImGuiCol_Text , ImVec4 ( 1.f , 1.f , 0.6f , 1.f ) ) ;
sel = ImGui : : Selectable ( txt , m_zoneInfoWindow = = zoneFree ) ;
ImGui : : PopStyleColor ( 1 ) ;
2018-04-02 12:36:07 +00:00
}
else
{
2018-04-02 12:38:08 +00:00
sel = ImGui : : Selectable ( txt , m_zoneInfoWindow = = zoneFree ) ;
2018-04-02 12:36:07 +00:00
}
2018-04-02 12:29:56 +00:00
auto hover = ImGui : : IsItemHovered ( ) ;
ImGui : : PopID ( ) ;
if ( sel )
{
2018-05-02 17:23:46 +00:00
ShowZoneInfo ( * zoneFree ) ;
2018-04-02 12:29:56 +00:00
}
if ( hover )
{
2018-04-02 12:36:07 +00:00
m_zoneHighlight = zoneFree ;
2018-04-02 12:29:56 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
{
2018-04-02 12:36:07 +00:00
ZoomToZone ( * zoneFree ) ;
2018-04-02 12:29:56 +00:00
}
2018-04-02 12:36:07 +00:00
ZoneTooltip ( * zoneFree ) ;
2018-04-02 12:29:56 +00:00
}
}
}
ImGui : : NextColumn ( ) ;
2018-06-19 20:19:33 +00:00
if ( v - > csAlloc = = 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " [alloc] " ) ;
2018-06-19 20:19:33 +00:00
}
else
{
2018-07-17 20:53:38 +00:00
SmallCallstackButton ( " alloc " , v - > csAlloc , idx ) ;
2018-06-19 20:19:33 +00:00
}
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
if ( v - > csFree = = 0 )
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " [free] " ) ;
2018-06-19 20:19:33 +00:00
}
else
{
2018-07-17 20:53:38 +00:00
SmallCallstackButton ( " free " , v - > csFree , idx ) ;
2018-06-19 20:19:33 +00:00
}
ImGui : : NextColumn ( ) ;
2018-04-02 00:19:46 +00:00
ptr + + ;
}
ImGui : : EndColumns ( ) ;
2018-04-02 12:44:45 +00:00
ImGui : : EndChild ( ) ;
2018-04-02 00:19:46 +00:00
}
2019-04-03 14:24:16 +00:00
static tracy_force_inline CallstackFrameTree * GetFrameTreeItemNoGroup ( flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > & tree , CallstackFrameId idx , const Worker & worker )
2018-08-14 16:37:06 +00:00
{
2019-04-03 14:24:16 +00:00
auto it = tree . find ( idx . data ) ;
2018-08-14 16:37:06 +00:00
if ( it = = tree . end ( ) )
{
2019-04-03 14:24:16 +00:00
it = tree . emplace ( idx . data , CallstackFrameTree { idx } ) . first ;
2018-08-14 16:37:06 +00:00
}
2019-04-03 14:24:16 +00:00
return & it - > second ;
}
static tracy_force_inline CallstackFrameTree * GetFrameTreeItemGroup ( flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > & tree , CallstackFrameId idx , const Worker & worker )
{
auto & frameData = * worker . GetCallstackFrame ( idx ) ;
auto & frame = frameData . data [ frameData . size - 1 ] ;
auto fidx = frame . name . idx ;
auto it = tree . find ( fidx ) ;
if ( it = = tree . end ( ) )
2018-08-14 16:37:06 +00:00
{
2019-04-03 14:24:16 +00:00
it = tree . emplace ( fidx , CallstackFrameTree { idx } ) . first ;
2018-08-14 16:37:06 +00:00
}
2019-04-03 14:24:16 +00:00
return & it - > second ;
2018-08-14 16:37:06 +00:00
}
2019-05-09 11:37:28 +00:00
flat_hash_map < uint32_t , View : : PathData , nohash < uint32_t > > View : : GetCallstackPaths ( const MemData & mem , bool onlyActive ) const
2018-08-14 16:37:06 +00:00
{
2018-08-19 14:34:26 +00:00
flat_hash_map < uint32_t , PathData , nohash < uint32_t > > pathSum ;
pathSum . reserve ( m_worker . GetCallstackPayloadCount ( ) ) ;
2018-08-18 17:13:46 +00:00
2018-08-18 17:44:29 +00:00
const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2 ;
2019-05-09 11:37:28 +00:00
if ( m_memInfo . restrictTime )
2018-08-14 16:37:06 +00:00
{
2019-05-09 11:37:28 +00:00
for ( auto & ev : mem . data )
2018-08-18 17:13:46 +00:00
{
2019-05-09 11:37:28 +00:00
if ( ev . csAlloc = = 0 ) continue ;
if ( ev . timeAlloc > = zvMid ) continue ;
if ( onlyActive & & ev . timeFree > = 0 & & ev . timeFree < zvMid ) continue ;
auto it = pathSum . find ( ev . csAlloc ) ;
if ( it = = pathSum . end ( ) )
{
pathSum . emplace ( ev . csAlloc , PathData { 1 , ev . size } ) ;
}
else
{
it - > second . cnt + + ;
it - > second . mem + = ev . size ;
}
2018-08-18 17:13:46 +00:00
}
2019-05-09 11:37:28 +00:00
}
else
{
for ( auto & ev : mem . data )
2018-08-14 16:37:06 +00:00
{
2019-05-09 11:37:28 +00:00
if ( ev . csAlloc = = 0 ) continue ;
if ( onlyActive & & ev . timeFree > = 0 ) continue ;
auto it = pathSum . find ( ev . csAlloc ) ;
if ( it = = pathSum . end ( ) )
{
pathSum . emplace ( ev . csAlloc , PathData { 1 , ev . size } ) ;
}
else
{
it - > second . cnt + + ;
it - > second . mem + = ev . size ;
}
2018-08-19 14:34:26 +00:00
}
}
2019-02-06 12:46:50 +00:00
return pathSum ;
}
2018-08-14 16:37:06 +00:00
2019-04-03 14:24:16 +00:00
flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > View : : GetCallstackFrameTreeBottomUp ( const MemData & mem ) const
2019-02-06 12:46:50 +00:00
{
2019-04-03 14:24:16 +00:00
flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > root ;
2019-05-09 11:37:28 +00:00
auto pathSum = GetCallstackPaths ( mem , m_activeOnlyBottomUp ) ;
2019-04-03 14:24:16 +00:00
if ( m_groupCallstackTreeByNameBottomUp )
2018-08-19 14:34:26 +00:00
{
2019-04-03 14:24:16 +00:00
for ( auto & path : pathSum )
{
auto & cs = m_worker . GetCallstack ( path . first ) ;
2018-08-18 17:13:46 +00:00
2019-04-03 14:24:16 +00:00
auto base = cs . back ( ) ;
auto treePtr = GetFrameTreeItemGroup ( root , base , m_worker ) ;
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
treePtr - > callstacks . emplace ( path . first ) ;
2018-08-18 17:13:46 +00:00
2019-04-03 14:24:16 +00:00
for ( int i = int ( cs . size ( ) ) - 2 ; i > = 0 ; i - - )
{
treePtr = GetFrameTreeItemGroup ( treePtr - > children , cs [ i ] , m_worker ) ;
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
treePtr - > callstacks . emplace ( path . first ) ;
}
}
}
else
{
for ( auto & path : pathSum )
2018-08-19 14:34:26 +00:00
{
2019-04-03 14:24:16 +00:00
auto & cs = m_worker . GetCallstack ( path . first ) ;
auto base = cs . back ( ) ;
auto treePtr = GetFrameTreeItemNoGroup ( root , base , m_worker ) ;
2019-02-06 21:36:21 +00:00
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
2018-09-27 20:56:44 +00:00
treePtr - > callstacks . emplace ( path . first ) ;
2019-04-03 14:24:16 +00:00
for ( int i = int ( cs . size ( ) ) - 2 ; i > = 0 ; i - - )
{
treePtr = GetFrameTreeItemNoGroup ( treePtr - > children , cs [ i ] , m_worker ) ;
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
treePtr - > callstacks . emplace ( path . first ) ;
}
2018-08-18 17:13:46 +00:00
}
2018-08-14 16:37:06 +00:00
}
2019-04-03 14:24:16 +00:00
2018-08-14 16:37:06 +00:00
return root ;
}
2019-04-03 14:24:16 +00:00
flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > View : : GetCallstackFrameTreeTopDown ( const MemData & mem ) const
2019-02-06 12:53:14 +00:00
{
2019-04-03 14:24:16 +00:00
flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > root ;
2019-05-09 11:37:28 +00:00
auto pathSum = GetCallstackPaths ( mem , m_activeOnlyTopDown ) ;
2019-04-03 14:24:16 +00:00
if ( m_groupCallstackTreeByNameTopDown )
2019-02-06 12:53:14 +00:00
{
2019-04-03 14:24:16 +00:00
for ( auto & path : pathSum )
{
auto & cs = m_worker . GetCallstack ( path . first ) ;
2019-02-06 12:53:14 +00:00
2019-04-03 14:24:16 +00:00
auto base = cs . front ( ) ;
auto treePtr = GetFrameTreeItemGroup ( root , base , m_worker ) ;
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
treePtr - > callstacks . emplace ( path . first ) ;
2019-02-06 12:53:14 +00:00
2019-04-03 14:24:16 +00:00
for ( int i = 1 ; i < cs . size ( ) ; i + + )
{
treePtr = GetFrameTreeItemGroup ( treePtr - > children , cs [ i ] , m_worker ) ;
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
treePtr - > callstacks . emplace ( path . first ) ;
}
}
}
else
{
for ( auto & path : pathSum )
2019-02-06 12:53:14 +00:00
{
2019-04-03 14:24:16 +00:00
auto & cs = m_worker . GetCallstack ( path . first ) ;
auto base = cs . front ( ) ;
auto treePtr = GetFrameTreeItemNoGroup ( root , base , m_worker ) ;
2019-02-06 21:36:21 +00:00
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
2019-02-06 12:53:14 +00:00
treePtr - > callstacks . emplace ( path . first ) ;
2019-04-03 14:24:16 +00:00
for ( int i = 1 ; i < cs . size ( ) ; i + + )
{
treePtr = GetFrameTreeItemNoGroup ( treePtr - > children , cs [ i ] , m_worker ) ;
treePtr - > count + = path . second . cnt ;
treePtr - > alloc + = path . second . mem ;
treePtr - > callstacks . emplace ( path . first ) ;
}
2019-02-06 12:53:14 +00:00
}
}
return root ;
}
2018-08-14 16:37:06 +00:00
2018-04-02 16:40:59 +00:00
enum { ChunkBits = 10 } ;
enum { PageBits = 10 } ;
2018-04-02 17:57:46 +00:00
enum { PageSize = 1 < < PageBits } ;
2018-04-02 16:40:59 +00:00
enum { PageChunkBits = ChunkBits + PageBits } ;
2018-04-02 17:57:46 +00:00
enum { PageChunkSize = 1 < < PageChunkBits } ;
2018-04-02 16:40:59 +00:00
2018-04-04 20:24:38 +00:00
uint32_t MemDecayColor [ 256 ] = {
0x0 , 0xFF077F07 , 0xFF078007 , 0xFF078207 , 0xFF078307 , 0xFF078507 , 0xFF078707 , 0xFF078807 ,
0xFF078A07 , 0xFF078B07 , 0xFF078D07 , 0xFF078F07 , 0xFF079007 , 0xFF089208 , 0xFF089308 , 0xFF089508 ,
0xFF089708 , 0xFF089808 , 0xFF089A08 , 0xFF089B08 , 0xFF089D08 , 0xFF089F08 , 0xFF08A008 , 0xFF08A208 ,
0xFF09A309 , 0xFF09A509 , 0xFF09A709 , 0xFF09A809 , 0xFF09AA09 , 0xFF09AB09 , 0xFF09AD09 , 0xFF09AF09 ,
0xFF09B009 , 0xFF09B209 , 0xFF09B309 , 0xFF09B509 , 0xFF0AB70A , 0xFF0AB80A , 0xFF0ABA0A , 0xFF0ABB0A ,
0xFF0ABD0A , 0xFF0ABF0A , 0xFF0AC00A , 0xFF0AC20A , 0xFF0AC30A , 0xFF0AC50A , 0xFF0AC70A , 0xFF0BC80B ,
0xFF0BCA0B , 0xFF0BCB0B , 0xFF0BCD0B , 0xFF0BCF0B , 0xFF0BD00B , 0xFF0BD20B , 0xFF0BD30B , 0xFF0BD50B ,
0xFF0BD70B , 0xFF0BD80B , 0xFF0BDA0B , 0xFF0CDB0C , 0xFF0CDD0C , 0xFF0CDF0C , 0xFF0CE00C , 0xFF0CE20C ,
0xFF0CE30C , 0xFF0CE50C , 0xFF0CE70C , 0xFF0CE80C , 0xFF0CEA0C , 0xFF0CEB0C , 0xFF0DED0D , 0xFF0DEF0D ,
0xFF0DF00D , 0xFF0DF20D , 0xFF0DF30D , 0xFF0DF50D , 0xFF0DF70D , 0xFF0DF80D , 0xFF0DFA0D , 0xFF0DFB0D ,
0xFF0DFD0D , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E ,
0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0EFF0E , 0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F ,
0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F , 0xFF0FFF0F ,
0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 ,
0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF10FF10 , 0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 ,
0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 , 0xFF11FF11 , 0xFF12FF12 ,
0x0 , 0xFF1212FF , 0xFF1111FF , 0xFF1111FF , 0xFF1111FF , 0xFF1111FF , 0xFF1111FF , 0xFF1111FF ,
0xFF1111FF , 0xFF1111FF , 0xFF1111FF , 0xFF1111FF , 0xFF1111FF , 0xFF1010FF , 0xFF1010FF , 0xFF1010FF ,
0xFF1010FF , 0xFF1010FF , 0xFF1010FF , 0xFF1010FF , 0xFF1010FF , 0xFF1010FF , 0xFF1010FF , 0xFF1010FF ,
0xFF1010FF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF ,
0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0F0FFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF ,
0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF , 0xFF0E0EFF ,
0xFF0D0DFD , 0xFF0D0DFB , 0xFF0D0DFA , 0xFF0D0DF8 , 0xFF0D0DF7 , 0xFF0D0DF5 , 0xFF0D0DF3 , 0xFF0D0DF2 ,
0xFF0D0DF0 , 0xFF0D0DEF , 0xFF0D0DED , 0xFF0C0CEB , 0xFF0C0CEA , 0xFF0C0CE8 , 0xFF0C0CE7 , 0xFF0C0CE5 ,
0xFF0C0CE3 , 0xFF0C0CE2 , 0xFF0C0CE0 , 0xFF0C0CDF , 0xFF0C0CDD , 0xFF0C0CDB , 0xFF0B0BDA , 0xFF0B0BD8 ,
0xFF0B0BD7 , 0xFF0B0BD5 , 0xFF0B0BD3 , 0xFF0B0BD2 , 0xFF0B0BD0 , 0xFF0B0BCF , 0xFF0B0BCD , 0xFF0B0BCB ,
0xFF0B0BCA , 0xFF0B0BC8 , 0xFF0A0AC7 , 0xFF0A0AC5 , 0xFF0A0AC3 , 0xFF0A0AC2 , 0xFF0A0AC0 , 0xFF0A0ABF ,
0xFF0A0ABD , 0xFF0A0ABB , 0xFF0A0ABA , 0xFF0A0AB8 , 0xFF0A0AB7 , 0xFF0909B5 , 0xFF0909B3 , 0xFF0909B2 ,
0xFF0909B0 , 0xFF0909AF , 0xFF0909AD , 0xFF0909AB , 0xFF0909AA , 0xFF0909A8 , 0xFF0909A7 , 0xFF0909A5 ,
0xFF0909A3 , 0xFF0808A2 , 0xFF0808A0 , 0xFF08089F , 0xFF08089D , 0xFF08089B , 0xFF08089A , 0xFF080898 ,
0xFF080897 , 0xFF080895 , 0xFF080893 , 0xFF080892 , 0xFF070790 , 0xFF07078F , 0xFF07078D , 0xFF07078B ,
0xFF07078A , 0xFF070788 , 0xFF070787 , 0xFF070785 , 0xFF070783 , 0xFF070782 , 0xFF070780 , 0xFF07077F ,
} ;
2019-05-19 11:15:54 +00:00
struct MemoryPage
2019-05-19 10:47:45 +00:00
{
2019-05-19 11:15:54 +00:00
uint64_t page ;
int8_t data [ PageSize ] ;
} ;
2019-05-19 11:45:02 +00:00
static tracy_force_inline MemoryPage & GetPage ( flat_hash_map < uint64_t , MemoryPage , nohash < uint64_t > > & memmap , uint64_t page )
2019-05-19 11:15:54 +00:00
{
auto it = memmap . find ( page ) ;
if ( it = = memmap . end ( ) )
{
it = memmap . emplace ( page , MemoryPage { page , { } } ) . first ;
}
return it - > second ;
}
2019-05-19 11:46:53 +00:00
static tracy_force_inline void FillPages ( flat_hash_map < uint64_t , MemoryPage , nohash < uint64_t > > & memmap , uint64_t c0 , uint64_t c1 , int8_t val )
2019-05-19 11:15:54 +00:00
{
auto p0 = c0 > > PageBits ;
const auto p1 = c1 > > PageBits ;
if ( p0 = = p1 )
{
const auto a0 = c0 & ( PageSize - 1 ) ;
const auto a1 = c1 & ( PageSize - 1 ) ;
auto & page = GetPage ( memmap , p0 ) ;
if ( a0 = = a1 )
{
page . data [ a0 ] = val ;
}
else
{
memset ( page . data + a0 , val , a1 - a0 + 1 ) ;
}
}
else
{
{
const auto a0 = c0 & ( PageSize - 1 ) ;
auto & page = GetPage ( memmap , p0 ) ;
memset ( page . data + a0 , val , PageSize - a0 ) ;
}
while ( + + p0 < p1 )
{
auto & page = GetPage ( memmap , p0 ) ;
memset ( page . data , val , PageSize ) ;
}
{
const auto a1 = c1 & ( PageSize - 1 ) ;
auto & page = GetPage ( memmap , p1 ) ;
memset ( page . data , val , a1 + 1 ) ;
}
}
}
std : : vector < MemoryPage > View : : GetMemoryPages ( ) const
{
std : : vector < MemoryPage > ret ;
2019-05-19 10:47:45 +00:00
2019-05-19 11:15:54 +00:00
static flat_hash_map < uint64_t , MemoryPage , nohash < uint64_t > > memmap ;
2019-05-19 10:47:45 +00:00
2019-05-19 11:15:54 +00:00
const auto & mem = m_worker . GetMemData ( ) ;
2019-05-19 10:47:45 +00:00
const auto memlow = mem . low ;
if ( m_memInfo . restrictTime )
{
const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2 ;
2019-05-19 14:26:59 +00:00
auto end = std : : upper_bound ( mem . data . begin ( ) , mem . data . end ( ) , zvMid , [ ] ( const auto & lhs , const auto & rhs ) { return lhs < rhs . timeAlloc ; } ) ;
for ( auto it = mem . data . begin ( ) ; it ! = end ; + + it )
2019-05-19 10:47:45 +00:00
{
2019-05-19 14:26:59 +00:00
auto & alloc = * it ;
2019-05-19 10:47:45 +00:00
const auto a0 = alloc . ptr - memlow ;
const auto a1 = a0 + alloc . size ;
int8_t val = alloc . timeFree < 0 ?
int8_t ( std : : max ( int64_t ( 1 ) , 127 - ( ( zvMid - alloc . timeAlloc ) > > 24 ) ) ) :
( alloc . timeFree > zvMid ?
int8_t ( std : : max ( int64_t ( 1 ) , 127 - ( ( zvMid - alloc . timeAlloc ) > > 24 ) ) ) :
int8_t ( - std : : max ( int64_t ( 1 ) , 127 - ( ( zvMid - alloc . timeFree ) > > 24 ) ) ) ) ;
const auto c0 = a0 > > ChunkBits ;
const auto c1 = a1 > > ChunkBits ;
2019-05-19 11:15:54 +00:00
FillPages ( memmap , c0 , c1 , val ) ;
2019-05-19 10:47:45 +00:00
}
}
else
{
const auto lastTime = m_worker . GetLastTime ( ) ;
for ( auto & alloc : mem . data )
{
const auto a0 = alloc . ptr - memlow ;
const auto a1 = a0 + alloc . size ;
const int8_t val = alloc . timeFree < 0 ?
int8_t ( std : : max ( int64_t ( 1 ) , 127 - ( ( lastTime - std : : min ( lastTime , alloc . timeAlloc ) ) > > 24 ) ) ) :
int8_t ( - std : : max ( int64_t ( 1 ) , 127 - ( ( lastTime - std : : min ( lastTime , alloc . timeFree ) ) > > 24 ) ) ) ;
const auto c0 = a0 > > ChunkBits ;
const auto c1 = a1 > > ChunkBits ;
2019-05-19 11:15:54 +00:00
FillPages ( memmap , c0 , c1 , val ) ;
2019-05-19 10:47:45 +00:00
}
}
2019-05-19 11:15:54 +00:00
std : : vector < flat_hash_map < uint64_t , MemoryPage , nohash < uint64_t > > : : const_iterator > itmap ;
itmap . reserve ( memmap . size ( ) ) ;
ret . reserve ( memmap . size ( ) ) ;
for ( auto it = memmap . begin ( ) ; it ! = memmap . end ( ) ; + + it ) itmap . emplace_back ( it ) ;
pdqsort_branchless ( itmap . begin ( ) , itmap . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . page < rhs - > second . page ; } ) ;
for ( auto & v : itmap ) ret . emplace_back ( v - > second ) ;
memmap . clear ( ) ;
return ret ;
2019-05-19 10:47:45 +00:00
}
2018-04-01 18:34:21 +00:00
void View : : DrawMemory ( )
{
auto & mem = m_worker . GetMemData ( ) ;
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 1100 , 500 ) , ImGuiCond_FirstUseEver ) ;
2018-04-01 19:24:30 +00:00
ImGui : : Begin ( " Memory " , & m_memInfo . show ) ;
2018-05-01 15:28:02 +00:00
if ( mem . data . empty ( ) )
{
ImGui : : TextWrapped ( " No memory data collected. " ) ;
ImGui : : End ( ) ;
return ;
}
2018-04-02 12:58:40 +00:00
ImGui : : Text ( " Total allocations: %-15s Active allocations: %-15s Memory usage: %-15s Memory span: %s " ,
RealToString ( mem . data . size ( ) , true ) ,
RealToString ( mem . active . size ( ) , true ) ,
2018-08-08 18:38:43 +00:00
MemSizeToString ( mem . usage ) ,
MemSizeToString ( mem . high - mem . low ) ) ;
2018-04-01 19:24:30 +00:00
2018-08-17 21:58:52 +00:00
# ifdef TRACY_EXTENDED_FONT
ImGui : : Checkbox ( ICON_FA_HISTORY " Restrict time " , & m_memInfo . restrictTime ) ;
# else
2018-04-02 14:07:33 +00:00
ImGui : : Checkbox ( " Restrict time " , & m_memInfo . restrictTime ) ;
2018-08-17 21:58:52 +00:00
# endif
2018-04-02 14:07:33 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " Don't show allocations beyond the middle of timeline display (it is indicated by purple line). " ) ;
2018-04-01 19:24:30 +00:00
2018-04-02 14:21:24 +00:00
const auto zvMid = m_zvStart + ( m_zvEnd - m_zvStart ) / 2 ;
2018-04-02 14:07:33 +00:00
ImGui : : Separator ( ) ;
2018-08-18 18:10:14 +00:00
# ifdef TRACY_EXTENDED_FONT
2018-08-25 13:05:05 +00:00
if ( ImGui : : TreeNode ( ICON_FA_AT " Allocations " ) )
2018-08-18 18:10:14 +00:00
# else
2018-08-25 13:05:05 +00:00
if ( ImGui : : TreeNode ( " Allocations " ) )
2018-08-18 18:10:14 +00:00
# endif
2018-04-01 19:24:30 +00:00
{
2019-03-15 00:31:06 +00:00
ImGui : : InputTextWithHint ( " ###address " , " Enter memory address to search for " , m_memInfo . pattern , 1024 ) ;
2018-08-25 13:05:05 +00:00
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_SEARCH " Find " ) )
# else
if ( ImGui : : Button ( " Find " ) )
# endif
{
m_memInfo . ptrFind = strtoull ( m_memInfo . pattern , nullptr , 0 ) ;
}
ImGui : : SameLine ( ) ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : Button ( ICON_FA_BAN " Clear " ) )
# else
if ( ImGui : : Button ( " Clear " ) )
# endif
{
m_memInfo . ptrFind = 0 ;
m_memInfo . pattern [ 0 ] = ' \0 ' ;
}
2018-04-02 14:07:33 +00:00
if ( m_memInfo . ptrFind ! = 0 )
2018-04-01 19:24:30 +00:00
{
2018-04-03 12:17:51 +00:00
std : : vector < const MemEvent * > match ;
2018-04-02 14:07:33 +00:00
match . reserve ( mem . active . size ( ) ) ; // heuristic
if ( m_memInfo . restrictTime )
2018-04-01 19:24:30 +00:00
{
2018-04-02 14:07:33 +00:00
for ( auto & v : mem . data )
{
2018-04-03 12:17:51 +00:00
if ( v . ptr < = m_memInfo . ptrFind & & v . ptr + v . size > m_memInfo . ptrFind & & v . timeAlloc < zvMid )
2018-04-02 14:07:33 +00:00
{
2018-04-03 12:17:51 +00:00
match . emplace_back ( & v ) ;
2018-04-02 14:07:33 +00:00
}
}
}
else
{
for ( auto & v : mem . data )
{
2018-04-03 12:17:51 +00:00
if ( v . ptr < = m_memInfo . ptrFind & & v . ptr + v . size > m_memInfo . ptrFind )
2018-04-02 14:07:33 +00:00
{
2018-04-03 12:17:51 +00:00
match . emplace_back ( & v ) ;
2018-04-02 14:07:33 +00:00
}
}
2018-04-01 19:24:30 +00:00
}
2018-04-02 14:07:33 +00:00
if ( match . empty ( ) )
2018-04-01 19:24:30 +00:00
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( " Found no allocations at given address " ) ;
2018-04-02 14:07:33 +00:00
}
else
{
2018-04-02 00:19:46 +00:00
ListMemData < decltype ( match . begin ( ) ) > ( match . begin ( ) , match . end ( ) , [ this ] ( auto & it ) {
auto & v = * it ;
2018-04-01 19:24:30 +00:00
if ( v - > ptr = = m_memInfo . ptrFind )
{
2018-04-01 20:00:57 +00:00
ImGui : : Text ( " 0x% " PRIx64 , m_memInfo . ptrFind ) ;
2018-04-01 19:24:30 +00:00
}
else
{
2018-04-01 20:00:57 +00:00
ImGui : : Text ( " 0x% " PRIx64 " +% " PRIu64 , v - > ptr , m_memInfo . ptrFind - v - > ptr ) ;
2018-04-01 19:24:30 +00:00
}
2018-06-21 22:10:00 +00:00
} , " ##allocations " ) ;
2018-04-01 19:24:30 +00:00
}
}
2018-04-02 14:07:33 +00:00
ImGui : : TreePop ( ) ;
2018-04-01 19:24:30 +00:00
}
2018-04-02 00:37:40 +00:00
ImGui : : Separator ( ) ;
2018-08-18 18:10:14 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : TreeNode ( ICON_FA_HEARTBEAT " Active allocations " ) )
# else
2018-04-02 00:37:40 +00:00
if ( ImGui : : TreeNode ( " Active allocations " ) )
2018-08-18 18:10:14 +00:00
# endif
2018-04-02 00:37:40 +00:00
{
2018-04-02 14:30:03 +00:00
uint64_t total = 0 ;
2018-04-03 12:17:51 +00:00
std : : vector < const MemEvent * > items ;
2018-04-02 13:45:11 +00:00
items . reserve ( mem . active . size ( ) ) ;
2018-04-02 14:07:33 +00:00
if ( m_memInfo . restrictTime )
2018-04-02 13:45:11 +00:00
{
2018-04-02 14:07:33 +00:00
for ( auto & v : mem . data )
{
2018-04-03 12:17:51 +00:00
if ( v . timeAlloc < zvMid & & ( v . timeFree > zvMid | | v . timeFree < 0 ) )
2018-04-02 14:07:33 +00:00
{
2018-04-03 12:17:51 +00:00
items . emplace_back ( & v ) ;
total + = v . size ;
2018-04-02 14:07:33 +00:00
}
}
2018-04-02 13:45:11 +00:00
}
2018-04-02 14:07:33 +00:00
else
{
2018-04-03 12:17:51 +00:00
auto ptr = mem . data . data ( ) ;
2018-04-02 14:07:33 +00:00
for ( auto & v : mem . active )
{
2018-04-03 12:17:51 +00:00
items . emplace_back ( ptr + v . second ) ;
2018-04-02 14:07:33 +00:00
}
2018-04-02 14:09:44 +00:00
pdqsort_branchless ( items . begin ( ) , items . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > timeAlloc < rhs - > timeAlloc ; } ) ;
2018-04-02 14:30:03 +00:00
total = mem . usage ;
2018-04-02 14:07:33 +00:00
}
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( items . size ( ) , true ) ) ;
2018-08-08 18:38:43 +00:00
ImGui : : Text ( " Memory usage: %s " , MemSizeToString ( total ) ) ;
2018-04-02 13:45:11 +00:00
ListMemData < decltype ( items . begin ( ) ) > ( items . begin ( ) , items . end ( ) , [ ] ( auto & v ) {
ImGui : : Text ( " 0x% " PRIx64 , ( * v ) - > ptr ) ;
2018-06-21 22:10:00 +00:00
} , " ##activeMem " ) ;
2018-04-02 00:37:40 +00:00
ImGui : : TreePop ( ) ;
}
2018-04-02 16:40:59 +00:00
ImGui : : Separator ( ) ;
2018-08-18 18:10:14 +00:00
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : TreeNode ( ICON_FA_MAP " Memory map " ) )
# else
2018-04-02 16:40:59 +00:00
if ( ImGui : : TreeNode ( " Memory map " ) )
2018-08-18 18:10:14 +00:00
# endif
2018-04-02 16:40:59 +00:00
{
2018-08-08 18:38:43 +00:00
ImGui : : Text ( " Single pixel: %s Single line: %s " , MemSizeToString ( 1 < < ChunkBits ) , MemSizeToString ( PageChunkSize ) ) ;
2018-04-02 18:00:05 +00:00
2018-04-02 16:40:59 +00:00
auto pages = GetMemoryPages ( ) ;
2019-05-19 11:15:54 +00:00
const size_t lines = pages . size ( ) ;
2018-04-02 16:40:59 +00:00
2018-04-02 17:57:46 +00:00
ImGui : : BeginChild ( " ##memMap " , ImVec2 ( PageSize + 2 , lines + 2 ) , false ) ;
2018-04-02 16:40:59 +00:00
auto draw = ImGui : : GetWindowDrawList ( ) ;
const auto wpos = ImGui : : GetCursorScreenPos ( ) + ImVec2 ( 1 , 1 ) ;
2018-04-03 18:38:50 +00:00
draw - > AddRect ( wpos - ImVec2 ( 1 , 1 ) , wpos + ImVec2 ( PageSize + 1 , lines + 1 ) , 0xFF666666 ) ;
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( PageSize , lines ) , 0xFF444444 ) ;
2018-04-02 16:40:59 +00:00
size_t line = 0 ;
2019-05-19 11:15:54 +00:00
for ( auto & page : pages )
2018-04-02 16:40:59 +00:00
{
2019-05-19 11:15:54 +00:00
size_t idx = 0 ;
while ( idx < PageSize )
2018-04-02 16:40:59 +00:00
{
2019-05-19 11:15:54 +00:00
if ( page . data [ idx ] = = 0 )
2018-04-02 16:40:59 +00:00
{
2019-05-19 11:15:54 +00:00
do
2018-04-02 16:40:59 +00:00
{
2019-05-19 11:15:54 +00:00
idx + + ;
2018-04-02 16:40:59 +00:00
}
2019-05-19 11:15:54 +00:00
while ( idx < PageSize & & page . data [ idx ] = = 0 ) ;
}
else
{
auto val = page . data [ idx ] ;
const auto i0 = idx ;
do
2018-04-02 16:40:59 +00:00
{
2019-05-19 11:15:54 +00:00
idx + + ;
2018-04-02 16:40:59 +00:00
}
2019-05-19 11:15:54 +00:00
while ( idx < PageSize & & page . data [ idx ] = = val ) ;
draw - > AddLine ( wpos + ImVec2 ( i0 , line ) , wpos + ImVec2 ( idx , line ) , MemDecayColor [ ( uint8_t ) val ] ) ;
2018-04-02 16:40:59 +00:00
}
}
2019-05-19 11:15:54 +00:00
line + + ;
2018-04-02 16:40:59 +00:00
}
ImGui : : EndChild ( ) ;
ImGui : : TreePop ( ) ;
}
2018-08-14 16:37:06 +00:00
ImGui : : Separator ( ) ;
2018-08-18 18:10:14 +00:00
# ifdef TRACY_EXTENDED_FONT
2019-02-06 12:53:14 +00:00
if ( ImGui : : TreeNode ( ICON_FA_ALIGN_JUSTIFY " Bottom-up call stack tree " ) )
# else
if ( ImGui : : TreeNode ( " Bottom-up call stack tree " ) )
# endif
{
2019-02-06 20:45:26 +00:00
ImGui : : Checkbox ( " Group by function name " , & m_groupCallstackTreeByNameBottomUp ) ;
2019-02-06 21:02:36 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " If enabled, only one source location will be displayed (which may be incorrect). " ) ;
2019-05-09 11:37:28 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Only active allocations " , & m_activeOnlyBottomUp ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Press ctrl key to display allocation info tooltip. " ) ;
TextDisabledUnformatted ( " Right click on function name to display allocations list. Right click on file name to open source file. " ) ;
2019-02-06 12:53:14 +00:00
auto & mem = m_worker . GetMemData ( ) ;
auto tree = GetCallstackFrameTreeBottomUp ( mem ) ;
int idx = 0 ;
DrawFrameTreeLevel ( tree , idx ) ;
ImGui : : TreePop ( ) ;
}
ImGui : : Separator ( ) ;
# ifdef TRACY_EXTENDED_FONT
if ( ImGui : : TreeNode ( ICON_FA_ALIGN_JUSTIFY " Top-down call stack tree " ) )
2018-08-18 18:10:14 +00:00
# else
2019-02-06 12:53:14 +00:00
if ( ImGui : : TreeNode ( " Top-down call stack tree " ) )
2018-08-18 18:10:14 +00:00
# endif
2018-08-14 16:37:06 +00:00
{
2019-02-06 20:45:26 +00:00
ImGui : : Checkbox ( " Group by function name " , & m_groupCallstackTreeByNameTopDown ) ;
2019-02-06 21:02:36 +00:00
ImGui : : SameLine ( ) ;
2019-02-10 02:02:54 +00:00
DrawHelpMarker ( " If enabled, only one source location will be displayed (which may be incorrect). " ) ;
2019-05-09 11:37:28 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Only active allocations " , & m_activeOnlyTopDown ) ;
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " Press ctrl key to display allocation info tooltip. " ) ;
TextDisabledUnformatted ( " Right click on function name to display allocations list. Right click on file name to open source file. " ) ;
2018-08-14 16:37:06 +00:00
auto & mem = m_worker . GetMemData ( ) ;
2019-02-06 12:53:14 +00:00
auto tree = GetCallstackFrameTreeTopDown ( mem ) ;
2018-08-14 16:37:06 +00:00
2018-08-17 20:31:55 +00:00
int idx = 0 ;
DrawFrameTreeLevel ( tree , idx ) ;
2018-08-14 16:37:06 +00:00
ImGui : : TreePop ( ) ;
}
2018-04-01 18:34:21 +00:00
ImGui : : End ( ) ;
}
2019-04-03 14:24:16 +00:00
void View : : DrawFrameTreeLevel ( const flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > & tree , int & idx )
2018-08-14 16:37:06 +00:00
{
auto & io = ImGui : : GetIO ( ) ;
2019-04-03 14:24:16 +00:00
std : : vector < flat_hash_map < uint64_t , CallstackFrameTree , nohash < uint64_t > > : : const_iterator > sorted ;
sorted . reserve ( tree . size ( ) ) ;
for ( auto it = tree . begin ( ) ; it ! = tree . end ( ) ; + + it )
{
sorted . emplace_back ( it ) ;
}
pdqsort_branchless ( sorted . begin ( ) , sorted . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . alloc > rhs - > second . alloc ; } ) ;
2018-08-18 00:23:55 +00:00
int lidx = 0 ;
2019-04-03 14:24:16 +00:00
for ( auto & _v : sorted )
2018-08-14 16:37:06 +00:00
{
2019-04-03 14:24:16 +00:00
auto & v = _v - > second ;
2018-08-18 00:23:55 +00:00
idx + + ;
2019-02-06 13:17:18 +00:00
auto & frameData = * m_worker . GetCallstackFrame ( v . frame ) ;
auto frame = frameData . data [ frameData . size - 1 ] ;
2018-08-14 16:37:06 +00:00
bool expand = false ;
if ( v . children . empty ( ) )
{
ImGui : : Indent ( ImGui : : GetTreeNodeToLabelSpacing ( ) ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetString ( frame . name ) ) ;
2018-08-14 16:37:06 +00:00
ImGui : : Unindent ( ImGui : : GetTreeNodeToLabelSpacing ( ) ) ;
}
else
{
2018-08-18 00:23:55 +00:00
ImGui : : PushID ( lidx + + ) ;
2018-08-18 18:00:24 +00:00
if ( tree . size ( ) = = 1 )
{
2019-02-06 13:17:18 +00:00
expand = ImGui : : TreeNodeEx ( m_worker . GetString ( frame . name ) , ImGuiTreeNodeFlags_DefaultOpen ) ;
2018-08-18 18:00:24 +00:00
}
else
{
2019-02-06 13:17:18 +00:00
expand = ImGui : : TreeNode ( m_worker . GetString ( frame . name ) ) ;
2018-08-18 18:00:24 +00:00
}
2018-08-14 16:37:06 +00:00
ImGui : : PopID ( ) ;
}
2018-09-27 21:05:46 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
auto & mem = m_worker . GetMemData ( ) . data ;
const auto sz = mem . size ( ) ;
2018-09-27 21:16:10 +00:00
m_memInfo . showAllocList = true ;
2018-09-27 21:05:46 +00:00
m_memInfo . allocList . clear ( ) ;
for ( size_t i = 0 ; i < sz ; i + + )
{
if ( v . callstacks . find ( mem [ i ] . csAlloc ) ! = v . callstacks . end ( ) )
{
2018-09-27 21:18:47 +00:00
m_memInfo . allocList . emplace_back ( i ) ;
2018-09-27 21:05:46 +00:00
}
}
}
2018-08-14 16:37:06 +00:00
if ( io . KeyCtrl & & ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
2019-02-06 21:36:21 +00:00
TextFocused ( " Allocations size: " , MemSizeToString ( v . alloc ) ) ;
TextFocused ( " Allocations count: " , RealToString ( v . count , true ) ) ;
TextFocused ( " Average allocation size: " , MemSizeToString ( v . alloc / v . count ) ) ;
2018-08-14 16:37:06 +00:00
ImGui : : SameLine ( ) ;
ImGui : : EndTooltip ( ) ;
}
2018-08-17 20:51:26 +00:00
if ( m_callstackTreeBuzzAnim . Match ( idx ) )
{
const auto time = m_callstackTreeBuzzAnim . Time ( ) ;
2018-08-18 12:14:33 +00:00
const auto indentVal = sin ( time * 60.f ) * 10.f * time ;
2018-08-17 20:51:26 +00:00
ImGui : : SameLine ( 0 , ImGui : : GetStyle ( ) . ItemSpacing . x + indentVal ) ;
}
else
2018-08-14 16:37:06 +00:00
{
ImGui : : SameLine ( ) ;
2018-08-17 20:51:26 +00:00
}
2019-02-06 13:17:18 +00:00
const auto fileName = m_worker . GetString ( frame . file ) ;
ImGui : : TextDisabled ( " %s:%i " , fileName , frame . line ) ;
2018-08-17 20:51:26 +00:00
if ( ImGui : : IsItemClicked ( 1 ) )
{
2018-08-18 18:38:14 +00:00
if ( FileExists ( fileName ) )
2018-08-17 20:51:26 +00:00
{
2019-02-06 13:17:18 +00:00
SetTextEditorFile ( fileName , frame . line ) ;
2018-08-17 20:51:26 +00:00
}
else
{
m_callstackTreeBuzzAnim . Enable ( idx , 0.5f ) ;
}
}
2019-02-06 21:36:21 +00:00
ImGui : : SameLine ( ) ;
if ( v . children . empty ( ) )
2018-08-17 20:51:26 +00:00
{
2019-02-06 21:36:21 +00:00
ImGui : : TextColored ( ImVec4 ( 0.2 , 0.8 , 0.8 , 1.0 ) , " %s (%s) " , MemSizeToString ( v . alloc ) , RealToString ( v . count , true ) ) ;
2018-08-14 16:37:06 +00:00
}
2019-02-06 21:36:21 +00:00
else
2018-08-14 16:37:06 +00:00
{
2019-02-06 21:36:21 +00:00
ImGui : : TextColored ( ImVec4 ( 0.8 , 0.8 , 0.2 , 1.0 ) , " %s (%s) " , MemSizeToString ( v . alloc ) , RealToString ( v . count , true ) ) ;
2018-08-14 16:37:06 +00:00
}
if ( expand )
{
2018-08-17 20:31:55 +00:00
DrawFrameTreeLevel ( v . children , idx ) ;
2018-08-14 16:37:06 +00:00
ImGui : : TreePop ( ) ;
}
}
}
2018-09-27 21:16:10 +00:00
void View : : DrawAllocList ( )
{
2018-09-27 21:18:47 +00:00
std : : vector < const MemEvent * > data ;
auto basePtr = m_worker . GetMemData ( ) . data . data ( ) ;
data . reserve ( m_memInfo . allocList . size ( ) ) ;
for ( auto & idx : m_memInfo . allocList )
{
data . emplace_back ( basePtr + idx ) ;
}
2019-06-17 21:49:10 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 1100 , 500 ) , ImGuiCond_FirstUseEver ) ;
2018-09-27 21:16:10 +00:00
ImGui : : Begin ( " Allocations list " , & m_memInfo . showAllocList ) ;
TextFocused ( " Number of allocations: " , RealToString ( m_memInfo . allocList . size ( ) , true ) ) ;
2019-01-06 20:15:49 +00:00
ListMemData < decltype ( data . begin ( ) ) > ( data . begin ( ) , data . end ( ) , [ ] ( auto & v ) {
2018-09-27 21:16:10 +00:00
ImGui : : Text ( " 0x% " PRIx64 , ( * v ) - > ptr ) ;
} , " ##allocations " ) ;
ImGui : : End ( ) ;
}
2018-04-28 13:49:51 +00:00
const char * View : : GetPlotName ( const PlotData * plot ) const
{
switch ( plot - > type )
{
case PlotType : : User :
return m_worker . GetString ( plot - > name ) ;
case PlotType : : Memory :
2018-08-17 22:24:23 +00:00
# ifdef TRACY_EXTENDED_FONT
return ICON_FA_MEMORY " Memory usage " ;
# else
2018-04-28 13:49:51 +00:00
return " Memory usage " ;
2019-02-21 21:45:39 +00:00
# endif
case PlotType : : SysTime :
# ifdef TRACY_EXTENDED_FONT
return ICON_FA_TACHOMETER_ALT " CPU usage " ;
# else
return " CPU usage " ;
2018-08-17 22:24:23 +00:00
# endif
2018-04-28 13:49:51 +00:00
default :
assert ( false ) ;
return nullptr ;
}
}
2017-10-22 13:37:24 +00:00
uint32_t View : : GetZoneColor ( const ZoneEvent & ev )
2017-10-01 17:31:22 +00:00
{
2018-10-09 13:54:28 +00:00
if ( m_findZone . show & & ! m_findZone . match . empty ( ) & & m_findZone . match [ m_findZone . selMatch ] = = ev . srcloc )
{
return 0xFF229999 ;
}
else
{
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
const auto color = srcloc . color ;
return color ! = 0 ? ( color | 0xFF000000 ) : 0xFFCC5555 ;
}
2017-10-01 17:31:22 +00:00
}
2017-11-11 21:56:05 +00:00
uint32_t View : : GetZoneColor ( const GpuEvent & ev )
2017-10-01 17:31:22 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-05 19:54:49 +00:00
const auto color = srcloc . color ;
2017-11-11 21:56:05 +00:00
return color ! = 0 ? ( color | 0xFF000000 ) : 0xFF222288 ;
2017-10-01 17:31:22 +00:00
}
2017-10-22 13:37:24 +00:00
uint32_t View : : GetZoneHighlight ( const ZoneEvent & ev , bool migration )
2017-09-29 19:57:00 +00:00
{
if ( m_zoneInfoWindow = = & ev )
{
return 0xFF44DD44 ;
}
2017-09-29 20:38:38 +00:00
else if ( m_zoneHighlight = = & ev )
{
return 0xFF4444FF ;
}
2018-07-28 17:53:11 +00:00
else if ( m_zoneSrcLocHighlight = = ev . srcloc )
{
return 0xFFEEEEEE ;
}
2017-10-01 17:58:53 +00:00
else if ( migration )
{
return 0xFFDD22DD ;
}
2017-09-29 19:57:00 +00:00
else
{
2017-10-01 17:38:45 +00:00
const auto color = GetZoneColor ( ev ) ;
return 0xFF000000 |
( std : : min < int > ( 0xFF , ( ( ( color & 0x00FF0000 ) > > 16 ) + 25 ) ) < < 16 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x0000FF00 ) > > 8 ) + 25 ) ) < < 8 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x000000FF ) ) + 25 ) ) ) ;
2017-09-29 19:57:00 +00:00
}
}
2017-11-11 21:56:05 +00:00
uint32_t View : : GetZoneHighlight ( const GpuEvent & ev )
{
2017-11-12 00:25:44 +00:00
if ( m_gpuInfoWindow = = & ev )
{
return 0xFF44DD44 ;
}
2017-11-12 00:28:07 +00:00
else if ( m_gpuHighlight = = & ev )
{
return 0xFF4444FF ;
}
2017-11-12 00:25:44 +00:00
else
{
const auto color = GetZoneColor ( ev ) ;
return 0xFF000000 |
( std : : min < int > ( 0xFF , ( ( ( color & 0x00FF0000 ) > > 16 ) + 25 ) ) < < 16 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x0000FF00 ) > > 8 ) + 25 ) ) < < 8 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x000000FF ) ) + 25 ) ) ) ;
}
2017-11-11 21:56:05 +00:00
}
2017-10-22 13:37:24 +00:00
float View : : GetZoneThickness ( const ZoneEvent & ev )
2017-09-30 11:45:02 +00:00
{
2018-10-09 13:54:28 +00:00
if ( m_zoneInfoWindow = = & ev | | m_zoneHighlight = = & ev | | ( m_findZone . show & & ! m_findZone . match . empty ( ) & & m_findZone . match [ m_findZone . selMatch ] = = ev . srcloc ) )
2017-09-30 11:45:02 +00:00
{
return 3.f ;
}
else
{
return 1.f ;
}
}
2017-11-11 21:56:05 +00:00
float View : : GetZoneThickness ( const GpuEvent & ev )
{
2017-11-12 00:28:07 +00:00
if ( m_gpuInfoWindow = = & ev | | m_gpuHighlight = = & ev )
2017-11-12 00:25:44 +00:00
{
return 3.f ;
}
else
{
return 1.f ;
}
2017-11-11 21:56:05 +00:00
}
2017-10-22 13:37:24 +00:00
void View : : ZoomToZone ( const ZoneEvent & ev )
2017-09-29 20:01:30 +00:00
{
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-10-08 09:38:03 +00:00
if ( end - ev . start < = 0 ) return ;
2017-11-27 21:12:26 +00:00
ZoomToRange ( ev . start , end ) ;
2017-09-29 20:01:30 +00:00
}
2017-11-11 21:56:05 +00:00
void View : : ZoomToZone ( const GpuEvent & ev )
{
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-11 21:56:05 +00:00
if ( end - ev . gpuStart < = 0 ) return ;
2018-06-27 23:12:25 +00:00
auto ctx = GetZoneCtx ( ev ) ;
if ( ! ctx )
{
ZoomToRange ( ev . gpuStart , end ) ;
}
else
{
const auto begin = ctx - > timeline . front ( ) - > gpuStart ;
const auto drift = GpuDrift ( ctx ) ;
ZoomToRange ( AdjustGpuTime ( ev . gpuStart , begin , drift ) , AdjustGpuTime ( end , begin , drift ) ) ;
}
2017-11-27 21:12:26 +00:00
}
void View : : ZoomToRange ( int64_t start , int64_t end )
{
2018-07-29 18:23:31 +00:00
if ( start = = end )
{
end = start + 1 ;
}
2017-11-27 21:41:30 +00:00
m_pause = true ;
2018-07-29 18:17:35 +00:00
m_highlightZoom . active = false ;
2019-06-21 11:08:41 +00:00
if ( ! m_playback . pause & & m_playback . sync ) m_playback . pause = true ;
2017-11-27 21:41:30 +00:00
m_zoomAnim . active = true ;
m_zoomAnim . start0 = m_zvStart ;
m_zoomAnim . start1 = start ;
m_zoomAnim . end0 = m_zvEnd ;
m_zoomAnim . end1 = end ;
m_zoomAnim . progress = 0 ;
2017-11-11 21:56:05 +00:00
}
2018-06-02 20:27:35 +00:00
void View : : ZoomToPrevFrame ( )
{
2018-08-04 17:47:09 +00:00
if ( m_zvStart > = m_worker . GetFrameBegin ( * m_frames , 0 ) )
2018-06-02 20:27:35 +00:00
{
2019-06-22 12:15:25 +00:00
size_t frame ;
2018-08-05 00:27:59 +00:00
if ( m_frames - > continuous )
{
2019-06-22 12:15:25 +00:00
frame = ( size_t ) m_worker . GetFrameRange ( * m_frames , m_zvStart , m_zvStart ) . first ;
2018-08-05 00:27:59 +00:00
}
else
{
2019-06-22 12:15:25 +00:00
frame = ( size_t ) m_worker . GetFrameRange ( * m_frames , m_zvStart , m_zvStart ) . second ;
2018-08-05 00:27:59 +00:00
}
2018-06-02 20:27:35 +00:00
if ( frame > 0 )
{
frame - - ;
2018-08-04 17:47:09 +00:00
const auto fbegin = m_worker . GetFrameBegin ( * m_frames , frame ) ;
const auto fend = m_worker . GetFrameEnd ( * m_frames , frame ) ;
2018-06-02 20:27:35 +00:00
ZoomToRange ( fbegin , fend ) ;
}
}
}
void View : : ZoomToNextFrame ( )
{
2019-03-17 19:51:54 +00:00
int64_t start ;
if ( m_zoomAnim . active )
{
start = m_zoomAnim . start1 ;
}
else
{
start = m_zvStart ;
}
2019-06-22 12:15:25 +00:00
size_t frame ;
2019-03-17 19:51:54 +00:00
if ( start < m_worker . GetFrameBegin ( * m_frames , 0 ) )
2018-06-02 20:27:35 +00:00
{
2019-06-22 12:06:10 +00:00
frame = 0 ;
2018-06-02 20:27:35 +00:00
}
else
{
2019-06-22 12:06:10 +00:00
frame = ( size_t ) m_worker . GetFrameRange ( * m_frames , start , start ) . first + 1 ;
2018-06-02 20:27:35 +00:00
}
2018-08-04 17:47:09 +00:00
if ( frame > = m_worker . GetFrameCount ( * m_frames ) ) return ;
2018-06-02 20:27:35 +00:00
2018-08-04 17:47:09 +00:00
const auto fbegin = m_worker . GetFrameBegin ( * m_frames , frame ) ;
const auto fend = m_worker . GetFrameEnd ( * m_frames , frame ) ;
2018-06-02 20:27:35 +00:00
ZoomToRange ( fbegin , fend ) ;
}
2018-06-22 18:21:02 +00:00
void View : : CenterAtTime ( int64_t t )
{
const auto hr = std : : max < uint64_t > ( 1 , ( m_zvEnd - m_zvStart ) / 2 ) ;
ZoomToRange ( t - hr , t + hr ) ;
}
2018-05-02 17:23:46 +00:00
void View : : ShowZoneInfo ( const ZoneEvent & ev )
{
2019-03-17 15:43:20 +00:00
if ( m_zoneInfoWindow & & m_zoneInfoWindow ! = & ev )
2018-05-02 17:23:46 +00:00
{
m_zoneInfoStack . push_back ( m_zoneInfoWindow ) ;
}
m_zoneInfoWindow = & ev ;
if ( m_gpuInfoWindow )
{
m_gpuInfoWindow = nullptr ;
m_gpuInfoStack . clear ( ) ;
}
}
void View : : ShowZoneInfo ( const GpuEvent & ev , uint64_t thread )
{
2019-03-17 15:43:20 +00:00
if ( m_gpuInfoWindow & & m_gpuInfoWindow ! = & ev )
2018-05-02 17:23:46 +00:00
{
m_gpuInfoStack . push_back ( m_gpuInfoWindow ) ;
}
m_gpuInfoWindow = & ev ;
m_gpuInfoWindowThread = thread ;
if ( m_zoneInfoWindow )
{
m_zoneInfoWindow = nullptr ;
m_zoneInfoStack . clear ( ) ;
}
}
2017-10-22 13:37:24 +00:00
void View : : ZoneTooltip ( const ZoneEvent & ev )
2017-09-29 20:55:24 +00:00
{
2018-03-19 15:08:50 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-02-13 13:57:47 +00:00
auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
const auto end = m_worker . GetZoneEnd ( ev ) ;
2019-01-23 12:44:11 +00:00
const auto ztime = end - ev . start ;
2019-03-29 23:52:25 +00:00
const auto selftime = GetZoneSelfTime ( ev ) ;
2017-09-29 20:55:24 +00:00
ImGui : : BeginTooltip ( ) ;
2018-06-29 14:15:59 +00:00
if ( ev . name . active )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetString ( ev . name ) ) ;
2018-06-29 14:15:59 +00:00
}
2017-11-17 23:51:04 +00:00
if ( srcloc . name . active )
{
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . name ) ) ;
2017-11-17 23:51:04 +00:00
}
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . function ) ) ;
2017-11-18 12:47:05 +00:00
ImGui : : Separator ( ) ;
2018-06-29 13:14:20 +00:00
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-06-29 16:39:20 +00:00
TextFocused ( " Thread: " , m_worker . GetThreadString ( tid ) ) ;
2018-03-19 15:08:50 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2018-03-19 15:14:01 +00:00
ImGui : : Separator ( ) ;
2019-01-23 12:44:11 +00:00
TextFocused ( " Execution time: " , TimeToString ( ztime ) ) ;
2019-06-22 11:22:13 +00:00
# ifndef TRACY_NO_STATISTICS
auto & zoneData = m_worker . GetZonesForSourceLocation ( ev . srcloc ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%% of average time) " , float ( ztime ) / zoneData . total * zoneData . zones . size ( ) * 100 ) ;
# endif
2019-01-23 12:44:11 +00:00
TextFocused ( " Self time: " , TimeToString ( selftime ) ) ;
2019-06-22 20:42:57 +00:00
if ( ztime ! = 0 )
{
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , 100.f * selftime / ztime ) ;
}
2018-04-14 14:50:04 +00:00
if ( ev . cpu_start > = 0 )
2017-10-01 17:21:25 +00:00
{
2019-02-10 01:50:34 +00:00
TextDisabledUnformatted ( " CPU: " ) ;
2018-06-29 16:39:20 +00:00
ImGui : : SameLine ( ) ;
2018-03-24 01:00:20 +00:00
if ( ev . end < 0 | | ev . cpu_start = = ev . cpu_end )
2017-10-01 17:21:25 +00:00
{
2018-06-29 16:39:20 +00:00
ImGui : : Text ( " %i " , ev . cpu_start ) ;
2017-10-01 17:21:25 +00:00
}
else
{
2018-06-29 16:39:20 +00:00
ImGui : : Text ( " %i -> %i " , ev . cpu_start , ev . cpu_end ) ;
2017-10-01 17:21:25 +00:00
}
}
2017-11-14 22:31:24 +00:00
if ( ev . text . active )
2017-09-29 20:55:24 +00:00
{
2017-10-28 19:50:06 +00:00
ImGui : : NewLine ( ) ;
2019-06-02 23:36:03 +00:00
TextColoredUnformatted ( ImVec4 ( 0xCC / 255.f , 0xCC / 255.f , 0x22 / 255.f , 1.f ) , m_worker . GetString ( ev . text ) ) ;
2017-09-29 20:55:24 +00:00
}
ImGui : : EndTooltip ( ) ;
}
2017-11-11 21:56:05 +00:00
void View : : ZoneTooltip ( const GpuEvent & ev )
{
2018-03-19 15:13:12 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
const auto end = m_worker . GetZoneEnd ( ev ) ;
2019-02-14 00:28:27 +00:00
const auto ztime = end - ev . gpuStart ;
2019-03-29 23:52:25 +00:00
const auto selftime = GetZoneSelfTime ( ev ) ;
2017-11-11 21:56:05 +00:00
ImGui : : BeginTooltip ( ) ;
2019-02-10 01:50:34 +00:00
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . name ) ) ;
ImGui : : TextUnformatted ( m_worker . GetString ( srcloc . function ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-06-29 13:14:20 +00:00
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-06-29 16:39:20 +00:00
TextFocused ( " Thread: " , m_worker . GetThreadString ( tid ) ) ;
2018-03-19 15:13:12 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2018-03-19 15:14:01 +00:00
ImGui : : Separator ( ) ;
2019-02-14 00:28:27 +00:00
TextFocused ( " GPU execution time: " , TimeToString ( ztime ) ) ;
TextFocused ( " GPU self time: " , TimeToString ( selftime ) ) ;
2019-06-22 20:42:57 +00:00
if ( ztime ! = 0 )
{
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%.2f%%) " , 100.f * selftime / ztime ) ;
}
2018-06-29 16:39:20 +00:00
TextFocused ( " CPU command setup time: " , TimeToString ( ev . cpuEnd - ev . cpuStart ) ) ;
2018-06-27 23:12:25 +00:00
auto ctx = GetZoneCtx ( ev ) ;
if ( ! ctx )
{
2018-06-29 16:39:20 +00:00
TextFocused ( " Delay to execution: " , TimeToString ( ev . gpuStart - ev . cpuStart ) ) ;
2018-06-27 23:12:25 +00:00
}
else
{
const auto begin = ctx - > timeline . front ( ) - > gpuStart ;
const auto drift = GpuDrift ( ctx ) ;
2018-06-29 16:39:20 +00:00
TextFocused ( " Delay to execution: " , TimeToString ( AdjustGpuTime ( ev . gpuStart , begin , drift ) - ev . cpuStart ) ) ;
2018-06-27 23:12:25 +00:00
}
2017-11-11 21:56:05 +00:00
ImGui : : EndTooltip ( ) ;
}
2018-06-19 20:19:33 +00:00
void View : : CallstackTooltip ( uint32_t idx )
{
auto & cs = m_worker . GetCallstack ( idx ) ;
ImGui : : BeginTooltip ( ) ;
2018-06-19 23:19:10 +00:00
int fidx = 0 ;
2018-06-19 20:19:33 +00:00
for ( auto & entry : cs )
{
2019-02-27 19:55:58 +00:00
auto frameData = m_worker . GetCallstackFrame ( entry ) ;
if ( ! frameData )
2018-06-19 23:19:10 +00:00
{
2019-02-27 19:55:58 +00:00
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
ImGui : : SameLine ( ) ;
2019-03-03 15:50:18 +00:00
ImGui : : Text ( " %p " , ( void * ) m_worker . GetCanonicalPointer ( entry ) ) ;
2018-06-19 23:19:10 +00:00
}
else
{
2019-02-27 19:55:58 +00:00
const auto fsz = frameData - > size ;
for ( uint8_t f = 0 ; f < fsz ; f + + )
{
const auto & frame = frameData - > data [ f ] ;
auto txt = m_worker . GetString ( frame . name ) ;
if ( fidx = = 0 & & f ! = fsz - 1 )
{
auto test = s_tracyStackFrames ;
bool match = false ;
do
{
if ( strcmp ( txt , * test ) = = 0 )
{
match = true ;
break ;
}
}
while ( * + + test ) ;
if ( match ) continue ;
}
if ( f = = fsz - 1 )
{
ImGui : : TextDisabled ( " %i. " , fidx + + ) ;
}
else
{
TextDisabledUnformatted ( " -- " ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : TextUnformatted ( txt ) ;
}
2018-06-19 23:19:10 +00:00
}
2018-06-19 20:19:33 +00:00
}
ImGui : : EndTooltip ( ) ;
}
2017-10-22 14:15:27 +00:00
const ZoneEvent * View : : GetZoneParent ( const ZoneEvent & zone ) const
{
2018-02-13 13:57:47 +00:00
for ( const auto & thread : m_worker . GetThreadData ( ) )
2017-10-22 14:15:27 +00:00
{
const ZoneEvent * parent = nullptr ;
const Vector < ZoneEvent * > * timeline = & thread - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . start , [ ] ( const auto & l , const auto & r ) { return l < r - > start ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . end > = 0 & & ( * it ) - > start > zone . end ) break ;
2017-10-22 14:15:27 +00:00
if ( * it = = & zone ) return parent ;
2018-07-22 14:05:50 +00:00
if ( ( * it ) - > child < 0 ) break ;
2017-10-22 14:15:27 +00:00
parent = * it ;
2018-07-22 14:05:50 +00:00
timeline = & m_worker . GetZoneChildren ( parent - > child ) ;
2017-10-22 14:15:27 +00:00
}
}
return nullptr ;
}
2017-11-12 00:25:44 +00:00
const GpuEvent * View : : GetZoneParent ( const GpuEvent & zone ) const
{
2018-02-13 13:57:47 +00:00
for ( const auto & ctx : m_worker . GetGpuData ( ) )
2017-11-12 00:25:44 +00:00
{
const GpuEvent * parent = nullptr ;
const Vector < GpuEvent * > * timeline = & ctx - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . gpuStart , [ ] ( const auto & l , const auto & r ) { return l < r - > gpuStart ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . gpuEnd > = 0 & & ( * it ) - > gpuStart > zone . gpuEnd ) break ;
2017-11-12 00:25:44 +00:00
if ( * it = = & zone ) return parent ;
2018-07-22 17:47:01 +00:00
if ( ( * it ) - > child < 0 ) break ;
2017-11-12 00:25:44 +00:00
parent = * it ;
2018-07-22 17:47:01 +00:00
timeline = & m_worker . GetGpuChildren ( parent - > child ) ;
2017-11-12 00:25:44 +00:00
}
}
return nullptr ;
}
2019-03-17 15:17:47 +00:00
const ThreadData * View : : GetZoneThreadData ( const ZoneEvent & zone ) const
2018-03-18 15:38:42 +00:00
{
for ( const auto & thread : m_worker . GetThreadData ( ) )
{
const Vector < ZoneEvent * > * timeline = & thread - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . start , [ ] ( const auto & l , const auto & r ) { return l < r - > start ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . end > = 0 & & ( * it ) - > start > zone . end ) break ;
2019-03-17 15:17:47 +00:00
if ( * it = = & zone ) return thread ;
2018-07-22 14:05:50 +00:00
if ( ( * it ) - > child < 0 ) break ;
timeline = & m_worker . GetZoneChildren ( ( * it ) - > child ) ;
2018-03-18 15:38:42 +00:00
}
}
2019-03-17 15:17:47 +00:00
return nullptr ;
}
uint64_t View : : GetZoneThread ( const ZoneEvent & zone ) const
{
auto threadData = GetZoneThreadData ( zone ) ;
return threadData ? threadData - > id : 0 ;
2018-03-18 15:38:42 +00:00
}
2018-03-19 15:11:37 +00:00
uint64_t View : : GetZoneThread ( const GpuEvent & zone ) const
{
2018-06-17 17:09:33 +00:00
if ( zone . thread = = 0 )
2018-03-19 15:11:37 +00:00
{
2018-06-17 17:09:33 +00:00
for ( const auto & ctx : m_worker . GetGpuData ( ) )
2018-03-19 15:11:37 +00:00
{
2018-06-17 17:09:33 +00:00
const Vector < GpuEvent * > * timeline = & ctx - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . gpuStart , [ ] ( const auto & l , const auto & r ) { return l < r - > gpuStart ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
if ( zone . gpuEnd > = 0 & & ( * it ) - > gpuStart > zone . gpuEnd ) break ;
if ( * it = = & zone ) return ctx - > thread ;
2018-07-22 17:47:01 +00:00
if ( ( * it ) - > child < 0 ) break ;
timeline = & m_worker . GetGpuChildren ( ( * it ) - > child ) ;
2018-06-17 17:09:33 +00:00
}
2018-03-19 15:11:37 +00:00
}
2018-06-17 17:09:33 +00:00
return 0 ;
}
else
{
return m_worker . DecompressThread ( zone . thread ) ;
2018-03-19 15:11:37 +00:00
}
}
2018-06-27 23:07:21 +00:00
const GpuCtxData * View : : GetZoneCtx ( const GpuEvent & zone ) const
{
for ( const auto & ctx : m_worker . GetGpuData ( ) )
{
const Vector < GpuEvent * > * timeline = & ctx - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . gpuStart , [ ] ( const auto & l , const auto & r ) { return l < r - > gpuStart ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
if ( zone . gpuEnd > = 0 & & ( * it ) - > gpuStart > zone . gpuEnd ) break ;
if ( * it = = & zone ) return ctx ;
2018-07-22 17:47:01 +00:00
if ( ( * it ) - > child < 0 ) break ;
timeline = & m_worker . GetGpuChildren ( ( * it ) - > child ) ;
2018-06-27 23:07:21 +00:00
}
}
return nullptr ;
}
2018-04-01 19:47:08 +00:00
const ZoneEvent * View : : FindZoneAtTime ( uint64_t thread , int64_t time ) const
{
// TODO add thread rev-map
ThreadData * td = nullptr ;
for ( const auto & t : m_worker . GetThreadData ( ) )
{
if ( t - > id = = thread )
{
td = t ;
break ;
}
}
if ( ! td ) return nullptr ;
const Vector < ZoneEvent * > * timeline = & td - > timeline ;
if ( timeline - > empty ( ) ) return nullptr ;
ZoneEvent * ret = nullptr ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , time , [ ] ( const auto & l , const auto & r ) { return l < r - > start ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
if ( ( * it ) - > start > time | | ( ( * it ) - > end > = 0 & & ( * it ) - > end < time ) ) return ret ;
ret = * it ;
2018-07-22 14:05:50 +00:00
if ( ( * it ) - > child < 0 ) return ret ;
timeline = & m_worker . GetZoneChildren ( ( * it ) - > child ) ;
2018-04-01 19:47:08 +00:00
}
}
2018-03-18 11:55:54 +00:00
# ifndef TRACY_NO_STATISTICS
2018-01-17 11:49:50 +00:00
void View : : FindZones ( )
{
2018-12-18 15:52:29 +00:00
m_findZone . match = m_worker . GetMatchingSourceLocation ( m_findZone . pattern , m_findZone . ignoreCase ) ;
2018-03-18 15:07:07 +00:00
if ( m_findZone . match . empty ( ) ) return ;
2018-03-04 20:10:10 +00:00
2018-03-18 15:07:07 +00:00
auto it = m_findZone . match . begin ( ) ;
while ( it ! = m_findZone . match . end ( ) )
2018-03-04 21:11:50 +00:00
{
2018-03-18 19:20:24 +00:00
if ( m_worker . GetZonesForSourceLocation ( * it ) . zones . empty ( ) )
2018-02-15 15:24:01 +00:00
{
2018-03-18 15:07:07 +00:00
it = m_findZone . match . erase ( it ) ;
}
else
{
+ + it ;
2018-02-15 15:24:01 +00:00
}
2018-01-17 11:49:50 +00:00
}
}
2018-04-21 22:52:33 +00:00
void View : : FindZonesCompare ( )
{
2018-12-18 15:56:19 +00:00
m_compare . match [ 0 ] = m_worker . GetMatchingSourceLocation ( m_compare . pattern , m_compare . ignoreCase ) ;
2018-04-21 22:52:33 +00:00
if ( ! m_compare . match [ 0 ] . empty ( ) )
{
auto it = m_compare . match [ 0 ] . begin ( ) ;
while ( it ! = m_compare . match [ 0 ] . end ( ) )
{
if ( m_worker . GetZonesForSourceLocation ( * it ) . zones . empty ( ) )
{
it = m_compare . match [ 0 ] . erase ( it ) ;
}
else
{
+ + it ;
}
}
}
2018-12-18 15:56:19 +00:00
m_compare . match [ 1 ] = m_compare . second - > GetMatchingSourceLocation ( m_compare . pattern , m_compare . ignoreCase ) ;
2018-04-21 22:52:33 +00:00
if ( ! m_compare . match [ 1 ] . empty ( ) )
{
auto it = m_compare . match [ 1 ] . begin ( ) ;
while ( it ! = m_compare . match [ 1 ] . end ( ) )
{
if ( m_compare . second - > GetZonesForSourceLocation ( * it ) . zones . empty ( ) )
{
it = m_compare . match [ 1 ] . erase ( it ) ;
}
else
{
+ + it ;
}
}
}
}
2018-03-18 11:55:54 +00:00
# endif
2018-01-17 11:49:50 +00:00
2019-02-27 01:27:05 +00:00
void View : : SmallCallstackButton ( const char * name , uint32_t callstack , int & idx , bool tooltip )
2018-07-17 20:53:38 +00:00
{
bool hilite = m_callstackInfoWindow = = callstack ;
if ( hilite )
{
2018-12-18 15:28:09 +00:00
SetButtonHighlightColor ( ) ;
2018-07-17 20:53:38 +00:00
}
ImGui : : PushID ( idx + + ) ;
if ( ImGui : : SmallButton ( name ) )
{
m_callstackInfoWindow = callstack ;
}
ImGui : : PopID ( ) ;
if ( hilite )
{
ImGui : : PopStyleColor ( 3 ) ;
}
2019-02-27 01:27:05 +00:00
if ( tooltip & & ImGui : : IsItemHovered ( ) )
2018-07-17 20:53:38 +00:00
{
CallstackTooltip ( callstack ) ;
}
}
2018-10-21 14:03:21 +00:00
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 ) ;
}
}
2019-01-23 12:39:44 +00:00
int64_t View : : GetZoneChildTime ( const ZoneEvent & zone )
{
int64_t time = 0 ;
if ( zone . child > = 0 )
{
for ( auto & v : m_worker . GetZoneChildren ( zone . child ) )
{
const auto childSpan = std : : max ( int64_t ( 0 ) , v - > end - v - > start ) ;
time + = childSpan ;
}
}
return time ;
}
2019-02-14 00:28:12 +00:00
int64_t View : : GetZoneChildTime ( const GpuEvent & zone )
{
int64_t time = 0 ;
if ( zone . child > = 0 )
{
for ( auto & v : m_worker . GetGpuChildren ( zone . child ) )
{
const auto childSpan = std : : max ( int64_t ( 0 ) , v - > gpuEnd - v - > gpuStart ) ;
time + = childSpan ;
}
}
return time ;
}
2019-01-23 12:59:14 +00:00
int64_t View : : GetZoneChildTimeFast ( const ZoneEvent & zone )
{
int64_t time = 0 ;
if ( zone . child > = 0 )
{
for ( auto & v : m_worker . GetZoneChildren ( zone . child ) )
{
assert ( v - > end > = 0 ) ;
time + = v - > end - v - > start ;
}
}
return time ;
}
2019-03-29 23:52:25 +00:00
int64_t View : : GetZoneSelfTime ( const ZoneEvent & zone )
{
if ( m_cache . zoneSelfTime . first = = & zone ) return m_cache . zoneSelfTime . second ;
2019-03-29 23:54:22 +00:00
if ( m_cache . zoneSelfTime2 . first = = & zone ) return m_cache . zoneSelfTime2 . second ;
2019-03-29 23:52:25 +00:00
const auto ztime = m_worker . GetZoneEnd ( zone ) - zone . start ;
const auto selftime = ztime - GetZoneChildTime ( zone ) ;
2019-03-29 23:54:22 +00:00
if ( zone . end > = 0 )
{
m_cache . zoneSelfTime2 = m_cache . zoneSelfTime ;
m_cache . zoneSelfTime = std : : make_pair ( & zone , selftime ) ;
}
2019-03-29 23:52:25 +00:00
return selftime ;
}
int64_t View : : GetZoneSelfTime ( const GpuEvent & zone )
{
if ( m_cache . gpuSelfTime . first = = & zone ) return m_cache . gpuSelfTime . second ;
2019-03-29 23:54:22 +00:00
if ( m_cache . gpuSelfTime2 . first = = & zone ) return m_cache . gpuSelfTime2 . second ;
2019-03-29 23:52:25 +00:00
const auto ztime = m_worker . GetZoneEnd ( zone ) - zone . gpuStart ;
const auto selftime = ztime - GetZoneChildTime ( zone ) ;
2019-03-29 23:54:22 +00:00
if ( zone . gpuEnd > = 0 )
{
m_cache . gpuSelfTime2 = m_cache . gpuSelfTime ;
m_cache . gpuSelfTime = std : : make_pair ( & zone , selftime ) ;
}
2019-03-29 23:52:25 +00:00
return selftime ;
}
2017-09-12 23:33:50 +00:00
}