mirror of
https://github.com/minetest/minetest.git
synced 2024-12-22 06:02:23 +01:00
Add support for Tracy profiler (#15113)
This commit is contained in:
parent
6f23de41fb
commit
4aec4fbe6f
@ -56,6 +56,11 @@ if((WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR APPLE)
|
|||||||
endif()
|
endif()
|
||||||
set(ENABLE_LTO ${DEFAULT_ENABLE_LTO} CACHE BOOL "Use Link Time Optimization")
|
set(ENABLE_LTO ${DEFAULT_ENABLE_LTO} CACHE BOOL "Use Link Time Optimization")
|
||||||
|
|
||||||
|
set(BUILD_WITH_TRACY FALSE CACHE BOOL
|
||||||
|
"Fetch and build with the Tracy profiler client")
|
||||||
|
set(FETCH_TRACY_GIT_TAG "master" CACHE STRING
|
||||||
|
"Git tag for fetching Tracy client. Match with your server (gui) version")
|
||||||
|
|
||||||
set(DEFAULT_RUN_IN_PLACE FALSE)
|
set(DEFAULT_RUN_IN_PLACE FALSE)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(DEFAULT_RUN_IN_PLACE TRUE)
|
set(DEFAULT_RUN_IN_PLACE TRUE)
|
||||||
@ -370,3 +375,19 @@ if(BUILD_DOCUMENTATION)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Fetch Tracy
|
||||||
|
if(BUILD_WITH_TRACY)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
message(STATUS "Fetching Tracy (${FETCH_TRACY_GIT_TAG})...")
|
||||||
|
FetchContent_Declare(
|
||||||
|
tracy
|
||||||
|
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
|
||||||
|
GIT_TAG ${FETCH_TRACY_GIT_TAG}
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(tracy)
|
||||||
|
message(STATUS "Fetching Tracy - done")
|
||||||
|
endif()
|
||||||
|
@ -40,6 +40,8 @@ General options and their default values:
|
|||||||
ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
|
ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
|
||||||
INSTALL_DEVTEST=FALSE - Whether the Development Test game should be installed alongside Minetest
|
INSTALL_DEVTEST=FALSE - Whether the Development Test game should be installed alongside Minetest
|
||||||
USE_GPROF=FALSE - Enable profiling using GProf
|
USE_GPROF=FALSE - Enable profiling using GProf
|
||||||
|
BUILD_WITH_TRACY=FALSE - Fetch and build with the Tracy profiler client
|
||||||
|
FETCH_TRACY_GIT_TAG=master - Git tag for fetching Tracy client. Match with your server (gui) version
|
||||||
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
|
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
|
||||||
|
|
||||||
Library specific options:
|
Library specific options:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
|
|
||||||
## Profiling Minetest on Linux
|
## Profiling Minetest on Linux with perf
|
||||||
|
|
||||||
We will be using a tool called "perf", which you can get by installing `perf` or `linux-perf` or `linux-tools-common`.
|
We will be using a tool called "perf", which you can get by installing `perf` or `linux-perf` or `linux-tools-common`.
|
||||||
|
|
||||||
@ -36,3 +36,54 @@ Give both files to the developer and also provide:
|
|||||||
* commit the source was built from and/or modified source code (if applicable)
|
* commit the source was built from and/or modified source code (if applicable)
|
||||||
|
|
||||||
Hotspot will resolve symbols correctly when pointing the sysroot option at the collected libs.
|
Hotspot will resolve symbols correctly when pointing the sysroot option at the collected libs.
|
||||||
|
|
||||||
|
|
||||||
|
## Profiling with Tracy
|
||||||
|
|
||||||
|
[Tracy](https://github.com/wolfpld/tracy) is
|
||||||
|
> A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling
|
||||||
|
> profiler for games and other applications.
|
||||||
|
|
||||||
|
It allows one to annotate important functions and generate traces, where one can
|
||||||
|
see when each individual function call happened, and how long it took.
|
||||||
|
|
||||||
|
Tracy can also record when frames, e.g. server step, start and end, and inspect
|
||||||
|
frames that took longer than usual. Minetest already contains annotations for
|
||||||
|
its frames.
|
||||||
|
|
||||||
|
See also [Tracy's official documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf).
|
||||||
|
|
||||||
|
### Installing
|
||||||
|
|
||||||
|
Tracy consists of a client (Minetest) and a server (the gui).
|
||||||
|
|
||||||
|
Install the server, e.g. using your package manager.
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
Build Minetest with `-DDBUILD_WITH_TRACY=1`, this will fetch Tracy for building
|
||||||
|
the Tracy client. And use `FETCH_TRACY_GIT_TAG` to get a version matching your
|
||||||
|
Tracy server, e.g. `-DFETCH_TRACY_GIT_TAG=v0.11.0` if it's `0.11.0`.
|
||||||
|
|
||||||
|
To actually use Tracy, you also have to enable it with Tracy's build options:
|
||||||
|
```
|
||||||
|
-DTRACY_ENABLE=1 -DTRACY_ONLY_LOCALHOST=1
|
||||||
|
```
|
||||||
|
|
||||||
|
See Tracy's documentation for more build options.
|
||||||
|
|
||||||
|
### Using in C++
|
||||||
|
|
||||||
|
Start the Tracy server and Minetest. You should see Minetest in the menu.
|
||||||
|
|
||||||
|
To actually get useful traces, you have to annotate functions with `ZoneScoped`
|
||||||
|
macros and recompile. Please refer to Tracy's official documentation.
|
||||||
|
|
||||||
|
### Using in Lua
|
||||||
|
|
||||||
|
Tracy also supports Lua.
|
||||||
|
If built with Tracy, Minetest loads its API in the global `tracy` table.
|
||||||
|
See Tracy's official documentation for more information.
|
||||||
|
|
||||||
|
Note: The whole Tracy Lua API is accessible to all mods. And we don't check if it
|
||||||
|
is or becomes insecure. Run untrusted mods at your own risk.
|
||||||
|
@ -11394,6 +11394,16 @@ Functions: bit.tobit, bit.tohex, bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshi
|
|||||||
|
|
||||||
See http://bitop.luajit.org/ for advanced information.
|
See http://bitop.luajit.org/ for advanced information.
|
||||||
|
|
||||||
|
Tracy Profiler
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Minetest can be built with support for the Tracy profiler, which can also be
|
||||||
|
useful for profiling mods and is exposed to Lua as the global `tracy`.
|
||||||
|
|
||||||
|
See doc/developing/misc.md for details.
|
||||||
|
|
||||||
|
Note: This is a development feature and not covered by compatibility promises.
|
||||||
|
|
||||||
Error Handling
|
Error Handling
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
@ -468,6 +468,10 @@ foreach(object_lib
|
|||||||
target_include_directories(${object_lib} PRIVATE ${link_includes})
|
target_include_directories(${object_lib} PRIVATE ${link_includes})
|
||||||
# Add objects from object library to main library
|
# Add objects from object library to main library
|
||||||
target_sources(IrrlichtMt PRIVATE $<TARGET_OBJECTS:${object_lib}>)
|
target_sources(IrrlichtMt PRIVATE $<TARGET_OBJECTS:${object_lib}>)
|
||||||
|
|
||||||
|
if(BUILD_WITH_TRACY)
|
||||||
|
target_link_libraries(${object_lib} PRIVATE Tracy::TracyClient)
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Alias target provides add_submodule compatibility
|
# Alias target provides add_submodule compatibility
|
||||||
|
@ -648,6 +648,9 @@ if(BUILD_CLIENT)
|
|||||||
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
|
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
|
||||||
target_link_libraries(${PROJECT_NAME} Catch2::Catch2)
|
target_link_libraries(${PROJECT_NAME} Catch2::Catch2)
|
||||||
endif()
|
endif()
|
||||||
|
if(BUILD_WITH_TRACY)
|
||||||
|
target_link_libraries(${PROJECT_NAME} Tracy::TracyClient)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(PRECOMPILE_HEADERS)
|
if(PRECOMPILE_HEADERS)
|
||||||
target_precompile_headers(${PROJECT_NAME} PRIVATE ${PRECOMPILED_HEADERS_LIST})
|
target_precompile_headers(${PROJECT_NAME} PRIVATE ${PRECOMPILED_HEADERS_LIST})
|
||||||
@ -715,6 +718,9 @@ if(BUILD_SERVER)
|
|||||||
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
|
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
|
||||||
target_link_libraries(${PROJECT_NAME}server Catch2::Catch2)
|
target_link_libraries(${PROJECT_NAME}server Catch2::Catch2)
|
||||||
endif()
|
endif()
|
||||||
|
if(BUILD_WITH_TRACY)
|
||||||
|
target_link_libraries(${PROJECT_NAME}server Tracy::TracyClient)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(PRECOMPILE_HEADERS)
|
if(PRECOMPILE_HEADERS)
|
||||||
target_precompile_headers(${PROJECT_NAME}server PRIVATE ${PRECOMPILED_HEADERS_LIST})
|
target_precompile_headers(${PROJECT_NAME}server PRIVATE ${PRECOMPILED_HEADERS_LIST})
|
||||||
|
@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "renderingengine.h"
|
#include "renderingengine.h"
|
||||||
#include "network/networkexceptions.h"
|
#include "network/networkexceptions.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
#include <IGUISpriteBank.h>
|
#include <IGUISpriteBank.h>
|
||||||
#include <ICameraSceneNode.h>
|
#include <ICameraSceneNode.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -544,15 +545,19 @@ void ClientLauncher::main_menu(MainMenuData *menudata)
|
|||||||
video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
|
video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
|
||||||
|
|
||||||
infostream << "Waiting for other menus" << std::endl;
|
infostream << "Waiting for other menus" << std::endl;
|
||||||
|
auto framemarker = FrameMarker("ClientLauncher::main_menu()-wait-frame").started();
|
||||||
while (m_rendering_engine->run() && !*kill) {
|
while (m_rendering_engine->run() && !*kill) {
|
||||||
if (!isMenuActive())
|
if (!isMenuActive())
|
||||||
break;
|
break;
|
||||||
driver->beginScene(true, true, video::SColor(255, 128, 128, 128));
|
driver->beginScene(true, true, video::SColor(255, 128, 128, 128));
|
||||||
m_rendering_engine->get_gui_env()->drawAll();
|
m_rendering_engine->get_gui_env()->drawAll();
|
||||||
driver->endScene();
|
driver->endScene();
|
||||||
|
framemarker.end();
|
||||||
// On some computers framerate doesn't seem to be automatically limited
|
// On some computers framerate doesn't seem to be automatically limited
|
||||||
sleep_ms(25);
|
sleep_ms(25);
|
||||||
|
framemarker.start();
|
||||||
}
|
}
|
||||||
|
framemarker.end();
|
||||||
infostream << "Waited for other menus" << std::endl;
|
infostream << "Waited for other menus" << std::endl;
|
||||||
|
|
||||||
auto *cur_control = m_rendering_engine->get_raw_device()->getCursorControl();
|
auto *cur_control = m_rendering_engine->get_raw_device()->getCursorControl();
|
||||||
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "camera.h" // CameraModes
|
#include "camera.h" // CameraModes
|
||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
#include "client/renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@ -714,6 +715,8 @@ void ClientMap::touchMapBlocks()
|
|||||||
|
|
||||||
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
||||||
|
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/basic_macros.h"
|
#include "util/basic_macros.h"
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
#include "mapblock_mesh.h"
|
#include "mapblock_mesh.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
@ -1750,6 +1751,8 @@ void MapblockMeshGenerator::drawNode()
|
|||||||
|
|
||||||
void MapblockMeshGenerator::generate()
|
void MapblockMeshGenerator::generate()
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
for (cur_node.p.Z = 0; cur_node.p.Z < data->side_length; cur_node.p.Z++)
|
for (cur_node.p.Z = 0; cur_node.p.Z < data->side_length; cur_node.p.Z++)
|
||||||
for (cur_node.p.Y = 0; cur_node.p.Y < data->side_length; cur_node.p.Y++)
|
for (cur_node.p.Y = 0; cur_node.p.Y < data->side_length; cur_node.p.Y++)
|
||||||
for (cur_node.p.X = 0; cur_node.p.X < data->side_length; cur_node.p.X++) {
|
for (cur_node.p.X = 0; cur_node.p.X < data->side_length; cur_node.p.X++) {
|
||||||
|
@ -79,6 +79,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "hud.h"
|
#include "hud.h"
|
||||||
#include "clientdynamicinfo.h"
|
#include "clientdynamicinfo.h"
|
||||||
#include <IAnimatedMeshSceneNode.h>
|
#include <IAnimatedMeshSceneNode.h>
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
|
|
||||||
#if USE_SOUND
|
#if USE_SOUND
|
||||||
#include "client/sound/sound_openal.h"
|
#include "client/sound/sound_openal.h"
|
||||||
@ -1140,6 +1141,8 @@ bool Game::startup(bool *kill,
|
|||||||
|
|
||||||
void Game::run()
|
void Game::run()
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
ProfilerGraph graph;
|
ProfilerGraph graph;
|
||||||
RunStats stats = {};
|
RunStats stats = {};
|
||||||
CameraOrientation cam_view_target = {};
|
CameraOrientation cam_view_target = {};
|
||||||
@ -1167,15 +1170,21 @@ void Game::run()
|
|||||||
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
|
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
|
||||||
g_settings->getBool("window_maximized");
|
g_settings->getBool("window_maximized");
|
||||||
|
|
||||||
|
auto framemarker = FrameMarker("Game::run()-frame").started();
|
||||||
|
|
||||||
while (m_rendering_engine->run()
|
while (m_rendering_engine->run()
|
||||||
&& !(*kill || g_gamecallback->shutdown_requested
|
&& !(*kill || g_gamecallback->shutdown_requested
|
||||||
|| (server && server->isShutdownRequested()))) {
|
|| (server && server->isShutdownRequested()))) {
|
||||||
|
|
||||||
|
framemarker.end();
|
||||||
|
|
||||||
// Calculate dtime =
|
// Calculate dtime =
|
||||||
// m_rendering_engine->run() from this iteration
|
// m_rendering_engine->run() from this iteration
|
||||||
// + Sleep time until the wanted FPS are reached
|
// + Sleep time until the wanted FPS are reached
|
||||||
draw_times.limit(device, &dtime, g_menumgr.pausesGame());
|
draw_times.limit(device, &dtime, g_menumgr.pausesGame());
|
||||||
|
|
||||||
|
framemarker.start();
|
||||||
|
|
||||||
const auto current_dynamic_info = ClientDynamicInfo::getCurrent();
|
const auto current_dynamic_info = ClientDynamicInfo::getCurrent();
|
||||||
if (!current_dynamic_info.equal(client_display_info)) {
|
if (!current_dynamic_info.equal(client_display_info)) {
|
||||||
client_display_info = current_dynamic_info;
|
client_display_info = current_dynamic_info;
|
||||||
@ -1232,6 +1241,8 @@ void Game::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
framemarker.end();
|
||||||
|
|
||||||
RenderingEngine::autosaveScreensizeAndCo(initial_screen_size, initial_window_maximized);
|
RenderingEngine::autosaveScreensizeAndCo(initial_screen_size, initial_window_maximized);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1671,9 +1682,13 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||||||
|
|
||||||
fps_control.reset();
|
fps_control.reset();
|
||||||
|
|
||||||
|
auto framemarker = FrameMarker("Game::connectToServer()-frame").started();
|
||||||
|
|
||||||
while (m_rendering_engine->run()) {
|
while (m_rendering_engine->run()) {
|
||||||
|
|
||||||
|
framemarker.end();
|
||||||
fps_control.limit(device, &dtime);
|
fps_control.limit(device, &dtime);
|
||||||
|
framemarker.start();
|
||||||
|
|
||||||
// Update client and server
|
// Update client and server
|
||||||
step(dtime);
|
step(dtime);
|
||||||
@ -1719,6 +1734,7 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||||||
// Update status
|
// Update status
|
||||||
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
||||||
}
|
}
|
||||||
|
framemarker.end();
|
||||||
} catch (con::PeerNotFoundException &e) {
|
} catch (con::PeerNotFoundException &e) {
|
||||||
warningstream << "This should not happen. Please report a bug." << std::endl;
|
warningstream << "This should not happen. Please report a bug." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -1736,9 +1752,11 @@ bool Game::getServerContent(bool *aborted)
|
|||||||
|
|
||||||
fps_control.reset();
|
fps_control.reset();
|
||||||
|
|
||||||
|
auto framemarker = FrameMarker("Game::getServerContent()-frame").started();
|
||||||
while (m_rendering_engine->run()) {
|
while (m_rendering_engine->run()) {
|
||||||
|
framemarker.end();
|
||||||
fps_control.limit(device, &dtime);
|
fps_control.limit(device, &dtime);
|
||||||
|
framemarker.start();
|
||||||
|
|
||||||
// Update client and server
|
// Update client and server
|
||||||
step(dtime);
|
step(dtime);
|
||||||
@ -1804,6 +1822,7 @@ bool Game::getServerContent(bool *aborted)
|
|||||||
texture_src, dtime, progress);
|
texture_src, dtime, progress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
framemarker.end();
|
||||||
|
|
||||||
*aborted = true;
|
*aborted = true;
|
||||||
infostream << "Connect aborted [device]" << std::endl;
|
infostream << "Connect aborted [device]" << std::endl;
|
||||||
@ -2773,6 +2792,8 @@ void Game::updatePauseState()
|
|||||||
|
|
||||||
inline void Game::step(f32 dtime)
|
inline void Game::step(f32 dtime)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
float fps_max = (!device->isWindowFocused() || g_menumgr.pausesGame()) ?
|
float fps_max = (!device->isWindowFocused() || g_menumgr.pausesGame()) ?
|
||||||
g_settings->getFloat("fps_max_unfocused") :
|
g_settings->getFloat("fps_max_unfocused") :
|
||||||
@ -4052,6 +4073,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
|
|||||||
void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
|
void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
|
||||||
const CameraOrientation &cam)
|
const CameraOrientation &cam)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
TimeTaker tt_update("Game::updateFrame()");
|
TimeTaker tt_update("Game::updateFrame()");
|
||||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||||
|
|
||||||
@ -4311,6 +4333,8 @@ void Game::updateShadows()
|
|||||||
|
|
||||||
void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
|
void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
const video::SColor fog_color = this->sky->getFogColor();
|
const video::SColor fog_color = this->sky->getFogColor();
|
||||||
const video::SColor sky_color = this->sky->getSkyColor();
|
const video::SColor sky_color = this->sky->getSkyColor();
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "minimap.h"
|
#include "minimap.h"
|
||||||
#include "content_mapblock.h"
|
#include "content_mapblock.h"
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
#include "client/meshgen/collector.h"
|
#include "client/meshgen/collector.h"
|
||||||
#include "client/renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -611,6 +612,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
|||||||
m_last_crack(-1),
|
m_last_crack(-1),
|
||||||
m_last_daynight_ratio((u32) -1)
|
m_last_daynight_ratio((u32) -1)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
for (auto &m : m_mesh)
|
for (auto &m : m_mesh)
|
||||||
m = new scene::SMesh();
|
m = new scene::SMesh();
|
||||||
m_enable_shaders = data->m_use_shaders;
|
m_enable_shaders = data->m_use_shaders;
|
||||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "sound_singleton.h"
|
#include "sound_singleton.h"
|
||||||
#include "util/numeric.h" // myrand()
|
#include "util/numeric.h" // myrand()
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
|
||||||
@ -501,6 +502,8 @@ void *OpenALSoundManager::run()
|
|||||||
|
|
||||||
u64 t_step_start = porting::getTimeMs();
|
u64 t_step_start = porting::getTimeMs();
|
||||||
while (true) {
|
while (true) {
|
||||||
|
auto framemarker = FrameMarker("OpenALSoundManager::run()-frame").started();
|
||||||
|
|
||||||
auto get_time_since_last_step = [&] {
|
auto get_time_since_last_step = [&] {
|
||||||
return (f32)(porting::getTimeMs() - t_step_start);
|
return (f32)(porting::getTimeMs() - t_step_start);
|
||||||
};
|
};
|
||||||
|
@ -41,3 +41,4 @@
|
|||||||
#cmakedefine01 BUILD_UNITTESTS
|
#cmakedefine01 BUILD_UNITTESTS
|
||||||
#cmakedefine01 BUILD_BENCHMARKS
|
#cmakedefine01 BUILD_BENCHMARKS
|
||||||
#cmakedefine01 USE_SDL2
|
#cmakedefine01 USE_SDL2
|
||||||
|
#cmakedefine01 BUILD_WITH_TRACY
|
||||||
|
@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <ICameraSceneNode.h>
|
#include <ICameraSceneNode.h>
|
||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
#include "client/imagefilters.h"
|
#include "client/imagefilters.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
|
|
||||||
#if USE_SOUND
|
#if USE_SOUND
|
||||||
#include "client/sound/sound_openal.h"
|
#include "client/sound/sound_openal.h"
|
||||||
@ -329,9 +330,12 @@ void GUIEngine::run()
|
|||||||
|
|
||||||
fps_control.reset();
|
fps_control.reset();
|
||||||
|
|
||||||
while (m_rendering_engine->run() && !m_startgame && !m_kill) {
|
auto framemarker = FrameMarker("GUIEngine::run()-frame").started();
|
||||||
|
|
||||||
|
while (m_rendering_engine->run() && !m_startgame && !m_kill) {
|
||||||
|
framemarker.end();
|
||||||
fps_control.limit(device, &dtime);
|
fps_control.limit(device, &dtime);
|
||||||
|
framemarker.start();
|
||||||
|
|
||||||
if (device->isWindowVisible()) {
|
if (device->isWindowVisible()) {
|
||||||
// check if we need to update the "upper left corner"-text
|
// check if we need to update the "upper left corner"-text
|
||||||
@ -371,6 +375,7 @@ void GUIEngine::run()
|
|||||||
m_menu->getAndroidUIInput();
|
m_menu->getAndroidUIInput();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
framemarker.end();
|
||||||
|
|
||||||
m_script->beforeClose();
|
m_script->beforeClose();
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -960,6 +961,8 @@ void TrackFreedMemory(size_t amount)
|
|||||||
|
|
||||||
void TriggerMemoryTrim()
|
void TriggerMemoryTrim()
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
constexpr auto MO = std::memory_order_relaxed;
|
constexpr auto MO = std::memory_order_relaxed;
|
||||||
if (memory_freed.load(MO) >= MEMORY_TRIM_THRESHOLD) {
|
if (memory_freed.load(MO) >= MEMORY_TRIM_THRESHOLD) {
|
||||||
// Synchronize call
|
// Synchronize call
|
||||||
|
@ -32,6 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "client/client.h"
|
#include "client/client.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BUILD_WITH_TRACY
|
||||||
|
#include "tracy/TracyLua.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
@ -95,6 +98,11 @@ ScriptApiBase::ScriptApiBase(ScriptingType type):
|
|||||||
lua_pushstring(m_luastack, LUA_BITLIBNAME);
|
lua_pushstring(m_luastack, LUA_BITLIBNAME);
|
||||||
lua_call(m_luastack, 1, 0);
|
lua_call(m_luastack, 1, 0);
|
||||||
|
|
||||||
|
#if BUILD_WITH_TRACY
|
||||||
|
// Load tracy lua bindings
|
||||||
|
tracy::LuaRegister(m_luastack);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Make the ScriptApiBase* accessible to ModApiBase
|
// Make the ScriptApiBase* accessible to ModApiBase
|
||||||
#if INDIRECT_SCRIPTAPI_RIDX
|
#if INDIRECT_SCRIPTAPI_RIDX
|
||||||
*(void **)(lua_newuserdata(m_luastack, sizeof(void *))) = this;
|
*(void **)(lua_newuserdata(m_luastack, sizeof(void *))) = this;
|
||||||
|
@ -109,7 +109,12 @@ void ScriptApiSecurity::initializeSecurity()
|
|||||||
"string",
|
"string",
|
||||||
"table",
|
"table",
|
||||||
"math",
|
"math",
|
||||||
"bit"
|
"bit",
|
||||||
|
// Not sure if completely safe. But if someone enables tracy, they'll
|
||||||
|
// know what they do.
|
||||||
|
#if BUILD_WITH_TRACY
|
||||||
|
"tracy",
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
static const char *io_whitelist[] = {
|
static const char *io_whitelist[] = {
|
||||||
"close",
|
"close",
|
||||||
@ -303,6 +308,11 @@ void ScriptApiSecurity::initializeSecurityClient()
|
|||||||
"table",
|
"table",
|
||||||
"math",
|
"math",
|
||||||
"bit",
|
"bit",
|
||||||
|
// Not sure if completely safe. But if someone enables tracy, they'll
|
||||||
|
// know what they do.
|
||||||
|
#if BUILD_WITH_TRACY
|
||||||
|
"tracy",
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
static const char *os_whitelist[] = {
|
static const char *os_whitelist[] = {
|
||||||
"clock",
|
"clock",
|
||||||
|
@ -75,6 +75,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "gameparams.h"
|
#include "gameparams.h"
|
||||||
#include "particles.h"
|
#include "particles.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
|
#include "util/tracy_wrapper.h"
|
||||||
|
|
||||||
class ClientNotFoundException : public BaseException
|
class ClientNotFoundException : public BaseException
|
||||||
{
|
{
|
||||||
@ -101,6 +102,8 @@ private:
|
|||||||
|
|
||||||
void *ServerThread::run()
|
void *ServerThread::run()
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -110,6 +113,7 @@ void *ServerThread::run()
|
|||||||
* server-step frequency. Receive() is used for waiting between the steps.
|
* server-step frequency. Receive() is used for waiting between the steps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
auto framemarker = FrameMarker("ServerThread::run()-frame").started();
|
||||||
try {
|
try {
|
||||||
m_server->AsyncRunStep(0.0f, true);
|
m_server->AsyncRunStep(0.0f, true);
|
||||||
} catch (con::ConnectionBindFailed &e) {
|
} catch (con::ConnectionBindFailed &e) {
|
||||||
@ -119,10 +123,12 @@ void *ServerThread::run()
|
|||||||
} catch (ModError &e) {
|
} catch (ModError &e) {
|
||||||
m_server->setAsyncFatalError(e.what());
|
m_server->setAsyncFatalError(e.what());
|
||||||
}
|
}
|
||||||
|
framemarker.end();
|
||||||
|
|
||||||
float dtime = 0.0f;
|
float dtime = 0.0f;
|
||||||
|
|
||||||
while (!stopRequested()) {
|
while (!stopRequested()) {
|
||||||
|
framemarker.start();
|
||||||
ScopeProfiler spm(g_profiler, "Server::RunStep() (max)", SPT_MAX);
|
ScopeProfiler spm(g_profiler, "Server::RunStep() (max)", SPT_MAX);
|
||||||
|
|
||||||
u64 t0 = porting::getTimeUs();
|
u64 t0 = porting::getTimeUs();
|
||||||
@ -149,6 +155,7 @@ void *ServerThread::run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
dtime = 1e-6f * (porting::getTimeUs() - t0);
|
dtime = 1e-6f * (porting::getTimeUs() - t0);
|
||||||
|
framemarker.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
END_DEBUG_EXCEPTION_HANDLER
|
END_DEBUG_EXCEPTION_HANDLER
|
||||||
@ -607,6 +614,9 @@ void Server::step()
|
|||||||
|
|
||||||
void Server::AsyncRunStep(float dtime, bool initial_step)
|
void Server::AsyncRunStep(float dtime, bool initial_step)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
auto framemarker = FrameMarker("Server::AsyncRunStep()-frame").started();
|
||||||
|
|
||||||
{
|
{
|
||||||
// Send blocks to clients
|
// Send blocks to clients
|
||||||
SendBlocks(dtime);
|
SendBlocks(dtime);
|
||||||
@ -1055,6 +1065,9 @@ void Server::AsyncRunStep(float dtime, bool initial_step)
|
|||||||
|
|
||||||
void Server::Receive(float timeout)
|
void Server::Receive(float timeout)
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
auto framemarker = FrameMarker("Server::Receive()-frame").started();
|
||||||
|
|
||||||
const u64 t0 = porting::getTimeUs();
|
const u64 t0 = porting::getTimeUs();
|
||||||
const float timeout_us = timeout * 1e6f;
|
const float timeout_us = timeout * 1e6f;
|
||||||
auto remaining_time_us = [&]() -> float {
|
auto remaining_time_us = [&]() -> float {
|
||||||
|
200
src/util/tracy_wrapper.h
Normal file
200
src/util/tracy_wrapper.h
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2024 DS
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper for <tracy/Tracy.hpp>, so that we can use Tracy's macros without
|
||||||
|
* having it as mandatory dependency.
|
||||||
|
*
|
||||||
|
* For annotations that you don't intend to upstream, you can also include
|
||||||
|
* <tracy/Tracy.hpp> directly (which also works in irr/).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "util/basic_macros.h"
|
||||||
|
|
||||||
|
#if BUILD_WITH_TRACY
|
||||||
|
|
||||||
|
#include <tracy/Tracy.hpp> // IWYU pragma: export
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Copied from Tracy.hpp
|
||||||
|
|
||||||
|
#define TracyNoop
|
||||||
|
|
||||||
|
#define ZoneNamed(x,y)
|
||||||
|
#define ZoneNamedN(x,y,z)
|
||||||
|
#define ZoneNamedC(x,y,z)
|
||||||
|
#define ZoneNamedNC(x,y,z,w)
|
||||||
|
|
||||||
|
#define ZoneTransient(x,y)
|
||||||
|
#define ZoneTransientN(x,y,z)
|
||||||
|
|
||||||
|
#define ZoneScoped
|
||||||
|
#define ZoneScopedN(x)
|
||||||
|
#define ZoneScopedC(x)
|
||||||
|
#define ZoneScopedNC(x,y)
|
||||||
|
|
||||||
|
#define ZoneText(x,y)
|
||||||
|
#define ZoneTextV(x,y,z)
|
||||||
|
#define ZoneTextF(x,...)
|
||||||
|
#define ZoneTextVF(x,y,...)
|
||||||
|
#define ZoneName(x,y)
|
||||||
|
#define ZoneNameV(x,y,z)
|
||||||
|
#define ZoneNameF(x,...)
|
||||||
|
#define ZoneNameVF(x,y,...)
|
||||||
|
#define ZoneColor(x)
|
||||||
|
#define ZoneColorV(x,y)
|
||||||
|
#define ZoneValue(x)
|
||||||
|
#define ZoneValueV(x,y)
|
||||||
|
#define ZoneIsActive false
|
||||||
|
#define ZoneIsActiveV(x) false
|
||||||
|
|
||||||
|
#define FrameMark
|
||||||
|
#define FrameMarkNamed(x)
|
||||||
|
#define FrameMarkStart(x)
|
||||||
|
#define FrameMarkEnd(x)
|
||||||
|
|
||||||
|
#define FrameImage(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define TracyLockable( type, varname ) type varname
|
||||||
|
#define TracyLockableN( type, varname, desc ) type varname
|
||||||
|
#define TracySharedLockable( type, varname ) type varname
|
||||||
|
#define TracySharedLockableN( type, varname, desc ) type varname
|
||||||
|
#define LockableBase( type ) type
|
||||||
|
#define SharedLockableBase( type ) type
|
||||||
|
#define LockMark(x) (void)x
|
||||||
|
#define LockableName(x,y,z)
|
||||||
|
|
||||||
|
#define TracyPlot(x,y)
|
||||||
|
#define TracyPlotConfig(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define TracyMessage(x,y)
|
||||||
|
#define TracyMessageL(x)
|
||||||
|
#define TracyMessageC(x,y,z)
|
||||||
|
#define TracyMessageLC(x,y)
|
||||||
|
#define TracyAppInfo(x,y)
|
||||||
|
|
||||||
|
#define TracyAlloc(x,y)
|
||||||
|
#define TracyFree(x)
|
||||||
|
#define TracySecureAlloc(x,y)
|
||||||
|
#define TracySecureFree(x)
|
||||||
|
|
||||||
|
#define TracyAllocN(x,y,z)
|
||||||
|
#define TracyFreeN(x,y)
|
||||||
|
#define TracySecureAllocN(x,y,z)
|
||||||
|
#define TracySecureFreeN(x,y)
|
||||||
|
|
||||||
|
#define ZoneNamedS(x,y,z)
|
||||||
|
#define ZoneNamedNS(x,y,z,w)
|
||||||
|
#define ZoneNamedCS(x,y,z,w)
|
||||||
|
#define ZoneNamedNCS(x,y,z,w,a)
|
||||||
|
|
||||||
|
#define ZoneTransientS(x,y,z)
|
||||||
|
#define ZoneTransientNS(x,y,z,w)
|
||||||
|
|
||||||
|
#define ZoneScopedS(x)
|
||||||
|
#define ZoneScopedNS(x,y)
|
||||||
|
#define ZoneScopedCS(x,y)
|
||||||
|
#define ZoneScopedNCS(x,y,z)
|
||||||
|
|
||||||
|
#define TracyAllocS(x,y,z)
|
||||||
|
#define TracyFreeS(x,y)
|
||||||
|
#define TracySecureAllocS(x,y,z)
|
||||||
|
#define TracySecureFreeS(x,y)
|
||||||
|
|
||||||
|
#define TracyAllocNS(x,y,z,w)
|
||||||
|
#define TracyFreeNS(x,y,z)
|
||||||
|
#define TracySecureAllocNS(x,y,z,w)
|
||||||
|
#define TracySecureFreeNS(x,y,z)
|
||||||
|
|
||||||
|
#define TracyMessageS(x,y,z)
|
||||||
|
#define TracyMessageLS(x,y)
|
||||||
|
#define TracyMessageCS(x,y,z,w)
|
||||||
|
#define TracyMessageLCS(x,y,z)
|
||||||
|
|
||||||
|
#define TracySourceCallbackRegister(x,y)
|
||||||
|
#define TracyParameterRegister(x,y)
|
||||||
|
#define TracyParameterSetup(x,y,z,w)
|
||||||
|
#define TracyIsConnected false
|
||||||
|
#define TracyIsStarted false
|
||||||
|
#define TracySetProgramName(x)
|
||||||
|
|
||||||
|
#define TracyFiberEnter(x)
|
||||||
|
#define TracyFiberEnterHint(x,y)
|
||||||
|
#define TracyFiberLeave
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Helper for making sure frames end in all possible control flow path
|
||||||
|
class FrameMarker
|
||||||
|
{
|
||||||
|
const char *m_name;
|
||||||
|
bool m_started = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FrameMarker(const char *name) : m_name(name) {}
|
||||||
|
|
||||||
|
~FrameMarker() { end(); }
|
||||||
|
|
||||||
|
DISABLE_CLASS_COPY(FrameMarker)
|
||||||
|
|
||||||
|
FrameMarker(FrameMarker &&other) noexcept :
|
||||||
|
m_name(other.m_name), m_started(other.m_started)
|
||||||
|
{
|
||||||
|
other.m_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameMarker &operator=(FrameMarker &&other) noexcept
|
||||||
|
{
|
||||||
|
if (&other != this) {
|
||||||
|
end();
|
||||||
|
m_name = other.m_name;
|
||||||
|
m_started = other.m_started;
|
||||||
|
other.m_started = false;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameMarker &&started() &&
|
||||||
|
{
|
||||||
|
if (!m_started) {
|
||||||
|
FrameMarkStart(m_name);
|
||||||
|
m_started = true;
|
||||||
|
}
|
||||||
|
return std::move(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
// no move happens, because we drop the reference
|
||||||
|
(void)std::move(*this).started();
|
||||||
|
}
|
||||||
|
|
||||||
|
void end()
|
||||||
|
{
|
||||||
|
if (m_started) {
|
||||||
|
m_started = false;
|
||||||
|
FrameMarkEnd(m_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user