diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj
index d598a5ac..321c9623 100644
--- a/profiler/build/win32/Tracy.vcxproj
+++ b/profiler/build/win32/Tracy.vcxproj
@@ -139,6 +139,7 @@
+
diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters
index 25b97ceb..a0eeed43 100644
--- a/profiler/build/win32/Tracy.vcxproj.filters
+++ b/profiler/build/win32/Tracy.vcxproj.filters
@@ -276,6 +276,9 @@
server
+
+ server
+
diff --git a/server/TracyView.cpp b/server/TracyView.cpp
index 0860b75c..08807a28 100644
--- a/server/TracyView.cpp
+++ b/server/TracyView.cpp
@@ -7951,305 +7951,6 @@ void View::DrawLockInfoWindow()
if( !visible ) m_lockInfoWindow = InvalidId;
}
-void View::DrawCpuDataWindow()
-{
- const auto scale = GetScale();
- ImGui::SetNextWindowSize( ImVec2( 700 * scale, 800 * scale ), ImGuiCond_FirstUseEver );
- ImGui::Begin( "CPU data", &m_showCpuDataWindow );
- if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
-
- struct PidData
- {
- std::vector tids;
- CpuThreadData data;
- };
-
- const auto& ctd = m_worker.GetCpuThreadData();
- unordered_flat_map pids;
- for( auto& v : ctd )
- {
- uint64_t pid = m_worker.GetPidFromTid( v.first );
- auto it = pids.find( pid );
- if( it == pids.end() )
- {
- it = pids.emplace( pid, PidData {} ).first;
- }
- it->second.tids.emplace_back( v.first );
- it->second.data.runningTime += v.second.runningTime;
- it->second.data.runningRegions += v.second.runningRegions;
- it->second.data.migrations += v.second.migrations;
- }
-
- TextFocused( "Tracked threads:", RealToString( ctd.size() ) );
- ImGui::SameLine();
- TextFocused( "Tracked processes:", RealToString( pids.size() ) );
- ImGui::Separator();
- ImGui::BeginChild( "##cpudata" );
- if( ImGui::BeginTable( "##cpudata", 5, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )
- {
- ImGui::TableSetupScrollFreeze( 0, 1 );
- ImGui::TableSetupColumn( "PID/TID", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
- ImGui::TableSetupColumn( "Name" );
- ImGui::TableSetupColumn( "Running time", ImGuiTableColumnFlags_PreferSortDescending );
- ImGui::TableSetupColumn( "Running regions", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
- ImGui::TableSetupColumn( "CPU migrations", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
- ImGui::TableHeadersRow();
-
- std::vector::iterator> psort;
- psort.reserve( pids.size() );
- for( auto it = pids.begin(); it != pids.end(); ++it ) psort.emplace_back( it );
- const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;
- switch( sortspec.ColumnIndex )
- {
- case 0:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first > r->first; } );
- }
- else
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );
- }
- break;
- case 1:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) > 0; } );
- }
- else
- {
- pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) < 0; } );
- }
- break;
- case 2:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime > r->second.data.runningTime; } );
- }
- else
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime < r->second.data.runningTime; } );
- }
- break;
- case 3:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions > r->second.data.runningRegions; } );
- }
- else
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions < r->second.data.runningRegions; } );
- }
- break;
- case 4:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations > r->second.data.migrations; } );
- }
- else
- {
- pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations < r->second.data.migrations; } );
- }
- break;
- default:
- assert( false );
- break;
- }
-
- const auto thisPid = m_worker.GetPid();
- const auto rtimespan = 1.0 / m_worker.GetLastTime();
- const auto ty = ImGui::GetTextLineHeight();
-
- auto& style = ImGui::GetStyle();
- const auto framePaddingY = style.FramePadding.y;
- for( auto& pidit : psort )
- {
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
-
- char buf[128];
- auto& pid = *pidit;
- const auto pidMatch = thisPid != 0 && thisPid == pid.first;
- auto name = m_worker.GetExternalName( pid.second.tids[0] ).first;
- if( pidMatch )
- {
- name = m_worker.GetCaptureProgram().c_str();
- ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.2f, 1.0f, 0.2f, 1.0f ) );
- }
- const auto pidtxt = pid.first == 0 ? "Unknown" : RealToString( pid.first );
- const auto expand = ImGui::TreeNode( pidtxt );
- if( ImGui::IsItemHovered() )
- {
- if( pidMatch )
- {
- m_drawThreadMigrations = pid.first;
- m_cpuDataThread = pid.first;
- }
- m_drawThreadHighlight = pid.first;
- }
- const auto tsz = pid.second.tids.size();
- if( tsz > 1 )
- {
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s)", RealToString( tsz ) );
- }
- ImGui::TableNextColumn();
- ImGui::TextUnformatted( pid.first == 0 ? "???" : name );
- if( ImGui::IsItemHovered() )
- {
- if( pidMatch )
- {
- m_drawThreadMigrations = pid.first;
- m_cpuDataThread = pid.first;
- }
- m_drawThreadHighlight = pid.first;
- }
- ImGui::TableNextColumn();
- PrintStringPercent( buf, TimeToString( pid.second.data.runningTime ), double( pid.second.data.runningTime ) * rtimespan * 100 );
- style.FramePadding.y = 0;
- ImGui::ProgressBar( double( pid.second.data.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
- style.FramePadding.y = framePaddingY;
- ImGui::TableNextColumn();
- ImGui::TextUnformatted( RealToString( pid.second.data.runningRegions ) );
- ImGui::TableNextColumn();
- ImGui::TextUnformatted( RealToString( pid.second.data.migrations ) );
- ImGui::SameLine();
- PrintStringPercent( buf, double( pid.second.data.migrations ) / pid.second.data.runningRegions * 100 );
- TextDisabledUnformatted( buf );
- if( expand )
- {
- ImGui::Separator();
- switch( sortspec.ColumnIndex )
- {
- case 0:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), []( const auto& l, const auto& r ) { return l > r; } );
- }
- else
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end() );
- }
- break;
- case 1:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) > 0; } );
- }
- else
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) < 0; } );
- }
- break;
- case 2:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime > ctd.find( r )->second.runningTime; } );
- }
- else
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime < ctd.find( r )->second.runningTime; } );
- }
- break;
- case 3:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions > ctd.find( r )->second.runningRegions; } );
- }
- else
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions < ctd.find( r )->second.runningRegions; } );
- }
- break;
- case 4:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations > ctd.find( r )->second.migrations; } );
- }
- else
- {
- pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations < ctd.find( r )->second.migrations; } );
- }
- break;
- default:
- assert( false );
- break;
- }
- for( auto& tid : pid.second.tids )
- {
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
-
- const auto tidMatch = pidMatch && m_worker.IsThreadLocal( tid );
- const char* tname;
- if( tidMatch )
- {
- tname = m_worker.GetThreadName( tid );
- ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 1.0f, 0.2f, 1.0f ) );
- }
- else
- {
- tname = m_worker.GetExternalName( tid ).second;
- }
- const auto& tit = ctd.find( tid );
- assert( tit != ctd.end() );
- ImGui::TextUnformatted( RealToString( tid ) );
- if( ImGui::IsItemHovered() )
- {
- if( tidMatch )
- {
- m_drawThreadMigrations = tid;
- m_cpuDataThread = tid;
- }
- m_drawThreadHighlight = tid;
- }
- ImGui::TableNextColumn();
- if( tidMatch )
- {
- SmallColorBox( GetThreadColor( tid, 0 ) );
- ImGui::SameLine();
- }
- ImGui::TextUnformatted( tname );
- if( ImGui::IsItemHovered() )
- {
- if( tidMatch )
- {
- m_drawThreadMigrations = tid;
- m_cpuDataThread = tid;
- }
- m_drawThreadHighlight = tid;
- }
- ImGui::TableNextColumn();
- PrintStringPercent( buf, TimeToString( tit->second.runningTime ), double( tit->second.runningTime ) * rtimespan * 100 );
- style.FramePadding.y = 0;
- ImGui::ProgressBar( double( tit->second.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
- style.FramePadding.y = framePaddingY;
- ImGui::TableNextColumn();
- ImGui::TextUnformatted( RealToString( tit->second.runningRegions ) );
- ImGui::TableNextColumn();
- ImGui::TextUnformatted( RealToString( tit->second.migrations ) );
- ImGui::SameLine();
- PrintStringPercent( buf, double( tit->second.migrations ) / tit->second.runningRegions * 100 );
- TextDisabledUnformatted( buf );
- if( tidMatch )
- {
- ImGui::PopStyleColor();
- }
- }
- ImGui::TreePop();
- ImGui::Separator();
- }
- if( pidMatch )
- {
- ImGui::PopStyleColor();
- }
- }
- ImGui::EndTable();
- }
- ImGui::EndChild();
- ImGui::End();
-}
-
void View::DrawSelectedAnnotation()
{
assert( m_selectedAnnotation );
diff --git a/server/TracyView_CpuData.cpp b/server/TracyView_CpuData.cpp
new file mode 100644
index 00000000..c1929be3
--- /dev/null
+++ b/server/TracyView_CpuData.cpp
@@ -0,0 +1,307 @@
+#include "TracyPrint.hpp"
+#include "TracyView.hpp"
+
+namespace tracy
+{
+
+void View::DrawCpuDataWindow()
+{
+ const auto scale = GetScale();
+ ImGui::SetNextWindowSize( ImVec2( 700 * scale, 800 * scale ), ImGuiCond_FirstUseEver );
+ ImGui::Begin( "CPU data", &m_showCpuDataWindow );
+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
+
+ struct PidData
+ {
+ std::vector tids;
+ CpuThreadData data;
+ };
+
+ const auto& ctd = m_worker.GetCpuThreadData();
+ unordered_flat_map pids;
+ for( auto& v : ctd )
+ {
+ uint64_t pid = m_worker.GetPidFromTid( v.first );
+ auto it = pids.find( pid );
+ if( it == pids.end() )
+ {
+ it = pids.emplace( pid, PidData {} ).first;
+ }
+ it->second.tids.emplace_back( v.first );
+ it->second.data.runningTime += v.second.runningTime;
+ it->second.data.runningRegions += v.second.runningRegions;
+ it->second.data.migrations += v.second.migrations;
+ }
+
+ TextFocused( "Tracked threads:", RealToString( ctd.size() ) );
+ ImGui::SameLine();
+ TextFocused( "Tracked processes:", RealToString( pids.size() ) );
+ ImGui::Separator();
+ ImGui::BeginChild( "##cpudata" );
+ if( ImGui::BeginTable( "##cpudata", 5, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY ) )
+ {
+ ImGui::TableSetupScrollFreeze( 0, 1 );
+ ImGui::TableSetupColumn( "PID/TID", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
+ ImGui::TableSetupColumn( "Name" );
+ ImGui::TableSetupColumn( "Running time", ImGuiTableColumnFlags_PreferSortDescending );
+ ImGui::TableSetupColumn( "Running regions", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
+ ImGui::TableSetupColumn( "CPU migrations", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
+ ImGui::TableHeadersRow();
+
+ std::vector::iterator> psort;
+ psort.reserve( pids.size() );
+ for( auto it = pids.begin(); it != pids.end(); ++it ) psort.emplace_back( it );
+ const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;
+ switch( sortspec.ColumnIndex )
+ {
+ case 0:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first > r->first; } );
+ }
+ else
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->first < r->first; } );
+ }
+ break;
+ case 1:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) > 0; } );
+ }
+ else
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l->second.tids[0] ).first, m_worker.GetExternalName( r->second.tids[0] ).first ) < 0; } );
+ }
+ break;
+ case 2:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime > r->second.data.runningTime; } );
+ }
+ else
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningTime < r->second.data.runningTime; } );
+ }
+ break;
+ case 3:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions > r->second.data.runningRegions; } );
+ }
+ else
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.runningRegions < r->second.data.runningRegions; } );
+ }
+ break;
+ case 4:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations > r->second.data.migrations; } );
+ }
+ else
+ {
+ pdqsort_branchless( psort.begin(), psort.end(), [] ( const auto& l, const auto& r ) { return l->second.data.migrations < r->second.data.migrations; } );
+ }
+ break;
+ default:
+ assert( false );
+ break;
+ }
+
+ const auto thisPid = m_worker.GetPid();
+ const auto rtimespan = 1.0 / m_worker.GetLastTime();
+ const auto ty = ImGui::GetTextLineHeight();
+
+ auto& style = ImGui::GetStyle();
+ const auto framePaddingY = style.FramePadding.y;
+ for( auto& pidit : psort )
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+
+ char buf[128];
+ auto& pid = *pidit;
+ const auto pidMatch = thisPid != 0 && thisPid == pid.first;
+ auto name = m_worker.GetExternalName( pid.second.tids[0] ).first;
+ if( pidMatch )
+ {
+ name = m_worker.GetCaptureProgram().c_str();
+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.2f, 1.0f, 0.2f, 1.0f ) );
+ }
+ const auto pidtxt = pid.first == 0 ? "Unknown" : RealToString( pid.first );
+ const auto expand = ImGui::TreeNode( pidtxt );
+ if( ImGui::IsItemHovered() )
+ {
+ if( pidMatch )
+ {
+ m_drawThreadMigrations = pid.first;
+ m_cpuDataThread = pid.first;
+ }
+ m_drawThreadHighlight = pid.first;
+ }
+ const auto tsz = pid.second.tids.size();
+ if( tsz > 1 )
+ {
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%s)", RealToString( tsz ) );
+ }
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted( pid.first == 0 ? "???" : name );
+ if( ImGui::IsItemHovered() )
+ {
+ if( pidMatch )
+ {
+ m_drawThreadMigrations = pid.first;
+ m_cpuDataThread = pid.first;
+ }
+ m_drawThreadHighlight = pid.first;
+ }
+ ImGui::TableNextColumn();
+ PrintStringPercent( buf, TimeToString( pid.second.data.runningTime ), double( pid.second.data.runningTime ) * rtimespan * 100 );
+ style.FramePadding.y = 0;
+ ImGui::ProgressBar( double( pid.second.data.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
+ style.FramePadding.y = framePaddingY;
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted( RealToString( pid.second.data.runningRegions ) );
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted( RealToString( pid.second.data.migrations ) );
+ ImGui::SameLine();
+ PrintStringPercent( buf, double( pid.second.data.migrations ) / pid.second.data.runningRegions * 100 );
+ TextDisabledUnformatted( buf );
+ if( expand )
+ {
+ ImGui::Separator();
+ switch( sortspec.ColumnIndex )
+ {
+ case 0:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), []( const auto& l, const auto& r ) { return l > r; } );
+ }
+ else
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end() );
+ }
+ break;
+ case 1:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) > 0; } );
+ }
+ else
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [this] ( const auto& l, const auto& r ) { return strcmp( m_worker.GetExternalName( l ).second, m_worker.GetExternalName( r ).second ) < 0; } );
+ }
+ break;
+ case 2:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime > ctd.find( r )->second.runningTime; } );
+ }
+ else
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningTime < ctd.find( r )->second.runningTime; } );
+ }
+ break;
+ case 3:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions > ctd.find( r )->second.runningRegions; } );
+ }
+ else
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.runningRegions < ctd.find( r )->second.runningRegions; } );
+ }
+ break;
+ case 4:
+ if( sortspec.SortDirection == ImGuiSortDirection_Descending )
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations > ctd.find( r )->second.migrations; } );
+ }
+ else
+ {
+ pdqsort_branchless( pid.second.tids.begin(), pid.second.tids.end(), [&ctd] ( const auto& l, const auto& r ) { return ctd.find( l )->second.migrations < ctd.find( r )->second.migrations; } );
+ }
+ break;
+ default:
+ assert( false );
+ break;
+ }
+ for( auto& tid : pid.second.tids )
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+
+ const auto tidMatch = pidMatch && m_worker.IsThreadLocal( tid );
+ const char* tname;
+ if( tidMatch )
+ {
+ tname = m_worker.GetThreadName( tid );
+ ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 1.0f, 0.2f, 1.0f ) );
+ }
+ else
+ {
+ tname = m_worker.GetExternalName( tid ).second;
+ }
+ const auto& tit = ctd.find( tid );
+ assert( tit != ctd.end() );
+ ImGui::TextUnformatted( RealToString( tid ) );
+ if( ImGui::IsItemHovered() )
+ {
+ if( tidMatch )
+ {
+ m_drawThreadMigrations = tid;
+ m_cpuDataThread = tid;
+ }
+ m_drawThreadHighlight = tid;
+ }
+ ImGui::TableNextColumn();
+ if( tidMatch )
+ {
+ SmallColorBox( GetThreadColor( tid, 0 ) );
+ ImGui::SameLine();
+ }
+ ImGui::TextUnformatted( tname );
+ if( ImGui::IsItemHovered() )
+ {
+ if( tidMatch )
+ {
+ m_drawThreadMigrations = tid;
+ m_cpuDataThread = tid;
+ }
+ m_drawThreadHighlight = tid;
+ }
+ ImGui::TableNextColumn();
+ PrintStringPercent( buf, TimeToString( tit->second.runningTime ), double( tit->second.runningTime ) * rtimespan * 100 );
+ style.FramePadding.y = 0;
+ ImGui::ProgressBar( double( tit->second.runningTime ) * rtimespan, ImVec2( -1, ty ), buf );
+ style.FramePadding.y = framePaddingY;
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted( RealToString( tit->second.runningRegions ) );
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted( RealToString( tit->second.migrations ) );
+ ImGui::SameLine();
+ PrintStringPercent( buf, double( tit->second.migrations ) / tit->second.runningRegions * 100 );
+ TextDisabledUnformatted( buf );
+ if( tidMatch )
+ {
+ ImGui::PopStyleColor();
+ }
+ }
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+ if( pidMatch )
+ {
+ ImGui::PopStyleColor();
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::EndChild();
+ ImGui::End();
+}
+
+
+}