mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 14:44:34 +00:00
Extract common zone algorithms from View.
This commit is contained in:
parent
2473760c04
commit
5b8c8c5309
@ -137,6 +137,7 @@
|
||||
<ClCompile Include="..\..\..\server\TracyUserData.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyView.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyView_FindZone.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyView_Utility.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyWeb.cpp" />
|
||||
<ClCompile Include="..\..\..\server\TracyWorker.cpp" />
|
||||
<ClCompile Include="..\..\..\zstd\common\debug.c" />
|
||||
|
@ -246,6 +246,9 @@
|
||||
<ClCompile Include="..\..\..\server\TracyView_FindZone.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\server\TracyView_Utility.cpp">
|
||||
<Filter>server</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
||||
|
@ -1,13 +1,25 @@
|
||||
#ifndef __TRACYCOLOR_HPP__
|
||||
#define __TRACYCOLOR_HPP__
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../common/TracyForceInline.hpp"
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
uint32_t GetHsvColor( uint64_t hue, int value );
|
||||
|
||||
template<int V = 25>
|
||||
static tracy_force_inline uint32_t HighlightColor( uint32_t color )
|
||||
{
|
||||
return 0xFF000000 |
|
||||
( std::min<int>( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + V ) ) << 16 ) |
|
||||
( std::min<int>( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + V ) ) << 8 ) |
|
||||
( std::min<int>( 0xFF, ( ( ( color & 0x000000FF ) ) + V ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -88,15 +88,6 @@ static inline bool AreOtherWaiting( uint64_t bitlist, uint64_t threadBit )
|
||||
return ( bitlist & ~threadBit ) != 0;
|
||||
}
|
||||
|
||||
template<int V = 25>
|
||||
static tracy_force_inline uint32_t HighlightColor( uint32_t color )
|
||||
{
|
||||
return 0xFF000000 |
|
||||
( std::min<int>( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + V ) ) << 16 ) |
|
||||
( std::min<int>( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + V ) ) << 8 ) |
|
||||
( std::min<int>( 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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) return nullptr;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) return false;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<GpuEvent>>* timeline = &td.second.timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<GpuEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<GpuEvent>>* timeline = &ctx->threadData.begin()->second.timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<GpuEvent>*)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<short_ptr<GpuEvent>>* timeline = &td.second.timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<GpuEvent>*)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<short_ptr<ZoneEvent>>* timeline = &td->timeline;
|
||||
if( timeline->empty() ) return nullptr;
|
||||
const ZoneEvent* ret = nullptr;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<ZoneEvent>*)&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<GpuEvent>*)&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<ZoneEvent>*)&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<ZoneEvent>*)&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<int64_t>( it->Start(), t0 );
|
||||
const auto c1 = std::min<int64_t>( 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<int64_t>( (*it)->Start(), t0 );
|
||||
const auto c1 = std::min<int64_t>( (*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; i<cnt-2; i++ )
|
||||
{
|
||||
running += it->End() - 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;
|
||||
|
721
server/TracyView_Utility.cpp
Normal file
721
server/TracyView_Utility.cpp
Normal file
@ -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<short_ptr<ZoneEvent>>* timeline = &td->timeline;
|
||||
if( timeline->empty() ) return nullptr;
|
||||
const ZoneEvent* ret = nullptr;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) return nullptr;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) return false;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<GpuEvent>>* timeline = &td.second.timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<GpuEvent>*)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<short_ptr<ZoneEvent>>* timeline = &thread->timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<ZoneEvent>*)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<short_ptr<GpuEvent>>* timeline = &ctx->threadData.begin()->second.timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<GpuEvent>*)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<short_ptr<GpuEvent>>* timeline = &td.second.timeline;
|
||||
if( timeline->empty() ) continue;
|
||||
for(;;)
|
||||
{
|
||||
if( timeline->is_magic() )
|
||||
{
|
||||
auto vec = (Vector<GpuEvent>*)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<ZoneEvent>*)&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<GpuEvent>*)&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<ZoneEvent>*)&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<ZoneEvent>*)&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<int64_t>( it->Start(), t0 );
|
||||
const auto c1 = std::min<int64_t>( 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<int64_t>( (*it)->Start(), t0 );
|
||||
const auto c1 = std::min<int64_t>( (*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; i<cnt-2; i++ )
|
||||
{
|
||||
running += it->End() - 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();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user