From 9d8ec1bc9d7ccd7aa56146366b1aa0d33addc2f5 Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Mon, 20 Mar 2023 12:37:48 -0700 Subject: [PATCH] vk: profiler: control profiler with r_speeds command use bits to enable particular performance data display: 0 -- off 1 -- simple frame time 2 -- more object count and sizes statistics (TODO) 4 -- overall gpu usage (TODO) 8 -- extended intra-frame data, function times graph, etc --- ref/vk/r_slows.c | 71 ++++++++++++++++++++++++++++++---------------- ref/vk/vk_common.h | 1 - ref/vk/vk_cvar.c | 6 ++-- ref/vk/vk_cvar.h | 8 +++++- ref/vk/vk_studio.c | 9 +----- 5 files changed, 59 insertions(+), 36 deletions(-) diff --git a/ref/vk/r_slows.c b/ref/vk/r_slows.c index d2a0f065..03c61a13 100644 --- a/ref/vk/r_slows.c +++ b/ref/vk/r_slows.c @@ -3,6 +3,7 @@ #include "shaders/ray_interop.h" // stats: struct LightCluster #include "vk_overlay.h" #include "vk_framectl.h" +#include "vk_cvar.h" #include "profiler.h" @@ -12,6 +13,18 @@ #define MAX_FRAMES_HISTORY 256 #define TARGET_FRAME_TIME (1000.f / 60.f) +// Valid bits for `r_speeds` argument: +enum { + SPEEDS_BIT_OFF = 0, // `r_speeds 0` turns off all performance stats display + SPEEDS_BIT_SIMPLE = 1, // `r_speeds 1` displays only basic info about frame time + SPEEDS_BIT_STATS = 2, // `r_speeds 2` displays additional metrics, i.e. lights counts, dynamic geometry upload sizes, etc (TODO) + SPEEDS_BIT_GPU_USAGE = 4, // `r_speeds 4` displays overall GPU usage stats (TODO) + SPEEDS_BIT_FRAME = 8, // `r_speeds 8` diplays details instrumental profiler frame data, e.g. specific functions times graphs, etc + + // These bits can be combined, e.g. `r_speeds 9`, 8+1, will display 1: basic timing info and 8: frame graphs +}; + + static struct { float frame_times[MAX_FRAMES_HISTORY]; uint32_t frame_num; @@ -182,46 +195,56 @@ static int drawFrames( uint32_t prev_frame_index, int y, const uint64_t gpu_fram return y; } -// FIXME move this to r_speeds or something like that +static void getCurrentFontMetrics(void) { + // hidpi scaling + float scale = gEngine.pfnGetCvarFloat("con_fontscale"); + if (scale <= 0.f) + scale = 1.f; + + // TODO these numbers are mostly fine for the "default" font. Unfortunately + // we don't have any access to real font metrics from here, ref_api_t doesn't give us anything about fonts. ;_; + g_slows.font_metrics.glyph_width = 8 * scale; + g_slows.font_metrics.glyph_height = 20 * scale; +} + void R_ShowExtendedProfilingData(uint32_t prev_frame_index, uint64_t gpu_frame_begin_ns, uint64_t gpu_frame_end_ns) { APROF_SCOPE_DECLARE_BEGIN(__FUNCTION__, __FUNCTION__); - { - // hidpi scaling - float scale = gEngine.pfnGetCvarFloat("con_fontscale"); - if (scale <= 0.f) - scale = 1.f; - - // TODO these numbers are mostly fine for the "default" font. Unfortunately - // we don't have any access to real font metrics from here, ref_api_t doesn't give us anything about fonts. ;_; - g_slows.font_metrics.glyph_width = 8 * scale; - g_slows.font_metrics.glyph_height = 20 * scale; - } - + const uint32_t speeds_bits = r_speeds->value; int line = 4; - { - const int dirty = g_lights.stats.dirty_cells; - gEngine.Con_NPrintf(line++, "Dirty light cells: %d, size = %dKiB, ranges = %d\n", dirty, (int)(dirty * sizeof(struct LightCluster) / 1024), g_lights.stats.ranges_uploaded); - } + + // TODO collect into a r_speeds_msg string, similar to ref/gl + //R_Speeds_Printf( "Renderer: ^1Engine^7\n\n" ); const uint32_t events = g_aprof.events_last_frame - prev_frame_index; const uint64_t frame_begin_time = APROF_EVENT_TIMESTAMP(g_aprof.events[prev_frame_index]); const unsigned long long delta_ns = APROF_EVENT_TIMESTAMP(g_aprof.events[g_aprof.events_last_frame]) - frame_begin_time; const float frame_time = delta_ns / 1e6; - const uint64_t gpu_time_ns = gpu_frame_end_ns - gpu_frame_begin_ns; - gEngine.Con_NPrintf(line++, "GPU frame time: %.03fms\n", gpu_time_ns * 1e-6); - gEngine.Con_NPrintf(line++, "aprof events this frame: %u, wraps: %d, frame time: %.03fms\n", events, g_aprof.current_frame_wraparounds, frame_time); + if (speeds_bits & SPEEDS_BIT_SIMPLE) { + const uint64_t gpu_time_ns = gpu_frame_end_ns - gpu_frame_begin_ns; + gEngine.Con_NPrintf(line++, "GPU frame time: %.03fms\n", gpu_time_ns * 1e-6); + } + + if (speeds_bits & SPEEDS_BIT_STATS) { + const int dirty = g_lights.stats.dirty_cells; + gEngine.Con_NPrintf(line++, "aprof events this frame: %u, wraps: %d, frame time: %.03fms\n", events, g_aprof.current_frame_wraparounds, frame_time); + gEngine.Con_NPrintf(line++, "Dirty light cells: %d, size = %dKiB, ranges = %d\n", dirty, (int)(dirty * sizeof(struct LightCluster) / 1024), g_lights.stats.ranges_uploaded); + } g_slows.frame_times[g_slows.frame_num] = frame_time; g_slows.frame_num = (g_slows.frame_num + 1) % MAX_FRAMES_HISTORY; handlePause( prev_frame_index ); - int y = 100; - const float frame_bar_y_scale = 2.f; // ms to pixels (somehow) - y = drawFrameTimeGraph( y, frame_bar_y_scale ) + 20; - y = drawFrames( prev_frame_index, y, gpu_frame_begin_ns, gpu_frame_end_ns ); + if (speeds_bits & SPEEDS_BIT_FRAME) { + getCurrentFontMetrics(); + int y = 100; + const float frame_bar_y_scale = 2.f; // ms to pixels (somehow) + y = drawFrameTimeGraph( y, frame_bar_y_scale ) + 20; + y = drawFrames( prev_frame_index, y, gpu_frame_begin_ns, gpu_frame_end_ns ); + } + APROF_SCOPE_END(__FUNCTION__); } diff --git a/ref/vk/vk_common.h b/ref/vk/vk_common.h index fdab7ffa..603a30b2 100644 --- a/ref/vk/vk_common.h +++ b/ref/vk/vk_common.h @@ -1,4 +1,3 @@ -//#include "xash3d_types.h" #include "const.h" // required for ref_api.h #include "cvardef.h" #include "com_model.h" diff --git a/ref/vk/vk_cvar.c b/ref/vk/vk_cvar.c index 2f8f6c3f..71b43943 100644 --- a/ref/vk/vk_cvar.c +++ b/ref/vk/vk_cvar.c @@ -6,13 +6,15 @@ DECLARE_CVAR(NONEXTERN_CVAR) #undef NONEXTERN_CVAR -static cvar_t *r_drawentities; +DEFINE_ENGINE_SHARED_CVAR_LIST() void VK_LoadCvars( void ) { +#define gEngfuncs gEngine // ... + RETRIEVE_ENGINE_SHARED_CVAR_LIST() + r_lighting_modulate = gEngine.Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" ); cl_lightstyle_lerping = gEngine.pfnGetCvarPointer( "cl_lightstyle_lerping", 0 ); - r_drawentities = gEngine.pfnGetCvarPointer( "r_drawentities", 0 ); r_lightmap = gEngine.Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" ); ui_infotool = gEngine.Cvar_Get( "ui_infotool", "0", FCVAR_CHEAT, "DEBUG: print entity info under crosshair" ); vk_only = gEngine.Cvar_Get( "vk_only", "0", FCVAR_GLCONFIG, "Full disable Ray Tracing pipeline" ); diff --git a/ref/vk/vk_cvar.h b/ref/vk/vk_cvar.h index 91db28d4..5ac4c08b 100644 --- a/ref/vk/vk_cvar.h +++ b/ref/vk/vk_cvar.h @@ -2,6 +2,11 @@ #include "cvardef.h" +#include "xash3d_types.h" // required for ref_api.h +#include "const.h" // required for ref_api.h +#include "com_model.h" // required for ref_api.h +#include "ref_api.h" + // from engine/common/cvar.h #define FCVAR_READ_ONLY (1<<17) // cannot be set by user at all, and can't be requested by CvarGetPointer from game dlls @@ -23,7 +28,8 @@ void VK_LoadCvarsAfterInit( void ); X(vk_only) \ X(vk_device_target_id) \ - #define EXTERN_CVAR(cvar) extern cvar_t *cvar; DECLARE_CVAR(EXTERN_CVAR) #undef EXTERN_CVAR + +DECLARE_ENGINE_SHARED_CVAR_LIST() diff --git a/ref/vk/vk_studio.c b/ref/vk/vk_studio.c index 9fc21504..a1e11d9e 100644 --- a/ref/vk/vk_studio.c +++ b/ref/vk/vk_studio.c @@ -6,6 +6,7 @@ #include "vk_previous_frame.h" #include "vk_renderstate.h" #include "vk_math.h" +#include "vk_cvar.h" #include "camera.h" #include "xash3d_mathlib.h" @@ -39,8 +40,6 @@ typedef struct model_t *model; } player_model_t; -cvar_t *r_glowshellfreq; - cvar_t r_shadows = { (char*)"r_shadows", (char*)"0", 0 }; typedef struct sortedmesh_s @@ -116,9 +115,7 @@ typedef struct } studio_draw_state_t; // studio-related cvars -static cvar_t *r_drawviewmodel; cvar_t *cl_righthand = NULL; -static cvar_t *cl_himodels; static r_studio_interface_t *pStudioDraw; static studio_draw_state_t g_studio; // global studio state @@ -144,11 +141,7 @@ static struct { void R_StudioInit( void ) { - cl_himodels = gEngine.pfnGetCvarPointer( "cl_himodels", 0 ); - r_drawviewmodel = gEngine.Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" ); - Matrix3x4_LoadIdentity( g_studio.rotationmatrix ); - r_glowshellfreq = gEngine.Cvar_Get( "r_glowshellfreq", "2.2", 0, "glowing shell frequency update" ); // g-cont. cvar disabled by Valve // gEngine.Cvar_RegisterVariable( &r_shadows );