2018-10-23 17:44:51 +00:00
# include <algorithm>
2018-08-17 15:24:50 +00:00
# include <assert.h>
2020-05-13 17:20:20 +00:00
# include <atomic>
2019-06-17 17:34:48 +00:00
# include <chrono>
2018-07-28 16:50:22 +00:00
# include <inttypes.h>
2017-09-15 19:25:47 +00:00
# include <imgui.h>
2018-08-29 23:31:57 +00:00
# include "imgui_impl_glfw.h"
# include "imgui_impl_opengl3.h"
2021-08-22 11:11:26 +00:00
# include "imgui_impl_opengl3_loader.h"
2019-06-26 16:41:42 +00:00
# include <mutex>
2018-10-23 17:39:09 +00:00
# include <stdint.h>
2017-09-15 19:25:47 +00:00
# include <stdio.h>
2018-07-15 18:10:34 +00:00
# include <stdlib.h>
2018-08-31 17:38:05 +00:00
# include <string>
2018-10-23 17:39:09 +00:00
# include <unordered_map>
2017-09-15 19:25:47 +00:00
# include <GLFW/glfw3.h>
2017-09-15 19:37:28 +00:00
# include <memory>
2017-10-18 21:18:32 +00:00
# include <sys/stat.h>
2019-06-02 17:39:07 +00:00
# include <locale.h>
2017-09-15 19:37:28 +00:00
2021-03-16 23:51:24 +00:00
# ifndef TRACY_NO_FILESELECTOR
# include ".. / nfd / nfd.h"
# endif
2021-08-22 11:11:26 +00:00
# ifdef _WIN32
# include <windows.h>
# endif
2019-06-02 15:51:58 +00:00
# define STB_IMAGE_IMPLEMENTATION
# define STBI_ONLY_PNG
# include "stb_image.h"
2019-06-17 17:45:47 +00:00
# include "../../common/TracyProtocol.hpp"
2018-10-23 17:39:09 +00:00
# include "../../server/tracy_pdqsort.h"
2020-01-28 20:49:36 +00:00
# include "../../server/tracy_robin_hood.h"
2018-04-21 21:19:48 +00:00
# include "../../server/TracyBadVersion.hpp"
2020-09-10 19:52:43 +00:00
# include "../../server/TracyFileHeader.hpp"
2017-09-30 14:58:02 +00:00
# include "../../server/TracyFileRead.hpp"
2018-08-17 21:08:07 +00:00
# include "../../server/TracyImGui.hpp"
2020-08-01 10:02:11 +00:00
# include "../../server/TracyMouse.hpp"
2019-06-18 18:51:12 +00:00
# include "../../server/TracyPrint.hpp"
2018-08-29 21:22:54 +00:00
# include "../../server/TracyStorage.hpp"
2020-09-10 19:40:19 +00:00
# include "../../server/TracyVersion.hpp"
2017-09-15 19:37:28 +00:00
# include "../../server/TracyView.hpp"
2021-06-04 12:33:12 +00:00
# include "../../server/TracyWeb.hpp"
2018-07-28 16:07:55 +00:00
# include "../../server/TracyWorker.hpp"
2018-07-29 12:24:24 +00:00
# include "../../server/TracyVersion.hpp"
2018-08-17 21:22:13 +00:00
# include "../../server/IconsFontAwesome5.h"
2018-07-29 12:24:24 +00:00
2021-02-10 23:30:41 +00:00
# include "misc/freetype/imgui_freetype.h"
2018-07-27 23:03:26 +00:00
# include "Arimo.hpp"
2018-08-17 18:57:26 +00:00
# include "Cousine.hpp"
2018-08-17 15:56:55 +00:00
# include "FontAwesomeSolid.hpp"
2019-06-02 16:03:56 +00:00
# include "icon.hpp"
2019-06-26 16:41:42 +00:00
# include "ResolvService.hpp"
2020-08-15 14:37:23 +00:00
# include "NativeWindow.hpp"
2020-09-12 10:46:00 +00:00
# include "HttpRequest.hpp"
2018-07-27 23:03:26 +00:00
2018-04-14 13:12:16 +00:00
static void glfw_error_callback ( int error , const char * description )
2017-09-15 19:25:47 +00:00
{
fprintf ( stderr , " Error %d: %s \n " , error , description ) ;
}
2020-08-15 14:37:23 +00:00
GLFWwindow * s_glfwWindow = nullptr ;
2018-08-17 15:24:50 +00:00
static bool s_customTitle = false ;
static void SetWindowTitleCallback ( const char * title )
{
assert ( s_glfwWindow ) ;
2020-08-11 16:51:57 +00:00
char tmp [ 1024 ] ;
sprintf ( tmp , " %s - Tracy Profiler %i.%i.%i " , title , tracy : : Version : : Major , tracy : : Version : : Minor , tracy : : Version : : Patch ) ;
glfwSetWindowTitle ( s_glfwWindow , tmp ) ;
2018-08-17 15:24:50 +00:00
s_customTitle = true ;
}
2020-01-10 01:10:07 +00:00
static void DrawContents ( ) ;
2020-01-10 01:10:28 +00:00
static void WindowRefreshCallback ( GLFWwindow * window )
{
DrawContents ( ) ;
}
2020-01-10 01:10:07 +00:00
2018-10-23 17:44:51 +00:00
std : : vector < std : : unordered_map < std : : string , uint64_t > : : const_iterator > RebuildConnectionHistory ( const std : : unordered_map < std : : string , uint64_t > & connHistMap )
{
std : : vector < std : : unordered_map < std : : string , uint64_t > : : const_iterator > ret ;
ret . reserve ( connHistMap . size ( ) ) ;
for ( auto it = connHistMap . begin ( ) ; it ! = connHistMap . end ( ) ; + + it )
{
ret . emplace_back ( it ) ;
}
tracy : : pdqsort_branchless ( ret . begin ( ) , ret . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second > rhs - > second ; } ) ;
return ret ;
}
2019-06-17 17:34:48 +00:00
struct ClientData
{
int64_t time ;
uint32_t protocolVersion ;
2020-09-20 20:15:10 +00:00
int32_t activeTime ;
2020-10-02 16:51:54 +00:00
uint16_t port ;
2019-06-17 17:34:48 +00:00
std : : string procName ;
2019-06-17 17:45:36 +00:00
std : : string address ;
2019-06-17 17:34:48 +00:00
} ;
2020-01-10 01:10:07 +00:00
enum class ViewShutdown { False , True , Join } ;
2020-03-08 13:51:28 +00:00
static tracy : : unordered_flat_map < uint64_t , ClientData > clients ;
2020-01-10 01:10:07 +00:00
static std : : unique_ptr < tracy : : View > view ;
static tracy : : BadVersionState badVer ;
2020-10-02 16:51:54 +00:00
static uint16_t port = 8086 ;
2020-01-10 01:10:07 +00:00
static const char * connectTo = nullptr ;
static char title [ 128 ] ;
2020-09-12 11:22:02 +00:00
static std : : thread loadThread , updateThread , updateNotesThread ;
2020-01-10 01:10:07 +00:00
static std : : unique_ptr < tracy : : UdpListen > broadcastListen ;
static std : : mutex resolvLock ;
2020-01-28 20:49:36 +00:00
static tracy : : unordered_flat_map < std : : string , std : : string > resolvMap ;
2020-01-10 01:10:07 +00:00
static ResolvService resolv ( port ) ;
static ImFont * bigFont ;
static ImFont * smallFont ;
static ImFont * fixedWidth ;
static char addr [ 1024 ] = { " 127.0.0.1 " } ;
static std : : unordered_map < std : : string , uint64_t > connHistMap ;
static std : : vector < std : : unordered_map < std : : string , uint64_t > : : const_iterator > connHistVec ;
2020-05-13 17:20:20 +00:00
static std : : atomic < ViewShutdown > viewShutdown { ViewShutdown : : False } ;
2020-01-10 01:10:07 +00:00
static double animTime = 0 ;
static float dpiScale = 1.f ;
2020-05-03 19:10:25 +00:00
static ImGuiTextFilter addrFilter , portFilter , progFilter ;
2020-08-15 12:59:16 +00:00
static std : : thread : : id mainThread ;
static std : : vector < std : : function < void ( ) > > mainThreadTasks ;
static std : : mutex mainThreadLock ;
2020-09-10 19:40:19 +00:00
static uint32_t updateVersion = 0 ;
2020-09-12 11:22:02 +00:00
static bool showReleaseNotes = false ;
static std : : string releaseNotes ;
2020-08-15 12:59:16 +00:00
void RunOnMainThread ( std : : function < void ( ) > cb )
{
if ( std : : this_thread : : get_id ( ) = = mainThread )
{
cb ( ) ;
}
else
{
std : : lock_guard < std : : mutex > lock ( mainThreadLock ) ;
mainThreadTasks . emplace_back ( cb ) ;
}
}
2020-01-10 01:10:07 +00:00
2018-03-24 21:20:06 +00:00
int main ( int argc , char * * argv )
2017-09-15 19:25:47 +00:00
{
2019-02-22 01:41:13 +00:00
sprintf ( title , " Tracy Profiler %i.%i.%i " , tracy : : Version : : Major , tracy : : Version : : Minor , tracy : : Version : : Patch ) ;
2018-07-29 12:24:24 +00:00
2018-08-31 17:38:19 +00:00
std : : string winPosFile = tracy : : GetSavePath ( " window.position " ) ;
int x = 200 , y = 200 , w = 1650 , h = 960 , maximize = 0 ;
{
FILE * f = fopen ( winPosFile . c_str ( ) , " rb " ) ;
if ( f )
{
uint32_t data [ 5 ] ;
fread ( data , 1 , sizeof ( data ) , f ) ;
fclose ( f ) ;
x = data [ 0 ] ;
y = data [ 1 ] ;
w = data [ 2 ] ;
h = data [ 3 ] ;
maximize = data [ 4 ] ;
}
2019-02-12 00:26:14 +00:00
if ( w < = 0 | | h < = 0 )
2019-02-10 01:11:59 +00:00
{
x = 200 ;
y = 200 ;
w = 1650 ;
h = 960 ;
maximize = 0 ;
}
2018-08-31 17:38:19 +00:00
}
2018-10-23 17:39:09 +00:00
std : : string connHistFile = tracy : : GetSavePath ( " connection.history " ) ;
{
FILE * f = fopen ( connHistFile . c_str ( ) , " rb " ) ;
if ( f )
{
uint64_t sz ;
fread ( & sz , 1 , sizeof ( sz ) , f ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t ssz , cnt ;
fread ( & ssz , 1 , sizeof ( ssz ) , f ) ;
assert ( ssz < 1024 ) ;
char tmp [ 1024 ] ;
fread ( tmp , 1 , ssz , f ) ;
fread ( & cnt , 1 , sizeof ( cnt ) , f ) ;
connHistMap . emplace ( std : : string ( tmp , tmp + ssz ) , cnt ) ;
}
fclose ( f ) ;
2018-10-23 17:44:51 +00:00
connHistVec = RebuildConnectionHistory ( connHistMap ) ;
2018-10-23 17:39:09 +00:00
}
}
2020-05-03 19:19:40 +00:00
std : : string filtersFile = tracy : : GetSavePath ( " client.filters " ) ;
{
FILE * f = fopen ( filtersFile . c_str ( ) , " rb " ) ;
if ( f )
{
uint8_t sz ;
fread ( & sz , 1 , sizeof ( sz ) , f ) ;
fread ( addrFilter . InputBuf , 1 , sz , f ) ;
addrFilter . Build ( ) ;
fread ( & sz , 1 , sizeof ( sz ) , f ) ;
fread ( portFilter . InputBuf , 1 , sz , f ) ;
portFilter . Build ( ) ;
fread ( & sz , 1 , sizeof ( sz ) , f ) ;
fread ( progFilter . InputBuf , 1 , sz , f ) ;
progFilter . Build ( ) ;
fclose ( f ) ;
}
}
2018-10-23 17:39:09 +00:00
2020-08-15 12:59:16 +00:00
mainThread = std : : this_thread : : get_id ( ) ;
2020-09-10 19:40:19 +00:00
updateThread = std : : thread ( [ ] {
2020-09-14 20:35:03 +00:00
HttpRequest ( " nereid.pl " , " /tracy/version " , 8099 , [ ] ( int size , char * data ) {
2020-09-12 10:46:00 +00:00
if ( size = = 4 )
{
uint32_t ver ;
memcpy ( & ver , data , 4 ) ;
RunOnMainThread ( [ ver ] { updateVersion = ver ; } ) ;
}
delete [ ] data ;
} ) ;
2020-09-10 19:40:19 +00:00
} ) ;
2017-09-15 19:25:47 +00:00
// Setup window
2018-04-14 13:12:16 +00:00
glfwSetErrorCallback ( glfw_error_callback ) ;
2018-08-29 23:31:57 +00:00
if ( ! glfwInit ( ) ) return 1 ;
2020-10-01 10:52:51 +00:00
# ifdef DISPLAY_SERVER_WAYLAND
glfwWindowHint ( GLFW_ALPHA_BITS , 0 ) ;
# else
2018-08-31 17:40:08 +00:00
glfwWindowHint ( GLFW_VISIBLE , 0 ) ;
2020-09-29 02:00:06 +00:00
# endif
2017-09-15 19:25:47 +00:00
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , 3 ) ;
2018-04-14 13:12:16 +00:00
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , 2 ) ;
2017-09-15 19:25:47 +00:00
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE ) ;
# if __APPLE__
glfwWindowHint ( GLFW_OPENGL_FORWARD_COMPAT , GL_TRUE ) ;
# endif
2018-08-31 17:38:19 +00:00
GLFWwindow * window = glfwCreateWindow ( w , h , title , NULL , NULL ) ;
2018-08-29 23:31:57 +00:00
if ( ! window ) return 1 ;
2019-06-02 16:03:56 +00:00
{
GLFWimage icon ;
icon . pixels = stbi_load_from_memory ( ( const stbi_uc * ) Icon_data , Icon_size , & icon . width , & icon . height , nullptr , 4 ) ;
glfwSetWindowIcon ( window , 1 , & icon ) ;
free ( icon . pixels ) ;
}
2018-08-31 17:38:19 +00:00
glfwSetWindowPos ( window , x , y ) ;
2018-08-31 18:05:40 +00:00
# ifdef GLFW_MAXIMIZED
2018-08-31 17:38:19 +00:00
if ( maximize ) glfwMaximizeWindow ( window ) ;
2018-08-31 18:05:40 +00:00
# endif
2018-08-17 15:24:50 +00:00
s_glfwWindow = window ;
2017-09-15 19:25:47 +00:00
glfwMakeContextCurrent ( window ) ;
glfwSwapInterval ( 1 ) ; // Enable vsync
2020-01-10 01:10:28 +00:00
glfwSetWindowRefreshCallback ( window , WindowRefreshCallback ) ;
2017-09-15 19:25:47 +00:00
2018-06-28 22:31:05 +00:00
# ifdef _WIN32
2018-07-13 21:41:38 +00:00
typedef UINT ( * GDFS ) ( void ) ;
GDFS getDpiForSystem = nullptr ;
HMODULE dll = GetModuleHandleW ( L " user32.dll " ) ;
2020-09-20 12:33:42 +00:00
if ( dll ! = INVALID_HANDLE_VALUE ) getDpiForSystem = ( GDFS ) GetProcAddress ( dll , " GetDpiForSystem " ) ;
if ( getDpiForSystem ) dpiScale = getDpiForSystem ( ) / 96.f ;
# elif defined __linux__
2020-09-26 10:26:18 +00:00
# if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 )
2020-09-20 12:33:42 +00:00
auto monitor = glfwGetWindowMonitor ( window ) ;
if ( ! monitor ) monitor = glfwGetPrimaryMonitor ( ) ;
if ( monitor )
{
float x , y ;
glfwGetMonitorContentScale ( monitor , & x , & y ) ;
dpiScale = x ;
}
2020-09-26 10:26:18 +00:00
# endif
2018-06-28 22:31:05 +00:00
# endif
2021-06-16 22:52:50 +00:00
const auto envDpiScale = getenv ( " TRACY_DPI_SCALE " ) ;
if ( envDpiScale )
{
const auto cnv = atof ( envDpiScale ) ;
if ( cnv ! = 0 ) dpiScale = cnv ;
}
2017-09-15 19:25:47 +00:00
// Setup ImGui binding
2018-08-29 23:31:57 +00:00
IMGUI_CHECKVERSION ( ) ;
2018-04-14 13:12:16 +00:00
ImGui : : CreateContext ( ) ;
2018-08-29 21:22:54 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2018-08-31 17:38:05 +00:00
std : : string iniFileName = tracy : : GetSavePath ( " imgui.ini " ) ;
io . IniFilename = iniFileName . c_str ( ) ;
2019-03-16 19:59:57 +00:00
io . ConfigFlags | = ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_DockingEnable ;
2018-08-29 21:22:54 +00:00
2018-08-29 23:31:57 +00:00
ImGui_ImplGlfw_InitForOpenGL ( window , true ) ;
ImGui_ImplOpenGL3_Init ( " #version 150 " ) ;
2017-09-15 19:25:47 +00:00
2018-08-17 15:56:55 +00:00
static const ImWchar rangesBasic [ ] = {
2018-07-27 23:03:26 +00:00
0x0020 , 0x00FF , // Basic Latin + Latin Supplement
0x03BC , 0x03BC , // micro
2019-03-14 00:14:06 +00:00
0x03C3 , 0x03C3 , // small sigma
2020-04-24 00:02:16 +00:00
0x2013 , 0x2013 , // en dash
2020-04-26 20:25:53 +00:00
0x2264 , 0x2264 , // less-than or equal to
2018-07-27 23:03:26 +00:00
0 ,
} ;
2018-08-17 15:56:55 +00:00
static const ImWchar rangesIcons [ ] = {
2018-08-17 21:22:13 +00:00
ICON_MIN_FA , ICON_MAX_FA ,
2018-08-17 15:56:55 +00:00
0
} ;
2021-02-10 23:30:41 +00:00
ImFontConfig configBasic ;
configBasic . FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting ;
2018-08-17 15:56:55 +00:00
ImFontConfig configMerge ;
configMerge . MergeMode = true ;
2021-02-10 23:30:41 +00:00
configMerge . FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting ;
2017-09-15 19:25:47 +00:00
2021-02-10 23:30:41 +00:00
io . Fonts - > AddFontFromMemoryCompressedTTF ( tracy : : Arimo_compressed_data , tracy : : Arimo_compressed_size , 15.0f * dpiScale , & configBasic , rangesBasic ) ;
2018-08-17 16:45:04 +00:00
io . Fonts - > AddFontFromMemoryCompressedTTF ( tracy : : FontAwesomeSolid_compressed_data , tracy : : FontAwesomeSolid_compressed_size , 14.0f * dpiScale , & configMerge , rangesIcons ) ;
2021-02-10 23:30:41 +00:00
fixedWidth = io . Fonts - > AddFontFromMemoryCompressedTTF ( tracy : : Cousine_compressed_data , tracy : : Cousine_compressed_size , 14.0f * dpiScale , & configBasic ) ;
2021-05-20 01:13:26 +00:00
bigFont = io . Fonts - > AddFontFromMemoryCompressedTTF ( tracy : : Arimo_compressed_data , tracy : : Arimo_compressed_size , 20.0f * dpiScale , & configBasic ) ;
2021-11-13 21:12:54 +00:00
io . Fonts - > AddFontFromMemoryCompressedTTF ( tracy : : FontAwesomeSolid_compressed_data , tracy : : FontAwesomeSolid_compressed_size , 19.0f * dpiScale , & configMerge , rangesIcons ) ;
2021-05-20 01:13:26 +00:00
smallFont = io . Fonts - > AddFontFromMemoryCompressedTTF ( tracy : : Arimo_compressed_data , tracy : : Arimo_compressed_size , 10.0f * dpiScale , & configBasic ) ;
2018-08-17 19:40:15 +00:00
2018-01-13 12:59:16 +00:00
ImGui : : StyleColorsDark ( ) ;
2018-01-13 13:08:14 +00:00
auto & style = ImGui : : GetStyle ( ) ;
2018-08-17 17:06:14 +00:00
style . WindowBorderSize = 1.f * dpiScale ;
style . FrameBorderSize = 1.f * dpiScale ;
2019-09-20 22:52:13 +00:00
style . FrameRounding = 5.f ;
2018-01-13 13:08:14 +00:00
style . Colors [ ImGuiCol_ScrollbarBg ] = ImVec4 ( 1 , 1 , 1 , 0.03f ) ;
2020-04-25 11:22:45 +00:00
style . Colors [ ImGuiCol_Header ] = ImVec4 ( 0.26f , 0.59f , 0.98f , 0.25f ) ;
style . Colors [ ImGuiCol_HeaderHovered ] = ImVec4 ( 0.26f , 0.59f , 0.98f , 0.35f ) ;
style . Colors [ ImGuiCol_HeaderActive ] = ImVec4 ( 0.26f , 0.59f , 0.98f , 0.45f ) ;
2019-09-20 22:52:13 +00:00
style . ScaleAllSizes ( dpiScale ) ;
2018-01-13 12:59:16 +00:00
2020-05-23 14:49:27 +00:00
if ( argc = = 2 )
{
auto f = std : : unique_ptr < tracy : : FileRead > ( tracy : : FileRead : : Open ( argv [ 1 ] ) ) ;
if ( f )
{
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , * f , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-05-23 14:49:27 +00:00
}
}
else
{
while ( argc > = 3 )
{
if ( strcmp ( argv [ 1 ] , " -a " ) = = 0 )
{
connectTo = argv [ 2 ] ;
}
else if ( strcmp ( argv [ 1 ] , " -p " ) = = 0 )
{
2020-10-02 16:51:54 +00:00
port = ( uint16_t ) atoi ( argv [ 2 ] ) ;
2020-05-23 14:49:27 +00:00
}
else
{
fprintf ( stderr , " Bad parameter: %s " , argv [ 1 ] ) ;
exit ( 1 ) ;
}
argc - = 2 ;
argv + = 2 ;
}
}
if ( connectTo )
{
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , connectTo , port , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-05-23 14:49:27 +00:00
}
2018-08-31 17:40:08 +00:00
glfwShowWindow ( window ) ;
2017-09-15 19:25:47 +00:00
// Main loop
while ( ! glfwWindowShouldClose ( window ) )
{
glfwPollEvents ( ) ;
2018-07-29 20:11:47 +00:00
if ( glfwGetWindowAttrib ( window , GLFW_ICONIFIED ) )
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 50 ) ) ;
continue ;
}
2020-01-10 01:10:07 +00:00
DrawContents ( ) ;
if ( ! glfwGetWindowAttrib ( window , GLFW_FOCUSED ) )
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 50 ) ) ;
}
2020-08-15 12:59:16 +00:00
std : : unique_lock < std : : mutex > lock ( mainThreadLock ) ;
if ( ! mainThreadTasks . empty ( ) )
{
std : : vector < std : : function < void ( ) > > tmp ;
std : : swap ( tmp , mainThreadTasks ) ;
lock . unlock ( ) ;
for ( auto & cb : tmp ) cb ( ) ;
}
2020-01-10 01:10:07 +00:00
}
2020-07-19 12:39:50 +00:00
if ( loadThread . joinable ( ) ) loadThread . join ( ) ;
2020-09-10 19:40:19 +00:00
if ( updateThread . joinable ( ) ) updateThread . join ( ) ;
2020-09-12 11:22:02 +00:00
if ( updateNotesThread . joinable ( ) ) updateNotesThread . join ( ) ;
2020-07-19 12:50:09 +00:00
view . reset ( ) ;
2020-07-19 12:39:50 +00:00
2020-01-10 01:10:07 +00:00
{
FILE * f = fopen ( winPosFile . c_str ( ) , " wb " ) ;
if ( f )
{
# ifdef GLFW_MAXIMIZED
uint32_t maximized = glfwGetWindowAttrib ( window , GLFW_MAXIMIZED ) ;
if ( maximized ) glfwRestoreWindow ( window ) ;
# else
uint32_t maximized = 0 ;
# endif
2018-07-29 20:11:47 +00:00
2020-01-10 01:10:07 +00:00
glfwGetWindowPos ( window , & x , & y ) ;
glfwGetWindowSize ( window , & w , & h ) ;
2018-08-17 14:54:56 +00:00
2020-01-10 01:10:07 +00:00
uint32_t data [ 5 ] = { uint32_t ( x ) , uint32_t ( y ) , uint32_t ( w ) , uint32_t ( h ) , maximized } ;
fwrite ( data , 1 , sizeof ( data ) , f ) ;
fclose ( f ) ;
}
}
2017-09-15 19:25:47 +00:00
2020-01-10 01:10:07 +00:00
// Cleanup
ImGui_ImplOpenGL3_Shutdown ( ) ;
ImGui_ImplGlfw_Shutdown ( ) ;
ImGui : : DestroyContext ( ) ;
glfwDestroyWindow ( window ) ;
glfwTerminate ( ) ;
{
FILE * f = fopen ( connHistFile . c_str ( ) , " wb " ) ;
if ( f )
2017-09-15 19:25:47 +00:00
{
2020-01-10 01:10:07 +00:00
uint64_t sz = uint64_t ( connHistMap . size ( ) ) ;
fwrite ( & sz , 1 , sizeof ( uint64_t ) , f ) ;
for ( auto & v : connHistMap )
2018-08-17 15:24:50 +00:00
{
2020-01-10 01:10:07 +00:00
sz = uint64_t ( v . first . size ( ) ) ;
fwrite ( & sz , 1 , sizeof ( uint64_t ) , f ) ;
fwrite ( v . first . c_str ( ) , 1 , sz , f ) ;
fwrite ( & v . second , 1 , sizeof ( v . second ) , f ) ;
2018-08-17 15:24:50 +00:00
}
2020-01-10 01:10:07 +00:00
fclose ( f ) ;
}
}
2020-05-03 19:19:40 +00:00
{
FILE * f = fopen ( filtersFile . c_str ( ) , " wb " ) ;
if ( f )
{
uint8_t sz = strlen ( addrFilter . InputBuf ) ;
fwrite ( & sz , 1 , sizeof ( sz ) , f ) ;
fwrite ( addrFilter . InputBuf , 1 , sz , f ) ;
sz = strlen ( portFilter . InputBuf ) ;
fwrite ( & sz , 1 , sizeof ( sz ) , f ) ;
fwrite ( portFilter . InputBuf , 1 , sz , f ) ;
sz = strlen ( progFilter . InputBuf ) ;
fwrite ( & sz , 1 , sizeof ( sz ) , f ) ;
fwrite ( progFilter . InputBuf , 1 , sz , f ) ;
fclose ( f ) ;
}
}
2020-01-10 01:10:07 +00:00
return 0 ;
}
static void DrawContents ( )
{
2020-03-06 21:11:29 +00:00
static bool reconnect = false ;
static std : : string reconnectAddr ;
2020-10-02 16:51:54 +00:00
static uint16_t reconnectPort ;
2020-05-03 19:10:25 +00:00
static bool showFilter = false ;
2020-03-06 21:11:29 +00:00
2020-01-10 01:10:07 +00:00
const ImVec4 clear_color = ImColor ( 114 , 144 , 154 ) ;
int display_w , display_h ;
glfwGetFramebufferSize ( s_glfwWindow , & display_w , & display_h ) ;
ImGui_ImplOpenGL3_NewFrame ( ) ;
ImGui_ImplGlfw_NewFrame ( ) ;
ImGui : : NewFrame ( ) ;
2020-08-01 10:02:11 +00:00
tracy : : MouseFrame ( ) ;
2020-01-10 01:10:07 +00:00
2020-08-15 14:19:36 +00:00
setlocale ( LC_NUMERIC , " C " ) ;
2020-01-10 01:10:07 +00:00
if ( ! view )
{
if ( s_customTitle )
{
s_customTitle = false ;
glfwSetWindowTitle ( s_glfwWindow , title ) ;
}
2018-08-17 15:24:50 +00:00
2020-01-10 01:10:07 +00:00
const auto time = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
if ( ! broadcastListen )
{
broadcastListen = std : : make_unique < tracy : : UdpListen > ( ) ;
if ( ! broadcastListen - > Listen ( port ) )
2019-06-17 17:34:48 +00:00
{
2020-01-10 01:10:07 +00:00
broadcastListen . reset ( ) ;
2019-06-17 17:34:48 +00:00
}
2020-01-10 01:10:07 +00:00
}
else
{
tracy : : IpAddress addr ;
size_t len ;
2020-09-20 20:08:34 +00:00
for ( ; ; )
2019-06-17 17:34:48 +00:00
{
2020-09-20 20:08:34 +00:00
auto msg = broadcastListen - > Read ( len , addr , 0 ) ;
if ( ! msg ) break ;
2020-09-20 20:27:49 +00:00
if ( len > sizeof ( tracy : : BroadcastMessage ) ) continue ;
2020-01-10 01:10:07 +00:00
tracy : : BroadcastMessage bm ;
memcpy ( & bm , msg , len ) ;
2019-06-17 17:34:48 +00:00
2020-01-10 01:10:07 +00:00
if ( bm . broadcastVersion = = tracy : : BroadcastVersion )
{
const uint32_t protoVer = bm . protocolVersion ;
const auto procname = bm . programName ;
const auto activeTime = bm . activeTime ;
2020-03-08 13:51:28 +00:00
const auto listenPort = bm . listenPort ;
2020-01-10 01:10:07 +00:00
auto address = addr . GetText ( ) ;
const auto ipNumerical = addr . GetNumber ( ) ;
2020-03-08 13:51:28 +00:00
const auto clientId = uint64_t ( ipNumerical ) | ( uint64_t ( listenPort ) < < 32 ) ;
auto it = clients . find ( clientId ) ;
2020-09-20 20:40:38 +00:00
if ( activeTime > = 0 )
2019-06-17 17:34:48 +00:00
{
2020-09-20 20:40:38 +00:00
if ( it = = clients . end ( ) )
2019-06-18 18:26:40 +00:00
{
2020-09-20 20:40:38 +00:00
std : : string ip ( address ) ;
resolvLock . lock ( ) ;
if ( resolvMap . find ( ip ) = = resolvMap . end ( ) )
{
resolvMap . emplace ( ip , ip ) ;
resolv . Query ( ipNumerical , [ ip ] ( std : : string & & name ) {
std : : lock_guard < std : : mutex > lock ( resolvLock ) ;
auto it = resolvMap . find ( ip ) ;
assert ( it ! = resolvMap . end ( ) ) ;
std : : swap ( it - > second , name ) ;
} ) ;
}
resolvLock . unlock ( ) ;
clients . emplace ( clientId , ClientData { time , protoVer , activeTime , listenPort , procname , std : : move ( ip ) } ) ;
}
else
{
it - > second . time = time ;
it - > second . activeTime = activeTime ;
it - > second . port = listenPort ;
if ( it - > second . protocolVersion ! = protoVer ) it - > second . protocolVersion = protoVer ;
if ( strcmp ( it - > second . procName . c_str ( ) , procname ) ! = 0 ) it - > second . procName = procname ;
2019-06-18 18:26:40 +00:00
}
2019-06-17 17:34:48 +00:00
}
2020-09-20 20:40:38 +00:00
else if ( it ! = clients . end ( ) )
2019-06-17 17:34:48 +00:00
{
2020-09-20 20:40:38 +00:00
clients . erase ( it ) ;
2019-06-17 17:34:48 +00:00
}
}
}
2020-01-10 01:10:07 +00:00
auto it = clients . begin ( ) ;
while ( it ! = clients . end ( ) )
{
const auto diff = time - it - > second . time ;
if ( diff > 4000 ) // 4s
{
it = clients . erase ( it ) ;
}
else
{
+ + it ;
}
}
}
2019-06-17 17:34:48 +00:00
2020-01-10 01:10:07 +00:00
auto & style = ImGui : : GetStyle ( ) ;
style . Colors [ ImGuiCol_WindowBg ] = ImVec4 ( 0.129f , 0.137f , 0.11f , 1.f ) ;
2021-04-07 23:35:58 +00:00
ImGui : : Begin ( " Get started " , nullptr , ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse ) ;
2020-01-10 01:10:07 +00:00
char buf [ 128 ] ;
sprintf ( buf , " Tracy Profiler %i.%i.%i " , tracy : : Version : : Major , tracy : : Version : : Minor , tracy : : Version : : Patch ) ;
ImGui : : PushFont ( bigFont ) ;
tracy : : TextCentered ( buf ) ;
ImGui : : PopFont ( ) ;
2020-10-12 00:42:37 +00:00
ImGui : : SameLine ( ImGui : : GetWindowContentRegionMax ( ) . x - ImGui : : CalcTextSize ( ICON_FA_WRENCH ) . x - ImGui : : GetStyle ( ) . FramePadding . x * 2 ) ;
if ( ImGui : : Button ( ICON_FA_WRENCH ) )
{
ImGui : : OpenPopup ( " About Tracy " ) ;
}
bool keepOpenAbout = true ;
if ( ImGui : : BeginPopupModal ( " About Tracy " , & keepOpenAbout , ImGuiWindowFlags_AlwaysAutoResize ) )
{
ImGui : : PushFont ( bigFont ) ;
tracy : : TextCentered ( buf ) ;
ImGui : : PopFont ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : TextUnformatted ( " A real time, nanosecond resolution, remote telemetry, hybrid \n frame and sampling profiler for games and other applications. " ) ;
ImGui : : Spacing ( ) ;
ImGui : : TextUnformatted ( " Created by Bartosz Taudul " ) ;
ImGui : : SameLine ( ) ;
2021-02-10 01:43:05 +00:00
tracy : : TextDisabledUnformatted ( " <wolf@nereid.pl> " ) ;
2020-10-12 00:42:37 +00:00
tracy : : TextDisabledUnformatted ( " Additional authors listed in AUTHORS file and in git history. " ) ;
ImGui : : Separator ( ) ;
tracy : : TextFocused ( " Protocol version " , tracy : : RealToString ( tracy : : ProtocolVersion ) ) ;
tracy : : TextFocused ( " Broadcast version " , tracy : : RealToString ( tracy : : BroadcastVersion ) ) ;
tracy : : TextFocused ( " Build date " , __DATE__ " , " __TIME__ ) ;
ImGui : : EndPopup ( ) ;
}
2020-01-10 01:10:07 +00:00
ImGui : : Spacing ( ) ;
if ( ImGui : : Button ( ICON_FA_BOOK " Manual " ) )
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://github.com/wolfpld/tracy/releases " ) ;
2020-01-10 01:10:07 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_GLOBE_AMERICAS " Web " ) )
{
2020-03-29 12:06:54 +00:00
ImGui : : OpenPopup ( " web " ) ;
2020-01-10 01:10:07 +00:00
}
2020-03-29 12:06:54 +00:00
if ( ImGui : : BeginPopup ( " web " ) )
2020-01-10 01:10:07 +00:00
{
2020-03-29 12:06:54 +00:00
if ( ImGui : : Selectable ( ICON_FA_HOME " Tracy Profiler home page " ) )
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://github.com/wolfpld/tracy " ) ;
2020-03-29 12:06:54 +00:00
}
ImGui : : Separator ( ) ;
if ( ImGui : : Selectable ( ICON_FA_VIDEO " Overview of v0.2 " ) )
2018-08-03 23:15:56 +00:00
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://www.youtube.com/watch?v=fB5B46lbapc " ) ;
2018-08-03 23:15:56 +00:00
}
2020-03-29 12:06:54 +00:00
if ( ImGui : : Selectable ( ICON_FA_VIDEO " New features in v0.3 " ) )
2018-07-15 18:10:41 +00:00
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://www.youtube.com/watch?v=3SXpDpDh2Uo " ) ;
2018-07-15 18:10:41 +00:00
}
2020-03-29 12:06:54 +00:00
if ( ImGui : : Selectable ( ICON_FA_VIDEO " New features in v0.4 " ) )
2019-06-11 00:12:34 +00:00
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://www.youtube.com/watch?v=eAkgkaO8B9o " ) ;
2019-06-11 00:12:34 +00:00
}
2020-03-29 12:06:54 +00:00
if ( ImGui : : Selectable ( ICON_FA_VIDEO " New features in v0.5 " ) )
2018-07-15 18:10:41 +00:00
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://www.youtube.com/watch?v=P6E7qLMmzTQ " ) ;
2018-10-09 17:28:24 +00:00
}
2020-03-29 12:06:54 +00:00
if ( ImGui : : Selectable ( ICON_FA_VIDEO " New features in v0.6 " ) )
2018-10-09 17:28:24 +00:00
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://www.youtube.com/watch?v=uJkrFgriuOo " ) ;
2018-07-15 18:10:41 +00:00
}
2020-06-11 12:30:08 +00:00
if ( ImGui : : Selectable ( ICON_FA_VIDEO " New features in v0.7 " ) )
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://www.youtube.com/watch?v=_hU7vw00MZ4 " ) ;
2020-06-11 12:30:08 +00:00
}
2020-01-10 01:10:07 +00:00
ImGui : : EndPopup ( ) ;
}
2020-03-29 12:06:54 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_COMMENT " Chat " ) )
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://discord.gg/pk78auc " ) ;
2020-03-29 12:06:54 +00:00
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( ICON_FA_HEART " Sponsor " ) )
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://github.com/sponsors/wolfpld/ " ) ;
2020-03-29 12:06:54 +00:00
}
2020-09-10 19:52:43 +00:00
if ( updateVersion ! = 0 & & updateVersion > tracy : : FileVersion ( tracy : : Version : : Major , tracy : : Version : : Minor , tracy : : Version : : Patch ) )
{
ImGui : : Separator ( ) ;
2020-09-12 11:22:02 +00:00
ImGui : : TextColored ( ImVec4 ( 1 , 1 , 0 , 1 ) , ICON_FA_EXCLAMATION " Update to %i.%i.%i is available! " , ( updateVersion > > 16 ) & 0xFF , ( updateVersion > > 8 ) & 0xFF , updateVersion & 0xFF ) ;
2020-09-10 19:52:43 +00:00
ImGui : : SameLine ( ) ;
2020-09-12 11:22:02 +00:00
if ( ImGui : : SmallButton ( ICON_FA_GIFT " Get it! " ) )
2020-09-10 19:52:43 +00:00
{
2020-09-12 11:22:02 +00:00
showReleaseNotes = true ;
if ( ! updateNotesThread . joinable ( ) )
{
updateNotesThread = std : : thread ( [ ] {
2020-09-14 20:35:03 +00:00
HttpRequest ( " nereid.pl " , " /tracy/notes " , 8099 , [ ] ( int size , char * data ) {
2020-09-12 11:22:02 +00:00
std : : string notes ( data , data + size ) ;
delete [ ] data ;
RunOnMainThread ( [ notes = move ( notes ) ] { releaseNotes = std : : move ( notes ) ; } ) ;
} ) ;
} ) ;
}
2020-09-10 19:52:43 +00:00
}
}
2020-01-10 01:10:07 +00:00
ImGui : : Separator ( ) ;
ImGui : : TextUnformatted ( " Client address " ) ;
bool connectClicked = false ;
connectClicked | = ImGui : : InputTextWithHint ( " ###connectaddress " , " Enter address " , addr , 1024 , ImGuiInputTextFlags_EnterReturnsTrue ) ;
if ( ! connHistVec . empty ( ) )
{
ImGui : : SameLine ( ) ;
if ( ImGui : : BeginCombo ( " ##frameCombo " , nullptr , ImGuiComboFlags_NoPreview ) )
2018-10-23 17:44:51 +00:00
{
2020-01-10 01:10:07 +00:00
int idxRemove = - 1 ;
const auto sz = std : : min < size_t > ( 5 , connHistVec . size ( ) ) ;
for ( size_t i = 0 ; i < sz ; i + + )
2018-10-23 17:44:51 +00:00
{
2020-01-10 01:10:07 +00:00
const auto & str = connHistVec [ i ] - > first ;
if ( ImGui : : Selectable ( str . c_str ( ) ) )
2018-10-23 17:44:51 +00:00
{
2020-01-10 01:10:07 +00:00
memcpy ( addr , str . c_str ( ) , str . size ( ) + 1 ) ;
2018-10-23 17:59:11 +00:00
}
2020-01-10 01:10:07 +00:00
if ( ImGui : : IsItemHovered ( ) & & ImGui : : IsKeyPressed ( ImGui : : GetKeyIndex ( ImGuiKey_Delete ) , false ) )
2018-10-23 17:59:11 +00:00
{
2020-01-10 01:10:07 +00:00
idxRemove = ( int ) i ;
2018-10-23 17:44:51 +00:00
}
2018-10-23 17:39:09 +00:00
}
2020-01-10 01:10:07 +00:00
if ( idxRemove > = 0 )
2018-10-23 17:39:09 +00:00
{
2020-01-10 01:10:07 +00:00
connHistMap . erase ( connHistVec [ idxRemove ] ) ;
connHistVec = RebuildConnectionHistory ( connHistMap ) ;
2018-10-23 17:39:09 +00:00
}
2020-01-10 01:10:07 +00:00
ImGui : : EndCombo ( ) ;
2017-09-15 19:37:28 +00:00
}
2020-01-10 01:10:07 +00:00
}
connectClicked | = ImGui : : Button ( ICON_FA_WIFI " Connect " ) ;
if ( connectClicked & & * addr & & ! loadThread . joinable ( ) )
{
2020-03-08 14:02:20 +00:00
const auto addrLen = strlen ( addr ) ;
std : : string addrStr ( addr , addr + addrLen ) ;
2020-01-10 01:10:07 +00:00
auto it = connHistMap . find ( addrStr ) ;
if ( it ! = connHistMap . end ( ) )
2017-09-30 12:32:30 +00:00
{
2020-01-10 01:10:07 +00:00
it - > second + + ;
2017-09-30 12:32:30 +00:00
}
2020-01-10 01:10:07 +00:00
else
2018-07-28 16:17:56 +00:00
{
2020-01-10 01:10:07 +00:00
connHistMap . emplace ( std : : move ( addrStr ) , 1 ) ;
2018-07-28 16:17:56 +00:00
}
2020-01-10 01:10:07 +00:00
connHistVec = RebuildConnectionHistory ( connHistMap ) ;
2018-04-21 12:31:33 +00:00
2020-03-08 14:02:20 +00:00
auto ptr = addr + addrLen - 1 ;
while ( ptr > addr & & * ptr ! = ' : ' ) ptr - - ;
if ( * ptr = = ' : ' )
{
std : : string addrPart = std : : string ( addr , ptr ) ;
2020-10-02 16:51:54 +00:00
uint16_t portPart = ( uint16_t ) atoi ( ptr + 1 ) ;
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , addrPart . c_str ( ) , portPart , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-03-08 14:02:20 +00:00
}
else
{
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , addr , port , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-03-08 14:02:20 +00:00
}
2020-01-10 01:10:07 +00:00
}
ImGui : : SameLine ( 0 , ImGui : : GetFontSize ( ) * 2 ) ;
2021-03-16 23:51:24 +00:00
# ifndef TRACY_NO_FILESELECTOR
2020-01-10 01:10:07 +00:00
if ( ImGui : : Button ( ICON_FA_FOLDER_OPEN " Open saved trace " ) & & ! loadThread . joinable ( ) )
{
nfdchar_t * fn ;
2020-06-09 23:52:17 +00:00
auto res = NFD_OpenDialog ( " tracy " , nullptr , & fn , GetMainWindowNative ( ) ) ;
2020-01-10 01:10:07 +00:00
if ( res = = NFD_OKAY )
2019-06-17 17:45:47 +00:00
{
2020-01-10 01:10:07 +00:00
try
2019-06-17 17:45:47 +00:00
{
2020-01-10 01:10:07 +00:00
auto f = std : : shared_ptr < tracy : : FileRead > ( tracy : : FileRead : : Open ( fn ) ) ;
if ( f )
2019-06-18 18:51:12 +00:00
{
2020-01-10 01:10:07 +00:00
loadThread = std : : thread ( [ f ] {
try
{
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , * f , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-01-10 01:10:07 +00:00
}
catch ( const tracy : : UnsupportedVersion & e )
{
badVer . state = tracy : : BadVersionState : : UnsupportedVersion ;
badVer . version = e . version ;
}
catch ( const tracy : : LegacyVersion & e )
{
badVer . state = tracy : : BadVersionState : : LegacyVersion ;
badVer . version = e . version ;
}
2020-05-03 18:49:13 +00:00
} ) ;
2019-06-17 17:45:47 +00:00
}
}
2020-01-10 01:10:07 +00:00
catch ( const tracy : : NotTracyDump & )
{
badVer . state = tracy : : BadVersionState : : BadFile ;
}
2020-02-12 18:53:37 +00:00
catch ( const tracy : : FileReadError & )
{
badVer . state = tracy : : BadVersionState : : ReadError ;
}
2019-06-17 17:45:47 +00:00
}
2020-01-10 01:10:07 +00:00
}
2019-06-17 17:45:47 +00:00
2020-01-10 01:10:07 +00:00
if ( badVer . state ! = tracy : : BadVersionState : : Ok )
{
if ( loadThread . joinable ( ) ) { loadThread . join ( ) ; }
tracy : : BadVersion ( badVer ) ;
2017-09-15 19:25:47 +00:00
}
2021-03-16 23:51:24 +00:00
# endif
2020-01-10 01:10:07 +00:00
if ( ! clients . empty ( ) )
2017-09-15 19:25:47 +00:00
{
2020-01-10 01:10:07 +00:00
ImGui : : Separator ( ) ;
ImGui : : TextUnformatted ( " Discovered clients: " ) ;
2020-05-03 19:10:25 +00:00
ImGui : : SameLine ( ) ;
tracy : : SmallToggleButton ( ICON_FA_FILTER " Filter " , showFilter ) ;
if ( addrFilter . IsActive ( ) | | portFilter . IsActive ( ) | | progFilter . IsActive ( ) )
{
ImGui : : SameLine ( ) ;
tracy : : TextColoredUnformatted ( 0xFF00FFFF , ICON_FA_EXCLAMATION_TRIANGLE ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : TextUnformatted ( " Filters are active " ) ;
ImGui : : EndTooltip ( ) ;
}
if ( showFilter )
{
ImGui : : SameLine ( ) ;
if ( ImGui : : SmallButton ( ICON_FA_BACKSPACE " Clear " ) )
{
addrFilter . Clear ( ) ;
portFilter . Clear ( ) ;
progFilter . Clear ( ) ;
}
}
}
if ( showFilter )
{
const auto w = ImGui : : GetFontSize ( ) * 12 ;
ImGui : : Separator ( ) ;
addrFilter . Draw ( " Address filter " , w ) ;
portFilter . Draw ( " Port filter " , w ) ;
progFilter . Draw ( " Program filter " , w ) ;
}
2020-01-10 01:10:07 +00:00
ImGui : : Separator ( ) ;
static bool widthSet = false ;
ImGui : : Columns ( 3 ) ;
if ( ! widthSet )
2019-06-17 17:34:48 +00:00
{
2020-01-10 01:10:07 +00:00
widthSet = true ;
const auto w = ImGui : : GetWindowWidth ( ) ;
ImGui : : SetColumnWidth ( 0 , w * 0.35f ) ;
ImGui : : SetColumnWidth ( 1 , w * 0.175f ) ;
ImGui : : SetColumnWidth ( 2 , w * 0.425f ) ;
2019-06-17 17:34:48 +00:00
}
2020-01-10 01:10:07 +00:00
std : : lock_guard < std : : mutex > lock ( resolvLock ) ;
2020-04-05 10:51:40 +00:00
int idx = 0 ;
2020-05-03 19:10:25 +00:00
int passed = 0 ;
2020-01-10 01:10:07 +00:00
for ( auto & v : clients )
2018-04-29 23:16:08 +00:00
{
2020-01-10 01:10:07 +00:00
const bool badProto = v . second . protocolVersion ! = tracy : : ProtocolVersion ;
bool sel = false ;
const auto & name = resolvMap . find ( v . second . address ) ;
assert ( name ! = resolvMap . end ( ) ) ;
2020-05-03 19:10:25 +00:00
if ( addrFilter . IsActive ( ) & & ! addrFilter . PassFilter ( name - > second . c_str ( ) ) & & ! addrFilter . PassFilter ( v . second . address . c_str ( ) ) ) continue ;
if ( portFilter . IsActive ( ) )
{
char buf [ 32 ] ;
2020-10-02 16:51:54 +00:00
sprintf ( buf , " % " PRIu16 , v . second . port ) ;
2020-05-03 19:10:25 +00:00
if ( ! portFilter . PassFilter ( buf ) ) continue ;
}
if ( progFilter . IsActive ( ) & & ! progFilter . PassFilter ( v . second . procName . c_str ( ) ) ) continue ;
2020-01-10 01:10:07 +00:00
ImGuiSelectableFlags flags = ImGuiSelectableFlags_SpanAllColumns ;
if ( badProto ) flags | = ImGuiSelectableFlags_Disabled ;
2020-04-05 10:51:40 +00:00
ImGui : : PushID ( idx + + ) ;
2020-03-08 13:51:28 +00:00
const bool selected = ImGui : : Selectable ( name - > second . c_str ( ) , & sel , flags ) ;
2020-04-05 10:51:40 +00:00
ImGui : : PopID ( ) ;
2020-03-08 15:19:58 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
char portstr [ 32 ] ;
2020-10-02 16:51:54 +00:00
sprintf ( portstr , " % " PRIu16 , v . second . port ) ;
2020-03-08 15:19:58 +00:00
ImGui : : BeginTooltip ( ) ;
2020-06-04 00:15:21 +00:00
if ( badProto )
{
tracy : : TextColoredUnformatted ( 0xFF0000FF , " Incompatible protocol! " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (used: %i, required: %i) " , v . second . protocolVersion , tracy : : ProtocolVersion ) ;
}
2020-03-08 15:19:58 +00:00
tracy : : TextFocused ( " IP: " , v . second . address . c_str ( ) ) ;
tracy : : TextFocused ( " Port: " , portstr ) ;
ImGui : : EndTooltip ( ) ;
}
2020-03-08 13:51:28 +00:00
if ( v . second . port ! = port )
2020-01-10 01:10:07 +00:00
{
2020-03-08 13:51:28 +00:00
ImGui : : SameLine ( ) ;
2020-10-02 16:51:54 +00:00
ImGui : : TextDisabled ( " :% " PRIu16 , v . second . port ) ;
2020-03-08 13:51:28 +00:00
}
if ( selected & & ! loadThread . joinable ( ) )
{
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , v . second . address . c_str ( ) , v . second . port , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-01-10 01:10:07 +00:00
}
ImGui : : NextColumn ( ) ;
const auto acttime = ( v . second . activeTime + ( time - v . second . time ) / 1000 ) * 1000000000ll ;
if ( badProto )
{
tracy : : TextDisabledUnformatted ( tracy : : TimeToString ( acttime ) ) ;
}
else
{
ImGui : : TextUnformatted ( tracy : : TimeToString ( acttime ) ) ;
}
ImGui : : NextColumn ( ) ;
if ( badProto )
{
tracy : : TextDisabledUnformatted ( v . second . procName . c_str ( ) ) ;
}
else
{
ImGui : : TextUnformatted ( v . second . procName . c_str ( ) ) ;
}
ImGui : : NextColumn ( ) ;
2020-05-03 19:10:25 +00:00
passed + + ;
2018-04-29 23:16:08 +00:00
}
2020-01-10 01:10:07 +00:00
ImGui : : EndColumns ( ) ;
2020-05-03 19:10:25 +00:00
if ( passed = = 0 )
{
ImGui : : TextUnformatted ( " All clients are filtered. " ) ;
}
2017-09-15 19:25:47 +00:00
}
2020-01-10 01:10:07 +00:00
ImGui : : End ( ) ;
2020-09-12 11:22:02 +00:00
if ( showReleaseNotes )
{
assert ( updateNotesThread . joinable ( ) ) ;
ImGui : : SetNextWindowSize ( ImVec2 ( 600 , 400 ) , ImGuiCond_FirstUseEver ) ;
ImGui : : Begin ( " Update available! " , & showReleaseNotes ) ;
if ( ImGui : : Button ( ICON_FA_DOWNLOAD " Download " ) )
{
2021-06-04 12:33:12 +00:00
tracy : : OpenWebpage ( " https://github.com/wolfpld/tracy/releases " ) ;
2020-09-12 11:22:02 +00:00
}
ImGui : : BeginChild ( " ###notes " , ImVec2 ( 0 , 0 ) , true ) ;
if ( releaseNotes . empty ( ) )
{
static float rnTime = 0 ;
rnTime + = ImGui : : GetIO ( ) . DeltaTime ;
tracy : : TextCentered ( " Fetching release notes... " ) ;
tracy : : DrawWaitingDots ( rnTime ) ;
}
else
{
ImGui : : PushFont ( fixedWidth ) ;
ImGui : : TextUnformatted ( releaseNotes . c_str ( ) ) ;
ImGui : : PopFont ( ) ;
}
ImGui : : EndChild ( ) ;
ImGui : : End ( ) ;
}
2020-01-10 01:10:07 +00:00
}
else
{
2020-09-12 11:22:02 +00:00
if ( showReleaseNotes ) showReleaseNotes = false ;
2020-01-10 01:10:07 +00:00
if ( broadcastListen )
2018-07-28 16:07:55 +00:00
{
2020-01-10 01:10:07 +00:00
broadcastListen . reset ( ) ;
clients . clear ( ) ;
2018-07-28 16:07:55 +00:00
}
2020-01-10 01:10:07 +00:00
if ( loadThread . joinable ( ) ) loadThread . join ( ) ;
view - > NotifyRootWindowSize ( display_w , display_h ) ;
if ( ! view - > Draw ( ) )
2018-07-28 16:07:55 +00:00
{
2020-05-13 17:20:20 +00:00
viewShutdown . store ( ViewShutdown : : True , std : : memory_order_relaxed ) ;
2020-03-06 21:11:29 +00:00
reconnect = view - > ReconnectRequested ( ) ;
if ( reconnect )
{
reconnectAddr = view - > GetAddress ( ) ;
reconnectPort = view - > GetPort ( ) ;
}
2020-01-10 01:10:07 +00:00
loadThread = std : : thread ( [ view = std : : move ( view ) ] ( ) mutable {
view . reset ( ) ;
2020-05-13 17:20:20 +00:00
viewShutdown . store ( ViewShutdown : : Join , std : : memory_order_relaxed ) ;
2020-01-10 01:10:07 +00:00
} ) ;
}
}
auto & progress = tracy : : Worker : : GetLoadProgress ( ) ;
auto totalProgress = progress . total . load ( std : : memory_order_relaxed ) ;
if ( totalProgress ! = 0 )
{
ImGui : : OpenPopup ( " Loading trace... " ) ;
}
if ( ImGui : : BeginPopupModal ( " Loading trace... " , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) )
{
tracy : : TextCentered ( ICON_FA_HOURGLASS_HALF ) ;
2019-03-06 01:49:21 +00:00
2020-01-10 01:10:07 +00:00
animTime + = ImGui : : GetIO ( ) . DeltaTime ;
tracy : : DrawWaitingDots ( animTime ) ;
2018-07-28 16:56:52 +00:00
2020-01-10 01:10:07 +00:00
auto currProgress = progress . progress . load ( std : : memory_order_relaxed ) ;
if ( totalProgress = = 0 )
{
ImGui : : CloseCurrentPopup ( ) ;
totalProgress = currProgress ;
2018-07-28 16:07:55 +00:00
}
2020-01-10 01:10:07 +00:00
switch ( currProgress )
2019-07-24 21:54:47 +00:00
{
2020-01-10 01:10:07 +00:00
case tracy : : LoadProgress : : Initialization :
ImGui : : TextUnformatted ( " Initialization... " ) ;
break ;
case tracy : : LoadProgress : : Locks :
ImGui : : TextUnformatted ( " Locks... " ) ;
break ;
case tracy : : LoadProgress : : Messages :
ImGui : : TextUnformatted ( " Messages... " ) ;
break ;
case tracy : : LoadProgress : : Zones :
ImGui : : TextUnformatted ( " CPU zones... " ) ;
2019-07-24 21:54:47 +00:00
break ;
2020-01-10 01:10:07 +00:00
case tracy : : LoadProgress : : GpuZones :
ImGui : : TextUnformatted ( " GPU zones... " ) ;
break ;
case tracy : : LoadProgress : : Plots :
ImGui : : TextUnformatted ( " Plots... " ) ;
break ;
case tracy : : LoadProgress : : Memory :
ImGui : : TextUnformatted ( " Memory... " ) ;
break ;
case tracy : : LoadProgress : : CallStacks :
ImGui : : TextUnformatted ( " Call stacks... " ) ;
break ;
case tracy : : LoadProgress : : FrameImages :
ImGui : : TextUnformatted ( " Frame images... " ) ;
break ;
case tracy : : LoadProgress : : ContextSwitches :
ImGui : : TextUnformatted ( " Context switches... " ) ;
break ;
case tracy : : LoadProgress : : ContextSwitchesPerCpu :
ImGui : : TextUnformatted ( " CPU context switches... " ) ;
2019-07-24 21:54:47 +00:00
break ;
default :
2020-01-10 01:10:07 +00:00
assert ( false ) ;
2019-07-24 21:54:47 +00:00
break ;
}
2020-01-10 01:10:07 +00:00
ImGui : : ProgressBar ( float ( currProgress ) / totalProgress , ImVec2 ( 200 * dpiScale , 0 ) ) ;
ImGui : : TextUnformatted ( " Progress... " ) ;
auto subTotal = progress . subTotal . load ( std : : memory_order_relaxed ) ;
auto subProgress = progress . subProgress . load ( std : : memory_order_relaxed ) ;
if ( subTotal = = 0 )
2019-07-24 21:54:47 +00:00
{
2020-01-10 01:10:07 +00:00
ImGui : : ProgressBar ( 1.f , ImVec2 ( 200 * dpiScale , 0 ) ) ;
2019-07-24 21:54:47 +00:00
}
2020-01-10 01:10:07 +00:00
else
2018-07-29 20:11:24 +00:00
{
2020-01-10 01:10:07 +00:00
ImGui : : ProgressBar ( float ( subProgress ) / subTotal , ImVec2 ( 200 * dpiScale , 0 ) ) ;
2018-07-29 20:11:24 +00:00
}
2020-01-10 01:10:07 +00:00
ImGui : : EndPopup ( ) ;
2017-09-15 19:25:47 +00:00
}
2020-05-13 17:20:20 +00:00
switch ( viewShutdown . load ( std : : memory_order_relaxed ) )
2018-08-31 17:38:19 +00:00
{
2020-01-10 01:10:07 +00:00
case ViewShutdown : : True :
ImGui : : OpenPopup ( " Capture cleanup... " ) ;
break ;
case ViewShutdown : : Join :
loadThread . join ( ) ;
2020-05-13 17:20:20 +00:00
viewShutdown . store ( ViewShutdown : : False , std : : memory_order_relaxed ) ;
2020-03-06 21:11:29 +00:00
if ( reconnect )
{
2020-08-15 12:59:16 +00:00
view = std : : make_unique < tracy : : View > ( RunOnMainThread , reconnectAddr . c_str ( ) , reconnectPort , fixedWidth , smallFont , bigFont , SetWindowTitleCallback , GetMainWindowNative ) ;
2020-03-06 21:11:29 +00:00
}
2020-01-10 01:10:07 +00:00
break ;
default :
break ;
2018-08-31 17:38:19 +00:00
}
2020-01-10 01:10:07 +00:00
if ( ImGui : : BeginPopupModal ( " Capture cleanup... " , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) )
2018-10-23 17:39:09 +00:00
{
2020-05-13 17:20:20 +00:00
if ( viewShutdown . load ( std : : memory_order_relaxed ) ! = ViewShutdown : : True ) ImGui : : CloseCurrentPopup ( ) ;
2020-01-10 01:10:07 +00:00
tracy : : TextCentered ( ICON_FA_BROOM ) ;
animTime + = ImGui : : GetIO ( ) . DeltaTime ;
tracy : : DrawWaitingDots ( animTime ) ;
2020-09-27 18:56:37 +00:00
ImGui : : TextUnformatted ( " Please wait, cleanup is in progress " ) ;
2020-01-10 01:10:07 +00:00
ImGui : : EndPopup ( ) ;
2018-10-23 17:39:09 +00:00
}
2020-01-10 01:10:07 +00:00
// Rendering
ImGui : : Render ( ) ;
glViewport ( 0 , 0 , display_w , display_h ) ;
glClearColor ( clear_color . x , clear_color . y , clear_color . z , clear_color . w ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
ImGui_ImplOpenGL3_RenderDrawData ( ImGui : : GetDrawData ( ) ) ;
2020-05-04 09:17:15 +00:00
// Update and Render additional Platform Windows
// (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
// For this specific demo app we could also call glfwMakeContextCurrent(window) directly)
if ( ImGui : : GetIO ( ) . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
{
GLFWwindow * backup_current_context = glfwGetCurrentContext ( ) ;
ImGui : : UpdatePlatformWindows ( ) ;
ImGui : : RenderPlatformWindowsDefault ( ) ;
glfwMakeContextCurrent ( backup_current_context ) ;
}
2020-01-10 01:10:07 +00:00
glfwSwapBuffers ( s_glfwWindow ) ;
2017-09-15 19:25:47 +00:00
}