diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..ed81bf65e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "code/thirdparty/tracy"] + path = code/thirdparty/tracy + url = https://github.com/wolfpld/tracy.git diff --git a/cmake/libraries/all.cmake b/cmake/libraries/all.cmake index f57bbd361..3082cfb29 100644 --- a/cmake/libraries/all.cmake +++ b/cmake/libraries/all.cmake @@ -10,3 +10,4 @@ include(libraries/zlib) include(libraries/libmad) include(libraries/flex_bison) include(libraries/recastnavigation) +include(libraries/tracy) diff --git a/cmake/libraries/tracy.cmake b/cmake/libraries/tracy.cmake new file mode 100644 index 000000000..187a8d5ec --- /dev/null +++ b/cmake/libraries/tracy.cmake @@ -0,0 +1,25 @@ +# Tracy profiler +option(TRACY_ENABLE "Enable the Tracy profiler" OFF) + +# Make sure we build Tracy as objects with LTO that we can then link into a shared library. +set(TRACY_LTO ON) +add_subdirectory(${SOURCE_DIR}/thirdparty/tracy) + +# In accordance with section 2.1.8, "Setup for multi-DLL projects" of the Tracy manual, +# we wrap TracyClient into a shared library that we then depend on. +if(TRACY_ENABLE) + add_library(tracy SHARED ${SOURCE_DIR}/sys/sys_tracy.cpp) + # Include Tracy as a private dependency so that we can control the public interface of the DLL. + target_link_libraries(tracy PRIVATE Tracy::TracyClient) + target_include_directories(tracy SYSTEM PUBLIC ${SOURCE_DIR}/thirdparty/tracy/public) + # Copy over the public compile definitions from the TracyClient target - it's already set up for MSVC imports, for example. + get_target_property(TRACY_DEFS Tracy::TracyClient INTERFACE_COMPILE_DEFINITIONS) + target_compile_definitions(tracy PUBLIC ${TRACY_DEFS}) + INSTALL(TARGETS tracy DESTINATION ${INSTALL_LIBDIR_FULL}) +else() + # Even when disabled, we still want the includes available so that empty Tracy macros are declared. + add_library(tracy INTERFACE) + target_include_directories(tracy SYSTEM INTERFACE ${SOURCE_DIR}/thirdparty/tracy/public) +endif() + +list(APPEND COMMON_LIBRARIES tracy) diff --git a/code/cgame/cg_view.c b/code/cgame/cg_view.c index fd160f3f4..1a2a6e6e9 100644 --- a/code/cgame/cg_view.c +++ b/code/cgame/cg_view.c @@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cg_local.h" #include "cg_parsemsg.h" +#include + //============================================================================ /* @@ -826,6 +828,8 @@ Generates and draws a game scene and status information at the given time. */ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, qboolean demoPlayback) { + TracyCZone(ctx, 1); + cg.time = serverTime; cg.frametime = frameTime; cg.demoPlayback = demoPlayback; @@ -843,6 +847,7 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, // if we haven't received any snapshots yet, all // we can draw is the information screen if (!cg.snap || (cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE)) { + TracyCZoneEnd(ctx); return; } @@ -1037,4 +1042,6 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView, if (cg_stats->integer) { cgi.Printf("cg.clientFrame:%i\n", cg.clientFrame); } + + TracyCZoneEnd(ctx); } diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp index 63a463978..92f28b80b 100644 --- a/code/client/cl_main.cpp +++ b/code/client/cl_main.cpp @@ -40,6 +40,8 @@ extern "C" { #include +#include + #ifdef USE_RENDERER_DLOPEN cvar_t* cl_renderer; #endif @@ -850,6 +852,8 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) { UI_ClearState(); UI_ForceMenuOff(false); + TracyMessageS(va("CL_MapLoading: %s", pszMapName), 15 + strlen(pszMapName), 16); + if (!flush) { // Don't do anything if it's not flushingb return; @@ -2672,6 +2676,8 @@ void CL_Frame ( int msec ) { return; } + ZoneScoped; + #ifdef USE_CURL if(clc.downloadCURLM) { CL_cURL_PerformDownload(); diff --git a/code/fgame/g_main.cpp b/code/fgame/g_main.cpp index ba2f40f00..160a1e176 100644 --- a/code/fgame/g_main.cpp +++ b/code/fgame/g_main.cpp @@ -46,6 +46,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # include #endif +#include + #define SAVEGAME_VERSION 80 #define PERSISTANT_VERSION 2 @@ -482,6 +484,8 @@ void G_RunFrame(int levelTime, int frameTime) static int processed[MAX_GENTITIES] = {0}; static int processedFrameID = 0; + ZoneScoped; + try { g_iInThinks = 0; diff --git a/code/qcommon/cm_load.c b/code/qcommon/cm_load.c index 56b20b013..8a4dcd5fc 100644 --- a/code/qcommon/cm_load.c +++ b/code/qcommon/cm_load.c @@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "cm_local.h" #include "../client/client.h" +#include + #ifdef BSPC #include "../bspc/l_qfiles.h" @@ -838,6 +840,8 @@ void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) { Com_Error( ERR_DROP, "CM_LoadMap: NULL name" ); } + TracyCMessageS(va("CM_LoadMap: %s", name), 12 + strlen(name), 16); + #ifndef BSPC cm_noAreas = Cvar_Get( "cm_noAreas", "0", CVAR_CHEAT ); cm_noCurves = Cvar_Get( "cm_noCurves", "0", CVAR_CHEAT ); diff --git a/code/qcommon/cmd.c b/code/qcommon/cmd.c index 338456a18..3a454a349 100644 --- a/code/qcommon/cmd.c +++ b/code/qcommon/cmd.c @@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "q_shared.h" #include "qcommon.h" +#include + #define MAX_CMD_BUFFER 128*1024 #define MAX_CMD_LINE 8192 // was increased for testing purposes #define MAX_ALIAS_NAME 32 @@ -989,6 +991,8 @@ void Cmd_ExecuteString( const char *text ) { cmd_function_t *cmd, **prev; cmdalias_t *a; + TracyCMessageS(va("Cmd_ExecuteString: %s", text), strlen(text) + 19, 0); + // execute the command line Cmd_TokenizeString( text ); if ( !Cmd_Argc() ) { diff --git a/code/qcommon/common.c b/code/qcommon/common.c index 46bd48048..3511a8c8a 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -47,6 +47,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../gamespy/q_gamespy.h" +#include + qboolean CL_FinishedIntro(void); #ifdef __cplusplus @@ -2495,6 +2497,8 @@ void Com_Frame( void ) { Sys_ProcessBackgroundTasks(); com_frameNumber++; + + TracyCFrameMark; } /* diff --git a/code/sdl/sdl_input.c b/code/sdl/sdl_input.c index 74761af79..51360966b 100644 --- a/code/sdl/sdl_input.c +++ b/code/sdl/sdl_input.c @@ -33,6 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../client/client.h" #include "../sys/sys_local.h" +#include + #if !SDL_VERSION_ATLEAST(2, 0, 17) #define KMOD_SCROLL KMOD_RESERVED #endif @@ -1248,6 +1250,8 @@ void IN_Frame( void ) { qboolean loading; + TracyCZone(ctx, 1); + IN_JoyMove( ); // If not DISCONNECTED (main menu) or ACTIVE (in game), we're loading @@ -1285,6 +1289,8 @@ void IN_Frame( void ) vidRestartTime = 0; Cbuf_AddText( "vid_restart\n" ); } + + TracyCZoneEnd(ctx); } /* diff --git a/code/server/sv_init.c b/code/server/sv_init.c index 5fa6ba3db..231032658 100644 --- a/code/server/sv_init.c +++ b/code/server/sv_init.c @@ -26,6 +26,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/bg_compat.h" #include "../gamespy/sv_gamespy.h" +#include + static char last_mapname[ MAX_QPATH ]; static int g_iSvsTimeFixupCount; static int *g_piSvsTimeFixups[ 2048 ]; @@ -587,6 +589,8 @@ void SV_SpawnServer( const char *server, qboolean loadgame, qboolean restart, qb qboolean keep_scripts; const char *p; + TracyCZone(ctx, 1); + keep_scripts = restart; Com_Printf ("------ Server Initialization ------\n"); @@ -975,6 +979,8 @@ void SV_SpawnServer( const char *server, qboolean loadgame, qboolean restart, qb if( g_gametype->integer != GT_SINGLE_PLAYER ) { SV_ServerLoaded(); } + + TracyCZoneEnd(ctx); } /* diff --git a/code/server/sv_main.c b/code/server/sv_main.c index f9ca50333..45408a2d2 100644 --- a/code/server/sv_main.c +++ b/code/server/sv_main.c @@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../gamespy/sv_gamespy.h" #include "../gamespy/sv_gqueryreporting.h" +#include + #ifdef USE_VOIP cvar_t *sv_voip; cvar_t *sv_voipProtocol; @@ -1059,10 +1061,13 @@ void SV_Frame( int msec ) { return; } + TracyCZone(ctx, 1); + SV_NET_UpdateAllNetProfileInfo(); // allow pause if only the local client is connected if ( SV_CheckPaused() ) { + TracyCZoneEnd(ctx); return; } @@ -1088,12 +1093,14 @@ void SV_Frame( int msec ) { if ( svs.time > 0x70000000 ) { SV_Shutdown( "Restarting server due to time wrapping" ); Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) ); + TracyCZoneEnd(ctx); return; } // this can happen considerably earlier when lots of clients play and the map doesn't change if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) { SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" ); Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) ); + TracyCZoneEnd(ctx); return; } @@ -1164,6 +1171,8 @@ void SV_Frame( int msec ) { SV_HandleNonPVSSound(); svs.lastTime = svs.time; + + TracyCZoneEnd(ctx); } /* diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index fd30a2134..bfc107a91 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -51,6 +51,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/q_shared.h" #include "../qcommon/qcommon.h" +#include +#if TRACY_ENABLE +extern TRACY_API void Sys_TracyShutdown(); +#endif + static char binaryPath[ MAX_OSPATH ] = { 0 }; static char installPath[ MAX_OSPATH ] = { 0 }; @@ -302,6 +307,10 @@ static Q_NO_RETURN void Sys_Exit( int exitCode ) Sys_PlatformExit( ); +#ifdef TRACY_ENABLE + Sys_TracyShutdown(); +#endif + exit( exitCode ); } diff --git a/code/sys/sys_tracy.cpp b/code/sys/sys_tracy.cpp new file mode 100644 index 000000000..8df75605d --- /dev/null +++ b/code/sys/sys_tracy.cpp @@ -0,0 +1,41 @@ +/* +=========================================================================== +Copyright (C) 2025 the OpenMoHAA team + +This file is part of OpenMoHAA source code. + +OpenMoHAA source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +OpenMoHAA source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with OpenMoHAA source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +// This file is compiled as part of the tracy target and contains C-linkage wrappers +// for advanced Tracy profiler functionality that isn't exposed via the TracyC API. + +// We are also still "inside" the Tracy client, so we need to patch up the import/export macros. +#undef TRACY_IMPORTS +#define TRACY_EXPORTS + +#include +#include + +extern "C" { + TRACY_API void Sys_TracyShutdown() + { + tracy::GetProfiler().RequestShutdown(); + while (!tracy::GetProfiler().HasShutdownFinished()) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } +} diff --git a/code/thirdparty/tracy b/code/thirdparty/tracy new file mode 160000 index 000000000..05cceee0d --- /dev/null +++ b/code/thirdparty/tracy @@ -0,0 +1 @@ +Subproject commit 05cceee0df3b8d7c6fa87e9638af311dbabc63cb