1
0
mirror of https://github.com/wolfpld/tracy synced 2025-05-02 21:53:52 +00:00

Draw GPU zones.

This commit is contained in:
Bartosz Taudul 2017-11-11 22:56:05 +01:00
parent 84100bd459
commit af81d999e9
3 changed files with 266 additions and 10 deletions

View File

@ -134,6 +134,7 @@ struct GpuCtxData
Vector<GpuEvent*> timeline;
Vector<GpuEvent*> stack;
Vector<GpuEvent*> queue;
bool showFull;
};
struct LockMap

View File

@ -139,6 +139,7 @@ View::View( const char* addr )
, m_drawRegion( false )
, m_showOptions( false )
, m_showMessages( false )
, m_drawGpuZones( true )
, m_drawZones( true )
, m_drawLocks( true )
, m_drawPlots( true )
@ -175,6 +176,7 @@ View::View( FileRead& f )
, m_drawRegion( false )
, m_showOptions( false )
, m_showMessages( false )
, m_drawGpuZones( true )
, m_drawZones( true )
, m_drawLocks( true )
, m_drawPlots( true )
@ -861,6 +863,7 @@ void View::ProcessGpuNewContext( const QueueGpuNewContext& ev )
assert( ev.context == m_gpuData.size() );
auto gpu = m_slab.AllocInit<GpuCtxData>();
gpu->timeDiff = int64_t( ev.cputime * m_timerMul - ev.gputime );
gpu->showFull = true;
std::lock_guard<std::mutex> lock( m_lock );
m_gpuData.push_back( gpu );
}
@ -1377,6 +1380,17 @@ int64_t View::GetZoneEnd( const ZoneEvent& ev ) const
}
}
int64_t View::GetZoneEnd( const GpuEvent& ev ) const
{
auto ptr = &ev;
for(;;)
{
if( ptr->gpuEnd != -1 ) return ptr->gpuEnd;
if( ptr->child.empty() ) return ptr->gpuStart;
ptr = ptr->child.back();
}
}
const char* View::GetString( uint64_t ptr ) const
{
const auto it = m_strings.find( ptr );
@ -1989,13 +2003,50 @@ void View::DrawZones()
const auto nspx = 1.0 / pxns;
// zones
LockHighlight nextLockHighlight { -1 };
const auto ty = ImGui::GetFontSize();
const auto ostep = ty + 1;
int offset = 0;
const auto to = 9.f;
const auto th = ( ty - to ) * sqrt( 3 ) * 0.5;
// gpu zones
if( m_drawGpuZones )
{
for( int i=0; i<m_gpuData.size(); i++ )
{
auto& v = m_gpuData[i];
draw->AddLine( wpos + ImVec2( 0, offset + ostep - 1 ), wpos + ImVec2( w, offset + ostep - 1 ), 0x33FFFFFF );
if( v->showFull )
{
draw->AddTriangleFilled( wpos + ImVec2( to/2, offset + to/2 ), wpos + ImVec2( ty - to/2, offset + to/2 ), wpos + ImVec2( ty * 0.5, offset + to/2 + th ), 0xFFFFFFFF );
}
else
{
draw->AddTriangle( wpos + ImVec2( to/2, offset + to/2 ), wpos + ImVec2( to/2, offset + ty - to/2 ), wpos + ImVec2( to/2 + th, offset + ty * 0.5 ), 0xFF888888 );
}
char buf[64];
sprintf( buf, "GPU context %i", i );
draw->AddText( wpos + ImVec2( ty, offset ), v->showFull ? 0xFFFFAAAA : 0xFF886666, buf );
if( hover && ImGui::IsMouseClicked( 0 ) && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset ), wpos + ImVec2( ty + ImGui::CalcTextSize( buf ).x, offset + ty ) ) )
{
v->showFull = !v->showFull;
}
offset += ostep;
if( v->showFull )
{
const auto depth = DrawGpuZoneLevel( v->timeline, hover, pxns, wpos, offset, 0 );
offset += ostep * depth;
}
offset += ostep * 0.2f;
}
}
// zones
LockHighlight nextLockHighlight { -1 };
for( auto& v : m_threads )
{
if( !v->visible ) continue;
@ -2131,7 +2182,7 @@ int View::DrawZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns,
{
auto& ev = **it;
auto& srcloc = GetSourceLocation( ev.srcloc );
const auto color = GetZoneColor( srcloc );
const auto color = GetZoneColor( ev );
const auto end = GetZoneEnd( ev );
const auto zsz = ( end - ev.start ) * pxns;
if( zsz < MinVisSize )
@ -2303,6 +2354,156 @@ int View::DrawZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns,
return maxdepth;
}
int View::DrawGpuZoneLevel( const Vector<GpuEvent*>& vec, bool hover, double pxns, const ImVec2& wpos, int _offset, int depth )
{
// cast to uint64_t, so that unended zones (end = -1) are still drawn
auto it = std::lower_bound( vec.begin(), vec.end(), m_zvStart - m_delay, [] ( const auto& l, const auto& r ) { return (uint64_t)l->gpuEnd < (uint64_t)r; } );
if( it == vec.end() ) return depth;
const auto zitend = std::lower_bound( vec.begin(), vec.end(), m_zvEnd + m_resolution, [] ( const auto& l, const auto& r ) { return l->gpuStart < r; } );
if( it == zitend ) return depth;
const auto w = ImGui::GetWindowContentRegionWidth() - 1;
const auto ty = ImGui::GetFontSize();
const auto ostep = ty + 1;
const auto offset = _offset + ostep * depth;
auto draw = ImGui::GetWindowDrawList();
const auto dsz = m_delay * pxns;
const auto rsz = m_resolution * pxns;
depth++;
int maxdepth = depth;
while( it < zitend )
{
auto& ev = **it;
auto& srcloc = GetSourceLocation( ev.srcloc );
const auto color = GetZoneColor( ev );
const auto end = GetZoneEnd( ev );
const auto zsz = ( end - ev.gpuStart ) * pxns;
if( zsz < MinVisSize )
{
int num = 1;
const auto px0 = ( ev.gpuStart - m_zvStart ) * pxns;
auto px1 = ( end - m_zvStart ) * pxns;
auto rend = end;
for(;;)
{
++it;
if( it == zitend ) break;
auto& srcloc2 = GetSourceLocation( (*it)->srcloc );
if( srcloc.color != srcloc2.color ) break;
const auto nend = GetZoneEnd( **it );
const auto pxnext = ( nend - m_zvStart ) * pxns;
if( pxnext - px1 >= MinVisSize * 2 ) break;
px1 = pxnext;
rend = nend;
num++;
}
draw->AddRectFilled( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty ), color );
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( std::max( px0, -10.0 ), offset ), wpos + ImVec2( std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), offset + ty ) ) )
{
if( num > 1 )
{
ImGui::BeginTooltip();
ImGui::Text( "Zones too small to display: %i", num );
ImGui::Text( "Execution time: %s", TimeToString( rend - ev.gpuStart ) );
ImGui::EndTooltip();
if( ImGui::IsMouseClicked( 2 ) && rend - ev.gpuStart > 0 )
{
m_zvStartNext = ev.gpuStart;
m_zvEndNext = rend;
}
}
else
{
ZoneTooltip( ev );
if( ImGui::IsMouseClicked( 2 ) && rend - ev.gpuStart > 0 )
{
ZoomToZone( ev );
}
}
}
char tmp[32];
sprintf( tmp, "%i", num );
const auto tsz = ImGui::CalcTextSize( tmp );
if( tsz.x < px1 - px0 )
{
const auto x = px0 + ( px1 - px0 - tsz.x ) / 2;
draw->AddText( wpos + ImVec2( x, offset ), 0xFF4488DD, tmp );
}
}
else
{
if( !ev.child.empty() )
{
const auto d = DrawGpuZoneLevel( ev.child, hover, pxns, wpos, _offset, depth );
if( d > maxdepth ) maxdepth = d;
}
const char* zoneName = GetString( ev.name );
auto tsz = ImGui::CalcTextSize( zoneName );
const auto pr0 = ( ev.gpuStart - m_zvStart ) * pxns;
const auto pr1 = ( end - m_zvStart ) * pxns;
const auto px0 = std::max( pr0, -10.0 );
const auto px1 = std::min( pr1, double( w + 10 ) );
draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + tsz.y ), color );
draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + tsz.y ), GetZoneHighlight( ev ), 0.f, -1, GetZoneThickness( ev ) );
if( dsz >= MinVisSize )
{
draw->AddRectFilled( wpos + ImVec2( pr0, offset ), wpos + ImVec2( std::min( pr0+dsz, pr1 ), offset + tsz.y ), 0x882222DD );
draw->AddRectFilled( wpos + ImVec2( pr1, offset ), wpos + ImVec2( pr1+dsz, offset + tsz.y ), 0x882222DD );
}
if( rsz >= MinVisSize )
{
draw->AddLine( wpos + ImVec2( pr0 + rsz, offset + round( tsz.y/2 ) ), wpos + ImVec2( pr0 - rsz, offset + round( tsz.y/2 ) ), 0xAAFFFFFF );
draw->AddLine( wpos + ImVec2( pr0 + rsz, offset + round( tsz.y/4 ) ), wpos + ImVec2( pr0 + rsz, offset + round( 3*tsz.y/4 ) ), 0xAAFFFFFF );
draw->AddLine( wpos + ImVec2( pr0 - rsz, offset + round( tsz.y/4 ) ), wpos + ImVec2( pr0 - rsz, offset + round( 3*tsz.y/4 ) ), 0xAAFFFFFF );
draw->AddLine( wpos + ImVec2( pr1 + rsz, offset + round( tsz.y/2 ) ), wpos + ImVec2( pr1 - rsz, offset + round( tsz.y/2 ) ), 0xAAFFFFFF );
draw->AddLine( wpos + ImVec2( pr1 + rsz, offset + round( tsz.y/4 ) ), wpos + ImVec2( pr1 + rsz, offset + round( 3*tsz.y/4 ) ), 0xAAFFFFFF );
draw->AddLine( wpos + ImVec2( pr1 - rsz, offset + round( tsz.y/4 ) ), wpos + ImVec2( pr1 - rsz, offset + round( 3*tsz.y/4 ) ), 0xAAFFFFFF );
}
if( tsz.x < zsz )
{
const auto x = ( ev.gpuStart - m_zvStart ) * pxns + ( ( end - ev.gpuStart ) * pxns - tsz.x ) / 2;
if( x < 0 || x > w - tsz.x )
{
ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + tsz.y * 2 ), true );
draw->AddText( wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset ), 0xFFFFFFFF, zoneName );
ImGui::PopClipRect();
}
else
{
draw->AddText( wpos + ImVec2( x, offset ), 0xFFFFFFFF, zoneName );
}
}
else
{
ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + tsz.y * 2 ), true );
draw->AddText( wpos + ImVec2( ( ev.gpuStart - m_zvStart ) * pxns, offset ), 0xFFFFFFFF, zoneName );
ImGui::PopClipRect();
}
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + tsz.y ) ) )
{
ZoneTooltip( ev );
if( m_zvStartNext == 0 && ImGui::IsMouseClicked( 2 ) )
{
ZoomToZone( ev );
}
}
++it;
}
}
return maxdepth;
}
static inline bool IsThreadWaiting( uint64_t bitlist, uint8_t thread )
{
return ( bitlist & ( uint64_t( 1 ) << thread ) ) != 0;
@ -3051,7 +3252,8 @@ void View::DrawOptions()
{
const auto tw = ImGui::GetFontSize();
ImGui::Begin( "Options", &m_showOptions, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_ShowBorders );
ImGui::Checkbox( "Draw zones", &m_drawZones );
ImGui::Checkbox( "Draw GPU zones", &m_drawGpuZones );
ImGui::Checkbox( "Draw CPU zones", &m_drawZones );
int ns = (int)m_namespace;
ImGui::Combo( "Namespaces", &ns, "Full\0Shortened\0None\0" );
m_namespace = (Namespace)ns;
@ -3114,15 +3316,18 @@ void View::DrawMessages()
uint32_t View::GetZoneColor( const ZoneEvent& ev )
{
return GetZoneColor( GetSourceLocation( ev.srcloc ) );
}
uint32_t View::GetZoneColor( const SourceLocation& srcloc )
{
auto& srcloc = GetSourceLocation( ev.srcloc );
const auto color = srcloc.color;
return color != 0 ? ( color | 0xFF000000 ) : 0xFFCC5555;
}
uint32_t View::GetZoneColor( const GpuEvent& ev )
{
auto& srcloc = GetSourceLocation( ev.srcloc );
const auto color = srcloc.color;
return color != 0 ? ( color | 0xFF000000 ) : 0xFF222288;
}
uint32_t View::GetZoneHighlight( const ZoneEvent& ev, bool migration )
{
if( m_zoneInfoWindow == &ev )
@ -3147,6 +3352,15 @@ uint32_t View::GetZoneHighlight( const ZoneEvent& ev, bool migration )
}
}
uint32_t View::GetZoneHighlight( const GpuEvent& ev )
{
const auto color = GetZoneColor( ev );
return 0xFF000000 |
( std::min<int>( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + 25 ) ) << 16 ) |
( std::min<int>( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + 25 ) ) << 8 ) |
( std::min<int>( 0xFF, ( ( ( color & 0x000000FF ) ) + 25 ) ) );
}
float View::GetZoneThickness( const ZoneEvent& ev )
{
if( m_zoneInfoWindow == &ev || m_zoneHighlight == &ev )
@ -3159,6 +3373,11 @@ float View::GetZoneThickness( const ZoneEvent& ev )
}
}
float View::GetZoneThickness( const GpuEvent& ev )
{
return 1.f;
}
void View::ZoomToZone( const ZoneEvent& ev )
{
const auto end = GetZoneEnd( ev );
@ -3167,6 +3386,14 @@ void View::ZoomToZone( const ZoneEvent& ev )
m_zvEndNext = end;
}
void View::ZoomToZone( const GpuEvent& ev )
{
const auto end = GetZoneEnd( ev );
if( end - ev.gpuStart <= 0 ) return;
m_zvStartNext = ev.gpuStart;
m_zvEndNext = end;
}
void View::ZoneTooltip( const ZoneEvent& ev )
{
int dmul = 1;
@ -3220,6 +3447,27 @@ void View::ZoneTooltip( const ZoneEvent& ev )
ImGui::EndTooltip();
}
void View::ZoneTooltip( const GpuEvent& ev )
{
auto& srcloc = GetSourceLocation( ev.srcloc );
const auto filename = GetString( srcloc.file );
const auto line = srcloc.line;
const auto func = GetString( srcloc.function );
const auto zoneName = GetString( ev.name );
const auto end = GetZoneEnd( ev );
ImGui::BeginTooltip();
ImGui::Text( "%s", func );
ImGui::Text( "%s:%i", filename, line );
ImGui::Text( "GPU execution time: %s", TimeToString( end - ev.gpuStart ) );
ImGui::Text( "CPU command setup time: %s", TimeToString( ev.cpuEnd - ev.cpuStart ) );
ImGui::Text( "Delay to execution: %s", TimeToString( ev.gpuStart - ev.cpuStart ) );
ImGui::EndTooltip();
}
const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone ) const
{
for( auto& thread : m_threads )

View File

@ -108,6 +108,7 @@ private:
int64_t GetFrameEnd( size_t idx ) const;
int64_t GetLastTime() const;
int64_t GetZoneEnd( const ZoneEvent& ev ) const;
int64_t GetZoneEnd( const GpuEvent& ev ) const;
const char* GetString( uint64_t ptr ) const;
const char* GetString( const StringRef& ref ) const;
const char* GetThreadString( uint64_t id ) const;
@ -121,6 +122,7 @@ private:
bool DrawZoneFrames();
void DrawZones();
int DrawZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, const ImVec2& wpos, int offset, int depth );
int DrawGpuZoneLevel( const Vector<GpuEvent*>& vec, bool hover, double pxns, const ImVec2& wpos, int offset, int depth );
int DrawLocks( uint64_t tid, bool hover, double pxns, const ImVec2& wpos, int offset, LockHighlight& highlight );
void DrawZoneInfoWindow();
int DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover );
@ -131,12 +133,16 @@ private:
void HandleZoneViewMouse( int64_t timespan, const ImVec2& wpos, float w, double& pxns );
uint32_t GetZoneColor( const ZoneEvent& ev );
uint32_t GetZoneColor( const SourceLocation& srcloc );
uint32_t GetZoneColor( const GpuEvent& ev );
uint32_t GetZoneHighlight( const ZoneEvent& ev, bool migration );
uint32_t GetZoneHighlight( const GpuEvent& ev );
float GetZoneThickness( const ZoneEvent& ev );
float GetZoneThickness( const GpuEvent& ev );
void ZoomToZone( const ZoneEvent& ev );
void ZoomToZone( const GpuEvent& ev );
void ZoneTooltip( const ZoneEvent& ev );
void ZoneTooltip( const GpuEvent& ev );
const ZoneEvent* GetZoneParent( const ZoneEvent& zone ) const;
TextData* GetTextData( ZoneEvent& zone );
@ -229,6 +235,7 @@ private:
bool m_showOptions;
bool m_showMessages;
bool m_drawGpuZones;
bool m_drawZones;
bool m_drawLocks;
bool m_drawPlots;