diff --git a/README.md b/README.md index b5c6be697..ddb0ac33a 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,12 @@ pip install meson ninja Or follow the [Meson quickstart guide](https://mesonbuild.com/Quick-guide.html). +### Tracy profiler + +This project can be built with Tracy profiling support. Tracy is available as a meson subproject (bundled in `subprojects/tracy`) and many distributions provide the Tracy tooling; on Arch/Manjaro you can get the latest build from the AUR as `tracy-git`. + +Tracy can be directly enabled if you enable the tracy meson option before compiling. + #### Docker (alternative) If you don't want to install dependencies, use the included devcontainer. Open the project in VS Code with the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension, or build manually: diff --git a/meson.build b/meson.build index 52b3f581a..f25205424 100644 --- a/meson.build +++ b/meson.build @@ -1,16 +1,16 @@ project( - '4jcraft', - ['cpp', 'c'], - version: '0.1.0', - meson_version: '>= 1.3', - default_options: [ - 'cpp_std=c++23', - 'warning_level=0', - 'buildtype=debugoptimized', # for now - 'unity=on', # merge source files per target - 'unity_size=8', # TODO: mess around with this - 'b_pch=true', # precompiled headers - ], + '4jcraft', + ['cpp', 'c'], + version: '0.1.0', + meson_version: '>= 1.3', + default_options: [ + 'cpp_std=c++23', + 'warning_level=0', + 'buildtype=debugoptimized', # for now + 'unity=on', # merge source files per target + 'unity_size=8', # TODO: mess around with this + 'b_pch=true', # precompiled headers + ], ) pymod = import('python') @@ -19,30 +19,30 @@ python = pymod.find_installation('python3', required: true) cc = meson.get_compiler('cpp') global_cpp_defs = [ - '-DSPLIT_SAVES', - '-D_LARGE_WORLDS', - '-D_EXTENDED_ACHIEVEMENTS', - '-D_DEBUG_MENUS_ENABLED', - '-D_DEBUG', - '-D_FORTIFY_SOURCE=2', - '-DDEBUG', + '-DSPLIT_SAVES', + '-D_LARGE_WORLDS', + '-D_EXTENDED_ACHIEVEMENTS', + '-D_DEBUG_MENUS_ENABLED', + '-D_DEBUG', + '-D_FORTIFY_SOURCE=2', + '-DDEBUG', ] if host_machine.system() == 'linux' - global_cpp_defs += ['-Dlinux', '-D__linux', '-D__linux__'] + global_cpp_defs += ['-Dlinux', '-D__linux', '-D__linux__'] endif if get_option('renderer') == 'gles' - global_cpp_defs += ['-DGLES'] - gl_dep = dependency('glesv2', required: true) - glu_dep = dependency('', required: false) + global_cpp_defs += ['-DGLES'] + gl_dep = dependency('glesv2', required: true) + glu_dep = dependency('', required: false) else - gl_dep = dependency('gl', required: true) - glu_dep = dependency('glu', required: true) + gl_dep = dependency('gl', required: true) + glu_dep = dependency('glu', required: true) endif if get_option('enable_vsync') - global_cpp_defs += ['-DENABLE_VSYNC'] + global_cpp_defs += ['-DENABLE_VSYNC'] endif if get_option('classic_panorama') @@ -50,22 +50,22 @@ if get_option('classic_panorama') endif if get_option('enable_frame_profiler') - global_cpp_defs += ['-DENABLE_FRAME_PROFILER'] + global_cpp_defs += ['-DENABLE_FRAME_PROFILER'] endif if get_option('ui_backend') == 'shiggy' - global_cpp_defs += ['-D_ENABLEIGGY'] + global_cpp_defs += ['-D_ENABLEIGGY'] endif if get_option('ui_backend') == 'java' - global_cpp_defs += '-DENABLE_JAVA_GUIS' + global_cpp_defs += '-DENABLE_JAVA_GUIS' endif add_project_arguments(global_cpp_defs, language: ['cpp', 'c']) global_cpp_args = [ - '-Wshift-count-overflow', - '-pipe', + '-Wshift-count-overflow', + '-pipe', ] add_project_arguments(global_cpp_args, language: 'cpp') @@ -79,6 +79,20 @@ stb_dep = declare_dependency(include_directories: stb) miniaudio_dep = dependency('miniaudio') +tracy_opt = get_option('tracy') + +if not tracy_opt.disabled() + tracy_proj = subproject('tracy', required: tracy_opt, default_options: ['tracy_enable=true']) + if tracy_proj.found() + tracy_client_dep = tracy_proj.get_variable('tracy_dep') + add_project_arguments('-DTRACY_ENABLE', language: ['cpp', 'c']) + else + tracy_client_dep = dependency('', required: false) + endif +else + tracy_client_dep = dependency('', required: false) +endif + subdir('targets/util') subdir('targets/java') subdir('targets/nbt') @@ -86,4 +100,4 @@ subdir('targets/platform') subdir('targets/resources') subdir('targets/minecraft') -subdir('targets/app') +subdir('targets/app') \ No newline at end of file diff --git a/meson.options b/meson.options index 4dc73f322..cbe2e2cd7 100644 --- a/meson.options +++ b/meson.options @@ -7,8 +7,8 @@ option( ) option('classic_panorama', - type : 'boolean', - value : false, + type : 'boolean', + value : false, description : 'Enable classic java edition panorama (ui_backend=java ONLY).') option( @@ -40,3 +40,10 @@ option( value: 'frustum', description: 'Occlusion culling mode. Off disables ALL CULLING (debug only!), Frustum disables offscreen rendering (default), BFS is experimental connectivity culling, hardware uses GPU queries.', ) + +option( + 'tracy', + type: 'feature', + value: 'auto', + description: 'Enable Tracy profiler' +) diff --git a/targets/app/common/Game.cpp b/targets/app/common/Game.cpp index aeb8668bd..34b83bbf3 100644 --- a/targets/app/common/Game.cpp +++ b/targets/app/common/Game.cpp @@ -92,6 +92,13 @@ #include "minecraft/server/PlayerList.h" #include "minecraft/server/level/ServerPlayer.h" +#ifdef TRACY_ENABLE + #include +#else + #define ZoneScoped + #define ZoneScopedN(name) +#endif + class BeaconTileEntity; class BrewingStandTileEntity; class DispenserTileEntity; @@ -2202,6 +2209,7 @@ void Game::SetActionConfirmed(void* param) { } void Game::HandleXuiActions(void) { + ZoneScoped; eXuiAction eAction; eTMSAction eTMS; void* param; @@ -4394,6 +4402,7 @@ void Game::InitTime() { // Desc: Updates the elapsed time since our last frame. //------------------------------------------------------------------------------------- void Game::UpdateTime() { + ZoneScoped; auto qwNewTime = time_util::clock::now(); auto qwDeltaTime = qwNewTime - m_Time.qwTime; @@ -5557,6 +5566,7 @@ void Game::unlockSaveNotification() { } int Game::RemoteSaveThreadProc(void* lpParameter) { + ZoneScoped; // The game should be stopped while we are doing this, but the connections // ticks may try to create some AABB's or Vec3's Compression::UseDefaultThreadStorage(); diff --git a/targets/app/meson.build b/targets/app/meson.build index db074a2c6..48d5aefaf 100644 --- a/targets/app/meson.build +++ b/targets/app/meson.build @@ -1,102 +1,106 @@ exclude_sources = [ - ' ! -path "*/common/*"', - ' ! -path "*/linux/*"', - ' ! -path "*/windows/*"', + ' ! -path "*/common/*"', + ' ! -path "*/linux/*"', + ' ! -path "*/windows/*"', ] # all sources except common/, linux/, windows/ client_sources = run_command( - 'sh', - '-c', 'find "' - + meson.current_source_dir() - + '" \\( -name "*.cpp" -o -name "*.c" \\)' - + ' '.join(exclude_sources), - check: true, + 'sh', + '-c', 'find "' + + meson.current_source_dir() + + '" \\( -name "*.cpp" -o -name "*.c" \\)' + + ' '.join(exclude_sources), + check: true, ).stdout().strip().split('\n') exclude_platform_common_sources = [ - ' ! -name "UIScene_InGameSaveManagementMenu.cpp"', + ' ! -name "UIScene_InGameSaveManagementMenu.cpp"', ] # all sources in common/ platform_sources = run_command( - 'sh', - '-c', 'find "' - + meson.current_source_dir() / 'common' - + '" \\( -name "*.cpp" -o -name "*.c" \\)' - + ' '.join(exclude_platform_common_sources), - check: true, + 'sh', + '-c', 'find "' + + meson.current_source_dir() / 'common' + + '" \\( -name "*.cpp" -o -name "*.c" \\)' + + ' '.join(exclude_platform_common_sources), + check: true, ).stdout().strip().split('\n') # linux-specific files if host_machine.system() == 'linux' - platform_sources += run_command( - 'sh', - '-c', 'find "' - + meson.current_source_dir() / 'linux' - + '" \\( -name "*.cpp" -o -name "*.c" \\) ', - check: true, - ).stdout().strip().split('\n') + platform_sources += run_command( + 'sh', + '-c', 'find "' + + meson.current_source_dir() / 'linux' + + '" \\( -name "*.cpp" -o -name "*.c" \\) ', + check: true, + ).stdout().strip().split('\n') endif client_dependencies = [ - java_dep, - nbt_dep, - render_dep, - input_dep, - profile_dep, - storage_dep, - assets_localisation_dep, - platform_dep, - minecraft_dep, - gl_dep, - glu_dep, - thread_dep, - dl_dep, - dependency('zlib'), - miniaudio_dep, - stb_dep, - util_dep, + java_dep, + nbt_dep, + render_dep, + input_dep, + profile_dep, + storage_dep, + assets_localisation_dep, + platform_dep, + minecraft_dep, + gl_dep, + glu_dep, + thread_dep, + dl_dep, + dependency('zlib'), + miniaudio_dep, + stb_dep, + util_dep, + tracy_client_dep, ] if get_option('ui_backend') == 'shiggy' - shiggy_dep = dependency( - 'shiggy', - fallback: ['shiggy', 'shiggy_dep'], - ) - client_dependencies += shiggy_dep + shiggy_dep = dependency( + 'shiggy', + fallback: ['shiggy', 'shiggy_dep'], + ) + client_dependencies += shiggy_dep endif platform_services_src = files('../platform/PlatformServices.cpp') client = executable( - 'Minecraft.Client', - client_sources + platform_sources + platform_services_src + localisation[1], - include_directories: include_directories('include', '..'), - dependencies: client_dependencies, - cpp_args: global_cpp_args - + global_cpp_defs - + [ - '-DUNICODE', - '-D_UNICODE', - ], - c_args: global_cpp_defs + ['-DUNICODE', '-D_UNICODE'], - install: true, - install_dir: '', + 'Minecraft.Client', + client_sources + + platform_sources + + platform_services_src + + localisation[1], + include_directories: include_directories('include', '..'), + dependencies: client_dependencies, + cpp_args: global_cpp_args + + global_cpp_defs + + [ + '-DUNICODE', + '-D_UNICODE', + ], + c_args: global_cpp_defs + ['-DUNICODE', '-D_UNICODE'], + install: true, + install_dir: '', ) custom_target( - 'copy_assets_to_client', - input: [client, media_archive], - output: 'assets.stamp', - command: [ - python, - meson.project_source_root() / 'scripts/copy_assets_to_client.py', - meson.project_source_root(), - meson.project_build_root(), - meson.current_build_dir(), - '@INPUT1@', - '@OUTPUT@', - ], - build_by_default: true, -) + 'copy_assets_to_client', + input: [client, media_archive], + output: 'assets.stamp', + command: [ + python, + meson.project_source_root() / 'scripts/copy_assets_to_client.py', + meson.project_source_root(), + meson.project_build_root(), + meson.current_build_dir(), + '@INPUT1@', + '@OUTPUT@', + ], + build_by_default: true, +) \ No newline at end of file diff --git a/targets/minecraft/client/Minecraft.cpp b/targets/minecraft/client/Minecraft.cpp index 80875804d..c136761d6 100644 --- a/targets/minecraft/client/Minecraft.cpp +++ b/targets/minecraft/client/Minecraft.cpp @@ -131,6 +131,13 @@ #include "minecraft/world/level/chunk/SparseDataStorage.h" #include "minecraft/world/level/chunk/SparseLightStorage.h" +#ifdef TRACY_ENABLE + #include +#else + #define ZoneScoped + #define ZoneScopedN(name) +#endif + class ChunkSource; // #define DISABLE_SPU_CODE @@ -1019,6 +1026,7 @@ void Minecraft::createPrimaryLocalPlayer(int iPad) { } void Minecraft::run_middle() { + ZoneScoped; static int64_t lastTime = 0; static bool bFirstTimeIntoGame = true; static bool bAutosaveTimerSet = false; @@ -1166,6 +1174,7 @@ void Minecraft::run_middle() { // 4J-PB - Once we're in the level, check if the players have // the level in their banned list and ask if they want to play // it + ZoneScopedN("Render Viewports"); for (int i = 0; i < XUSER_MAX_COUNT; i++) { if (localplayers[i] && (app.GetBanListCheck(i) == false) && !Minecraft::GetInstance()->isTutorial() && @@ -1813,6 +1822,7 @@ void Minecraft::run_middle() { */ } } // lock_guard scope + FrameMark; } void Minecraft::run_end() { destroy(); } @@ -1990,6 +2000,7 @@ void Minecraft::verify() { } void Minecraft::levelTickUpdateFunc(void* pParam) { + ZoneScoped; Level* pLevel = (Level*)pParam; pLevel->tick(); } @@ -2003,6 +2014,7 @@ void Minecraft::levelTickThreadInitFunc() { // textures are to be updated - this will be true for the last time this tick // runs with bFirst true void Minecraft::tick(bool bFirst, bool bUpdateTextures) { + ZoneScoped; int iPad = player->GetXboxPad(); // OutputDebugString("Minecraft::tick\n"); @@ -4517,6 +4529,7 @@ int Minecraft::InGame_SignInReturned(void* pParam, bool bContinue, int iPad) { } void Minecraft::tickAllConnections() { + ZoneScoped; int oldIdx = getLocalPlayerIdx(); for (unsigned int i = 0; i < XUSER_MAX_COUNT; i++) { std::shared_ptr mplp = localplayers[i]; diff --git a/targets/minecraft/meson.build b/targets/minecraft/meson.build index a01210c79..a6f6646fb 100644 --- a/targets/minecraft/meson.build +++ b/targets/minecraft/meson.build @@ -58,6 +58,7 @@ lib_minecraft = static_library('minecraft', assets_localisation_dep, platform_dep, util_dep, + tracy_client_dep, dependency('zlib'), ], include_directories : include_directories('..'),