mirror of
https://github.com/wolfpld/tracy.git
synced 2026-06-08 00:23:47 +00:00
adding "flatten view" to sequence points
This commit is contained in:
@@ -44,6 +44,7 @@ uint32_t TimelineItemThread::HeaderColor() const
|
||||
auto& crash = m_worker.GetCrashEvent();
|
||||
if( crash.thread == m_thread->id ) return 0xFF2222FF;
|
||||
if( m_thread->isFiber ) return 0xFF88FF88;
|
||||
if( m_thread->isFlatView ) return 0xFFFFCC88; // light blue (ABGR)
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
@@ -52,6 +53,7 @@ uint32_t TimelineItemThread::HeaderColorInactive() const
|
||||
auto& crash = m_worker.GetCrashEvent();
|
||||
if( crash.thread == m_thread->id ) return 0xFF111188;
|
||||
if( m_thread->isFiber ) return 0xFF448844;
|
||||
if( m_thread->isFlatView ) return 0xFF886644; // darker light blue
|
||||
return 0xFF888888;
|
||||
}
|
||||
|
||||
@@ -235,6 +237,8 @@ void TimelineItemThread::HeaderTooltip( const char* label ) const
|
||||
|
||||
void TimelineItemThread::HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth )
|
||||
{
|
||||
if( m_thread->isFlatView ) return;
|
||||
|
||||
m_view.DrawThreadMessagesList( ctx, m_msgDraw, offset, m_thread->id );
|
||||
|
||||
const bool hasGhostZones = m_worker.AreGhostZonesReady() && !m_thread->ghostZones.empty();
|
||||
@@ -275,6 +279,16 @@ void TimelineItemThread::DrawOverlay( const ImVec2& ul, const ImVec2& dr )
|
||||
|
||||
void TimelineItemThread::DrawExtraPopupItems()
|
||||
{
|
||||
if( m_thread->isFlatView )
|
||||
{
|
||||
if( ImGui::MenuItem( ICON_FA_TRASH_CAN " Destroy flatten view" ) )
|
||||
{
|
||||
m_view.QueueDestroyFlattenViewByTid( m_thread->id );
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_view.GetSelectThread() == m_thread->id )
|
||||
{
|
||||
if( ImGui::MenuItem( ICON_FA_TIMELINE " Unselect in CPU timeline" ) )
|
||||
@@ -493,7 +507,7 @@ int TimelineItemThread::PreprocessZoneLevel( const TimelineContext& ctx, const V
|
||||
if( hasChildren ) childrenInherited = DarkenColorSlightly( color );
|
||||
}
|
||||
}
|
||||
if( hasChildren )
|
||||
if( hasChildren && !m_thread->isFlatView )
|
||||
{
|
||||
const auto d = PreprocessZoneLevel( ctx, m_worker.GetZoneChildren( ev.Child() ), depth + 1, visible, childrenInherited );
|
||||
if( d > maxdepth ) maxdepth = d;
|
||||
|
||||
@@ -1230,9 +1230,17 @@ bool View::DrawImpl()
|
||||
{
|
||||
AddAnnotation( s, e );
|
||||
}
|
||||
if( m_seqFlattenPopupSeqId != 0 )
|
||||
{
|
||||
if( ImGui::Selectable( ICON_FA_DIAGRAM_PROJECT " Flatten sequence timeline" ) )
|
||||
{
|
||||
MakeFlattenView( m_seqFlattenPopupSeqId );
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
m_setRangePopupOpen = ImGui::IsPopupOpen( "SetZoneRange" );
|
||||
if( !m_setRangePopupOpen ) m_seqFlattenPopupSeqId = 0;
|
||||
|
||||
if( m_zoomAnim.active )
|
||||
{
|
||||
|
||||
@@ -171,6 +171,7 @@ public:
|
||||
}
|
||||
|
||||
void HighlightThread( uint64_t thread );
|
||||
void QueueDestroyFlattenViewByTid( uint64_t tid );
|
||||
void SelectThread( uint64_t thread );
|
||||
uint64_t GetSelectThread() const { return m_selectedThread; }
|
||||
void ZoomToRange( int64_t start, int64_t end, bool pause = true );
|
||||
@@ -279,8 +280,10 @@ private:
|
||||
void DrawTimelineFrames( const FrameData& frames );
|
||||
void DrawTimeline();
|
||||
void DrawSampleList( const TimelineContext& ctx, const std::vector<SamplesDraw>& drawList, const Vector<SampleData>& vec, int offset, uint64_t tid );
|
||||
void DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineDraw>& drawList, int offset, uint64_t tid, int maxDepth, double margin );
|
||||
void DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineDraw>& drawList, int offset, uint64_t tid, int maxDepth, double margin, bool isFlatView );
|
||||
void DrawSeqArrows( double pxns, const ImVec2& wpos );
|
||||
void MakeFlattenView( uint64_t seqId );
|
||||
void DestroyFlattenView( uint64_t seqId );
|
||||
void DrawThreadCropper( const int depth, const uint64_t tid, const float xPos, const float yPos, const float ostep, const float cropperWidth, const bool hasCtxSwitches );
|
||||
void DrawContextSwitchList( const TimelineContext& ctx, const std::vector<ContextSwitchDraw>& drawList, const Vector<ContextSwitchData>& ctxSwitch, int offset, int endOffset, bool isFiber );
|
||||
int DispatchGpuZoneLevel( const Vector<short_ptr<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 );
|
||||
@@ -537,6 +540,16 @@ private:
|
||||
};
|
||||
std::vector<SeqArrowDraw> m_seqArrowDraw;
|
||||
unordered_flat_map<const ZoneEvent*, float> m_seqZoneYPos;
|
||||
|
||||
struct FlattenView
|
||||
{
|
||||
std::unique_ptr<ThreadData> td;
|
||||
uint64_t seqId;
|
||||
};
|
||||
std::vector<FlattenView> m_flattenViews;
|
||||
std::vector<uint64_t> m_flattenViewDestroyQueue;
|
||||
uint32_t m_nextFlattenTid = 1;
|
||||
uint64_t m_seqFlattenPopupSeqId = 0;
|
||||
int m_frameHover = -1;
|
||||
bool m_messagesScrollBottom;
|
||||
|
||||
|
||||
@@ -261,6 +261,12 @@ void View::DrawTimeline()
|
||||
m_zoneHover2.Decay( nullptr );
|
||||
m_seqArrowDraw.clear();
|
||||
m_seqZoneYPos.clear();
|
||||
|
||||
for( auto seqId : m_flattenViewDestroyQueue )
|
||||
{
|
||||
DestroyFlattenView( seqId );
|
||||
}
|
||||
m_flattenViewDestroyQueue.clear();
|
||||
m_findZone.range.StartFrame();
|
||||
m_statRange.StartFrame();
|
||||
m_flameRange.StartFrame();
|
||||
@@ -398,6 +404,10 @@ void View::DrawTimeline()
|
||||
}
|
||||
m_threadReinsert.clear();
|
||||
}
|
||||
for( const auto& fv : m_flattenViews )
|
||||
{
|
||||
m_tc.AddItem<TimelineItemThread>( fv.td.get() );
|
||||
}
|
||||
for( const auto& v : m_threadOrder )
|
||||
{
|
||||
m_tc.AddItem<TimelineItemThread>( v );
|
||||
|
||||
@@ -76,7 +76,7 @@ void View::DrawThread( const TimelineContext& ctx, const ThreadData& thread, con
|
||||
if( !draw.empty() && yPos <= yMax && yPos + ostep * croppedDepth >= yMin )
|
||||
{
|
||||
// Only apply margin when croppingActive to avoid text moving around when mouse is getting close to the cropper widget
|
||||
DrawZoneList( ctx, draw, offset, thread.id, croppedDepth, croppingActive ? cropperAdditionalMargin + GetScale() /* Ensure text has a bit of space for text */ : 0.f );
|
||||
DrawZoneList( ctx, draw, offset, thread.id, croppedDepth, croppingActive ? cropperAdditionalMargin + GetScale() /* Ensure text has a bit of space for text */ : 0.f, thread.isFlatView != 0 );
|
||||
}
|
||||
offset += ostep * croppedDepth;
|
||||
|
||||
@@ -230,7 +230,7 @@ void View::DrawThreadOverlays( const ThreadData& thread, const ImVec2& ul, const
|
||||
}
|
||||
|
||||
|
||||
void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineDraw>& drawList, int _offset, uint64_t tid, int maxDepth, double margin )
|
||||
void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineDraw>& drawList, int _offset, uint64_t tid, int maxDepth, double margin, bool isFlatView )
|
||||
{
|
||||
auto draw = ImGui::GetWindowDrawList();
|
||||
const auto w = ctx.w;
|
||||
@@ -356,12 +356,23 @@ void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineD
|
||||
|
||||
const auto& seqRefMap = m_worker.GetZoneSeqRef();
|
||||
const auto seqIt = seqRefMap.find( &ev );
|
||||
if( seqIt != seqRefMap.end() )
|
||||
if( !isFlatView && seqIt != seqRefMap.end() )
|
||||
{
|
||||
m_seqZoneYPos[&ev] = wpos.y + offset + ty * 0.5f;
|
||||
}
|
||||
|
||||
const auto zoneColor = GetZoneColorData( ev, tid, v.depth, v.inheritedColor );
|
||||
// Preserve original-thread coloring when rendered on a flat view.
|
||||
uint64_t colorTid = tid;
|
||||
if( isFlatView && seqIt != seqRefMap.end() )
|
||||
{
|
||||
const auto& seqMap = m_worker.GetSequences();
|
||||
auto sit = seqMap.find( seqIt->second.seqId );
|
||||
if( sit != seqMap.end() && seqIt->second.continuationIdx < sit->second->continuations.size() )
|
||||
{
|
||||
colorTid = sit->second->continuations[seqIt->second.continuationIdx].tid;
|
||||
}
|
||||
}
|
||||
const auto zoneColor = GetZoneColorData( ev, colorTid, v.depth, v.inheritedColor );
|
||||
const char* zoneName = m_worker.GetZoneName( ev );
|
||||
|
||||
auto tsz = ImGui::CalcTextSize( zoneName );
|
||||
@@ -395,7 +406,11 @@ void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineD
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y + 1 ) ) )
|
||||
{
|
||||
ZoneTooltip( ev );
|
||||
if( IsMouseClickReleased( 1 ) ) m_setRangePopup = RangeSlim { ev.Start(), m_worker.GetZoneEnd( ev ), true };
|
||||
if( IsMouseClickReleased( 1 ) )
|
||||
{
|
||||
m_setRangePopup = RangeSlim { ev.Start(), m_worker.GetZoneEnd( ev ), true };
|
||||
m_seqFlattenPopupSeqId = ( !isFlatView && seqIt != seqRefMap.end() ) ? seqIt->second.seqId : 0;
|
||||
}
|
||||
|
||||
if( !m_zoomAnim.active && IsMouseClicked( 2 ) )
|
||||
{
|
||||
@@ -417,7 +432,7 @@ void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineD
|
||||
m_zoneSrcLocHighlight = ev.SrcLoc();
|
||||
m_zoneHover = &ev;
|
||||
|
||||
if( seqIt != seqRefMap.end() )
|
||||
if( !isFlatView && seqIt != seqRefMap.end() )
|
||||
{
|
||||
const auto& seqMap = m_worker.GetSequences();
|
||||
const auto sit = seqMap.find( seqIt->second.seqId );
|
||||
@@ -438,6 +453,7 @@ void View::DrawZoneList( const TimelineContext& ctx, const std::vector<TimelineD
|
||||
conts[idx+1].resumeTime, (const ZoneEvent*)conts[idx+1].zone } );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -701,6 +717,72 @@ void View::DrawThreadCropper( const int depth, const uint64_t tid, const float x
|
||||
}
|
||||
}
|
||||
|
||||
void View::MakeFlattenView( uint64_t seqId )
|
||||
{
|
||||
for( const auto& fv : m_flattenViews )
|
||||
{
|
||||
if( fv.seqId == seqId ) return; // idempotent
|
||||
}
|
||||
const auto& seqMap = m_worker.GetSequences();
|
||||
auto sit = seqMap.find( seqId );
|
||||
if( sit == seqMap.end() || sit->second->continuations.empty() ) return;
|
||||
const auto& conts = sit->second->continuations;
|
||||
|
||||
const uint64_t synthTid = ( uint64_t(2) << 32 ) | m_nextFlattenTid++;
|
||||
|
||||
auto td = std::make_unique<ThreadData>();
|
||||
td->id = synthTid;
|
||||
td->count = 0;
|
||||
td->nextZoneId = 0;
|
||||
td->kernelSampleCnt = 0;
|
||||
td->isFiber = 0;
|
||||
td->isFlatView = 1;
|
||||
td->fiber = nullptr;
|
||||
td->stackCount = nullptr;
|
||||
td->groupHint = 0;
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
td->ghostIdx = 0;
|
||||
#endif
|
||||
|
||||
for( const auto& c : conts )
|
||||
{
|
||||
td->timeline.push_back( c.zone );
|
||||
}
|
||||
|
||||
char name[128];
|
||||
const auto* firstZone = (const ZoneEvent*)conts[0].zone;
|
||||
const char* zName = m_worker.GetZoneName( *firstZone );
|
||||
std::snprintf( name, sizeof( name ), "flat: %s", zName ? zName : "?" );
|
||||
m_worker.RegisterFlattenThreadName( synthTid, name, strlen( name ) );
|
||||
|
||||
m_flattenViews.push_back( FlattenView{ std::move( td ), seqId } );
|
||||
}
|
||||
|
||||
void View::DestroyFlattenView( uint64_t seqId )
|
||||
{
|
||||
for( auto it = m_flattenViews.begin(); it != m_flattenViews.end(); ++it )
|
||||
{
|
||||
if( it->seqId == seqId )
|
||||
{
|
||||
m_worker.UnregisterFlattenThreadName( it->td->id );
|
||||
m_flattenViews.erase( it );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void View::QueueDestroyFlattenViewByTid( uint64_t tid )
|
||||
{
|
||||
for( const auto& fv : m_flattenViews )
|
||||
{
|
||||
if( fv.td->id == tid )
|
||||
{
|
||||
m_flattenViewDestroyQueue.push_back( fv.seqId );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void View::DrawSeqArrows( double pxns, const ImVec2& wpos )
|
||||
{
|
||||
if( m_seqArrowDraw.empty() ) return;
|
||||
|
||||
@@ -706,6 +706,7 @@ struct ThreadData
|
||||
Vector<SampleData> ctxSwitchSamples;
|
||||
uint64_t kernelSampleCnt;
|
||||
uint8_t isFiber;
|
||||
uint8_t isFlatView = 0;
|
||||
ThreadData* fiber;
|
||||
uint8_t* stackCount;
|
||||
int32_t groupHint;
|
||||
|
||||
@@ -3695,6 +3695,18 @@ void Worker::CheckFiberName( uint64_t id, uint64_t tid )
|
||||
if( m_sock.IsValid() ) Query( ServerQueryFiberName, id );
|
||||
}
|
||||
|
||||
void Worker::RegisterFlattenThreadName( uint64_t tid, const char* name, size_t sz )
|
||||
{
|
||||
if( m_data.threadNames.find( tid ) != m_data.threadNames.end() ) return;
|
||||
const auto sl = StoreString( name, sz );
|
||||
m_data.threadNames.emplace( tid, sl.ptr );
|
||||
}
|
||||
|
||||
void Worker::UnregisterFlattenThreadName( uint64_t tid )
|
||||
{
|
||||
m_data.threadNames.erase( tid );
|
||||
}
|
||||
|
||||
void Worker::CheckExternalName( uint64_t id )
|
||||
{
|
||||
if( m_data.externalNames.find( id ) != m_data.externalNames.end() ) return;
|
||||
|
||||
@@ -614,6 +614,8 @@ public:
|
||||
const char* GetString( const StringRef& ref ) const;
|
||||
const char* GetString( const StringIdx& idx ) const;
|
||||
const char* GetThreadName( uint64_t id ) const;
|
||||
void RegisterFlattenThreadName( uint64_t tid, const char* name, size_t sz );
|
||||
void UnregisterFlattenThreadName( uint64_t tid );
|
||||
bool IsThreadLocal( uint64_t id ) { return IsThreadLocal( id, m_data.threadDataLast ); }
|
||||
bool IsThreadLocal( uint64_t id, ThreadCache& cache );
|
||||
bool IsThreadFiber( uint64_t id );
|
||||
|
||||
Reference in New Issue
Block a user