diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj index 321c9623..c324f225 100644 --- a/profiler/build/win32/Tracy.vcxproj +++ b/profiler/build/win32/Tracy.vcxproj @@ -137,6 +137,7 @@ + diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters index a0eeed43..81f20cb2 100644 --- a/profiler/build/win32/Tracy.vcxproj.filters +++ b/profiler/build/win32/Tracy.vcxproj.filters @@ -279,6 +279,9 @@ server + + server + diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 08807a28..a2fc95c2 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -7284,347 +7284,6 @@ void View::DrawSamplesStatistics( Vector& data, int64_t timeRange, Accu } } -void View::DrawCallstackWindow() -{ - bool show = true; - const auto scale = GetScale(); - ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 500 * scale ), ImGuiCond_FirstUseEver ); - ImGui::Begin( "Call stack", &show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse ); - if( !ImGui::GetCurrentWindowRead()->SkipItems ) - { - DrawCallstackTable( m_callstackInfoWindow, true ); - } - ImGui::End(); - if( !show ) m_callstackInfoWindow = 0; -} - -void View::DrawCallstackTable( uint32_t callstack, bool globalEntriesButton ) -{ - auto& cs = m_worker.GetCallstack( callstack ); - if( ClipboardButton() ) - { - std::ostringstream s; - int fidx = 0; - int bidx = 0; - for( auto& entry : cs ) - { - char buf[64*1024]; - auto frameData = m_worker.GetCallstackFrame( entry ); - if( !frameData ) - { - sprintf( buf, "%3i. %p\n", fidx++, (void*)m_worker.GetCanonicalPointer( entry ) ); - } - else - { - auto ptr = buf; - const auto fsz = frameData->size; - for( uint8_t f=0; fdata[f]; - auto txt = m_worker.GetString( frame.name ); - - if( fidx == 0 && f != fsz-1 ) - { - auto test = tracy::s_tracyStackFrames; - bool match = false; - do - { - if( strcmp( txt, *test ) == 0 ) - { - match = true; - break; - } - } - while( *++test ); - if( match ) continue; - } - - bidx++; - - if( f == fsz-1 ) - { - ptr += sprintf( ptr, "%3i. ", fidx++ ); - } - else - { - ptr += sprintf( ptr, "inl. " ); - } - ptr += sprintf( ptr, "%s ", txt ); - txt = m_worker.GetString( frame.file ); - if( frame.line == 0 ) - { - ptr += sprintf( ptr, "(%s)", txt ); - } - else - { - ptr += sprintf( ptr, "(%s:%" PRIu32 ")", txt, frame.line ); - } - if( frameData->imageName.Active() ) - { - ptr += sprintf( ptr, " %s\n", m_worker.GetString( frameData->imageName ) ); - } - else - { - ptr += sprintf( ptr, "\n" ); - } - } - } - s << buf; - } - ImGui::SetClipboardText( s.str().c_str() ); - } - ImGui::SameLine(); - ImGui::TextUnformatted( ICON_FA_AT " Frame location:" ); - ImGui::SameLine(); - ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) ); - ImGui::RadioButton( "Source code", &m_showCallstackFrameAddress, 0 ); - ImGui::SameLine(); - ImGui::RadioButton( "Entry point", &m_showCallstackFrameAddress, 3 ); - ImGui::SameLine(); - ImGui::RadioButton( "Return address", &m_showCallstackFrameAddress, 1 ); - ImGui::SameLine(); - ImGui::RadioButton( "Symbol address", &m_showCallstackFrameAddress, 2 ); - - if( globalEntriesButton && m_worker.AreCallstackSamplesReady() ) - { - auto frame = m_worker.GetCallstackFrame( *cs.begin() ); - if( frame && frame->data[0].symAddr != 0 ) - { - auto sym = m_worker.GetSymbolStats( frame->data[0].symAddr ); - if( sym && !sym->parents.empty() ) - { - ImGui::SameLine(); - ImGui::Spacing(); - ImGui::SameLine(); - if( ImGui::Button( ICON_FA_DOOR_OPEN " Global entry statistics" ) ) - { - ShowSampleParents( frame->data[0].symAddr, true ); - } - } - } - } - ImGui::PopStyleVar(); - - ImGui::Separator(); - if( ImGui::BeginTable( "##callstack", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY ) ) - { - ImGui::TableSetupScrollFreeze( 0, 1 ); - ImGui::TableSetupColumn( "Frame", ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize ); - ImGui::TableSetupColumn( "Function" ); - ImGui::TableSetupColumn( "Location" ); - ImGui::TableSetupColumn( "Image" ); - ImGui::TableHeadersRow(); - - int fidx = 0; - int bidx = 0; - for( auto& entry : cs ) - { - auto frameData = m_worker.GetCallstackFrame( entry ); - if( !frameData ) - { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text( "%i", fidx++ ); - ImGui::TableNextColumn(); - char buf[32]; - sprintf( buf, "%p", (void*)m_worker.GetCanonicalPointer( entry ) ); - ImGui::TextUnformatted( buf ); - if( ImGui::IsItemClicked() ) - { - ImGui::SetClipboardText( buf ); - } - } - else - { - const auto fsz = frameData->size; - for( uint8_t f=0; fdata[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; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - bidx++; - if( f == fsz-1 ) - { - ImGui::Text( "%i", fidx++ ); - } - else - { - ImGui::PushFont( m_smallFont ); - TextDisabledUnformatted( "inline" ); - ImGui::PopFont(); - } - ImGui::TableNextColumn(); - { - ImGui::PushTextWrapPos( 0.0f ); - if( txt[0] == '[' ) - { - TextDisabledUnformatted( txt ); - } - else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 ) - { - TextColoredUnformatted( 0xFF8888FF, txt ); - } - else - { - ImGui::TextUnformatted( txt ); - } - ImGui::PopTextWrapPos(); - } - if( ImGui::IsItemClicked() ) - { - ImGui::SetClipboardText( txt ); - } - ImGui::TableNextColumn(); - ImGui::PushTextWrapPos( 0.0f ); - float indentVal = 0.f; - if( m_callstackBuzzAnim.Match( bidx ) ) - { - const auto time = m_callstackBuzzAnim.Time(); - indentVal = sin( time * 60.f ) * 10.f * time; - ImGui::Indent( indentVal ); - } - txt = m_worker.GetString( frame.file ); - switch( m_showCallstackFrameAddress ) - { - case 0: - TextDisabledUnformatted( LocationToString( txt, frame.line ) ); - if( ImGui::IsItemClicked() ) - { - ImGui::SetClipboardText( LocationToString( txt, frame.line ) ); - } - break; - case 1: - if( entry.sel == 0 ) - { - const auto addr = m_worker.GetCanonicalPointer( entry ); - ImGui::TextDisabled( "0x%" PRIx64, addr ); - if( ImGui::IsItemClicked() ) - { - char tmp[32]; - sprintf( tmp, "0x%" PRIx64, addr ); - ImGui::SetClipboardText( tmp ); - } - } - else - { - ImGui::TextDisabled( "Custom #%" PRIu64, entry.idx ); - } - break; - case 2: - if( entry.sel == 0 ) - { - ImGui::TextDisabled( "0x%" PRIx64, frame.symAddr ); - if( ImGui::IsItemClicked() ) - { - char tmp[32]; - sprintf( tmp, "0x%" PRIx64, frame.symAddr ); - ImGui::SetClipboardText( tmp ); - } - } - else - { - ImGui::TextDisabled( "Custom #%" PRIu64, entry.idx ); - } - break; - case 3: - { - const auto sym = m_worker.GetSymbolData( frame.symAddr ); - if( sym ) - { - const auto symtxt = m_worker.GetString( sym->file ); - TextDisabledUnformatted( LocationToString( symtxt, sym->line ) ); - if( ImGui::IsItemClicked() ) - { - ImGui::SetClipboardText( symtxt ); - } - } - else - { - TextDisabledUnformatted( "[unknown]" ); - } - break; - } - default: - assert( false ); - break; - } - if( ImGui::IsItemHovered() ) - { - if( m_showCallstackFrameAddress == 3 ) - { - const auto sym = m_worker.GetSymbolData( frame.symAddr ); - if( sym ) - { - const auto symtxt = m_worker.GetString( sym->file ); - DrawSourceTooltip( symtxt, sym->line ); - } - } - else - { - DrawSourceTooltip( txt, frame.line ); - } - if( ImGui::IsItemClicked( 1 ) ) - { - if( m_showCallstackFrameAddress == 3 ) - { - const auto sym = m_worker.GetSymbolData( frame.symAddr ); - if( sym ) - { - const auto symtxt = m_worker.GetString( sym->file ); - if( !ViewDispatch( symtxt, sym->line, frame.symAddr ) ) - { - m_callstackBuzzAnim.Enable( bidx, 0.5f ); - } - } - else - { - m_callstackBuzzAnim.Enable( bidx, 0.5f ); - } - } - else - { - if( !ViewDispatch( txt, frame.line, frame.symAddr ) ) - { - m_callstackBuzzAnim.Enable( bidx, 0.5f ); - } - } - } - } - if( indentVal != 0.f ) - { - ImGui::Unindent( indentVal ); - } - ImGui::PopTextWrapPos(); - ImGui::TableNextColumn(); - if( frameData->imageName.Active() ) - { - TextDisabledUnformatted( m_worker.GetString( frameData->imageName ) ); - } - } - } - } - ImGui::EndTable(); - } -} - void View::DrawMemoryAllocWindow() { bool show = true; @@ -10498,83 +10157,6 @@ void View::ZoneTooltip( const GpuEvent& ev ) ImGui::EndTooltip(); } -void View::CallstackTooltip( uint32_t idx ) -{ - ImGui::BeginTooltip(); - CallstackTooltipContents( idx ); - ImGui::EndTooltip(); -} - -void View::CallstackTooltipContents( uint32_t idx ) -{ - auto& cs = m_worker.GetCallstack( idx ); - int fidx = 0; - for( auto& entry : cs ) - { - auto frameData = m_worker.GetCallstackFrame( entry ); - if( !frameData ) - { - ImGui::TextDisabled( "%i.", fidx++ ); - ImGui::SameLine(); - ImGui::Text( "%p", (void*)m_worker.GetCanonicalPointer( entry ) ); - } - else - { - const auto fsz = frameData->size; - for( uint8_t f=0; fdata[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( ICON_FA_CARET_RIGHT ); - } - ImGui::SameLine(); - if( txt[0] == '[' ) - { - TextDisabledUnformatted( txt ); - } - else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 ) - { - TextColoredUnformatted( 0xFF8888FF, txt ); - } - else - { - ImGui::TextUnformatted( txt ); - } - if( frameData->imageName.Active() ) - { - ImGui::SameLine(); - ImGui::PushFont( m_smallFont ); - ImGui::AlignTextToFramePadding(); - TextDisabledUnformatted( m_worker.GetString( frameData->imageName ) ); - ImGui::PopFont(); - } - } - } - } -} - void View::CrashTooltip() { auto& crash = m_worker.GetCrashEvent(); @@ -10584,61 +10166,6 @@ void View::CrashTooltip() ImGui::EndTooltip(); } -void View::SmallCallstackButton( const char* name, uint32_t callstack, int& idx, bool tooltip ) -{ - bool hilite = m_callstackInfoWindow == callstack; - if( hilite ) - { - SetButtonHighlightColor(); - } - ImGui::PushID( idx++ ); - if( ImGui::SmallButton( name ) ) - { - m_callstackInfoWindow = callstack; - } - ImGui::PopID(); - if( hilite ) - { - ImGui::PopStyleColor( 3 ); - } - if( tooltip && ImGui::IsItemHovered() ) - { - CallstackTooltip( callstack ); - } -} - -void View::DrawCallstackCalls( uint32_t callstack, uint16_t limit ) const -{ - const auto& csdata = m_worker.GetCallstack( callstack ); - const auto cssz = std::min( csdata.size(), limit ); - bool first = true; - for( uint16_t i=0; idata[frameData->size - 1]; - auto txt = m_worker.GetString( frame.name ); - if( txt[0] == '[' ) - { - TextDisabledUnformatted( txt ); - } - else - { - ImGui::TextUnformatted( txt ); - } - } -} - void View::DrawSourceTooltip( const char* filename, uint32_t srcline, int before, int after, bool separateTooltip ) { if( !filename ) return; diff --git a/server/TracyView_Callstack.cpp b/server/TracyView_Callstack.cpp new file mode 100644 index 00000000..20554806 --- /dev/null +++ b/server/TracyView_Callstack.cpp @@ -0,0 +1,483 @@ +#include + +#include "../common/TracyStackFrames.hpp" +#include "TracyPrint.hpp" +#include "TracyView.hpp" + +namespace tracy +{ + +void View::DrawCallstackWindow() +{ + bool show = true; + const auto scale = GetScale(); + ImGui::SetNextWindowSize( ImVec2( 1400 * scale, 500 * scale ), ImGuiCond_FirstUseEver ); + ImGui::Begin( "Call stack", &show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse ); + if( !ImGui::GetCurrentWindowRead()->SkipItems ) + { + DrawCallstackTable( m_callstackInfoWindow, true ); + } + ImGui::End(); + if( !show ) m_callstackInfoWindow = 0; +} + +void View::DrawCallstackTable( uint32_t callstack, bool globalEntriesButton ) +{ + auto& cs = m_worker.GetCallstack( callstack ); + if( ClipboardButton() ) + { + std::ostringstream s; + int fidx = 0; + int bidx = 0; + for( auto& entry : cs ) + { + char buf[64*1024]; + auto frameData = m_worker.GetCallstackFrame( entry ); + if( !frameData ) + { + sprintf( buf, "%3i. %p\n", fidx++, (void*)m_worker.GetCanonicalPointer( entry ) ); + } + else + { + auto ptr = buf; + const auto fsz = frameData->size; + for( uint8_t f=0; fdata[f]; + auto txt = m_worker.GetString( frame.name ); + + if( fidx == 0 && f != fsz-1 ) + { + auto test = tracy::s_tracyStackFrames; + bool match = false; + do + { + if( strcmp( txt, *test ) == 0 ) + { + match = true; + break; + } + } + while( *++test ); + if( match ) continue; + } + + bidx++; + + if( f == fsz-1 ) + { + ptr += sprintf( ptr, "%3i. ", fidx++ ); + } + else + { + ptr += sprintf( ptr, "inl. " ); + } + ptr += sprintf( ptr, "%s ", txt ); + txt = m_worker.GetString( frame.file ); + if( frame.line == 0 ) + { + ptr += sprintf( ptr, "(%s)", txt ); + } + else + { + ptr += sprintf( ptr, "(%s:%" PRIu32 ")", txt, frame.line ); + } + if( frameData->imageName.Active() ) + { + ptr += sprintf( ptr, " %s\n", m_worker.GetString( frameData->imageName ) ); + } + else + { + ptr += sprintf( ptr, "\n" ); + } + } + } + s << buf; + } + ImGui::SetClipboardText( s.str().c_str() ); + } + ImGui::SameLine(); + ImGui::TextUnformatted( ICON_FA_AT " Frame location:" ); + ImGui::SameLine(); + ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 0, 0 ) ); + ImGui::RadioButton( "Source code", &m_showCallstackFrameAddress, 0 ); + ImGui::SameLine(); + ImGui::RadioButton( "Entry point", &m_showCallstackFrameAddress, 3 ); + ImGui::SameLine(); + ImGui::RadioButton( "Return address", &m_showCallstackFrameAddress, 1 ); + ImGui::SameLine(); + ImGui::RadioButton( "Symbol address", &m_showCallstackFrameAddress, 2 ); + + if( globalEntriesButton && m_worker.AreCallstackSamplesReady() ) + { + auto frame = m_worker.GetCallstackFrame( *cs.begin() ); + if( frame && frame->data[0].symAddr != 0 ) + { + auto sym = m_worker.GetSymbolStats( frame->data[0].symAddr ); + if( sym && !sym->parents.empty() ) + { + ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); + if( ImGui::Button( ICON_FA_DOOR_OPEN " Global entry statistics" ) ) + { + ShowSampleParents( frame->data[0].symAddr, true ); + } + } + } + } + ImGui::PopStyleVar(); + + ImGui::Separator(); + if( ImGui::BeginTable( "##callstack", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY ) ) + { + ImGui::TableSetupScrollFreeze( 0, 1 ); + ImGui::TableSetupColumn( "Frame", ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize ); + ImGui::TableSetupColumn( "Function" ); + ImGui::TableSetupColumn( "Location" ); + ImGui::TableSetupColumn( "Image" ); + ImGui::TableHeadersRow(); + + int fidx = 0; + int bidx = 0; + for( auto& entry : cs ) + { + auto frameData = m_worker.GetCallstackFrame( entry ); + if( !frameData ) + { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text( "%i", fidx++ ); + ImGui::TableNextColumn(); + char buf[32]; + sprintf( buf, "%p", (void*)m_worker.GetCanonicalPointer( entry ) ); + ImGui::TextUnformatted( buf ); + if( ImGui::IsItemClicked() ) + { + ImGui::SetClipboardText( buf ); + } + } + else + { + const auto fsz = frameData->size; + for( uint8_t f=0; fdata[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; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + bidx++; + if( f == fsz-1 ) + { + ImGui::Text( "%i", fidx++ ); + } + else + { + ImGui::PushFont( m_smallFont ); + TextDisabledUnformatted( "inline" ); + ImGui::PopFont(); + } + ImGui::TableNextColumn(); + { + ImGui::PushTextWrapPos( 0.0f ); + if( txt[0] == '[' ) + { + TextDisabledUnformatted( txt ); + } + else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 ) + { + TextColoredUnformatted( 0xFF8888FF, txt ); + } + else + { + ImGui::TextUnformatted( txt ); + } + ImGui::PopTextWrapPos(); + } + if( ImGui::IsItemClicked() ) + { + ImGui::SetClipboardText( txt ); + } + ImGui::TableNextColumn(); + ImGui::PushTextWrapPos( 0.0f ); + float indentVal = 0.f; + if( m_callstackBuzzAnim.Match( bidx ) ) + { + const auto time = m_callstackBuzzAnim.Time(); + indentVal = sin( time * 60.f ) * 10.f * time; + ImGui::Indent( indentVal ); + } + txt = m_worker.GetString( frame.file ); + switch( m_showCallstackFrameAddress ) + { + case 0: + TextDisabledUnformatted( LocationToString( txt, frame.line ) ); + if( ImGui::IsItemClicked() ) + { + ImGui::SetClipboardText( LocationToString( txt, frame.line ) ); + } + break; + case 1: + if( entry.sel == 0 ) + { + const auto addr = m_worker.GetCanonicalPointer( entry ); + ImGui::TextDisabled( "0x%" PRIx64, addr ); + if( ImGui::IsItemClicked() ) + { + char tmp[32]; + sprintf( tmp, "0x%" PRIx64, addr ); + ImGui::SetClipboardText( tmp ); + } + } + else + { + ImGui::TextDisabled( "Custom #%" PRIu64, entry.idx ); + } + break; + case 2: + if( entry.sel == 0 ) + { + ImGui::TextDisabled( "0x%" PRIx64, frame.symAddr ); + if( ImGui::IsItemClicked() ) + { + char tmp[32]; + sprintf( tmp, "0x%" PRIx64, frame.symAddr ); + ImGui::SetClipboardText( tmp ); + } + } + else + { + ImGui::TextDisabled( "Custom #%" PRIu64, entry.idx ); + } + break; + case 3: + { + const auto sym = m_worker.GetSymbolData( frame.symAddr ); + if( sym ) + { + const auto symtxt = m_worker.GetString( sym->file ); + TextDisabledUnformatted( LocationToString( symtxt, sym->line ) ); + if( ImGui::IsItemClicked() ) + { + ImGui::SetClipboardText( symtxt ); + } + } + else + { + TextDisabledUnformatted( "[unknown]" ); + } + break; + } + default: + assert( false ); + break; + } + if( ImGui::IsItemHovered() ) + { + if( m_showCallstackFrameAddress == 3 ) + { + const auto sym = m_worker.GetSymbolData( frame.symAddr ); + if( sym ) + { + const auto symtxt = m_worker.GetString( sym->file ); + DrawSourceTooltip( symtxt, sym->line ); + } + } + else + { + DrawSourceTooltip( txt, frame.line ); + } + if( ImGui::IsItemClicked( 1 ) ) + { + if( m_showCallstackFrameAddress == 3 ) + { + const auto sym = m_worker.GetSymbolData( frame.symAddr ); + if( sym ) + { + const auto symtxt = m_worker.GetString( sym->file ); + if( !ViewDispatch( symtxt, sym->line, frame.symAddr ) ) + { + m_callstackBuzzAnim.Enable( bidx, 0.5f ); + } + } + else + { + m_callstackBuzzAnim.Enable( bidx, 0.5f ); + } + } + else + { + if( !ViewDispatch( txt, frame.line, frame.symAddr ) ) + { + m_callstackBuzzAnim.Enable( bidx, 0.5f ); + } + } + } + } + if( indentVal != 0.f ) + { + ImGui::Unindent( indentVal ); + } + ImGui::PopTextWrapPos(); + ImGui::TableNextColumn(); + if( frameData->imageName.Active() ) + { + TextDisabledUnformatted( m_worker.GetString( frameData->imageName ) ); + } + } + } + } + ImGui::EndTable(); + } +} + +void View::SmallCallstackButton( const char* name, uint32_t callstack, int& idx, bool tooltip ) +{ + bool hilite = m_callstackInfoWindow == callstack; + if( hilite ) + { + SetButtonHighlightColor(); + } + ImGui::PushID( idx++ ); + if( ImGui::SmallButton( name ) ) + { + m_callstackInfoWindow = callstack; + } + ImGui::PopID(); + if( hilite ) + { + ImGui::PopStyleColor( 3 ); + } + if( tooltip && ImGui::IsItemHovered() ) + { + CallstackTooltip( callstack ); + } +} + +void View::DrawCallstackCalls( uint32_t callstack, uint16_t limit ) const +{ + const auto& csdata = m_worker.GetCallstack( callstack ); + const auto cssz = std::min( csdata.size(), limit ); + bool first = true; + for( uint16_t i=0; idata[frameData->size - 1]; + auto txt = m_worker.GetString( frame.name ); + if( txt[0] == '[' ) + { + TextDisabledUnformatted( txt ); + } + else + { + ImGui::TextUnformatted( txt ); + } + } +} + +void View::CallstackTooltip( uint32_t idx ) +{ + ImGui::BeginTooltip(); + CallstackTooltipContents( idx ); + ImGui::EndTooltip(); +} + +void View::CallstackTooltipContents( uint32_t idx ) +{ + auto& cs = m_worker.GetCallstack( idx ); + int fidx = 0; + for( auto& entry : cs ) + { + auto frameData = m_worker.GetCallstackFrame( entry ); + if( !frameData ) + { + ImGui::TextDisabled( "%i.", fidx++ ); + ImGui::SameLine(); + ImGui::Text( "%p", (void*)m_worker.GetCanonicalPointer( entry ) ); + } + else + { + const auto fsz = frameData->size; + for( uint8_t f=0; fdata[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( ICON_FA_CARET_RIGHT ); + } + ImGui::SameLine(); + if( txt[0] == '[' ) + { + TextDisabledUnformatted( txt ); + } + else if( m_worker.GetCanonicalPointer( entry ) >> 63 != 0 ) + { + TextColoredUnformatted( 0xFF8888FF, txt ); + } + else + { + ImGui::TextUnformatted( txt ); + } + if( frameData->imageName.Active() ) + { + ImGui::SameLine(); + ImGui::PushFont( m_smallFont ); + ImGui::AlignTextToFramePadding(); + TextDisabledUnformatted( m_worker.GetString( frameData->imageName ) ); + ImGui::PopFont(); + } + } + } + } +} + +}