diff --git a/profiler/src/profiler/TracyView.cpp b/profiler/src/profiler/TracyView.cpp index c670aa3a..1252f898 100644 --- a/profiler/src/profiler/TracyView.cpp +++ b/profiler/src/profiler/TracyView.cpp @@ -758,6 +758,8 @@ bool View::DrawImpl() return keepOpen; } + m_worker.UpdateDeadlocks(); + if( m_achievements ) { if( m_worker.IsConnected() ) Achieve( "connectToClient" ); diff --git a/profiler/src/profiler/TracyView.hpp b/profiler/src/profiler/TracyView.hpp index 2495a388..57f56ef1 100644 --- a/profiler/src/profiler/TracyView.hpp +++ b/profiler/src/profiler/TracyView.hpp @@ -68,6 +68,8 @@ struct MessagesDraw; struct CpuUsageDraw; struct CpuCtxDraw; struct LockDraw; +struct DeadlockGroup; +struct DeadlockMember; struct PlotDraw; struct FlameGraphContext; @@ -211,6 +213,12 @@ public: void DrawThread( const TimelineContext& ctx, const ThreadData& thread, const std::vector& draw, const std::vector& ctxDraw, const std::vector& samplesDraw, const std::vector>& lockDraw, int& offset, int depth, bool hasCtxSwitches, bool hasSamples ); void DrawThreadMessagesList( const TimelineContext& ctx, const std::vector& drawList, int offset, uint64_t tid ); void DrawThreadOverlays( const ThreadData& thread, const ImVec2& ul, const ImVec2& dr ); + + static constexpr uint64_t AnyThread = ~0ull; + static constexpr uint32_t AnyLock = ~0u; + void DrawDeadlockMembers( const DeadlockGroup& group, const Vector& members ) const; + void DrawDeadlockDetail( uint64_t thread, uint32_t lock ) const; + bool DrawGpu( const TimelineContext& ctx, const GpuCtxData& gpu, int& offset ); bool DrawCpuData( const TimelineContext& ctx, const std::vector& cpuDraw, const std::vector>& ctxDraw, int& offset, bool hasCpuData ); void DrawThreadMigrations( const TimelineContext& ctx, const int origOffset, uint64_t thread ); @@ -419,7 +427,8 @@ private: void ShowZoneInfo( const ZoneEvent& ev ); void ShowZoneInfo( const GpuEvent& ev, uint64_t thread ); - + void DeadlockTooltip( const DeadlockGroup& group, const Vector& members ) const; + void DeadlocksTooltip(); void ZoneTooltip( const ZoneEvent& ev ); void ZoneTooltip( const GpuEvent& ev ); void CallstackTooltip( uint32_t idx ); diff --git a/profiler/src/profiler/TracyView_NotificationArea.cpp b/profiler/src/profiler/TracyView_NotificationArea.cpp index 24f11068..f9ee407f 100644 --- a/profiler/src/profiler/TracyView_NotificationArea.cpp +++ b/profiler/src/profiler/TracyView_NotificationArea.cpp @@ -10,6 +10,82 @@ namespace tracy extern double s_time; +void View::DrawDeadlockMembers( const DeadlockGroup& group, const Vector& members ) const +{ + const auto& lockMap = m_worker.GetLockMap(); + for( uint32_t i=group.first; isecond ) ); + } + 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& 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