mirror of
https://github.com/wolfpld/tracy
synced 2025-04-29 12:23:53 +00:00
Extract context switch UI from View.
This commit is contained in:
parent
c9f77ee5fa
commit
10dbefefab
@ -121,6 +121,7 @@
|
|||||||
<ClCompile Include="..\..\..\server\TracyBadVersion.cpp" />
|
<ClCompile Include="..\..\..\server\TracyBadVersion.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyColor.cpp" />
|
<ClCompile Include="..\..\..\server\TracyColor.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyFilesystem.cpp" />
|
<ClCompile Include="..\..\..\server\TracyFilesystem.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\server\TracyImGui.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyMemory.cpp" />
|
<ClCompile Include="..\..\..\server\TracyMemory.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyMicroArchitecture.cpp" />
|
<ClCompile Include="..\..\..\server\TracyMicroArchitecture.cpp" />
|
||||||
<ClCompile Include="..\..\..\server\TracyMmap.cpp" />
|
<ClCompile Include="..\..\..\server\TracyMmap.cpp" />
|
||||||
|
@ -261,6 +261,9 @@
|
|||||||
<ClCompile Include="..\..\..\server\TracyView_ContextSwitch.cpp">
|
<ClCompile Include="..\..\..\server\TracyView_ContextSwitch.cpp">
|
||||||
<Filter>server</Filter>
|
<Filter>server</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\server\TracyImGui.cpp">
|
||||||
|
<Filter>server</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
<ClInclude Include="..\..\..\common\tracy_lz4.hpp">
|
||||||
|
50
server/TracyImGui.cpp
Normal file
50
server/TracyImGui.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "TracyImGui.hpp"
|
||||||
|
|
||||||
|
namespace tracy
|
||||||
|
{
|
||||||
|
|
||||||
|
void DrawZigZag( ImDrawList* draw, const ImVec2& wpos, double start, double end, double h, uint32_t color, float thickness )
|
||||||
|
{
|
||||||
|
const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
|
||||||
|
|
||||||
|
const auto spanSz = end - start;
|
||||||
|
if( spanSz <= h * 0.5 )
|
||||||
|
{
|
||||||
|
DrawLine( draw, dpos + ImVec2( start, 0 ), wpos + ImVec2( start + spanSz, round( -spanSz ) ), color, thickness );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto h05 = round( h * 0.5 );
|
||||||
|
const auto h2 = h*2;
|
||||||
|
int steps = int( ( end - start ) / h2 );
|
||||||
|
|
||||||
|
auto path = (ImVec2*)alloca( sizeof( ImVec2 ) * ( 2 * steps + 4 ) );
|
||||||
|
auto ptr = path;
|
||||||
|
|
||||||
|
*ptr++ = dpos + ImVec2( start, 0 );
|
||||||
|
*ptr++ = dpos + ImVec2( start + h05, -h05 );
|
||||||
|
start += h05;
|
||||||
|
|
||||||
|
while( steps-- )
|
||||||
|
{
|
||||||
|
*ptr++ = dpos + ImVec2( start + h, h05 );
|
||||||
|
*ptr++ = dpos + ImVec2( start + h2, -h05 );
|
||||||
|
start += h2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( end - start <= h )
|
||||||
|
{
|
||||||
|
const auto span = end - start;
|
||||||
|
*ptr++ = dpos + ImVec2( start + span, round( span - h*0.5 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto span = end - start - h;
|
||||||
|
*ptr++ = dpos + ImVec2( start + h, h05 );
|
||||||
|
*ptr++ = dpos + ImVec2( start + h + span, round( h*0.5 - span ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
draw->AddPolyline( path, ptr - path, color, 0, thickness );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,8 @@ static inline ImVec2 operator-( const ImVec2& l, const ImVec2& r ) { return ImVe
|
|||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void DrawZigZag( ImDrawList* draw, const ImVec2& wpos, double start, double end, double h, uint32_t color, float thickness = 1.f );
|
||||||
|
|
||||||
static const ImVec4 SyntaxColors[] = {
|
static const ImVec4 SyntaxColors[] = {
|
||||||
{ 0.7f, 0.7f, 0.7f, 1 }, // default
|
{ 0.7f, 0.7f, 0.7f, 1 }, // default
|
||||||
{ 0.45f, 0.68f, 0.32f, 1 }, // comment
|
{ 0.45f, 0.68f, 0.32f, 1 }, // comment
|
||||||
|
@ -79,7 +79,6 @@ static inline bool AreOtherWaiting( uint64_t bitlist, uint64_t threadBit )
|
|||||||
|
|
||||||
|
|
||||||
enum { MinVisSize = 3 };
|
enum { MinVisSize = 3 };
|
||||||
enum { MinCtxSize = 4 };
|
|
||||||
enum { MinFrameSize = 5 };
|
enum { MinFrameSize = 5 };
|
||||||
|
|
||||||
static View* s_instance = nullptr;
|
static View* s_instance = nullptr;
|
||||||
@ -2498,50 +2497,6 @@ static uint32_t MixGhostColor( uint32_t c0, uint32_t c1 )
|
|||||||
( ( ( ( ( c0 & 0x000000FF ) ) + 3 * ( ( c1 & 0x000000FF ) ) ) >> 2 ) );
|
( ( ( ( ( c0 & 0x000000FF ) ) + 3 * ( ( c1 & 0x000000FF ) ) ) >> 2 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawZigZag( ImDrawList* draw, const ImVec2& wpos, double start, double end, double h, uint32_t color, float thickness = 1.f )
|
|
||||||
{
|
|
||||||
const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
|
|
||||||
|
|
||||||
const auto spanSz = end - start;
|
|
||||||
if( spanSz <= h * 0.5 )
|
|
||||||
{
|
|
||||||
DrawLine( draw, dpos + ImVec2( start, 0 ), wpos + ImVec2( start + spanSz, round( -spanSz ) ), color, thickness );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto h05 = round( h * 0.5 );
|
|
||||||
const auto h2 = h*2;
|
|
||||||
int steps = int( ( end - start ) / h2 );
|
|
||||||
|
|
||||||
auto path = (ImVec2*)alloca( sizeof( ImVec2 ) * ( 2 * steps + 4 ) );
|
|
||||||
auto ptr = path;
|
|
||||||
|
|
||||||
*ptr++ = dpos + ImVec2( start, 0 );
|
|
||||||
*ptr++ = dpos + ImVec2( start + h05, -h05 );
|
|
||||||
start += h05;
|
|
||||||
|
|
||||||
while( steps-- )
|
|
||||||
{
|
|
||||||
*ptr++ = dpos + ImVec2( start + h, h05 );
|
|
||||||
*ptr++ = dpos + ImVec2( start + h2, -h05 );
|
|
||||||
start += h2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( end - start <= h )
|
|
||||||
{
|
|
||||||
const auto span = end - start;
|
|
||||||
*ptr++ = dpos + ImVec2( start + span, round( span - h*0.5 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto span = end - start - h;
|
|
||||||
*ptr++ = dpos + ImVec2( start + h, h05 );
|
|
||||||
*ptr++ = dpos + ImVec2( start + h + span, round( h*0.5 - span ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
draw->AddPolyline( path, ptr - path, color, 0, thickness );
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t GetColorMuted( uint32_t color, bool active )
|
static uint32_t GetColorMuted( uint32_t color, bool active )
|
||||||
{
|
{
|
||||||
if( active )
|
if( active )
|
||||||
@ -3767,247 +3722,6 @@ void View::DrawZones()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::DrawContextSwitches( const ContextSwitch* ctx, const Vector<SampleData>& sampleData, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int endOffset, bool isFiber )
|
|
||||||
{
|
|
||||||
const auto lineSize = 2 * GetScale();
|
|
||||||
|
|
||||||
auto& vec = ctx->v;
|
|
||||||
auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, m_vd.zvStart ), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
|
||||||
if( it == vec.end() ) return;
|
|
||||||
if( it != vec.begin() ) --it;
|
|
||||||
|
|
||||||
auto citend = std::lower_bound( it, vec.end(), m_vd.zvEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
|
||||||
if( it == citend ) return;
|
|
||||||
if( citend != vec.end() ) ++citend;
|
|
||||||
|
|
||||||
const auto w = ImGui::GetContentRegionAvail().x - 1;
|
|
||||||
const auto ty = round( ImGui::GetTextLineHeight() * 0.75f );
|
|
||||||
const auto ty05 = round( ty * 0.5f );
|
|
||||||
auto draw = ImGui::GetWindowDrawList();
|
|
||||||
const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
|
|
||||||
|
|
||||||
auto pit = citend;
|
|
||||||
double minpx = -10.0;
|
|
||||||
|
|
||||||
while( it < citend )
|
|
||||||
{
|
|
||||||
auto& ev = *it;
|
|
||||||
if( pit != citend )
|
|
||||||
{
|
|
||||||
const bool migration = pit->Cpu() != ev.Cpu();
|
|
||||||
const auto px0 = std::max( { ( pit->End() - m_vd.zvStart ) * pxns, -10.0, minpx } );
|
|
||||||
const auto pxw = ( ev.WakeupVal() - m_vd.zvStart ) * pxns;
|
|
||||||
const auto px1 = std::min( ( ev.Start() - m_vd.zvStart ) * pxns, w + 10.0 );
|
|
||||||
const auto color = migration ? 0xFFEE7711 : 0xFF2222AA;
|
|
||||||
if( m_vd.darkenContextSwitches )
|
|
||||||
{
|
|
||||||
draw->AddRectFilled( dpos + ImVec2( px0, offset + ty05 ), dpos + ImVec2( px1, endOffset ), 0x661C2321 );
|
|
||||||
}
|
|
||||||
DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( std::min( pxw, w+10.0 ), offset + ty05 - 0.5f ), color, lineSize );
|
|
||||||
if( ev.WakeupVal() != ev.Start() )
|
|
||||||
{
|
|
||||||
DrawLine( draw, dpos + ImVec2( std::max( pxw, 10.0 ), offset + ty05 - 0.5f ), dpos + ImVec2( px1, offset + ty05 - 0.5f ), 0xFF2280A0, lineSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( hover )
|
|
||||||
{
|
|
||||||
bool tooltip = false;
|
|
||||||
if( ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( pxw, offset + ty ) ) )
|
|
||||||
{
|
|
||||||
ImGui::BeginTooltip();
|
|
||||||
if( isFiber )
|
|
||||||
{
|
|
||||||
TextFocused( "Fiber is", "yielding" );
|
|
||||||
TextFocused( "Yield time:", TimeToString( ev.Start() - pit->End() ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TextFocused( "Thread is", migration ? "migrating CPUs" : "waiting" );
|
|
||||||
TextFocused( "Waiting time:", TimeToString( ev.WakeupVal() - pit->End() ) );
|
|
||||||
if( migration )
|
|
||||||
{
|
|
||||||
TextFocused( "CPU:", RealToString( pit->Cpu() ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
TextFocused( ICON_FA_LONG_ARROW_ALT_RIGHT, RealToString( ev.Cpu() ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
|
||||||
}
|
|
||||||
if( pit->Reason() != 100 )
|
|
||||||
{
|
|
||||||
TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( pit->Reason() ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::PushFont( m_smallFont );
|
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
TextDisabledUnformatted( DecodeContextSwitchReason( pit->Reason() ) );
|
|
||||||
ImGui::PopFont();
|
|
||||||
}
|
|
||||||
TextFocused( "Wait state:", DecodeContextSwitchStateCode( pit->State() ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::PushFont( m_smallFont );
|
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
TextDisabledUnformatted( DecodeContextSwitchState( pit->State() ) );
|
|
||||||
ImGui::PopFont();
|
|
||||||
}
|
|
||||||
tooltip = true;
|
|
||||||
|
|
||||||
if( IsMouseClicked( 2 ) )
|
|
||||||
{
|
|
||||||
ZoomToRange( pit->End(), ev.WakeupVal() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( ev.WakeupVal() != ev.Start() && ImGui::IsMouseHoveringRect( wpos + ImVec2( pxw, offset ), wpos + ImVec2( px1, offset + ty ) ) )
|
|
||||||
{
|
|
||||||
assert( !isFiber );
|
|
||||||
ImGui::BeginTooltip();
|
|
||||||
TextFocused( "Thread is", "waking up" );
|
|
||||||
TextFocused( "Scheduling delay:", TimeToString( ev.Start() - ev.WakeupVal() ) );
|
|
||||||
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
|
||||||
if( IsMouseClicked( 2 ) )
|
|
||||||
{
|
|
||||||
ZoomToRange( pit->End(), ev.WakeupVal() );
|
|
||||||
}
|
|
||||||
tooltip = true;
|
|
||||||
}
|
|
||||||
if( tooltip )
|
|
||||||
{
|
|
||||||
if( !sampleData.empty() )
|
|
||||||
{
|
|
||||||
auto sdit = std::lower_bound( sampleData.begin(), sampleData.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
|
||||||
bool found = sdit != sampleData.end() && sdit->time.Val() == ev.Start();
|
|
||||||
if( !found && it != vec.begin() )
|
|
||||||
{
|
|
||||||
auto eit = it;
|
|
||||||
--eit;
|
|
||||||
sdit = std::lower_bound( sampleData.begin(), sampleData.end(), eit->End(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
|
||||||
found = sdit != sampleData.end() && sdit->time.Val() == eit->End();
|
|
||||||
}
|
|
||||||
if( found )
|
|
||||||
{
|
|
||||||
ImGui::Separator();
|
|
||||||
TextDisabledUnformatted( ICON_FA_HOURGLASS_HALF " Wait stack:" );
|
|
||||||
CallstackTooltipContents( sdit->callstack.Val() );
|
|
||||||
if( ImGui::IsMouseClicked( 0 ) )
|
|
||||||
{
|
|
||||||
m_callstackInfoWindow = sdit->callstack.Val();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto end = ev.IsEndValid() ? ev.End() : m_worker.GetLastTime();
|
|
||||||
const auto zsz = std::max( ( end - ev.Start() ) * pxns, pxns * 0.5 );
|
|
||||||
if( zsz < MinCtxSize )
|
|
||||||
{
|
|
||||||
const auto MinCtxNs = MinCtxSize * nspx;
|
|
||||||
int num = 0;
|
|
||||||
const auto px0 = std::max( ( ev.Start() - m_vd.zvStart ) * pxns, -10.0 );
|
|
||||||
auto px1ns = end - m_vd.zvStart;
|
|
||||||
auto rend = end;
|
|
||||||
auto nextTime = end + MinCtxNs;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
const auto prevIt = it;
|
|
||||||
it = std::lower_bound( it, citend, nextTime, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
|
||||||
if( it == prevIt ) ++it;
|
|
||||||
num += std::distance( prevIt, it );
|
|
||||||
if( it == citend ) break;
|
|
||||||
const auto nend = it->IsEndValid() ? it->End() : m_worker.GetLastTime();
|
|
||||||
const auto nsnext = nend - m_vd.zvStart;
|
|
||||||
if( nsnext - px1ns >= MinCtxNs * 2 ) break;
|
|
||||||
px1ns = nsnext;
|
|
||||||
rend = nend;
|
|
||||||
nextTime = nend + nspx;
|
|
||||||
}
|
|
||||||
minpx = std::min( std::max( px1ns * pxns, px0+MinCtxSize ), double( w + 10 ) );
|
|
||||||
if( num == 1 )
|
|
||||||
{
|
|
||||||
DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( minpx, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize );
|
|
||||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) )
|
|
||||||
{
|
|
||||||
ImGui::BeginTooltip();
|
|
||||||
if( isFiber )
|
|
||||||
{
|
|
||||||
const auto tid = m_worker.DecompressThread( ev.Thread() );
|
|
||||||
TextFocused( "Fiber is", "running" );
|
|
||||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
|
||||||
TextFocused( "Thread:", m_worker.GetThreadName( tid ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::TextDisabled( "(%s)", RealToString( tid ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TextFocused( "Thread is", "running" );
|
|
||||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
|
||||||
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
|
||||||
}
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
|
|
||||||
if( IsMouseClicked( 2 ) )
|
|
||||||
{
|
|
||||||
ZoomToRange( ev.Start(), rend );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DrawZigZag( draw, wpos + ImVec2( 0, offset + ty05 ), px0, minpx, ty/4, 0xFF888888, 1.5 );
|
|
||||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) )
|
|
||||||
{
|
|
||||||
ImGui::BeginTooltip();
|
|
||||||
TextFocused( isFiber ? "Fiber is" : "Thread is", "changing activity multiple times" );
|
|
||||||
TextFocused( "Number of running regions:", RealToString( num ) );
|
|
||||||
TextFocused( "Time:", TimeToString( rend - ev.Start() ) );
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
|
|
||||||
if( IsMouseClicked( 2 ) )
|
|
||||||
{
|
|
||||||
ZoomToRange( ev.Start(), rend );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pit = it-1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto px0 = std::max( { ( ev.Start() - m_vd.zvStart ) * pxns, -10.0, minpx } );
|
|
||||||
const auto px1 = std::min( ( end - m_vd.zvStart ) * pxns, w + 10.0 );
|
|
||||||
DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( px1, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize );
|
|
||||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + ty + 1 ) ) )
|
|
||||||
{
|
|
||||||
ImGui::BeginTooltip();
|
|
||||||
if( isFiber )
|
|
||||||
{
|
|
||||||
const auto tid = m_worker.DecompressThread( ev.Thread() );
|
|
||||||
TextFocused( "Fiber is", "running" );
|
|
||||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
|
||||||
TextFocused( "Thread:", m_worker.GetThreadName( tid ) );
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::TextDisabled( "(%s)", RealToString( tid ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TextFocused( "Thread is", "running" );
|
|
||||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
|
||||||
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
|
||||||
}
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
|
|
||||||
if( IsMouseClicked( 2 ) )
|
|
||||||
{
|
|
||||||
ZoomToRange( ev.Start(), end );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pit = it;
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::DrawSamples( const Vector<SampleData>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset )
|
void View::DrawSamples( const Vector<SampleData>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset )
|
||||||
{
|
{
|
||||||
auto it = std::lower_bound( vec.begin(), vec.end(), m_vd.zvStart, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
auto it = std::lower_bound( vec.begin(), vec.end(), m_vd.zvStart, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "TracyMouse.hpp"
|
||||||
|
#include "TracyPrint.hpp"
|
||||||
#include "TracyView.hpp"
|
#include "TracyView.hpp"
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum { MinCtxSize = 4 };
|
||||||
|
|
||||||
const char* View::DecodeContextSwitchReasonCode( uint8_t reason )
|
const char* View::DecodeContextSwitchReasonCode( uint8_t reason )
|
||||||
{
|
{
|
||||||
switch( reason )
|
switch( reason )
|
||||||
@ -127,4 +133,245 @@ const char* View::DecodeContextSwitchState( uint8_t state )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void View::DrawContextSwitches( const ContextSwitch* ctx, const Vector<SampleData>& sampleData, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int endOffset, bool isFiber )
|
||||||
|
{
|
||||||
|
const auto lineSize = 2 * GetScale();
|
||||||
|
|
||||||
|
auto& vec = ctx->v;
|
||||||
|
auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, m_vd.zvStart ), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||||
|
if( it == vec.end() ) return;
|
||||||
|
if( it != vec.begin() ) --it;
|
||||||
|
|
||||||
|
auto citend = std::lower_bound( it, vec.end(), m_vd.zvEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
||||||
|
if( it == citend ) return;
|
||||||
|
if( citend != vec.end() ) ++citend;
|
||||||
|
|
||||||
|
const auto w = ImGui::GetContentRegionAvail().x - 1;
|
||||||
|
const auto ty = round( ImGui::GetTextLineHeight() * 0.75f );
|
||||||
|
const auto ty05 = round( ty * 0.5f );
|
||||||
|
auto draw = ImGui::GetWindowDrawList();
|
||||||
|
const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
|
||||||
|
|
||||||
|
auto pit = citend;
|
||||||
|
double minpx = -10.0;
|
||||||
|
|
||||||
|
while( it < citend )
|
||||||
|
{
|
||||||
|
auto& ev = *it;
|
||||||
|
if( pit != citend )
|
||||||
|
{
|
||||||
|
const bool migration = pit->Cpu() != ev.Cpu();
|
||||||
|
const auto px0 = std::max( { ( pit->End() - m_vd.zvStart ) * pxns, -10.0, minpx } );
|
||||||
|
const auto pxw = ( ev.WakeupVal() - m_vd.zvStart ) * pxns;
|
||||||
|
const auto px1 = std::min( ( ev.Start() - m_vd.zvStart ) * pxns, w + 10.0 );
|
||||||
|
const auto color = migration ? 0xFFEE7711 : 0xFF2222AA;
|
||||||
|
if( m_vd.darkenContextSwitches )
|
||||||
|
{
|
||||||
|
draw->AddRectFilled( dpos + ImVec2( px0, offset + ty05 ), dpos + ImVec2( px1, endOffset ), 0x661C2321 );
|
||||||
|
}
|
||||||
|
DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( std::min( pxw, w+10.0 ), offset + ty05 - 0.5f ), color, lineSize );
|
||||||
|
if( ev.WakeupVal() != ev.Start() )
|
||||||
|
{
|
||||||
|
DrawLine( draw, dpos + ImVec2( std::max( pxw, 10.0 ), offset + ty05 - 0.5f ), dpos + ImVec2( px1, offset + ty05 - 0.5f ), 0xFF2280A0, lineSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hover )
|
||||||
|
{
|
||||||
|
bool tooltip = false;
|
||||||
|
if( ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( pxw, offset + ty ) ) )
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
if( isFiber )
|
||||||
|
{
|
||||||
|
TextFocused( "Fiber is", "yielding" );
|
||||||
|
TextFocused( "Yield time:", TimeToString( ev.Start() - pit->End() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextFocused( "Thread is", migration ? "migrating CPUs" : "waiting" );
|
||||||
|
TextFocused( "Waiting time:", TimeToString( ev.WakeupVal() - pit->End() ) );
|
||||||
|
if( migration )
|
||||||
|
{
|
||||||
|
TextFocused( "CPU:", RealToString( pit->Cpu() ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
TextFocused( ICON_FA_LONG_ARROW_ALT_RIGHT, RealToString( ev.Cpu() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
||||||
|
}
|
||||||
|
if( pit->Reason() != 100 )
|
||||||
|
{
|
||||||
|
TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( pit->Reason() ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushFont( m_smallFont );
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
TextDisabledUnformatted( DecodeContextSwitchReason( pit->Reason() ) );
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
TextFocused( "Wait state:", DecodeContextSwitchStateCode( pit->State() ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushFont( m_smallFont );
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
TextDisabledUnformatted( DecodeContextSwitchState( pit->State() ) );
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
tooltip = true;
|
||||||
|
|
||||||
|
if( IsMouseClicked( 2 ) )
|
||||||
|
{
|
||||||
|
ZoomToRange( pit->End(), ev.WakeupVal() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ev.WakeupVal() != ev.Start() && ImGui::IsMouseHoveringRect( wpos + ImVec2( pxw, offset ), wpos + ImVec2( px1, offset + ty ) ) )
|
||||||
|
{
|
||||||
|
assert( !isFiber );
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
TextFocused( "Thread is", "waking up" );
|
||||||
|
TextFocused( "Scheduling delay:", TimeToString( ev.Start() - ev.WakeupVal() ) );
|
||||||
|
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
||||||
|
if( IsMouseClicked( 2 ) )
|
||||||
|
{
|
||||||
|
ZoomToRange( pit->End(), ev.WakeupVal() );
|
||||||
|
}
|
||||||
|
tooltip = true;
|
||||||
|
}
|
||||||
|
if( tooltip )
|
||||||
|
{
|
||||||
|
if( !sampleData.empty() )
|
||||||
|
{
|
||||||
|
auto sdit = std::lower_bound( sampleData.begin(), sampleData.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
||||||
|
bool found = sdit != sampleData.end() && sdit->time.Val() == ev.Start();
|
||||||
|
if( !found && it != vec.begin() )
|
||||||
|
{
|
||||||
|
auto eit = it;
|
||||||
|
--eit;
|
||||||
|
sdit = std::lower_bound( sampleData.begin(), sampleData.end(), eit->End(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
|
||||||
|
found = sdit != sampleData.end() && sdit->time.Val() == eit->End();
|
||||||
|
}
|
||||||
|
if( found )
|
||||||
|
{
|
||||||
|
ImGui::Separator();
|
||||||
|
TextDisabledUnformatted( ICON_FA_HOURGLASS_HALF " Wait stack:" );
|
||||||
|
CallstackTooltipContents( sdit->callstack.Val() );
|
||||||
|
if( ImGui::IsMouseClicked( 0 ) )
|
||||||
|
{
|
||||||
|
m_callstackInfoWindow = sdit->callstack.Val();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto end = ev.IsEndValid() ? ev.End() : m_worker.GetLastTime();
|
||||||
|
const auto zsz = std::max( ( end - ev.Start() ) * pxns, pxns * 0.5 );
|
||||||
|
if( zsz < MinCtxSize )
|
||||||
|
{
|
||||||
|
const auto MinCtxNs = MinCtxSize * nspx;
|
||||||
|
int num = 0;
|
||||||
|
const auto px0 = std::max( ( ev.Start() - m_vd.zvStart ) * pxns, -10.0 );
|
||||||
|
auto px1ns = end - m_vd.zvStart;
|
||||||
|
auto rend = end;
|
||||||
|
auto nextTime = end + MinCtxNs;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
const auto prevIt = it;
|
||||||
|
it = std::lower_bound( it, citend, nextTime, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||||
|
if( it == prevIt ) ++it;
|
||||||
|
num += std::distance( prevIt, it );
|
||||||
|
if( it == citend ) break;
|
||||||
|
const auto nend = it->IsEndValid() ? it->End() : m_worker.GetLastTime();
|
||||||
|
const auto nsnext = nend - m_vd.zvStart;
|
||||||
|
if( nsnext - px1ns >= MinCtxNs * 2 ) break;
|
||||||
|
px1ns = nsnext;
|
||||||
|
rend = nend;
|
||||||
|
nextTime = nend + nspx;
|
||||||
|
}
|
||||||
|
minpx = std::min( std::max( px1ns * pxns, px0+MinCtxSize ), double( w + 10 ) );
|
||||||
|
if( num == 1 )
|
||||||
|
{
|
||||||
|
DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( minpx, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize );
|
||||||
|
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) )
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
if( isFiber )
|
||||||
|
{
|
||||||
|
const auto tid = m_worker.DecompressThread( ev.Thread() );
|
||||||
|
TextFocused( "Fiber is", "running" );
|
||||||
|
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||||
|
TextFocused( "Thread:", m_worker.GetThreadName( tid ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled( "(%s)", RealToString( tid ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextFocused( "Thread is", "running" );
|
||||||
|
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||||
|
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
|
||||||
|
if( IsMouseClicked( 2 ) )
|
||||||
|
{
|
||||||
|
ZoomToRange( ev.Start(), rend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawZigZag( draw, wpos + ImVec2( 0, offset + ty05 ), px0, minpx, ty/4, 0xFF888888, 1.5 );
|
||||||
|
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) )
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
TextFocused( isFiber ? "Fiber is" : "Thread is", "changing activity multiple times" );
|
||||||
|
TextFocused( "Number of running regions:", RealToString( num ) );
|
||||||
|
TextFocused( "Time:", TimeToString( rend - ev.Start() ) );
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
|
||||||
|
if( IsMouseClicked( 2 ) )
|
||||||
|
{
|
||||||
|
ZoomToRange( ev.Start(), rend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pit = it-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto px0 = std::max( { ( ev.Start() - m_vd.zvStart ) * pxns, -10.0, minpx } );
|
||||||
|
const auto px1 = std::min( ( end - m_vd.zvStart ) * pxns, w + 10.0 );
|
||||||
|
DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( px1, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize );
|
||||||
|
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + ty + 1 ) ) )
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
if( isFiber )
|
||||||
|
{
|
||||||
|
const auto tid = m_worker.DecompressThread( ev.Thread() );
|
||||||
|
TextFocused( "Fiber is", "running" );
|
||||||
|
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||||
|
TextFocused( "Thread:", m_worker.GetThreadName( tid ) );
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled( "(%s)", RealToString( tid ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextFocused( "Thread is", "running" );
|
||||||
|
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||||
|
TextFocused( "CPU:", RealToString( ev.Cpu() ) );
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
|
||||||
|
if( IsMouseClicked( 2 ) )
|
||||||
|
{
|
||||||
|
ZoomToRange( ev.Start(), end );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pit = it;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user