From af81d999e937ca22eaa86ffd8340d176fc6eb603 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sat, 11 Nov 2017 22:56:05 +0100 Subject: [PATCH] Draw GPU zones. --- server/TracyEvent.hpp | 1 + server/TracyView.cpp | 266 ++++++++++++++++++++++++++++++++++++++++-- server/TracyView.hpp | 9 +- 3 files changed, 266 insertions(+), 10 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 69d28fcd..d6246e46 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -134,6 +134,7 @@ struct GpuCtxData Vector timeline; Vector stack; Vector queue; + bool showFull; }; struct LockMap diff --git a/server/TracyView.cpp b/server/TracyView.cpp index b65bae90..b7bf98e4 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -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(); gpu->timeDiff = int64_t( ev.cputime * m_timerMul - ev.gputime ); + gpu->showFull = true; std::lock_guard 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; iAddLine( 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& 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& vec, bool hover, double pxns, return maxdepth; } +int View::DrawGpuZoneLevel( const Vector& 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( 0xFF, ( ( ( color & 0x00FF0000 ) >> 16 ) + 25 ) ) << 16 ) | + ( std::min( 0xFF, ( ( ( color & 0x0000FF00 ) >> 8 ) + 25 ) ) << 8 ) | + ( std::min( 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 ) diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 77d2c09e..816724a3 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -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& vec, bool hover, double pxns, const ImVec2& wpos, int offset, int depth ); + int DrawGpuZoneLevel( const Vector& 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;