Skip to content

Commit

Permalink
(core) integrates Tracy client
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cipharius committed May 15, 2023
1 parent 8af8646 commit 7bf64a1
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 12 deletions.
1 change: 1 addition & 0 deletions external/git/.gitignore
Expand Up @@ -2,3 +2,4 @@ luajit
freetype
openal
libuvc
tracy
1 change: 1 addition & 0 deletions external/git/clone.sh
Expand Up @@ -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"
28 changes: 25 additions & 3 deletions src/CMakeLists.txt
Expand Up @@ -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)
Expand All @@ -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")
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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}\"
)
Expand Down Expand Up @@ -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 "")
Expand Down Expand Up @@ -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}\"
)
Expand Down Expand Up @@ -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}\"
)
Expand Down
4 changes: 4 additions & 0 deletions src/engine/arcan_conductor.c
Expand Up @@ -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, "");

Expand Down
10 changes: 6 additions & 4 deletions src/engine/arcan_general.h
Expand Up @@ -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,
Expand All @@ -206,23 +208,23 @@ 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

#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

#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
Expand Down
4 changes: 4 additions & 0 deletions src/engine/arcan_hmeta.h
Expand Up @@ -35,6 +35,10 @@
#include <sqlite3.h>
#include <lua.h>

#ifdef WITH_TRACY
#include "tracy/TracyC.h"
#endif

#include "getopt.h"
#include "arcan_math.h"
#include "arcan_general.h"
Expand Down
6 changes: 5 additions & 1 deletion src/engine/arcan_lua.c
Expand Up @@ -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);
}
Expand Down
208 changes: 206 additions & 2 deletions src/engine/arcan_trace.c
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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; i<tracy_ctx.mark_ids_len; i++) {
const struct MarkID *mark_id = &tracy_ctx.mark_ids[i];
if (mark_id->sys == 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; i<tracy_ctx.mark_ids_len; i++) {
const struct MarkID mark_id = tracy_ctx.mark_ids[i];
if (strcmp(mark_id.sys, sys) == 0 && strcmp(mark_id.subsys, subsys) == 0) {
tracy_ctx.mark_ids[tracy_ctx.mark_ids_len] = (struct MarkID){
.sys = sys,
.subsys = subsys,
.zone_id = mark_id.zone_id
};
tracy_ctx.mark_ids_len++;
return mark_id.zone_id;
}
}

if (tracy_ctx.zone_id == TRACY_ZONES) {
fprintf(stderr, "trace zone cache overflow");
exit(EXIT_FAILURE);
}

// Sluggish path
const uint16_t s_len = strlen(sys) + strlen(subsys) + 4;
const uint16_t zone_id = tracy_ctx.zone_id;
const uint16_t mark_id = tracy_ctx.mark_ids_len;
tracy_ctx.zone_id++;
tracy_ctx.mark_ids_len++;

tracy_ctx.zone_name[zone_id] = malloc(s_len);
tracy_ctx.zone_name_len[zone_id] = MIN(
s_len - 1,
snprintf(tracy_ctx.zone_name[zone_id], s_len, "[%s] %s", sys, subsys)
);

tracy_ctx.zone_loc[zone_id] = (struct ___tracy_source_location_data){
.file = file,
.function = function,
.line = line
};

tracy_ctx.mark_ids[mark_id] = (struct MarkID){
.sys = sys,
.subsys = subsys,
.zone_id = zone_id
};

return zone_id;
}
#endif

void arcan_trace_mark(
const char* sys, const char* subsys,
uint8_t trigger, uint8_t tracelevel,
uint64_t ident, uint32_t quant, const char* message)
uint64_t ident, uint32_t quant, const char* message,
const char* file_name, const char* func_name,
uint32_t line)
{
if (!arcan_trace_enabled)
return;

#ifdef WITH_TRACY
const uint16_t zid = get_zone_id(sys, subsys, file_name, func_name, line);

switch (trigger) {
case 0: // ONESHOT
{
TracyCZoneCtx ctx = ___tracy_emit_zone_begin(&tracy_ctx.zone_loc[zid], true);

___tracy_emit_zone_name(ctx, tracy_ctx.zone_name[zid], tracy_ctx.zone_name_len[zid]);
___tracy_emit_zone_color(ctx, color_lut[tracelevel]);

___tracy_emit_zone_text(ctx, "[ONESHOT]", 9);

___tracy_emit_zone_text(ctx, "Ident:", 6);
___tracy_emit_zone_value(ctx, ident);

___tracy_emit_zone_text(ctx, "\nQuant:", 7);
___tracy_emit_zone_value(ctx, quant);

if (message) {
___tracy_emit_zone_text(ctx, "\nMessage:", 9);
___tracy_emit_zone_text(ctx, message, strlen(message));
}

___tracy_emit_zone_end(ctx);
}
break;
case 1: // ENTER
{
TracyCZoneCtx ctx = ___tracy_emit_zone_begin_callstack(&tracy_ctx.zone_loc[zid], 8, true);

___tracy_emit_zone_name(ctx, tracy_ctx.zone_name[zid], tracy_ctx.zone_name_len[zid]);
___tracy_emit_zone_color(ctx, color_lut[tracelevel]);

___tracy_emit_zone_text(ctx, "Enter ident:", 12);
___tracy_emit_zone_value(ctx, ident);

___tracy_emit_zone_text(ctx, "\nEnter quant:", 13);
___tracy_emit_zone_value(ctx, quant);

if (message) {
___tracy_emit_zone_text(ctx, "\nEnter message:", 15);
___tracy_emit_zone_text(ctx, message, strlen(message));
}

if (tracy_ctx.zone_stack_len == TRACY_STACK) {
fprintf(stderr, "trace zone stack overflow");
exit(EXIT_FAILURE);
}

const struct ZoneCtx zone = { .ctx = ctx, .zone_id = zid };
tracy_ctx.zone_stack[tracy_ctx.zone_stack_len] = zone;
tracy_ctx.zone_stack_len++;
}
break;
case 2: // EXIT
{
struct ZoneCtx* ctx = NULL;

for (uint16_t i=tracy_ctx.zone_stack_len; i>0; i--) {
if (tracy_ctx.zone_stack[i-1].zone_id == zid) {
ctx = &tracy_ctx.zone_stack[i-1];

for (uint16_t j=i; i<tracy_ctx.zone_stack_len-1; j++) {
tracy_ctx.zone_stack[j-1] = tracy_ctx.zone_stack[j];
}

tracy_ctx.zone_stack_len--;
break;
}
}

if (!ctx) {
fprintf(stderr, "unmatched trace mark exit (sys: %s, subsys: %s)\n", sys, subsys);
exit(EXIT_FAILURE);
}

___tracy_emit_zone_text(ctx->ctx, "\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;
Expand Down

0 comments on commit 7bf64a1

Please sign in to comment.