mirror of
https://github.com/wolfpld/tracy.git
synced 2026-10-23 01:00:54 +00:00
401 lines
14 KiB
C++
401 lines
14 KiB
C++
#include "TracyImGui.hpp"
|
|
#include "TracyMouse.hpp"
|
|
#include "TracyPrint.hpp"
|
|
#include "TracyTimelineItem.hpp"
|
|
#include "TracyView.hpp"
|
|
#include "../Fonts.hpp"
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
extern double s_time;
|
|
|
|
void View::DrawDeadlockMembers( const DeadlockGroup& group, const Vector<DeadlockMember>& members ) const
|
|
{
|
|
const auto& lockMap = m_worker.GetLockMap();
|
|
for( uint32_t i=group.first; i<group.first+group.cnt; i++ )
|
|
{
|
|
const auto& m = members[i];
|
|
const auto it = lockMap.find( m.lock );
|
|
assert( it != lockMap.end() );
|
|
if( m.holder == m.thread )
|
|
{
|
|
ImGui::Text( "\"%s\" waits for %u: %s (upgrade request)", m_worker.GetThreadName( m.thread ), m.lock, GetLockDisplayName( m_worker, *it->second ) );
|
|
}
|
|
else
|
|
{
|
|
ImGui::Text( "\"%s\" waits for %u: %s, held by \"%s\"", m_worker.GetThreadName( m.thread ), m.lock, GetLockDisplayName( m_worker, *it->second ), m_worker.GetThreadName( m.holder ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void View::DrawDeadlockDetail( uint64_t thread, uint32_t lock ) const
|
|
{
|
|
const auto& dgroups = m_worker.GetDeadlockGroups();
|
|
const auto& dmembers = m_worker.GetDeadlockMembers();
|
|
for( const auto& g : dgroups )
|
|
{
|
|
bool match = false;
|
|
for( uint32_t i=g.first; i<g.first+g.cnt; i++ )
|
|
{
|
|
const auto& m = dmembers[i];
|
|
if( ( thread == AnyThread || m.thread == thread ) && ( lock == AnyLock || m.lock == lock ) )
|
|
{
|
|
match = true;
|
|
break;
|
|
}
|
|
}
|
|
if( !match ) continue;
|
|
ImGui::Separator();
|
|
TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), "Deadlock detected" );
|
|
TextFocused( "Cycle closed at:", TimeToString( g.time ) );
|
|
DrawDeadlockMembers( g, dmembers );
|
|
}
|
|
}
|
|
|
|
void View::DeadlockTooltip( const DeadlockGroup& group, const Vector<DeadlockMember>& members ) const
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Deadlock detected" );
|
|
TextFocused( "Cycle closed at:", TimeToString( group.time ) );
|
|
ImGui::Separator();
|
|
DrawDeadlockMembers( group, members );
|
|
ImGui::EndTooltip();
|
|
}
|
|
|
|
void View::DeadlocksTooltip()
|
|
{
|
|
const auto& groups = m_worker.GetDeadlockGroups();
|
|
const auto& members = m_worker.GetDeadlockMembers();
|
|
if( groups.size() == 1 )
|
|
{
|
|
DeadlockTooltip( groups[0], members );
|
|
return;
|
|
}
|
|
ImGui::BeginTooltip();
|
|
ImGui::Text( "%zu deadlocks detected", groups.size() );
|
|
for( size_t gi=0; gi<groups.size(); gi++ )
|
|
{
|
|
const auto& g = groups[gi];
|
|
ImGui::Separator();
|
|
ImGui::Text( "Cycle #%zu closed at: %s", gi+1, TimeToString( g.time ) );
|
|
ImGui::Indent( ImGui::GetTextLineHeight() );
|
|
DrawDeadlockMembers( g, members );
|
|
ImGui::Unindent( ImGui::GetTextLineHeight() );
|
|
}
|
|
ImGui::EndTooltip();
|
|
}
|
|
|
|
void View::DrawNotificationArea()
|
|
{
|
|
if( m_sendQueueWarning.enabled )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 0, 0.5, 1, 1 ), ICON_FA_SATELLITE_DISH );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "The client is slow to answer queries." );
|
|
ImGui::TextUnformatted( "" );
|
|
ImGui::TextWrapped( "Such behavior is typically caused by the symbol resolution performed client-side. If this is a problem, you may try the following options:" );
|
|
ImGui::BulletText( "Disable inline-symbol resolution with TRACY_NO_CALLSTACK_INLINES" );
|
|
ImGui::BulletText( "Disable call stack sampling with TRACY_NO_SAMPLING" );
|
|
ImGui::BulletText( "Disable context switch call stacks with TRACY_NO_WAIT_STACKS" );
|
|
ImGui::BulletText( "Change sampling frequency with TRACY_SAMPLING_HZ" );
|
|
ImGui::BulletText( "Disable symbol resolution altogether with TRACY_NO_CALLSTACK" );
|
|
ImGui::TextWrapped( "For more information, please refer to the manual." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_sendQueueWarning.enabled = false;
|
|
}
|
|
}
|
|
auto& io = ImGui::GetIO();
|
|
const auto ty = ImGui::GetTextLineHeight();
|
|
if( m_worker.IsConnected() )
|
|
{
|
|
size_t sqs;
|
|
{
|
|
std::shared_lock<std::shared_mutex> lock( m_worker.GetMbpsDataLock() );
|
|
sqs = m_worker.GetSendQueueSize();
|
|
}
|
|
if( sqs != 0 )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), ICON_FA_SATELLITE_DISH );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
TextFocused( "Query backlog:", RealToString( sqs ) );
|
|
ImGui::EndTooltip();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const auto sif = m_worker.GetSendInFlight();
|
|
if( sif != 0 ) m_sendInFlightTime = s_time;
|
|
if( s_time - m_sendInFlightTime < 0.1f )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.75f, 0, 1 ), ICON_FA_SATELLITE_DISH );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
TextFocused( "Queries in flight:", RealToString( sif ) );
|
|
ImGui::EndTooltip();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
auto& crash = m_worker.GetCrashEvent();
|
|
if( crash.thread != 0 )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), ICON_FA_SKULL );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
CrashTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) )
|
|
{
|
|
m_callstackView = {
|
|
.id = crash.callstack,
|
|
.thread = crash.thread
|
|
};
|
|
}
|
|
if( IsMouseClicked( ImGuiMouseButton_Middle ) )
|
|
{
|
|
CenterAtTime( crash.time );
|
|
}
|
|
}
|
|
}
|
|
const auto& deadlocks = m_worker.GetDeadlockGroups();
|
|
if( !deadlocks.empty() )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0, 0, 1 ), ICON_FA_ARROWS_SPIN );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
DeadlocksTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) )
|
|
{
|
|
m_showInfo = true;
|
|
}
|
|
}
|
|
}
|
|
if( m_worker.AreSamplesInconsistent() )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EYE_DROPPER );
|
|
TooltipIfHovered( "Sampling data and ghost zones may be displayed wrongly due to data inconsistency. Save and reload the trace to fix this." );
|
|
}
|
|
if( m_worker.HasExcessiveZoneDepth() )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_LAYER_GROUP );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
const auto t = m_worker.GetExcessiveZoneDepthTime();
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Some zones exceed the maximum nesting depth of 256 and are not displayed." );
|
|
ImGui::Separator();
|
|
TextFocused( "First occurrence:", TimeToString( t - m_worker.GetFirstTime() ) );
|
|
ImGui::TextDisabled( "Click to center the view at this time." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) CenterAtTime( t );
|
|
}
|
|
}
|
|
if( m_vd.drawEmptyLabels )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EXPAND );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Displaying empty labels." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawEmptyLabels = false;
|
|
}
|
|
}
|
|
if( !m_vd.drawContextSwitches )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_PERSON_HIKING );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Context switches are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawContextSwitches = true;
|
|
}
|
|
}
|
|
if( !m_vd.drawCpuData )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_SLIDERS );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "CPU data is hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawCpuData = true;
|
|
}
|
|
}
|
|
if( !m_vd.drawGpuZones )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_DISPLAY );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "GPU zones are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawGpuZones = true;
|
|
}
|
|
}
|
|
if( !m_vd.drawZones )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_MICROCHIP );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "CPU zones are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawZones = true;
|
|
}
|
|
}
|
|
if( !m_vd.ghostZones )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_GHOST );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Ghost zones are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.ghostZones = true;
|
|
}
|
|
}
|
|
if( !m_vd.drawLocks )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_LOCK );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Locks are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawLocks = true;
|
|
}
|
|
}
|
|
if( !m_vd.drawPlots )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_SIGNATURE );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Plots are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawPlots = true;
|
|
}
|
|
}
|
|
if( !m_vd.drawSections )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_ARROWS_LEFT_RIGHT_TO_LINE );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Sections are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_vd.drawSections = true;
|
|
}
|
|
}
|
|
{
|
|
bool hidden = false;
|
|
for( auto& v : m_visMap )
|
|
{
|
|
if( !v.second )
|
|
{
|
|
hidden = true;
|
|
break;
|
|
}
|
|
}
|
|
if( !hidden )
|
|
{
|
|
for( auto& v : m_sectionVisMap )
|
|
{
|
|
if( !v.second )
|
|
{
|
|
hidden = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( !hidden )
|
|
{
|
|
for( auto& v : m_tc.GetItemMap() )
|
|
{
|
|
if( !v.second->IsVisible() )
|
|
{
|
|
hidden = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( hidden )
|
|
{
|
|
ImGui::SameLine();
|
|
TextColoredUnformatted( ImVec4( 1, 0.5, 0, 1 ), ICON_FA_EYE_LOW_VISION );
|
|
if( ImGui::IsItemHovered() )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Some timeline entries are hidden." );
|
|
ImGui::EndTooltip();
|
|
if( IsMouseClicked( ImGuiMouseButton_Left ) ) m_showOptions = true;
|
|
}
|
|
}
|
|
}
|
|
if( !m_worker.IsBackgroundDone() )
|
|
{
|
|
ImGui::SameLine();
|
|
DrawWaitingDots( s_time, false );
|
|
auto rmin = ImGui::GetItemRectMin();
|
|
const auto rmax = ImGui::GetItemRectMax();
|
|
if( ImGui::IsMouseHoveringRect( rmin, rmax ) )
|
|
{
|
|
ImGui::BeginTooltip();
|
|
ImGui::TextUnformatted( "Processing background tasks" );
|
|
ImGui::EndTooltip();
|
|
}
|
|
}
|
|
if( m_saveThreadState.load( std::memory_order_relaxed ) == SaveThreadState::Saving )
|
|
{
|
|
ImGui::SameLine();
|
|
ImGui::TextUnformatted( ICON_FA_FLOPPY_DISK " Saving trace…" );
|
|
m_notificationTime = 0;
|
|
}
|
|
else if( m_notificationTime > 0 )
|
|
{
|
|
m_notificationTime -= std::min( io.DeltaTime, 0.25f );
|
|
ImGui::SameLine();
|
|
TextDisabledUnformatted( m_notificationText.c_str() );
|
|
}
|
|
|
|
ImGui::PushFont( g_fonts.normal, FontSmall );
|
|
const auto wpos = ImGui::GetWindowPos();
|
|
const auto w = ImGui::GetContentRegionAvail().x;
|
|
const auto fps = RealToString( int( io.Framerate + 0.5f ) );
|
|
const auto fpssz = ImGui::CalcTextSize( fps ).x;
|
|
ImGui::GetWindowDrawList()->AddText( wpos + ImVec2( w-fpssz, 0 ), 0x88FFFFFF, fps );
|
|
|
|
#ifndef NDEBUG
|
|
const auto dsz = ImGui::CalcTextSize( "8888 DEBUG" ).x;
|
|
ImGui::GetWindowDrawList()->AddText( wpos + ImVec2( w-dsz, 0 ), 0x886666FF, "DEBUG" );
|
|
#endif
|
|
|
|
ImGui::PopFont();
|
|
}
|
|
|
|
}
|