From e9f62761b4a7aba78d8fb870b1108d685b843351 Mon Sep 17 00:00:00 2001 From: David McCloskey Date: Wed, 6 Apr 2022 13:34:28 -0700 Subject: [PATCH] Adding support for profiling using Tracy. Signed-off-by: David McCloskey --- include/private/vkd3d_profiling.h | 41 +++++++++++++ include/private/vkd3d_threads.h | 1 + libs/vkd3d-common/meson.build | 8 +++ libs/vkd3d-common/profiling.c | 98 +++++++++++++++++++++++++++++++ libs/vkd3d/swapchain.c | 4 +- meson.build | 30 +++++++++- meson_options.txt | 2 + subprojects/tracy.wrap | 3 + 8 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 subprojects/tracy.wrap diff --git a/include/private/vkd3d_profiling.h b/include/private/vkd3d_profiling.h index a784dfc0..4a829d00 100644 --- a/include/private/vkd3d_profiling.h +++ b/include/private/vkd3d_profiling.h @@ -25,6 +25,39 @@ #ifdef VKD3D_ENABLE_PROFILING +#ifdef TRACY_ENABLE + +#include + +void tracy_set_thread_name( const char* name ); +void tracy_emit_frame_mark(); +TracyCZoneCtx tracy_emit_zone_begin( const struct ___tracy_source_location_data* srcloc, int active ); +void tracy_emit_zone_end( TracyCZoneCtx ctx ); + +#define VKD3D_PROFILE_THREAD_NAME(name) tracy_set_thread_name((name)) +#define VKD3D_PROFILE_FRAME() tracy_emit_frame_mark() + +void vkd3d_init_profiling(void); +bool vkd3d_uses_profiling(void); + +#define VKD3D_STRINGIZE1(x) #x +#define VKD3D_STRINGIZE(x) VKD3D_STRINGIZE1(x) + +#define VKD3D_REGION_DECL(name) TracyCZoneCtx _vkd3d_tracy_##name +/* Copied from definition of TracyCZoneN. In this implementation, _vkd3d_tracy_##name is expected + * to be defined by VKD3D_REGION_DECL. */ +#define VKD3D_REGION_BEGIN(name) static const struct ___tracy_source_location_data TracyConcat(__tracy_source_location,__LINE__) = { VKD3D_STRINGIZE(name), __func__, __FILE__, (uint32_t)__LINE__, 0 }; _vkd3d_tracy_##name = tracy_emit_zone_begin( &TracyConcat(__tracy_source_location,__LINE__), 1 ) +#define VKD3D_REGION_END_ITERATIONS(name, iter) tracy_emit_zone_end(_vkd3d_tracy_##name) + +#else + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#endif + void vkd3d_init_profiling(void); bool vkd3d_uses_profiling(void); unsigned int vkd3d_profiling_register_region(const char *name, spinlock_t *lock, uint32_t *latch); @@ -50,6 +83,12 @@ void vkd3d_profiling_notify_work(unsigned int index, uint64_t start_ticks, uint6 vkd3d_profiling_notify_work(_vkd3d_region_index_##name, _vkd3d_region_begin_tick_##name, _vkd3d_region_end_tick_##name, iter); \ } while(0) + +#define VKD3D_PROFILE_THREAD_NAME(name) ((void)0) +#define VKD3D_PROFILE_FRAME() ((void)0) + +#endif /* TRACY_ENABLE */ + #else static inline void vkd3d_init_profiling(void) { @@ -57,6 +96,8 @@ static inline void vkd3d_init_profiling(void) #define VKD3D_REGION_DECL(name) ((void)0) #define VKD3D_REGION_BEGIN(name) ((void)0) #define VKD3D_REGION_END_ITERATIONS(name, iter) ((void)0) +#define VKD3D_PROFILE_THREAD_NAME(name) ((void)0) +#define VKD3D_PROFILE_FRAME() ((void)0) #endif /* VKD3D_ENABLE_PROFILING */ #define VKD3D_REGION_END(name) VKD3D_REGION_END_ITERATIONS(name, 1) diff --git a/include/private/vkd3d_threads.h b/include/private/vkd3d_threads.h index 51414cec..2b38f412 100644 --- a/include/private/vkd3d_threads.h +++ b/include/private/vkd3d_threads.h @@ -217,6 +217,7 @@ static inline int condvar_reltime_wait_timeout_seconds(condvar_reltime_t *cond, static inline void vkd3d_set_thread_name(const char *name) { + VKD3D_PROFILE_THREAD_NAME(name); (void)name; } diff --git a/libs/vkd3d-common/meson.build b/libs/vkd3d-common/meson.build index d079c30b..631859e2 100644 --- a/libs/vkd3d-common/meson.build +++ b/libs/vkd3d-common/meson.build @@ -8,10 +8,18 @@ vkd3d_common_src = [ 'platform.c', ] +vkd3d_common_dependencies = [] + +if enable_tracy + vkd3d_common_dependencies += [ tracy_dep ] +endif + vkd3d_common_lib = static_library('vkd3d_common', vkd3d_common_src, vkd3d_header_files, + dependencies : vkd3d_common_dependencies, include_directories : vkd3d_private_includes, override_options : [ 'c_std='+vkd3d_c_std ]) vkd3d_common_dep = declare_dependency( link_with : vkd3d_common_lib, + dependencies : vkd3d_common_dependencies, include_directories : [ vkd3d_public_includes, vkd3d_common_lib.private_dir_include() ]) diff --git a/libs/vkd3d-common/profiling.c b/libs/vkd3d-common/profiling.c index 9c7f0b4a..ff2afc68 100644 --- a/libs/vkd3d-common/profiling.c +++ b/libs/vkd3d-common/profiling.c @@ -123,6 +123,7 @@ static void vkd3d_init_profiling_path(const char *path) } #endif +#ifndef TRACY_ENABLE static void vkd3d_init_profiling_once(void) { char path[VKD3D_PATH_MAX]; @@ -131,16 +132,57 @@ static void vkd3d_init_profiling_once(void) if (strlen(path) > 0) vkd3d_init_profiling_path(path); } +#else +#include "vkd3d_platform.h" + +#ifdef DYNAMIC_TRACY + +static void (*pfn_tracy_set_thread_name)( const char* name ); +static void (*pfn_tracy_emit_frame_mark)( const char* name ); +static TracyCZoneCtx (*pfn_tracy_emit_zone_begin)( const struct ___tracy_source_location_data* srcloc, int active ); +static void (*pfn_tracy_emit_zone_end)( TracyCZoneCtx ctx ); + +static void vkd3d_init_profiling_once(void) +{ +#if defined(_WIN32) +#define SONAME_TRACY "tracy.dll" +#else +#error "Unrecognized platform." +#endif + + vkd3d_module_t tracy = vkd3d_dlopen(SONAME_TRACY); + if(tracy) + { + pfn_tracy_set_thread_name = vkd3d_dlsym(tracy, "___tracy_set_thread_name"); + pfn_tracy_emit_frame_mark = vkd3d_dlsym(tracy, "___tracy_emit_frame_mark"); + pfn_tracy_emit_zone_begin = vkd3d_dlsym(tracy, "___tracy_emit_zone_begin"); + pfn_tracy_emit_zone_end = vkd3d_dlsym(tracy, "___tracy_emit_zone_end"); + } +} +#else +static void vkd3d_init_profiling_once(void) +{ +} +#endif /* DYNAMIC_TRACY */ + +#endif /* TRACY_ENABLE */ void vkd3d_init_profiling(void) { pthread_once(&profiling_block_once, vkd3d_init_profiling_once); } +#ifndef TRACY_ENABLE bool vkd3d_uses_profiling(void) { return mapped_blocks != NULL; } +#else +bool vkd3d_uses_profiling(void) +{ + return true; +} +#endif /* TRACY_ENABLE */ unsigned int vkd3d_profiling_register_region(const char *name, spinlock_t *lock, uint32_t *latch) { @@ -195,4 +237,60 @@ void vkd3d_profiling_notify_work(unsigned int index, spinlock_release(lock); } +#ifdef TRACY_ENABLE + +#ifdef DYNAMIC_TRACY + +void tracy_set_thread_name(const char *name) +{ + if(pfn_tracy_set_thread_name) + pfn_tracy_set_thread_name(name); +} + +void tracy_emit_frame_mark() +{ + if(pfn_tracy_emit_frame_mark) + pfn_tracy_emit_frame_mark(0); +} + +TracyCZoneCtx tracy_emit_zone_begin(const struct ___tracy_source_location_data *srcloc, int active) +{ + TracyCZoneCtx ctx; + if(pfn_tracy_emit_zone_begin) + ctx = pfn_tracy_emit_zone_begin(srcloc, active); + return ctx; +} + +void tracy_emit_zone_end(TracyCZoneCtx ctx) +{ + if(pfn_tracy_emit_zone_end) + pfn_tracy_emit_zone_end(ctx); +} + +#else + +void tracy_set_thread_name(const char *name) +{ + ___tracy_set_thread_name(name); +} + +void tracy_emit_frame_mark() +{ + ___tracy_emit_frame_mark(0); +} + +TracyCZoneCtx tracy_emit_zone_begin(const struct ___tracy_source_location_data *srcloc, int active) +{ + return ___tracy_emit_zone_begin(srcloc, active); +} + +void tracy_emit_zone_end(TracyCZoneCtx ctx) +{ + ___tracy_emit_zone_end(ctx); +} + +#endif /* DYNAMIC_TRACY */ + +#endif /* TRACY_ENABLE */ + #endif /* VKD3D_ENABLE_PROFILING */ diff --git a/libs/vkd3d/swapchain.c b/libs/vkd3d/swapchain.c index 5e943a6b..6e23ad4d 100644 --- a/libs/vkd3d/swapchain.c +++ b/libs/vkd3d/swapchain.c @@ -1903,7 +1903,9 @@ static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain, present_info.waitSemaphoreCount = 1; present_info.pWaitSemaphores = &swapchain->vk_present_semaphores[swapchain->vk_image_index]; - if ((vr = VK_CALL(vkQueuePresentKHR(vk_queue, &present_info))) >= 0) + vr = VK_CALL(vkQueuePresentKHR(vk_queue, &present_info)); + VKD3D_PROFILE_FRAME(); + if (vr >= 0) { swapchain->frame_id = (swapchain->frame_id + 1) % swapchain->buffer_count; swapchain->vk_image_index = INVALID_VK_IMAGE_INDEX; diff --git a/meson.build b/meson.build index e9815b50..30728e59 100644 --- a/meson.build +++ b/meson.build @@ -20,6 +20,8 @@ enable_profiling = get_option('enable_profiling') enable_renderdoc = get_option('enable_renderdoc') enable_descriptor_qa = get_option('enable_descriptor_qa') enable_trace = get_option('enable_trace') +enable_tracy = get_option('enable_tracy') +dynamic_tracy = get_option('dynamic_tracy') if enable_d3d12 == 'auto' enable_d3d12 = vkd3d_platform == 'windows' @@ -48,7 +50,7 @@ if enable_d3d12 add_project_arguments('-DVKD3D_BUILD_STANDALONE_D3D12', language : 'c') endif -if enable_profiling +if enable_profiling or enable_tracy add_project_arguments('-DVKD3D_ENABLE_PROFILING', language : 'c') endif @@ -69,6 +71,14 @@ if enable_breadcrumbs add_project_arguments('-DVKD3D_ENABLE_BREADCRUMBS', language : 'c') endif +if enable_tracy + add_project_arguments('-DTRACY_ENABLE', language : 'c') + + if dynamic_tracy + add_project_arguments('-DDYNAMIC_TRACY', language : 'c') + endif +endif + vkd3d_external_includes = [ './subprojects/Vulkan-Headers/include', './subprojects/SPIRV-Headers/include' ] vkd3d_public_includes = [ './include' ] + vkd3d_external_includes vkd3d_private_includes = [ './include/private' ] + vkd3d_public_includes @@ -158,6 +168,24 @@ vkd3d_version = vcs_tag( dxil_spirv = subproject('dxil-spirv') dxil_spirv_dep = dxil_spirv.get_variable('dxil_spirv_dep') +if enable_tracy + tracy_options = [ + 'tracy_on_demand=true', + 'tracy_no_callstack=true', + 'tracy_delayed_init=true', + 'tracy_no_sys_trace=true' + ] + + if dynamic_tracy + tracy_options += [ + 'tracy_shared_libs=true' + ] + endif + + tracy = subproject('tracy', default_options : tracy_options) + tracy_dep = tracy.get_variable('tracy_dep') +endif + subdir('include') subdir('libs') diff --git a/meson_options.txt b/meson_options.txt index 3f4f6eff..9d86f4dc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -5,3 +5,5 @@ option('enable_profiling', type : 'boolean', value : false) option('enable_renderdoc', type : 'boolean', value : false) option('enable_descriptor_qa', type : 'boolean', value : false) option('enable_trace', type : 'combo', value : 'auto', choices : ['false', 'true', 'auto']) +option('enable_tracy', type : 'boolean', value : false) +option('dynamic_tracy', type : 'boolean', value : false) diff --git a/subprojects/tracy.wrap b/subprojects/tracy.wrap new file mode 100644 index 00000000..a24292cc --- /dev/null +++ b/subprojects/tracy.wrap @@ -0,0 +1,3 @@ +[wrap-git] +url = https://github.com/wolfpld/tracy.git +revision = 9b15870991da9ebf7d4e2b808691c3ce91af9356