From 7bf64a1bda2cdf82a2f172035df95235ad187e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valts=20Liepi=C5=86=C5=A1?= Date: Mon, 15 May 2023 15:37:20 +0300 Subject: [PATCH] (core) integrates Tracy client This provides a Tracy client integration which hooks into the existing arcan tracing facilities. Effectively that means the Tracy client specific code can be kept mainly confined in the arcan_trace.c, but with slightly more performance overhead compared to directly using Tracy API for marking execution zones. As a side effect to this integration the CMake platform lists had to be refactored. During hybrid platform build phase, the C definitions got wiped, so platform specific build flags had to be seperated in order to keep global build flags intact. --- external/git/.gitignore | 1 + external/git/clone.sh | 1 + src/CMakeLists.txt | 28 +++- src/engine/arcan_conductor.c | 4 + src/engine/arcan_general.h | 10 +- src/engine/arcan_hmeta.h | 4 + src/engine/arcan_lua.c | 6 +- src/engine/arcan_trace.c | 208 +++++++++++++++++++++++++++- src/platform/cmake/CMakeLists.LWA | 1 + src/platform/cmake/CMakeLists.Video | 4 +- 10 files changed, 255 insertions(+), 12 deletions(-) diff --git a/external/git/.gitignore b/external/git/.gitignore index 1056aca00..8074c0121 100644 --- a/external/git/.gitignore +++ b/external/git/.gitignore @@ -2,3 +2,4 @@ luajit freetype openal libuvc +tracy diff --git a/external/git/clone.sh b/external/git/clone.sh index 52ff751b3..9e2ee66c0 100755 --- a/external/git/clone.sh +++ b/external/git/clone.sh @@ -20,3 +20,4 @@ fi git clone http://luajit.org/git/luajit-2.0.git "$DIR/luajit" git clone https://github.com/letoram/openal.git "$DIR/openal" git clone https://github.com/libuvc/libuvc.git "$DIR/libuvc" +git clone https://github.com/wolfpld/tracy.git "$DIR/tracy" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ac75bc51..bc6d5c1db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,7 @@ else() option(ENABLE_LWA "Build LWA client (arcan-in-arcan)" ON) option(ENABLE_SIMD "Build with SIMD vector instruction set support" ON) option(ENABLE_SIMD_ALIGNED "Assert that SIMD data sources are 16-byte aligned" OFF) + option(ENABLE_TRACY "Build with Tracy client integration (external/git folder)" OFF) option(DISABLE_WAYLAND "Never build wayland support" OFF) option(HYBRID_SDL "Produce an arcan_sdl main binary as well" OFF) option(HYBRID_HEADLESS "Produce a headless binary as well" OFF) @@ -179,6 +180,7 @@ else() # amsg(" as optimization profile.") amsg("${CL_YEL}\t\t-DSIMD_ALIGNED=${CL_GRN}[Off|On]${CL_RST} - SIMD support assumes 16-byte alignment") amsg("${CL_YEL}\t-DENABLE_LTO=${CL_GRN}[Off|On]${CL_RST} - Build with Link-Time Optimizations") + amsg("${CL_YEL}\t-DENABLE_TRACY=${CL_GRN}[Off|On]${CL_RST} - Build with Tracy integration") amsg("") amsg("${CL_WHT}Dependency Management:${CL_RST}") amsg("${CL_YEL}\t-DSTATIC_SQLite3=${CL_GRN}[Off|On]${CL_RST} - In-source SQLite3") @@ -531,6 +533,22 @@ else() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endif() +if (ENABLE_TRACY) + option(TRACY_ENABLE "" ON) + option(TRACY_ON_DEMAND "" ON) + add_subdirectory( + ${EXTERNAL_SRC_DIR}/git/tracy + ${CMAKE_CURRENT_BINARY_DIR}/tracy + ) + list(APPEND ARCAN_DEFINITIONS WITH_TRACY) + list(APPEND ARCAN_LIBRARIES + TracyClient + ) + amsg("${CL_YEL}tracy support\t${CL_GRN}enabled${CL_RST}") +else() + amsg("${CL_YEL}tracy support\t${CL_RED}disabled${CL_RST}") +endif() + set(SHMIF_TUI true) add_subdirectory(shmif) add_subdirectory(a12) @@ -588,6 +606,7 @@ else() target_compile_definitions(arcan PRIVATE ${ARCAN_DEFINITIONS} ${ARCAN_NOLWA_DEFINITIONS} + ${PLATFORM_DEFINITIONS} ARCAN_BUILDVERSION=\"${SOURCE_TAG}-${PLATFORM_BUILDTAG}-${CMAKE_SYSTEM_NAME}\" FRAMESERVER_MODESTRING=\"${FRAMESERVER_MODESTRING}\" ) @@ -628,8 +647,7 @@ else() amsg("-- Appending sdl platform build--") set(VIDEO_PLATFORM "sdl2") set(INPUT_PLATFORM "sdl2") - set(ARCAN_DEFINITIONS "") - set(ARCAN_NOLWA_DEFINITIONS "") + set(PLATFORM_DEFINITIONS "") set(VIDEO_PLATFORM_SOURCES "") set(AUDIO_PLATFORM_SOURCES "") set(INPUT_PLATFORM_SOURCES "") @@ -662,6 +680,7 @@ else() target_compile_definitions(arcan_sdl PRIVATE ${ARCAN_DEFINITIONS} ${ARCAN_NOLWA_DEFINITIONS} + ${PLATFORM_DEFINITIONS} ARCAN_BUILDVERSION=\"${SOURCE_TAG}-${PLATFORM_BUILDTAG}-${CMAKE_SYSTEM_NAME}\" FRAMESERVER_MODESTRING=\"${FRAMESERVER_MODESTRING}\" ) @@ -706,7 +725,10 @@ else() set(PLATFORM_BUILDTAG headless-${AGP_PLATFORM}-${AUDIO_PLATFORM}-headless-${LUA_TAG}-${DISTR_TAG}) target_compile_definitions(arcan_headless PRIVATE - ${ARCAN_DEFINITIONS} ${ARCAN_NOLWA_DEFINITIONS} ARCAN_HEADLESS + ${ARCAN_DEFINITIONS} + ${ARCAN_NOLWA_DEFINITIONS} + ${PLATFORM_DEFINITIONS} + ARCAN_HEADLESS FRAMESERVER_MODESTRING=\"${FRAMESERVER_MODESTRING}\" ARCAN_BUILDVERSION=\"${SOURCE_TAG}-${PLATFORM_BUILDTAG}-${CMAKE_SYSTEM_NAME}\" ) diff --git a/src/engine/arcan_conductor.c b/src/engine/arcan_conductor.c index 1faa76235..d81296b8d 100644 --- a/src/engine/arcan_conductor.c +++ b/src/engine/arcan_conductor.c @@ -574,6 +574,10 @@ static int trigger_video_synch(float frag) TRACE_MARK_ENTER("conductor", "platform-frame", TRACE_SYS_DEFAULT, conductor.tick_count, frag, ""); arcan_lua_callvoidfun(main_lua_context, "preframe_pulse", false, NULL); platform_video_synch(conductor.tick_count, frag, NULL, NULL); + + #ifdef WITH_TRACY + TracyCFrameMark + #endif arcan_lua_callvoidfun(main_lua_context, "postframe_pulse", false, NULL); TRACE_MARK_EXIT("conductor", "platform-frame", TRACE_SYS_DEFAULT, conductor.tick_count, frag, ""); diff --git a/src/engine/arcan_general.h b/src/engine/arcan_general.h index 6bd2a67dc..8d628dc8c 100644 --- a/src/engine/arcan_general.h +++ b/src/engine/arcan_general.h @@ -193,7 +193,9 @@ void arcan_trace_mark( const char* sys, const char* subsys, uint8_t trigger, uint8_t tracelevel, uint64_t identifier, - uint32_t quant, const char* message); + uint32_t quant, const char* message, + const char* file_name, const char* func_name, + uint32_t line); enum trace_level { TRACE_SYS_DEFAULT = 0, @@ -206,7 +208,7 @@ enum trace_level { #ifndef TRACE_MARK_ENTER #define TRACE_MARK_ENTER(A, B, C, D, E, F) do { \ if (arcan_trace_enabled){ \ - arcan_trace_mark((A), (B), 1, (C), (D), (E), (F));\ + arcan_trace_mark((A), (B), 1, (C), (D), (E), (F), __FILE__, __FUNCTION__, __LINE__);\ }\ } while (0); #endif @@ -214,7 +216,7 @@ enum trace_level { #ifndef TRACE_MARK_ONESHOT #define TRACE_MARK_ONESHOT(A, B, C, D, E, F) do { \ if (arcan_trace_enabled){ \ - arcan_trace_mark((A), (B), 0, (C), (D), (E), (F));\ + arcan_trace_mark((A), (B), 0, (C), (D), (E), (F), __FILE__, __FUNCTION__, __LINE__);\ }\ } while (0); #endif @@ -222,7 +224,7 @@ enum trace_level { #ifndef TRACE_MARK_EXIT #define TRACE_MARK_EXIT(A, B, C, D, E, F) do { \ if (arcan_trace_enabled){ \ - arcan_trace_mark((A), (B), 2, (C), (D), (E), (F));\ + arcan_trace_mark((A), (B), 2, (C), (D), (E), (F), __FILE__, __FUNCTION__, __LINE__);\ }\ } while (0); #endif diff --git a/src/engine/arcan_hmeta.h b/src/engine/arcan_hmeta.h index d26ecb269..b32f3b9ca 100644 --- a/src/engine/arcan_hmeta.h +++ b/src/engine/arcan_hmeta.h @@ -35,6 +35,10 @@ #include #include +#ifdef WITH_TRACY +#include "tracy/TracyC.h" +#endif + #include "getopt.h" #include "arcan_math.h" #include "arcan_general.h" diff --git a/src/engine/arcan_lua.c b/src/engine/arcan_lua.c index 30f51b7d7..88f534680 100644 --- a/src/engine/arcan_lua.c +++ b/src/engine/arcan_lua.c @@ -10309,7 +10309,11 @@ static int benchtracedata(lua_State* ctx) "expecting: TRACE_PATH_DEFAULT, SLOW, FAST, WARN or ERROR\n"); } - arcan_trace_mark("lua", subsys, trigger, level, ident, quant, message); + lua_Debug ar; + lua_getstack(ctx, 2, &ar); + lua_getinfo(ctx, "nSl", &ar); + + arcan_trace_mark("lua", subsys, trigger, level, ident, quant, message, ar.short_src, ar.name, ar.currentline); LUA_ETRACE("benchmark_tracedata", NULL, 0); } diff --git a/src/engine/arcan_trace.c b/src/engine/arcan_trace.c index 254dc4e03..096ca312f 100644 --- a/src/engine/arcan_trace.c +++ b/src/engine/arcan_trace.c @@ -10,7 +10,12 @@ #include "arcan_math.h" #include "arcan_general.h" -bool arcan_trace_enabled; +#ifdef WITH_TRACY +#include "tracy/TracyC.h" +bool arcan_trace_enabled = true; +#else +bool arcan_trace_enabled = false; +#endif static uint8_t* buffer; static size_t buffer_sz; @@ -24,7 +29,9 @@ void arcan_trace_setbuffer(uint8_t* buf, size_t buf_sz, bool* finish_flag) buffer = NULL; buffer_flag = NULL; buffer_pos = 0; + #ifndef WITH_TRACE arcan_trace_enabled = false; + #endif } if (!buf || !buf_sz) @@ -49,14 +56,211 @@ static bool append_string(const char* str) return true; } +#ifdef WITH_TRACY +const uint32_t color_lut[] = { + 0x000000, // DEFAULT + 0x02dffc, // SLOW + 0x41d12b, // FAST + 0xefd13b, // WARN + 0xc63629, // ERROR +}; + +struct MarkID { + const char* sys; + const char* subsys; + uint16_t zone_id; +}; + +struct ZoneCtx { + TracyCZoneCtx ctx; + uint16_t zone_id; +}; + +#define TRACY_ZONES 256 +#define TRACY_MARKS TRACY_ZONES*2 +#define TRACY_STACK 64 +static struct { + struct MarkID mark_ids[TRACY_MARKS]; + + char* zone_name[TRACY_ZONES]; + uint16_t zone_name_len[TRACY_ZONES]; + struct ___tracy_source_location_data zone_loc[TRACY_ZONES]; + + struct ZoneCtx zone_stack[TRACY_STACK]; + + uint16_t mark_ids_len; + uint16_t zone_id; + uint16_t zone_stack_len; +} tracy_ctx; + +uint16_t get_zone_id(const char* sys, const char* subsys, const char* file, const char* function, uint32_t line) { + // Fast path + for (uint16_t i=0; isys == sys && mark_id->subsys == subsys) + return mark_id->zone_id; + } + + if (tracy_ctx.mark_ids_len == TRACY_MARKS) { + fprintf(stderr, "trace mark cache overflow"); + exit(EXIT_FAILURE); + } + + // Slow path + for (uint16_t i=0; i0; i--) { + if (tracy_ctx.zone_stack[i-1].zone_id == zid) { + ctx = &tracy_ctx.zone_stack[i-1]; + + for (uint16_t j=i; ictx, "\nExit ident:", 12); + ___tracy_emit_zone_value(ctx->ctx, ident); + + ___tracy_emit_zone_text(ctx->ctx, "\nExit quant:", 12); + ___tracy_emit_zone_value(ctx->ctx, quant); + + if (message) { + ___tracy_emit_zone_text(ctx->ctx, "\nExit message:", 14); + ___tracy_emit_zone_text(ctx->ctx, message, strlen(message)); + } + + ___tracy_emit_zone_end(ctx->ctx); + } + break; + }; + #endif + + if (!buffer) + return; + size_t start_ofs = buffer_pos; size_t sys_len = strlen(sys) + 1; diff --git a/src/platform/cmake/CMakeLists.LWA b/src/platform/cmake/CMakeLists.LWA index 5419db205..514a93b9c 100644 --- a/src/platform/cmake/CMakeLists.LWA +++ b/src/platform/cmake/CMakeLists.LWA @@ -98,6 +98,7 @@ add_dependencies(arcan_lwa arcan_shmif_int arcan_shmif_intext ${MAIN_DEPS}) target_compile_definitions(arcan_lwa PRIVATE ARCAN_LWA ${ARCAN_DEFINITIONS} + ${PLATFORM_DEFINITIONS} ) target_include_directories(arcan_lwa PRIVATE ${INCLUDE_DIRS}) diff --git a/src/platform/cmake/CMakeLists.Video b/src/platform/cmake/CMakeLists.Video index f73b4c4f9..084747b2a 100644 --- a/src/platform/cmake/CMakeLists.Video +++ b/src/platform/cmake/CMakeLists.Video @@ -27,7 +27,7 @@ if(VIDEO_PLATFORM STREQUAL "egl-gles") if (GLES2_BCM_IMPLEMENTATION) amsg("broadcom (BCM) GLES implementation found, set BCM_ROOT to bad dir to disable") - list(APPEND ARCAN_DEFINITIONS WITH_BCM) + list(APPEND PLATFORM_DEFINITIONS WITH_BCM) set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/platform/egl-gles/video.c APPEND PROPERTY COMPILE_FLAGS -fgnu89-inline) endif() @@ -70,7 +70,7 @@ elseif(VIDEO_PLATFORM STREQUAL "egl-dri") ${PLATFORM_ROOT}/stub/libbacklight.c) endif() set(LWA_PLATFORM_STR "egl-dri-rnode") - list(APPEND ARCAN_DEFINITIONS ARCAN_EGL_DRI) + list(APPEND PLATFORM_DEFINITIONS ARCAN_EGL_DRI) # # only option on OSX/Windows currently, would also work for # drawing to Wayland compositors (though the list of dependencies