diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj
index 3698b299..df509ee0 100644
--- a/profiler/build/win32/Tracy.vcxproj
+++ b/profiler/build/win32/Tracy.vcxproj
@@ -147,6 +147,7 @@
+
diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters
index 4d3c011f..02e485b6 100644
--- a/profiler/build/win32/Tracy.vcxproj.filters
+++ b/profiler/build/win32/Tracy.vcxproj.filters
@@ -306,6 +306,9 @@
server
+
+ server
+
diff --git a/server/TracyView.cpp b/server/TracyView.cpp
index dadc6c38..0f46143c 100644
--- a/server/TracyView.cpp
+++ b/server/TracyView.cpp
@@ -5038,316 +5038,6 @@ int View::DrawCpuData( int offset, double pxns, const ImVec2& wpos, bool hover,
return offset;
}
-void View::DrawMessages()
-{
- const auto& msgs = m_worker.GetMessages();
-
- const auto scale = GetScale();
- ImGui::SetNextWindowSize( ImVec2( 1200 * scale, 600 * scale ), ImGuiCond_FirstUseEver );
- ImGui::Begin( "Messages", &m_showMessages );
- if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
-
- if( msgs.empty() )
- {
- ImGui::TextUnformatted( "No messages were collected." );
- ImGui::End();
- return;
- }
-
- size_t tsz = 0;
- for( const auto& t : m_threadOrder ) if( !t->messages.empty() ) tsz++;
-
- bool filterChanged = m_messageFilter.Draw( ICON_FA_FILTER " Filter messages", 200 );
- ImGui::SameLine();
- if( ImGui::Button( ICON_FA_BACKSPACE " Clear" ) )
- {
- m_messageFilter.Clear();
- filterChanged = true;
- }
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- TextFocused( "Total message count:", RealToString( msgs.size() ) );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- TextFocused( "Visible messages:", RealToString( m_visibleMessages ) );
- if( m_worker.GetFrameImageCount() != 0 )
- {
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- ImGui::Checkbox( ICON_FA_IMAGE " Show frame images", &m_showMessageImages );
- }
-
- bool threadsChanged = false;
- auto expand = ImGui::TreeNode( ICON_FA_RANDOM " Visible threads:" );
- ImGui::SameLine();
- ImGui::TextDisabled( "(%zu)", tsz );
- if( expand )
- {
- auto& crash = m_worker.GetCrashEvent();
-
- ImGui::SameLine();
- if( ImGui::SmallButton( "Select all" ) )
- {
- for( const auto& t : m_threadOrder )
- {
- VisibleMsgThread( t->id ) = true;
- }
- threadsChanged = true;
- }
- ImGui::SameLine();
- if( ImGui::SmallButton( "Unselect all" ) )
- {
- for( const auto& t : m_threadOrder )
- {
- VisibleMsgThread( t->id ) = false;
- }
- threadsChanged = true;
- }
-
- int idx = 0;
- for( const auto& t : m_threadOrder )
- {
- if( t->messages.empty() ) continue;
- ImGui::PushID( idx++ );
- const auto threadColor = GetThreadColor( t->id, 0 );
- SmallColorBox( threadColor );
- ImGui::SameLine();
- if( SmallCheckbox( m_worker.GetThreadName( t->id ), &VisibleMsgThread( t->id ) ) )
- {
- threadsChanged = true;
- }
- ImGui::PopID();
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s)", RealToString( t->messages.size() ) );
- if( crash.thread == t->id )
- {
- ImGui::SameLine();
- TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Crashed" );
- }
- if( t->isFiber )
- {
- ImGui::SameLine();
- TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );
- }
- }
- ImGui::TreePop();
- }
-
- const bool msgsChanged = msgs.size() != m_prevMessages;
- if( filterChanged || threadsChanged )
- {
- bool showCallstack = false;
- m_msgList.reserve( msgs.size() );
- m_msgList.clear();
- if( m_messageFilter.IsActive() )
- {
- for( size_t i=0; ithread );
- if( VisibleMsgThread( tid ) )
- {
- const auto text = m_worker.GetString( msgs[i]->ref );
- if( m_messageFilter.PassFilter( text ) )
- {
- if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
- m_msgList.push_back_no_space_check( uint32_t( i ) );
- }
- }
- }
- }
- else
- {
- for( size_t i=0; ithread );
- if( VisibleMsgThread( tid ) )
- {
- if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
- m_msgList.push_back_no_space_check( uint32_t( i ) );
- }
- }
- }
- m_messagesShowCallstack = showCallstack;
- m_visibleMessages = m_msgList.size();
- if( msgsChanged ) m_prevMessages = msgs.size();
- }
- else if( msgsChanged )
- {
- assert( m_prevMessages < msgs.size() );
- bool showCallstack = m_messagesShowCallstack;
- m_msgList.reserve( msgs.size() );
- if( m_messageFilter.IsActive() )
- {
- for( size_t i=m_prevMessages; ithread );
- if( VisibleMsgThread( tid ) )
- {
- const auto text = m_worker.GetString( msgs[i]->ref );
- if( m_messageFilter.PassFilter( text ) )
- {
- if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
- m_msgList.push_back_no_space_check( uint32_t( i ) );
- }
- }
- }
- }
- else
- {
- for( size_t i=m_prevMessages; ithread );
- if( VisibleMsgThread( tid ) )
- {
- if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
- m_msgList.push_back_no_space_check( uint32_t( i ) );
- }
- }
- }
- m_messagesShowCallstack = showCallstack;
- m_visibleMessages = m_msgList.size();
- m_prevMessages = msgs.size();
- }
-
- bool hasCallstack = m_messagesShowCallstack;
- ImGui::Separator();
- ImGui::BeginChild( "##messages" );
- const int colNum = hasCallstack ? 4 : 3;
- if( ImGui::BeginTable( "##messages", colNum, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_Hideable ) )
- {
- ImGui::TableSetupScrollFreeze( 0, 1 );
- ImGui::TableSetupColumn( "Time", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
- ImGui::TableSetupColumn( "Thread" );
- ImGui::TableSetupColumn( "Message" );
- if( hasCallstack ) ImGui::TableSetupColumn( "Call stack" );
- ImGui::TableHeadersRow();
-
- int idx = 0;
- if( m_msgToFocus )
- {
- for( const auto& msgIdx : m_msgList )
- {
- DrawMessageLine( *msgs[msgIdx], hasCallstack, idx );
- }
- }
- else
- {
- ImGuiListClipper clipper;
- clipper.Begin( m_msgList.size() );
- while( clipper.Step() )
- {
- for( auto i=clipper.DisplayStart; i= ImGui::GetScrollMaxY() )
- {
- ImGui::SetScrollHereY( 1.f );
- }
- ImGui::EndTable();
- }
- ImGui::EndChild();
- ImGui::End();
-}
-
-void View::DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx )
-{
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
- const auto text = m_worker.GetString( msg.ref );
- const auto tid = m_worker.DecompressThread( msg.thread );
- ImGui::PushID( &msg );
- if( ImGui::Selectable( TimeToStringExact( msg.time ), m_msgHighlight == &msg, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap ) )
- {
- CenterAtTime( msg.time );
- }
- if( ImGui::IsItemHovered() )
- {
- m_msgHighlight = &msg;
-
- if( m_showMessageImages )
- {
- const auto frameIdx = m_worker.GetFrameRange( *m_frames, msg.time, msg.time ).first;
- auto fi = m_worker.GetFrameImage( *m_frames, frameIdx );
- if( fi )
- {
- ImGui::BeginTooltip();
- if( fi != m_frameTexturePtr )
- {
- if( !m_frameTexture ) m_frameTexture = MakeTexture();
- UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );
- m_frameTexturePtr = fi;
- }
- if( fi->flip )
- {
- ImGui::Image( m_frameTexture, ImVec2( fi->w, fi->h ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );
- }
- else
- {
- ImGui::Image( m_frameTexture, ImVec2( fi->w, fi->h ) );
- }
- ImGui::EndTooltip();
- }
- }
- }
- if( m_msgToFocus == &msg )
- {
- ImGui::SetScrollHereY();
- m_msgToFocus.Decay( nullptr );
- m_messagesScrollBottom = false;
- }
- ImGui::PopID();
- ImGui::TableNextColumn();
- SmallColorBox( GetThreadColor( tid, 0 ) );
- ImGui::SameLine();
- if( m_worker.IsThreadFiber( tid ) )
- {
- TextColoredUnformatted( 0xFF88FF88, m_worker.GetThreadName( tid ) );
- }
- else
- {
- ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );
- }
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s)", RealToString( tid ) );
- ImGui::TableNextColumn();
- auto tend = text;
- while( *tend != '\0' && *tend != '\n' ) tend++;
- ImGui::PushStyleColor( ImGuiCol_Text, msg.color );
- const auto cw = ImGui::GetContentRegionAvail().x;
- const auto tw = ImGui::CalcTextSize( text, tend ).x;
- ImGui::TextUnformatted( text, tend );
- if( tw > cw && ImGui::IsItemHovered() )
- {
- ImGui::SetNextWindowSize( ImVec2( 1000 * GetScale(), 0 ) );
- ImGui::BeginTooltip();
- ImGui::TextWrapped( "%s", text );
- ImGui::EndTooltip();
- }
- ImGui::PopStyleColor();
- if( hasCallstack )
- {
- ImGui::TableNextColumn();
- const auto cs = msg.callstack.Val();
- if( cs != 0 )
- {
- SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );
- ImGui::SameLine();
- DrawCallstackCalls( cs, 4 );
- }
- }
-}
-
void View::DrawHistogramMinMaxLabel( ImDrawList* draw, int64_t tmin, int64_t tmax, ImVec2 wpos, float w, float ty )
{
const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
diff --git a/server/TracyView_Messages.cpp b/server/TracyView_Messages.cpp
new file mode 100644
index 00000000..684fa5ed
--- /dev/null
+++ b/server/TracyView_Messages.cpp
@@ -0,0 +1,317 @@
+#include "TracyPrint.hpp"
+#include "TracyView.hpp"
+
+namespace tracy
+{
+
+void View::DrawMessages()
+{
+ const auto& msgs = m_worker.GetMessages();
+
+ const auto scale = GetScale();
+ ImGui::SetNextWindowSize( ImVec2( 1200 * scale, 600 * scale ), ImGuiCond_FirstUseEver );
+ ImGui::Begin( "Messages", &m_showMessages );
+ if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
+
+ if( msgs.empty() )
+ {
+ ImGui::TextUnformatted( "No messages were collected." );
+ ImGui::End();
+ return;
+ }
+
+ size_t tsz = 0;
+ for( const auto& t : m_threadOrder ) if( !t->messages.empty() ) tsz++;
+
+ bool filterChanged = m_messageFilter.Draw( ICON_FA_FILTER " Filter messages", 200 );
+ ImGui::SameLine();
+ if( ImGui::Button( ICON_FA_BACKSPACE " Clear" ) )
+ {
+ m_messageFilter.Clear();
+ filterChanged = true;
+ }
+ ImGui::SameLine();
+ ImGui::Spacing();
+ ImGui::SameLine();
+ TextFocused( "Total message count:", RealToString( msgs.size() ) );
+ ImGui::SameLine();
+ ImGui::Spacing();
+ ImGui::SameLine();
+ TextFocused( "Visible messages:", RealToString( m_visibleMessages ) );
+ if( m_worker.GetFrameImageCount() != 0 )
+ {
+ ImGui::SameLine();
+ ImGui::Spacing();
+ ImGui::SameLine();
+ ImGui::Checkbox( ICON_FA_IMAGE " Show frame images", &m_showMessageImages );
+ }
+
+ bool threadsChanged = false;
+ auto expand = ImGui::TreeNode( ICON_FA_RANDOM " Visible threads:" );
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%zu)", tsz );
+ if( expand )
+ {
+ auto& crash = m_worker.GetCrashEvent();
+
+ ImGui::SameLine();
+ if( ImGui::SmallButton( "Select all" ) )
+ {
+ for( const auto& t : m_threadOrder )
+ {
+ VisibleMsgThread( t->id ) = true;
+ }
+ threadsChanged = true;
+ }
+ ImGui::SameLine();
+ if( ImGui::SmallButton( "Unselect all" ) )
+ {
+ for( const auto& t : m_threadOrder )
+ {
+ VisibleMsgThread( t->id ) = false;
+ }
+ threadsChanged = true;
+ }
+
+ int idx = 0;
+ for( const auto& t : m_threadOrder )
+ {
+ if( t->messages.empty() ) continue;
+ ImGui::PushID( idx++ );
+ const auto threadColor = GetThreadColor( t->id, 0 );
+ SmallColorBox( threadColor );
+ ImGui::SameLine();
+ if( SmallCheckbox( m_worker.GetThreadName( t->id ), &VisibleMsgThread( t->id ) ) )
+ {
+ threadsChanged = true;
+ }
+ ImGui::PopID();
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%s)", RealToString( t->messages.size() ) );
+ if( crash.thread == t->id )
+ {
+ ImGui::SameLine();
+ TextColoredUnformatted( ImVec4( 1.f, 0.2f, 0.2f, 1.f ), ICON_FA_SKULL " Crashed" );
+ }
+ if( t->isFiber )
+ {
+ ImGui::SameLine();
+ TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );
+ }
+ }
+ ImGui::TreePop();
+ }
+
+ const bool msgsChanged = msgs.size() != m_prevMessages;
+ if( filterChanged || threadsChanged )
+ {
+ bool showCallstack = false;
+ m_msgList.reserve( msgs.size() );
+ m_msgList.clear();
+ if( m_messageFilter.IsActive() )
+ {
+ for( size_t i=0; ithread );
+ if( VisibleMsgThread( tid ) )
+ {
+ const auto text = m_worker.GetString( msgs[i]->ref );
+ if( m_messageFilter.PassFilter( text ) )
+ {
+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
+ m_msgList.push_back_no_space_check( uint32_t( i ) );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( size_t i=0; ithread );
+ if( VisibleMsgThread( tid ) )
+ {
+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
+ m_msgList.push_back_no_space_check( uint32_t( i ) );
+ }
+ }
+ }
+ m_messagesShowCallstack = showCallstack;
+ m_visibleMessages = m_msgList.size();
+ if( msgsChanged ) m_prevMessages = msgs.size();
+ }
+ else if( msgsChanged )
+ {
+ assert( m_prevMessages < msgs.size() );
+ bool showCallstack = m_messagesShowCallstack;
+ m_msgList.reserve( msgs.size() );
+ if( m_messageFilter.IsActive() )
+ {
+ for( size_t i=m_prevMessages; ithread );
+ if( VisibleMsgThread( tid ) )
+ {
+ const auto text = m_worker.GetString( msgs[i]->ref );
+ if( m_messageFilter.PassFilter( text ) )
+ {
+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
+ m_msgList.push_back_no_space_check( uint32_t( i ) );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( size_t i=m_prevMessages; ithread );
+ if( VisibleMsgThread( tid ) )
+ {
+ if( !showCallstack && msgs[i]->callstack.Val() != 0 ) showCallstack = true;
+ m_msgList.push_back_no_space_check( uint32_t( i ) );
+ }
+ }
+ }
+ m_messagesShowCallstack = showCallstack;
+ m_visibleMessages = m_msgList.size();
+ m_prevMessages = msgs.size();
+ }
+
+ bool hasCallstack = m_messagesShowCallstack;
+ ImGui::Separator();
+ ImGui::BeginChild( "##messages" );
+ const int colNum = hasCallstack ? 4 : 3;
+ if( ImGui::BeginTable( "##messages", colNum, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_Hideable ) )
+ {
+ ImGui::TableSetupScrollFreeze( 0, 1 );
+ ImGui::TableSetupColumn( "Time", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize );
+ ImGui::TableSetupColumn( "Thread" );
+ ImGui::TableSetupColumn( "Message" );
+ if( hasCallstack ) ImGui::TableSetupColumn( "Call stack" );
+ ImGui::TableHeadersRow();
+
+ int idx = 0;
+ if( m_msgToFocus )
+ {
+ for( const auto& msgIdx : m_msgList )
+ {
+ DrawMessageLine( *msgs[msgIdx], hasCallstack, idx );
+ }
+ }
+ else
+ {
+ ImGuiListClipper clipper;
+ clipper.Begin( m_msgList.size() );
+ while( clipper.Step() )
+ {
+ for( auto i=clipper.DisplayStart; i= ImGui::GetScrollMaxY() )
+ {
+ ImGui::SetScrollHereY( 1.f );
+ }
+ ImGui::EndTable();
+ }
+ ImGui::EndChild();
+ ImGui::End();
+}
+
+void View::DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx )
+{
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ const auto text = m_worker.GetString( msg.ref );
+ const auto tid = m_worker.DecompressThread( msg.thread );
+ ImGui::PushID( &msg );
+ if( ImGui::Selectable( TimeToStringExact( msg.time ), m_msgHighlight == &msg, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap ) )
+ {
+ CenterAtTime( msg.time );
+ }
+ if( ImGui::IsItemHovered() )
+ {
+ m_msgHighlight = &msg;
+
+ if( m_showMessageImages )
+ {
+ const auto frameIdx = m_worker.GetFrameRange( *m_frames, msg.time, msg.time ).first;
+ auto fi = m_worker.GetFrameImage( *m_frames, frameIdx );
+ if( fi )
+ {
+ ImGui::BeginTooltip();
+ if( fi != m_frameTexturePtr )
+ {
+ if( !m_frameTexture ) m_frameTexture = MakeTexture();
+ UpdateTexture( m_frameTexture, m_worker.UnpackFrameImage( *fi ), fi->w, fi->h );
+ m_frameTexturePtr = fi;
+ }
+ if( fi->flip )
+ {
+ ImGui::Image( m_frameTexture, ImVec2( fi->w, fi->h ), ImVec2( 0, 1 ), ImVec2( 1, 0 ) );
+ }
+ else
+ {
+ ImGui::Image( m_frameTexture, ImVec2( fi->w, fi->h ) );
+ }
+ ImGui::EndTooltip();
+ }
+ }
+ }
+ if( m_msgToFocus == &msg )
+ {
+ ImGui::SetScrollHereY();
+ m_msgToFocus.Decay( nullptr );
+ m_messagesScrollBottom = false;
+ }
+ ImGui::PopID();
+ ImGui::TableNextColumn();
+ SmallColorBox( GetThreadColor( tid, 0 ) );
+ ImGui::SameLine();
+ if( m_worker.IsThreadFiber( tid ) )
+ {
+ TextColoredUnformatted( 0xFF88FF88, m_worker.GetThreadName( tid ) );
+ }
+ else
+ {
+ ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );
+ }
+ ImGui::SameLine();
+ ImGui::TextDisabled( "(%s)", RealToString( tid ) );
+ ImGui::TableNextColumn();
+ auto tend = text;
+ while( *tend != '\0' && *tend != '\n' ) tend++;
+ ImGui::PushStyleColor( ImGuiCol_Text, msg.color );
+ const auto cw = ImGui::GetContentRegionAvail().x;
+ const auto tw = ImGui::CalcTextSize( text, tend ).x;
+ ImGui::TextUnformatted( text, tend );
+ if( tw > cw && ImGui::IsItemHovered() )
+ {
+ ImGui::SetNextWindowSize( ImVec2( 1000 * GetScale(), 0 ) );
+ ImGui::BeginTooltip();
+ ImGui::TextWrapped( "%s", text );
+ ImGui::EndTooltip();
+ }
+ ImGui::PopStyleColor();
+ if( hasCallstack )
+ {
+ ImGui::TableNextColumn();
+ const auto cs = msg.callstack.Val();
+ if( cs != 0 )
+ {
+ SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );
+ ImGui::SameLine();
+ DrawCallstackCalls( cs, 4 );
+ }
+ }
+}
+
+}