diff --git a/profiler/src/profiler/TracyTimelineItemThread.cpp b/profiler/src/profiler/TracyTimelineItemThread.cpp index 930425d9..865aaec1 100644 --- a/profiler/src/profiler/TracyTimelineItemThread.cpp +++ b/profiler/src/profiler/TracyTimelineItemThread.cpp @@ -54,6 +54,7 @@ bool TimelineItemThread::IsEmpty() const return crash.thread != m_thread->id && m_thread->timeline.empty() && m_thread->messages.empty() && + !m_thread->inLocks && ( !m_worker.AreGhostZonesReady() || m_thread->ghostZones.empty() ); } @@ -280,7 +281,8 @@ void TimelineItemThread::HeaderExtraContents( const TimelineContext& ctx, int of bool TimelineItemThread::DrawContents( const TimelineContext& ctx, int& offset ) { m_view.DrawThread( ctx, *m_thread, m_draw, m_ctxDraw, m_samplesDraw, m_lockDraw, offset, m_depth, m_hasCtxSwitch, m_hasSamples ); - if( m_depth == 0 && !m_hasMessages && ( !m_view.GetViewData().drawSamples || !m_hasSamples ) ) + const bool lockRows = std::any_of( m_lockDraw.begin(), m_lockDraw.end(), [] ( const std::unique_ptr& ld ) { return ld->forceDraw || !ld->data.empty(); } ); + if( m_depth == 0 && !m_hasMessages && !lockRows && ( !m_view.GetViewData().drawSamples || !m_hasSamples ) ) { auto& crash = m_worker.GetCrashEvent(); return crash.thread == m_thread->id; diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index b19e9c99..517a6958 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -642,6 +642,7 @@ struct ThreadData SortedVector ctxSwitchSamples; uint64_t kernelSampleCnt; uint8_t isFiber; + uint8_t inLocks; // has a thread slot in at least one lock map ThreadData* fiber; uint8_t* stackCount; int32_t groupHint; diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 2bba2679..673e9bd5 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -932,6 +932,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks, bool allow td->groupHint = 0; } td->id = tid; + td->inLocks = 0; m_data.zonesCnt += td->count; uint32_t tsz; f.Read( tsz ); @@ -1009,6 +1010,16 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks, bool allow m_threadMap.emplace( tid, td ); } + for( auto& lit : m_data.lockMap ) + { + auto& lock = *lit.second; + for( auto& ti : lock.threads ) + { + auto it = m_threadMap.find( ti.thread ); + if( it != m_threadMap.end() ) it->second->inLocks = 1; + } + } + s_loadProgress.progress.store( LoadProgress::GpuZones, std::memory_order_relaxed ); f.Read( sz ); s_loadProgress.subTotal.store( sz, std::memory_order_relaxed ); @@ -3575,6 +3586,7 @@ ThreadData* Worker::NewThread( uint64_t thread, bool fiber, int32_t groupHint ) td->kernelSampleCnt = 0; td->pendingSample.time.Clear(); td->isFiber = fiber; + td->inLocks = 0; td->fiber = nullptr; td->stackCount = (uint8_t*)m_slab.AllocBig( sizeof( uint8_t ) * 64*1024 ); memset( td->stackCount, 0, sizeof( uint8_t ) * 64*1024 ); @@ -5533,13 +5545,14 @@ void Worker::ProcessLockThreadEvent( uint64_t id, int64_t time, uint64_t thread, assert( type < LockEvent::Type::WaitShared || lock.type == LockType::SharedLockable ); const auto lt = TscTime( RefTime( m_refTimeSerial, time ) ); - NoticeThread( thread ); + const auto td = NoticeThread( thread ); const auto slot = GetLockSlot( lock, thread ); if( slot == LockEvent::NoThread ) { LockThreadOverflowFailure(); return; } + td->inLocks = 1; AppendLock( lock, lt, slot, type ); }