diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj index ddb0bdc3..85406f8b 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 5e1b22db..1895bfaf 100644 --- a/profiler/build/win32/Tracy.vcxproj.filters +++ b/profiler/build/win32/Tracy.vcxproj.filters @@ -246,6 +246,9 @@ server + + server + diff --git a/server/TracyColor.hpp b/server/TracyColor.hpp index 78534be8..6dfad6dd 100644 --- a/server/TracyColor.hpp +++ b/server/TracyColor.hpp @@ -1,13 +1,25 @@ #ifndef __TRACYCOLOR_HPP__ #define __TRACYCOLOR_HPP__ +#include #include +#include "../common/TracyForceInline.hpp" + namespace tracy { uint32_t GetHsvColor( uint64_t hue, int value ); +template +static tracy_force_inline uint32_t HighlightColor( uint32_t color ) +{ + return 0xFF000000 | + ( std::min( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + V ) ) << 16 ) | + ( std::min( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + V ) ) << 8 ) | + ( std::min( 0xFF, ( ( ( color & 0x000000FF ) ) + V ) ) ); +} + } #endif diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 1a39e45a..d3f39e7d 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -88,15 +88,6 @@ static inline bool AreOtherWaiting( uint64_t bitlist, uint64_t threadBit ) return ( bitlist & ~threadBit ) != 0; } -template -static tracy_force_inline uint32_t HighlightColor( uint32_t color ) -{ - return 0xFF000000 | - ( std::min( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + V ) ) << 16 ) | - ( std::min( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + V ) ) << 8 ) | - ( std::min( 0xFF, ( ( ( color & 0x000000FF ) ) + V ) ) ); -} - enum { MinVisSize = 3 }; enum { MinCtxSize = 4 }; @@ -16856,153 +16847,6 @@ const char* View::GetPlotName( const PlotData* plot ) const } } -uint32_t View::GetThreadColor( uint64_t thread, int depth ) -{ - if( m_vd.dynamicColors == 0 ) return 0xFFCC5555; - return GetHsvColor( thread, depth ); -} - -uint32_t View::GetRawSrcLocColor( const SourceLocation& srcloc, int depth ) -{ - auto namehash = srcloc.namehash; - if( namehash == 0 && srcloc.function.active ) - { - const auto f = m_worker.GetString( srcloc.function ); - namehash = charutil::hash( f ); - if( namehash == 0 ) namehash++; - srcloc.namehash = namehash; - } - if( namehash == 0 ) - { - return GetHsvColor( uint64_t( &srcloc ), depth ); - } - else - { - return GetHsvColor( namehash, depth ); - } -} - -uint32_t View::GetSrcLocColor( const SourceLocation& srcloc, int depth ) -{ - const auto color = srcloc.color; - if( color != 0 && !m_vd.forceColors ) return color | 0xFF000000; - if( m_vd.dynamicColors == 0 ) return 0xFFCC5555; - return GetRawSrcLocColor( srcloc, depth ); -} - -uint32_t View::GetZoneColor( const ZoneEvent& ev, uint64_t thread, int depth ) -{ - const auto sl = ev.SrcLoc(); - const auto& srcloc = m_worker.GetSourceLocation( sl ); - if( !m_vd.forceColors ) - { - if( m_worker.HasZoneExtra( ev ) ) - { - const auto custom_color = m_worker.GetZoneExtra( ev ).color.Val(); - if( custom_color != 0 ) return custom_color | 0xFF000000; - } - const auto color = srcloc.color; - if( color != 0 ) return color | 0xFF000000; - } - switch( m_vd.dynamicColors ) - { - case 0: - return 0xFFCC5555; - case 1: - return GetHsvColor( thread, depth ); - case 2: - return GetRawSrcLocColor( srcloc, depth ); - default: - assert( false ); - return 0; - } -} - -uint32_t View::GetZoneColor( const GpuEvent& ev ) -{ - const auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() ); - const auto color = srcloc.color; - return color != 0 ? ( color | 0xFF000000 ) : 0xFF222288; -} - -View::ZoneColorData View::GetZoneColorData( const ZoneEvent& ev, uint64_t thread, int depth ) -{ - ZoneColorData ret; - const auto& srcloc = ev.SrcLoc(); - if( m_zoneInfoWindow == &ev ) - { - ret.color = GetZoneColor( ev, thread, depth ); - ret.accentColor = 0xFF44DD44; - ret.thickness = 3.f; - ret.highlight = true; - } - else if( m_zoneHighlight == &ev ) - { - ret.color = GetZoneColor( ev, thread, depth ); - ret.accentColor = 0xFF4444FF; - ret.thickness = 3.f; - ret.highlight = true; - } - else if( m_zoneSrcLocHighlight == srcloc ) - { - ret.color = GetZoneColor( ev, thread, depth ); - ret.accentColor = 0xFFEEEEEE; - ret.thickness = 1.f; - ret.highlight = true; - } - else if( m_findZone.show && !m_findZone.match.empty() && m_findZone.match[m_findZone.selMatch] == srcloc ) - { - uint32_t color = 0xFF229999; - if( m_findZone.highlight.active ) - { - const auto zt = m_worker.GetZoneEnd( ev ) - ev.Start(); - if( zt >= m_findZone.highlight.start && zt <= m_findZone.highlight.end ) - { - color = 0xFFFFCC66; - } - } - ret.color = color; - ret.accentColor = HighlightColor( color ); - ret.thickness = 3.f; - ret.highlight = true; - } - else - { - const auto color = GetZoneColor( ev, thread, depth ); - ret.color = color; - ret.accentColor = HighlightColor( color ); - ret.thickness = 1.f; - ret.highlight = false; - } - return ret; -} - -View::ZoneColorData View::GetZoneColorData( const GpuEvent& ev ) -{ - ZoneColorData ret; - const auto color = GetZoneColor( ev ); - ret.color = color; - if( m_gpuInfoWindow == &ev ) - { - ret.accentColor = 0xFF44DD44; - ret.thickness = 3.f; - ret.highlight = true; - } - else if( m_gpuHighlight == &ev ) - { - ret.accentColor = 0xFF4444FF; - ret.thickness = 3.f; - ret.highlight = true; - } - else - { - ret.accentColor = HighlightColor( color ); - ret.thickness = 1.f; - ret.highlight = false; - } - return ret; -} - void View::ZoomToZone( const ZoneEvent& ev ) { const auto end = m_worker.GetZoneEnd( ev ); @@ -17387,383 +17231,6 @@ void View::CrashTooltip() ImGui::EndTooltip(); } -const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone ) const -{ -#ifndef TRACY_NO_STATISTICS - if( m_worker.AreSourceLocationZonesReady() ) - { - auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); - if( !slz.zones.empty() && slz.zones.is_sorted() ) - { - auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); - if( it != slz.zones.end() && it->Zone() == &zone ) - { - return GetZoneParent( zone, m_worker.DecompressThread( it->Thread() ) ); - } - } - } -#endif - - for( const auto& thread : m_worker.GetThreadData() ) - { - const ZoneEvent* parent = nullptr; - const Vector>* timeline = &thread->timeline; - if( timeline->empty() ) continue; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( it != vec->begin() ) --it; - if( zone.IsEndValid() && it->Start() > zone.End() ) break; - if( it == &zone ) return parent; - if( !it->HasChildren() ) break; - parent = it; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); - if( it != timeline->begin() ) --it; - if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; - if( *it == &zone ) return parent; - if( !(*it)->HasChildren() ) break; - parent = *it; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - } - } - return nullptr; -} - -const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone, uint64_t tid ) const -{ - const auto thread = m_worker.GetThreadData( tid ); - const ZoneEvent* parent = nullptr; - const Vector>* timeline = &thread->timeline; - if( timeline->empty() ) return nullptr; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( it != vec->begin() ) --it; - if( zone.IsEndValid() && it->Start() > zone.End() ) break; - if( it == &zone ) return parent; - if( !it->HasChildren() ) break; - parent = it; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); - if( it != timeline->begin() ) --it; - if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; - if( *it == &zone ) return parent; - if( !(*it)->HasChildren() ) break; - parent = *it; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - } - return nullptr; -} - -bool View::IsZoneReentry( const ZoneEvent& zone ) const -{ -#ifndef TRACY_NO_STATISTICS - if( m_worker.AreSourceLocationZonesReady() ) - { - auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); - if( !slz.zones.empty() && slz.zones.is_sorted() ) - { - auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); - if( it != slz.zones.end() && it->Zone() == &zone ) - { - return IsZoneReentry( zone, m_worker.DecompressThread( it->Thread() ) ); - } - } - } -#endif - - for( const auto& thread : m_worker.GetThreadData() ) - { - const ZoneEvent* parent = nullptr; - const Vector>* timeline = &thread->timeline; - if( timeline->empty() ) continue; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( it != vec->begin() ) --it; - if( zone.IsEndValid() && it->Start() > zone.End() ) break; - if( it == &zone ) return false; - if( !it->HasChildren() ) break; - parent = it; - if (parent->SrcLoc() == zone.SrcLoc() ) return true; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); - if( it != timeline->begin() ) --it; - if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; - if( *it == &zone ) return false; - if( !(*it)->HasChildren() ) break; - parent = *it; - if (parent->SrcLoc() == zone.SrcLoc() ) return true; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - } - } - return false; -} - -bool View::IsZoneReentry( const ZoneEvent& zone, uint64_t tid ) const -{ - const auto thread = m_worker.GetThreadData( tid ); - const ZoneEvent* parent = nullptr; - const Vector>* timeline = &thread->timeline; - if( timeline->empty() ) return false; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( it != vec->begin() ) --it; - if( zone.IsEndValid() && it->Start() > zone.End() ) break; - if( it == &zone ) return false; - if( !it->HasChildren() ) break; - parent = it; - if (parent->SrcLoc() == zone.SrcLoc() ) return true; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); - if( it != timeline->begin() ) --it; - if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; - if( *it == &zone ) return false; - if( !(*it)->HasChildren() ) break; - parent = *it; - if (parent->SrcLoc() == zone.SrcLoc() ) return true; - timeline = &m_worker.GetZoneChildren( parent->Child() ); - } - } - return false; -} - -const GpuEvent* View::GetZoneParent( const GpuEvent& zone ) const -{ - for( const auto& ctx : m_worker.GetGpuData() ) - { - for( const auto& td : ctx->threadData ) - { - const GpuEvent* parent = nullptr; - const Vector>* timeline = &td.second.timeline; - if( timeline->empty() ) continue; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } ); - if( it != vec->begin() ) --it; - if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break; - if( it == &zone ) return parent; - if( it->Child() < 0 ) break; - parent = it; - timeline = &m_worker.GetGpuChildren( parent->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } ); - if( it != timeline->begin() ) --it; - if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break; - if( *it == &zone ) return parent; - if( (*it)->Child() < 0 ) break; - parent = *it; - timeline = &m_worker.GetGpuChildren( parent->Child() ); - } - } - } - } - return nullptr; -} - -const ThreadData* View::GetZoneThreadData( const ZoneEvent& zone ) const -{ -#ifndef TRACY_NO_STATISTICS - if( m_worker.AreSourceLocationZonesReady() ) - { - auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); - if( !slz.zones.empty() && slz.zones.is_sorted() ) - { - auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); - if( it != slz.zones.end() && it->Zone() == &zone ) - { - return m_worker.GetThreadData( m_worker.DecompressThread( it->Thread() ) ); - } - } - } -#endif - - for( const auto& thread : m_worker.GetThreadData() ) - { - const Vector>* timeline = &thread->timeline; - if( timeline->empty() ) continue; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( it != vec->begin() ) --it; - if( zone.IsEndValid() && it->Start() > zone.End() ) break; - if( it == &zone ) return thread; - if( !it->HasChildren() ) break; - timeline = &m_worker.GetZoneChildren( it->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); - if( it != timeline->begin() ) --it; - if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; - if( *it == &zone ) return thread; - if( !(*it)->HasChildren() ) break; - timeline = &m_worker.GetZoneChildren( (*it)->Child() ); - } - } - } - return nullptr; -} - -uint64_t View::GetZoneThread( const ZoneEvent& zone ) const -{ - auto threadData = GetZoneThreadData( zone ); - return threadData ? threadData->id : 0; -} - -uint64_t View::GetZoneThread( const GpuEvent& zone ) const -{ - if( zone.Thread() == 0 ) - { - for( const auto& ctx : m_worker.GetGpuData() ) - { - if ( ctx->threadData.size() != 1 ) continue; - const Vector>* timeline = &ctx->threadData.begin()->second.timeline; - if( timeline->empty() ) continue; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } ); - if( it != vec->begin() ) --it; - if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break; - if( it == &zone ) return ctx->thread; - if( it->Child() < 0 ) break; - timeline = &m_worker.GetGpuChildren( it->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } ); - if( it != timeline->begin() ) --it; - if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break; - if( *it == &zone ) return ctx->thread; - if( (*it)->Child() < 0 ) break; - timeline = &m_worker.GetGpuChildren( (*it)->Child() ); - } - } - } - return 0; - } - else - { - return m_worker.DecompressThread( zone.Thread() ); - } -} - -const GpuCtxData* View::GetZoneCtx( const GpuEvent& zone ) const -{ - for( const auto& ctx : m_worker.GetGpuData() ) - { - for( const auto& td : ctx->threadData ) - { - const Vector>* timeline = &td.second.timeline; - if( timeline->empty() ) continue; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } ); - if( it != vec->begin() ) --it; - if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break; - if( it == &zone ) return ctx; - if( it->Child() < 0 ) break; - timeline = &m_worker.GetGpuChildren( it->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } ); - if( it != timeline->begin() ) --it; - if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break; - if( *it == &zone ) return ctx; - if( (*it)->Child() < 0 ) break; - timeline = &m_worker.GetGpuChildren( (*it)->Child() ); - } - } - } - } - return nullptr; -} - -const ZoneEvent* View::FindZoneAtTime( uint64_t thread, int64_t time ) const -{ - // TODO add thread rev-map - ThreadData* td = nullptr; - for( const auto& t : m_worker.GetThreadData() ) - { - if( t->id == thread ) - { - td = t; - break; - } - } - if( !td ) return nullptr; - - const Vector>* timeline = &td->timeline; - if( timeline->empty() ) return nullptr; - const ZoneEvent* ret = nullptr; - for(;;) - { - if( timeline->is_magic() ) - { - auto vec = (Vector*)timeline; - auto it = std::upper_bound( vec->begin(), vec->end(), time, [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( it != vec->begin() ) --it; - if( it->Start() > time || ( it->IsEndValid() && it->End() < time ) ) return ret; - ret = it; - if( !it->HasChildren() ) return ret; - timeline = &m_worker.GetZoneChildren( it->Child() ); - } - else - { - auto it = std::upper_bound( timeline->begin(), timeline->end(), time, [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); - if( it != timeline->begin() ) --it; - if( (*it)->Start() > time || ( (*it)->IsEndValid() && (*it)->End() < time ) ) return ret; - ret = *it; - if( !(*it)->HasChildren() ) return ret; - timeline = &m_worker.GetZoneChildren( (*it)->Child() ); - } - } -} - #ifndef TRACY_NO_STATISTICS void View::FindZonesCompare() { @@ -17877,195 +17344,6 @@ void View::SetViewToLastFrames() } } -int64_t View::GetZoneChildTime( const ZoneEvent& zone ) -{ - int64_t time = 0; - if( zone.HasChildren() ) - { - auto& children = m_worker.GetZoneChildren( zone.Child() ); - if( children.is_magic() ) - { - auto& vec = *(Vector*)&children; - for( auto& v : vec ) - { - const auto childSpan = std::max( int64_t( 0 ), v.End() - v.Start() ); - time += childSpan; - } - } - else - { - for( auto& v : children ) - { - const auto childSpan = std::max( int64_t( 0 ), v->End() - v->Start() ); - time += childSpan; - } - } - } - return time; -} - -int64_t View::GetZoneChildTime( const GpuEvent& zone ) -{ - int64_t time = 0; - if( zone.Child() >= 0 ) - { - auto& children = m_worker.GetGpuChildren( zone.Child() ); - if( children.is_magic() ) - { - auto& vec = *(Vector*)&children; - for( auto& v : vec ) - { - const auto childSpan = std::max( int64_t( 0 ), v.GpuEnd() - v.GpuStart() ); - time += childSpan; - } - } - else - { - for( auto& v : children ) - { - const auto childSpan = std::max( int64_t( 0 ), v->GpuEnd() - v->GpuStart() ); - time += childSpan; - } - } - } - return time; -} - -int64_t View::GetZoneChildTimeFast( const ZoneEvent& zone ) -{ - int64_t time = 0; - if( zone.HasChildren() ) - { - auto& children = m_worker.GetZoneChildren( zone.Child() ); - if( children.is_magic() ) - { - auto& vec = *(Vector*)&children; - for( auto& v : vec ) - { - assert( v.IsEndValid() ); - time += v.End() - v.Start(); - } - } - else - { - for( auto& v : children ) - { - assert( v->IsEndValid() ); - time += v->End() - v->Start(); - } - } - } - return time; -} - -int64_t View::GetZoneChildTimeFastClamped( const ZoneEvent& zone, int64_t t0, int64_t t1 ) -{ - int64_t time = 0; - if( zone.HasChildren() ) - { - auto& children = m_worker.GetZoneChildren( zone.Child() ); - if( children.is_magic() ) - { - auto& vec = *(Vector*)&children; - auto it = std::lower_bound( vec.begin(), vec.end(), t0, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } ); - if( it == vec.end() ) return 0; - const auto zitend = std::lower_bound( it, vec.end(), t1, [] ( const auto& l, const auto& r ) { return l.Start() < r; } ); - if( it == zitend ) return 0; - while( it < zitend ) - { - const auto c0 = std::max( it->Start(), t0 ); - const auto c1 = std::min( it->End(), t1 ); - time += c1 - c0; - ++it; - } - } - else - { - auto it = std::lower_bound( children.begin(), children.end(), t0, [] ( const auto& l, const auto& r ) { return (uint64_t)l->End() < (uint64_t)r; } ); - if( it == children.end() ) return 0; - const auto zitend = std::lower_bound( it, children.end(), t1, [] ( const auto& l, const auto& r ) { return l->Start() < r; } ); - if( it == zitend ) return 0; - while( it < zitend ) - { - const auto c0 = std::max( (*it)->Start(), t0 ); - const auto c1 = std::min( (*it)->End(), t1 ); - time += c1 - c0; - ++it; - } - } - } - return time; -} - -int64_t View::GetZoneSelfTime( const ZoneEvent& zone ) -{ - if( m_cache.zoneSelfTime.first == &zone ) return m_cache.zoneSelfTime.second; - if( m_cache.zoneSelfTime2.first == &zone ) return m_cache.zoneSelfTime2.second; - const auto ztime = m_worker.GetZoneEnd( zone ) - zone.Start(); - const auto selftime = ztime - GetZoneChildTime( zone ); - if( zone.IsEndValid() ) - { - m_cache.zoneSelfTime2 = m_cache.zoneSelfTime; - m_cache.zoneSelfTime = std::make_pair( &zone, selftime ); - } - return selftime; -} - -int64_t View::GetZoneSelfTime( const GpuEvent& zone ) -{ - if( m_cache.gpuSelfTime.first == &zone ) return m_cache.gpuSelfTime.second; - if( m_cache.gpuSelfTime2.first == &zone ) return m_cache.gpuSelfTime2.second; - const auto ztime = m_worker.GetZoneEnd( zone ) - zone.GpuStart(); - const auto selftime = ztime - GetZoneChildTime( zone ); - if( zone.GpuEnd() >= 0 ) - { - m_cache.gpuSelfTime2 = m_cache.gpuSelfTime; - m_cache.gpuSelfTime = std::make_pair( &zone, selftime ); - } - return selftime; -} - -bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt ) -{ - auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } ); - if( it == ctx->v.end() ) return false; - const auto end = m_worker.GetZoneEnd( ev ); - const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); - if( eit == ctx->v.end() ) return false; - cnt = std::distance( it, eit ); - if( cnt == 0 ) return false; - if( cnt == 1 ) - { - time = end - ev.Start(); - } - else - { - int64_t running = it->End() - ev.Start(); - ++it; - for( uint64_t i=0; iEnd() - it->Start(); - ++it; - } - running += end - it->Start(); - time = running; - } - return true; -} - -const char* View::SourceSubstitution( const char* srcFile ) const -{ - if( !m_sourceRegexValid || m_sourceSubstitutions.empty() ) return srcFile; - static std::string res, tmp; - res.assign( srcFile ); - for( auto& v : m_sourceSubstitutions ) - { - tmp = std::regex_replace( res, v.regex, v.target ); - std::swap( tmp, res ); - } - return res.c_str(); -} - void View::DrawSourceTooltip( const char* filename, uint32_t srcline, int before, int after, bool separateTooltip ) { if( !filename ) return; diff --git a/server/TracyView_Utility.cpp b/server/TracyView_Utility.cpp new file mode 100644 index 00000000..6b376f4c --- /dev/null +++ b/server/TracyView_Utility.cpp @@ -0,0 +1,721 @@ +#include "TracyColor.hpp" +#include "TracyView.hpp" + +namespace tracy +{ + +uint32_t View::GetThreadColor( uint64_t thread, int depth ) +{ + if( m_vd.dynamicColors == 0 ) return 0xFFCC5555; + return GetHsvColor( thread, depth ); +} + +uint32_t View::GetRawSrcLocColor( const SourceLocation& srcloc, int depth ) +{ + auto namehash = srcloc.namehash; + if( namehash == 0 && srcloc.function.active ) + { + const auto f = m_worker.GetString( srcloc.function ); + namehash = charutil::hash( f ); + if( namehash == 0 ) namehash++; + srcloc.namehash = namehash; + } + if( namehash == 0 ) + { + return GetHsvColor( uint64_t( &srcloc ), depth ); + } + else + { + return GetHsvColor( namehash, depth ); + } +} + +uint32_t View::GetSrcLocColor( const SourceLocation& srcloc, int depth ) +{ + const auto color = srcloc.color; + if( color != 0 && !m_vd.forceColors ) return color | 0xFF000000; + if( m_vd.dynamicColors == 0 ) return 0xFFCC5555; + return GetRawSrcLocColor( srcloc, depth ); +} + +uint32_t View::GetZoneColor( const ZoneEvent& ev, uint64_t thread, int depth ) +{ + const auto sl = ev.SrcLoc(); + const auto& srcloc = m_worker.GetSourceLocation( sl ); + if( !m_vd.forceColors ) + { + if( m_worker.HasZoneExtra( ev ) ) + { + const auto custom_color = m_worker.GetZoneExtra( ev ).color.Val(); + if( custom_color != 0 ) return custom_color | 0xFF000000; + } + const auto color = srcloc.color; + if( color != 0 ) return color | 0xFF000000; + } + switch( m_vd.dynamicColors ) + { + case 0: + return 0xFFCC5555; + case 1: + return GetHsvColor( thread, depth ); + case 2: + return GetRawSrcLocColor( srcloc, depth ); + default: + assert( false ); + return 0; + } +} + +uint32_t View::GetZoneColor( const GpuEvent& ev ) +{ + const auto& srcloc = m_worker.GetSourceLocation( ev.SrcLoc() ); + const auto color = srcloc.color; + return color != 0 ? ( color | 0xFF000000 ) : 0xFF222288; +} + +View::ZoneColorData View::GetZoneColorData( const ZoneEvent& ev, uint64_t thread, int depth ) +{ + ZoneColorData ret; + const auto& srcloc = ev.SrcLoc(); + if( m_zoneInfoWindow == &ev ) + { + ret.color = GetZoneColor( ev, thread, depth ); + ret.accentColor = 0xFF44DD44; + ret.thickness = 3.f; + ret.highlight = true; + } + else if( m_zoneHighlight == &ev ) + { + ret.color = GetZoneColor( ev, thread, depth ); + ret.accentColor = 0xFF4444FF; + ret.thickness = 3.f; + ret.highlight = true; + } + else if( m_zoneSrcLocHighlight == srcloc ) + { + ret.color = GetZoneColor( ev, thread, depth ); + ret.accentColor = 0xFFEEEEEE; + ret.thickness = 1.f; + ret.highlight = true; + } + else if( m_findZone.show && !m_findZone.match.empty() && m_findZone.match[m_findZone.selMatch] == srcloc ) + { + uint32_t color = 0xFF229999; + if( m_findZone.highlight.active ) + { + const auto zt = m_worker.GetZoneEnd( ev ) - ev.Start(); + if( zt >= m_findZone.highlight.start && zt <= m_findZone.highlight.end ) + { + color = 0xFFFFCC66; + } + } + ret.color = color; + ret.accentColor = HighlightColor( color ); + ret.thickness = 3.f; + ret.highlight = true; + } + else + { + const auto color = GetZoneColor( ev, thread, depth ); + ret.color = color; + ret.accentColor = HighlightColor( color ); + ret.thickness = 1.f; + ret.highlight = false; + } + return ret; +} + +View::ZoneColorData View::GetZoneColorData( const GpuEvent& ev ) +{ + ZoneColorData ret; + const auto color = GetZoneColor( ev ); + ret.color = color; + if( m_gpuInfoWindow == &ev ) + { + ret.accentColor = 0xFF44DD44; + ret.thickness = 3.f; + ret.highlight = true; + } + else if( m_gpuHighlight == &ev ) + { + ret.accentColor = 0xFF4444FF; + ret.thickness = 3.f; + ret.highlight = true; + } + else + { + ret.accentColor = HighlightColor( color ); + ret.thickness = 1.f; + ret.highlight = false; + } + return ret; +} + + +const ZoneEvent* View::FindZoneAtTime( uint64_t thread, int64_t time ) const +{ + // TODO add thread rev-map + ThreadData* td = nullptr; + for( const auto& t : m_worker.GetThreadData() ) + { + if( t->id == thread ) + { + td = t; + break; + } + } + if( !td ) return nullptr; + + const Vector>* timeline = &td->timeline; + if( timeline->empty() ) return nullptr; + const ZoneEvent* ret = nullptr; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), time, [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( it->Start() > time || ( it->IsEndValid() && it->End() < time ) ) return ret; + ret = it; + if( !it->HasChildren() ) return ret; + timeline = &m_worker.GetZoneChildren( it->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), time, [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( (*it)->Start() > time || ( (*it)->IsEndValid() && (*it)->End() < time ) ) return ret; + ret = *it; + if( !(*it)->HasChildren() ) return ret; + timeline = &m_worker.GetZoneChildren( (*it)->Child() ); + } + } +} + +const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone ) const +{ +#ifndef TRACY_NO_STATISTICS + if( m_worker.AreSourceLocationZonesReady() ) + { + auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); + if( !slz.zones.empty() && slz.zones.is_sorted() ) + { + auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); + if( it != slz.zones.end() && it->Zone() == &zone ) + { + return GetZoneParent( zone, m_worker.DecompressThread( it->Thread() ) ); + } + } + } +#endif + + for( const auto& thread : m_worker.GetThreadData() ) + { + const ZoneEvent* parent = nullptr; + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return parent; + if( !it->HasChildren() ) break; + parent = it; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return parent; + if( !(*it)->HasChildren() ) break; + parent = *it; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + } + } + return nullptr; +} + +const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone, uint64_t tid ) const +{ + const auto thread = m_worker.GetThreadData( tid ); + const ZoneEvent* parent = nullptr; + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) return nullptr; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return parent; + if( !it->HasChildren() ) break; + parent = it; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return parent; + if( !(*it)->HasChildren() ) break; + parent = *it; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + } + return nullptr; +} + +bool View::IsZoneReentry( const ZoneEvent& zone ) const +{ +#ifndef TRACY_NO_STATISTICS + if( m_worker.AreSourceLocationZonesReady() ) + { + auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); + if( !slz.zones.empty() && slz.zones.is_sorted() ) + { + auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); + if( it != slz.zones.end() && it->Zone() == &zone ) + { + return IsZoneReentry( zone, m_worker.DecompressThread( it->Thread() ) ); + } + } + } +#endif + + for( const auto& thread : m_worker.GetThreadData() ) + { + const ZoneEvent* parent = nullptr; + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return false; + if( !it->HasChildren() ) break; + parent = it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return false; + if( !(*it)->HasChildren() ) break; + parent = *it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + } + } + return false; +} + +bool View::IsZoneReentry( const ZoneEvent& zone, uint64_t tid ) const +{ + const auto thread = m_worker.GetThreadData( tid ); + const ZoneEvent* parent = nullptr; + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) return false; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return false; + if( !it->HasChildren() ) break; + parent = it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return false; + if( !(*it)->HasChildren() ) break; + parent = *it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + } + return false; +} + +const GpuEvent* View::GetZoneParent( const GpuEvent& zone ) const +{ + for( const auto& ctx : m_worker.GetGpuData() ) + { + for( const auto& td : ctx->threadData ) + { + const GpuEvent* parent = nullptr; + const Vector>* timeline = &td.second.timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } ); + if( it != vec->begin() ) --it; + if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break; + if( it == &zone ) return parent; + if( it->Child() < 0 ) break; + parent = it; + timeline = &m_worker.GetGpuChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } ); + if( it != timeline->begin() ) --it; + if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break; + if( *it == &zone ) return parent; + if( (*it)->Child() < 0 ) break; + parent = *it; + timeline = &m_worker.GetGpuChildren( parent->Child() ); + } + } + } + } + return nullptr; +} + +const ThreadData* View::GetZoneThreadData( const ZoneEvent& zone ) const +{ +#ifndef TRACY_NO_STATISTICS + if( m_worker.AreSourceLocationZonesReady() ) + { + auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); + if( !slz.zones.empty() && slz.zones.is_sorted() ) + { + auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); + if( it != slz.zones.end() && it->Zone() == &zone ) + { + return m_worker.GetThreadData( m_worker.DecompressThread( it->Thread() ) ); + } + } + } +#endif + + for( const auto& thread : m_worker.GetThreadData() ) + { + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return thread; + if( !it->HasChildren() ) break; + timeline = &m_worker.GetZoneChildren( it->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return thread; + if( !(*it)->HasChildren() ) break; + timeline = &m_worker.GetZoneChildren( (*it)->Child() ); + } + } + } + return nullptr; +} + +uint64_t View::GetZoneThread( const ZoneEvent& zone ) const +{ + auto threadData = GetZoneThreadData( zone ); + return threadData ? threadData->id : 0; +} + +uint64_t View::GetZoneThread( const GpuEvent& zone ) const +{ + if( zone.Thread() == 0 ) + { + for( const auto& ctx : m_worker.GetGpuData() ) + { + if ( ctx->threadData.size() != 1 ) continue; + const Vector>* timeline = &ctx->threadData.begin()->second.timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } ); + if( it != vec->begin() ) --it; + if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break; + if( it == &zone ) return ctx->thread; + if( it->Child() < 0 ) break; + timeline = &m_worker.GetGpuChildren( it->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } ); + if( it != timeline->begin() ) --it; + if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break; + if( *it == &zone ) return ctx->thread; + if( (*it)->Child() < 0 ) break; + timeline = &m_worker.GetGpuChildren( (*it)->Child() ); + } + } + } + return 0; + } + else + { + return m_worker.DecompressThread( zone.Thread() ); + } +} + +const GpuCtxData* View::GetZoneCtx( const GpuEvent& zone ) const +{ + for( const auto& ctx : m_worker.GetGpuData() ) + { + for( const auto& td : ctx->threadData ) + { + const Vector>* timeline = &td.second.timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r.GpuStart(); } ); + if( it != vec->begin() ) --it; + if( zone.GpuEnd() >= 0 && it->GpuStart() > zone.GpuEnd() ) break; + if( it == &zone ) return ctx; + if( it->Child() < 0 ) break; + timeline = &m_worker.GetGpuChildren( it->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.GpuStart(), [] ( const auto& l, const auto& r ) { return (uint64_t)l < (uint64_t)r->GpuStart(); } ); + if( it != timeline->begin() ) --it; + if( zone.GpuEnd() >= 0 && (*it)->GpuStart() > zone.GpuEnd() ) break; + if( *it == &zone ) return ctx; + if( (*it)->Child() < 0 ) break; + timeline = &m_worker.GetGpuChildren( (*it)->Child() ); + } + } + } + } + return nullptr; +} + +int64_t View::GetZoneChildTime( const ZoneEvent& zone ) +{ + int64_t time = 0; + if( zone.HasChildren() ) + { + auto& children = m_worker.GetZoneChildren( zone.Child() ); + if( children.is_magic() ) + { + auto& vec = *(Vector*)&children; + for( auto& v : vec ) + { + const auto childSpan = std::max( int64_t( 0 ), v.End() - v.Start() ); + time += childSpan; + } + } + else + { + for( auto& v : children ) + { + const auto childSpan = std::max( int64_t( 0 ), v->End() - v->Start() ); + time += childSpan; + } + } + } + return time; +} + +int64_t View::GetZoneChildTime( const GpuEvent& zone ) +{ + int64_t time = 0; + if( zone.Child() >= 0 ) + { + auto& children = m_worker.GetGpuChildren( zone.Child() ); + if( children.is_magic() ) + { + auto& vec = *(Vector*)&children; + for( auto& v : vec ) + { + const auto childSpan = std::max( int64_t( 0 ), v.GpuEnd() - v.GpuStart() ); + time += childSpan; + } + } + else + { + for( auto& v : children ) + { + const auto childSpan = std::max( int64_t( 0 ), v->GpuEnd() - v->GpuStart() ); + time += childSpan; + } + } + } + return time; +} + +int64_t View::GetZoneChildTimeFast( const ZoneEvent& zone ) +{ + int64_t time = 0; + if( zone.HasChildren() ) + { + auto& children = m_worker.GetZoneChildren( zone.Child() ); + if( children.is_magic() ) + { + auto& vec = *(Vector*)&children; + for( auto& v : vec ) + { + assert( v.IsEndValid() ); + time += v.End() - v.Start(); + } + } + else + { + for( auto& v : children ) + { + assert( v->IsEndValid() ); + time += v->End() - v->Start(); + } + } + } + return time; +} + +int64_t View::GetZoneChildTimeFastClamped( const ZoneEvent& zone, int64_t t0, int64_t t1 ) +{ + int64_t time = 0; + if( zone.HasChildren() ) + { + auto& children = m_worker.GetZoneChildren( zone.Child() ); + if( children.is_magic() ) + { + auto& vec = *(Vector*)&children; + auto it = std::lower_bound( vec.begin(), vec.end(), t0, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } ); + if( it == vec.end() ) return 0; + const auto zitend = std::lower_bound( it, vec.end(), t1, [] ( const auto& l, const auto& r ) { return l.Start() < r; } ); + if( it == zitend ) return 0; + while( it < zitend ) + { + const auto c0 = std::max( it->Start(), t0 ); + const auto c1 = std::min( it->End(), t1 ); + time += c1 - c0; + ++it; + } + } + else + { + auto it = std::lower_bound( children.begin(), children.end(), t0, [] ( const auto& l, const auto& r ) { return (uint64_t)l->End() < (uint64_t)r; } ); + if( it == children.end() ) return 0; + const auto zitend = std::lower_bound( it, children.end(), t1, [] ( const auto& l, const auto& r ) { return l->Start() < r; } ); + if( it == zitend ) return 0; + while( it < zitend ) + { + const auto c0 = std::max( (*it)->Start(), t0 ); + const auto c1 = std::min( (*it)->End(), t1 ); + time += c1 - c0; + ++it; + } + } + } + return time; +} + +int64_t View::GetZoneSelfTime( const ZoneEvent& zone ) +{ + if( m_cache.zoneSelfTime.first == &zone ) return m_cache.zoneSelfTime.second; + if( m_cache.zoneSelfTime2.first == &zone ) return m_cache.zoneSelfTime2.second; + const auto ztime = m_worker.GetZoneEnd( zone ) - zone.Start(); + const auto selftime = ztime - GetZoneChildTime( zone ); + if( zone.IsEndValid() ) + { + m_cache.zoneSelfTime2 = m_cache.zoneSelfTime; + m_cache.zoneSelfTime = std::make_pair( &zone, selftime ); + } + return selftime; +} + +int64_t View::GetZoneSelfTime( const GpuEvent& zone ) +{ + if( m_cache.gpuSelfTime.first == &zone ) return m_cache.gpuSelfTime.second; + if( m_cache.gpuSelfTime2.first == &zone ) return m_cache.gpuSelfTime2.second; + const auto ztime = m_worker.GetZoneEnd( zone ) - zone.GpuStart(); + const auto selftime = ztime - GetZoneChildTime( zone ); + if( zone.GpuEnd() >= 0 ) + { + m_cache.gpuSelfTime2 = m_cache.gpuSelfTime; + m_cache.gpuSelfTime = std::make_pair( &zone, selftime ); + } + return selftime; +} + +bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt ) +{ + auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } ); + if( it == ctx->v.end() ) return false; + const auto end = m_worker.GetZoneEnd( ev ); + const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( eit == ctx->v.end() ) return false; + cnt = std::distance( it, eit ); + if( cnt == 0 ) return false; + if( cnt == 1 ) + { + time = end - ev.Start(); + } + else + { + int64_t running = it->End() - ev.Start(); + ++it; + for( uint64_t i=0; iEnd() - it->Start(); + ++it; + } + running += end - it->Start(); + time = running; + } + return true; +} + +const char* View::SourceSubstitution( const char* srcFile ) const +{ + if( !m_sourceRegexValid || m_sourceSubstitutions.empty() ) return srcFile; + static std::string res, tmp; + res.assign( srcFile ); + for( auto& v : m_sourceSubstitutions ) + { + tmp = std::regex_replace( res, v.regex, v.target ); + std::swap( tmp, res ); + } + return res.c_str(); +} + +}