mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-13 20:50:23 +01:00
vk: add "persistent" speeds metrics for used memory, etc
Renames previous METRICS to COUNTERS. These are still reset to zero every frame. Adds new METRICS which are preserved, maintained externally to speeds, and only sampled by speeds code once per frame. Also adds new metrics: - `studio.cached_submodels` -- number of submodels in cache - `geom.used` -- memory used by long allocations - `geom.{vertices,indices}` -- counts of vertices/indices for long allocations - `geom.dyn_{vertices,indices}` -- counts of vertices/indices for single-frame dynamic allocations
This commit is contained in:
parent
d13c0d4748
commit
f691b4b4b0
@ -28,13 +28,13 @@ r_block_t R_BlockAllocLong(r_blocks_t *blocks, uint32_t size, uint32_t alignment
|
||||
|
||||
const alo_block_t ablock = aloPoolAllocate(blocks->long_pool, size, alignment);
|
||||
if (ablock.offset == ALO_ALLOC_FAILED) {
|
||||
/* gEngine.Con_Reportf("aloPoolAllocate failed\n"); */
|
||||
gEngine.Con_Reportf(S_ERROR "aloPoolAllocate failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
const int metablock_index = allocMetablock(blocks);
|
||||
if (metablock_index < 0) {
|
||||
/* gEngine.Con_Reportf("allocMettablock failed\n"); */
|
||||
gEngine.Con_Reportf(S_ERROR "allocMetablock failed\n");
|
||||
aloPoolFree(blocks->long_pool, ablock.index);
|
||||
return ret;
|
||||
}
|
||||
@ -50,6 +50,7 @@ r_block_t R_BlockAllocLong(r_blocks_t *blocks, uint32_t size, uint32_t alignment
|
||||
|
||||
/* gEngine.Con_Reportf("block alloc %dKiB => index=%d offset=%u\n", (int)size/1024, metablock_index, (int)ret.offset); */
|
||||
|
||||
blocks->allocated_long += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -65,6 +66,7 @@ void R_BlocksCreate(r_blocks_t *blocks, uint32_t size, uint32_t once_size, int e
|
||||
memset(blocks, 0, sizeof(*blocks));
|
||||
|
||||
blocks->size = size;
|
||||
blocks->allocated_long = 0;
|
||||
|
||||
blocks->long_pool = aloPoolCreate(size - once_size, expected_allocs, 4);
|
||||
aloIntPoolGrow(&blocks->blocks.freelist, expected_allocs);
|
||||
@ -94,6 +96,7 @@ void R_BlockRelease(const r_block_t *block) {
|
||||
|
||||
aloPoolFree(blocks->long_pool, metablock->long_index);
|
||||
aloIntPoolFree(&blocks->blocks.freelist, block->impl_.index);
|
||||
blocks->allocated_long -= block->size;
|
||||
}
|
||||
|
||||
void R_BlocksDestroy(r_blocks_t *blocks) {
|
||||
|
@ -30,6 +30,9 @@ typedef struct r_blocks_s {
|
||||
alo_int_pool_t freelist;
|
||||
struct r_blocks_block_s *storage;
|
||||
} blocks;
|
||||
|
||||
// This is an estimate, it doesn't count alignment holes
|
||||
int allocated_long;
|
||||
} r_blocks_t;
|
||||
|
||||
r_block_t R_BlockAllocLong(r_blocks_t *blocks, uint32_t size, uint32_t alignment);
|
||||
|
@ -30,6 +30,7 @@ enum {
|
||||
|
||||
typedef struct {
|
||||
int *p_value;
|
||||
qboolean reset;
|
||||
char name[64];
|
||||
const char *var_name;
|
||||
const char *src_file;
|
||||
@ -213,7 +214,7 @@ static void drawCPUProfilerScopes(int draw, const aprof_event_t *events, uint64_
|
||||
const uint64_t delta_ns = timestamp_ns - stack[depth].begin_ns;
|
||||
|
||||
if (!g_speeds.frame.scopes[scope_id].initialized) {
|
||||
R_SpeedsRegisterMetric(&g_speeds.frame.scopes[scope_id].time_us, "scope", scope->name, kSpeedsMetricMicroseconds, scope->name, __FILE__, __LINE__);
|
||||
R_SpeedsRegisterMetric(&g_speeds.frame.scopes[scope_id].time_us, "scope", scope->name, kSpeedsMetricMicroseconds, /*reset*/ true, scope->name, __FILE__, __LINE__);
|
||||
|
||||
g_speeds.frame.scopes[scope_id].initialized = 1;
|
||||
}
|
||||
@ -431,7 +432,7 @@ static void drawGPUProfilerScopes(qboolean draw, int y, uint64_t frame_begin_tim
|
||||
const char *name = gpurofl->scopes[scope_index].name;
|
||||
|
||||
if (!g_speeds.frame.gpu_scopes[scope_index].initialized) {
|
||||
R_SpeedsRegisterMetric(&g_speeds.frame.gpu_scopes[scope_index].time_us, "gpuscope", name, kSpeedsMetricMicroseconds, name, __FILE__, __LINE__);
|
||||
R_SpeedsRegisterMetric(&g_speeds.frame.gpu_scopes[scope_index].time_us, "gpuscope", name, kSpeedsMetricMicroseconds, /*reset*/ true, name, __FILE__, __LINE__);
|
||||
g_speeds.frame.gpu_scopes[scope_index].initialized = 1;
|
||||
}
|
||||
|
||||
@ -523,10 +524,11 @@ static void printMetrics( void ) {
|
||||
}
|
||||
}
|
||||
|
||||
static void clearMetrics( void ) {
|
||||
static void resetMetrics( void ) {
|
||||
for (int i = 0; i < g_speeds.metrics_count; ++i) {
|
||||
const r_speeds_metric_t *const metric = g_speeds.metrics + i;
|
||||
*metric->p_value = 0;
|
||||
if (metric->reset)
|
||||
*metric->p_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -817,10 +819,10 @@ void R_SpeedsInit( void ) {
|
||||
gEngine.Cmd_AddCommand("r_speeds_list_metrics", listMetrics, "List all registered metrics");
|
||||
gEngine.Cmd_AddCommand("r_speeds_graph", graphCmd, "Manipulate add/remove metrics graphs");
|
||||
|
||||
R_SPEEDS_METRIC(g_speeds.frame.frame_time_us, "frame", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_METRIC(g_speeds.frame.cpu_time_us, "cpu", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_METRIC(g_speeds.frame.cpu_wait_time_us, "cpu_wait", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_METRIC(g_speeds.frame.gpu_time_us, "gpu", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_COUNTER(g_speeds.frame.frame_time_us, "frame", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_COUNTER(g_speeds.frame.cpu_time_us, "cpu", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_COUNTER(g_speeds.frame.cpu_wait_time_us, "cpu_wait", kSpeedsMetricMicroseconds);
|
||||
R_SPEEDS_COUNTER(g_speeds.frame.gpu_time_us, "gpu", kSpeedsMetricMicroseconds);
|
||||
}
|
||||
|
||||
// grab r_speeds message
|
||||
@ -841,11 +843,12 @@ qboolean R_SpeedsMessage( char *out, size_t size )
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_SpeedsRegisterMetric(int* p_value, const char *module, const char *name, r_speeds_metric_type_t type, const char *var_name, const char *file, int line) {
|
||||
void R_SpeedsRegisterMetric(int* p_value, const char *module, const char *name, r_speeds_metric_type_t type, qboolean reset, const char *var_name, const char *file, int line) {
|
||||
ASSERT(g_speeds.metrics_count < MAX_SPEEDS_METRICS);
|
||||
|
||||
r_speeds_metric_t *metric = g_speeds.metrics + (g_speeds.metrics_count++);
|
||||
metric->p_value = p_value;
|
||||
metric->reset = reset;
|
||||
|
||||
Q_snprintf(metric->name, sizeof(metric->name), "%s.%s", module, name);
|
||||
|
||||
@ -927,7 +930,7 @@ void R_SpeedsDisplayMore(uint32_t prev_frame_index, const struct vk_combuf_scope
|
||||
|
||||
doListMetrics();
|
||||
|
||||
clearMetrics();
|
||||
resetMetrics();
|
||||
|
||||
APROF_SCOPE_END(function);
|
||||
}
|
||||
|
@ -16,7 +16,15 @@ typedef enum {
|
||||
kSpeedsMetricMicroseconds,
|
||||
} r_speeds_metric_type_t;
|
||||
|
||||
void R_SpeedsRegisterMetric(int* p_value, const char *module, const char *name, r_speeds_metric_type_t type, const char *var_name, const char *file, int line);
|
||||
// TODO upper limit argument
|
||||
void R_SpeedsRegisterMetric(int* p_value, const char *module, const char *name, r_speeds_metric_type_t type, qboolean reset, const char *var_name, const char *file, int line);
|
||||
|
||||
// A counter is a value accumulated during a single frame, and reset to zero between frames.
|
||||
// Examples: drawn models count, scope times, etc.
|
||||
#define R_SPEEDS_COUNTER(var, name, type) \
|
||||
R_SpeedsRegisterMetric(&(var), MODULE_NAME, name, type, /*reset*/ true, #var, __FILE__, __LINE__)
|
||||
|
||||
// A metric is computed and preserved across frame boundaries.
|
||||
// Examples: total allocated memory, cache sizes, etc.
|
||||
#define R_SPEEDS_METRIC(var, name, type) \
|
||||
R_SpeedsRegisterMetric(&(var), MODULE_NAME, name, type, #var, __FILE__, __LINE__)
|
||||
R_SpeedsRegisterMetric(&(var), MODULE_NAME, name, type, /*reset*/ false, #var, __FILE__, __LINE__)
|
||||
|
@ -32,7 +32,7 @@ static struct {
|
||||
} g_beam;
|
||||
|
||||
qboolean R_BeamInit(void) {
|
||||
R_SPEEDS_METRIC(g_beam.stats.beams, "count", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_beam.stats.beams, "count", kSpeedsMetricCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -95,9 +95,9 @@ qboolean VK_BrushInit( void )
|
||||
{
|
||||
VK_InitRandomTable ();
|
||||
|
||||
R_SPEEDS_METRIC(g_brush.stat.models_drawn, "drawn", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_brush.stat.water_surfaces_drawn, "water.surfaces", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_brush.stat.water_polys_drawn, "water.polys", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_brush.stat.models_drawn, "drawn", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_brush.stat.water_surfaces_drawn, "water.surfaces", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_brush.stat.water_polys_drawn, "water.polys", kSpeedsMetricCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "vk_geometry.h"
|
||||
#include "vk_buffer.h"
|
||||
#include "vk_staging.h"
|
||||
#include "vk_framectl.h" // MAX_CONCURRENT_FRAMES
|
||||
#include "r_speeds.h"
|
||||
|
||||
#define MODULE_NAME "geom"
|
||||
|
||||
#define MAX_BUFFER_VERTICES_STATIC (128 * 1024)
|
||||
#define MAX_BUFFER_INDICES_STATIC (MAX_BUFFER_VERTICES_STATIC * 3)
|
||||
@ -18,6 +20,11 @@
|
||||
static struct {
|
||||
vk_buffer_t buffer;
|
||||
r_blocks_t alloc;
|
||||
|
||||
struct {
|
||||
int vertices, indices;
|
||||
int dyn_vertices, dyn_indices;
|
||||
} stats;
|
||||
} g_geom;
|
||||
|
||||
r_geometry_range_t R_GeometryRangeAlloc(int vertices, int indices) {
|
||||
@ -38,11 +45,17 @@ r_geometry_range_t R_GeometryRangeAlloc(int vertices, int indices) {
|
||||
ret.vertices.count = vertices;
|
||||
ret.indices.count = indices;
|
||||
|
||||
g_geom.stats.indices += indices;
|
||||
g_geom.stats.vertices += vertices;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void R_GeometryRangeFree(const r_geometry_range_t* range) {
|
||||
R_BlockRelease(&range->block_handle);
|
||||
|
||||
g_geom.stats.indices -= range->indices.count;
|
||||
g_geom.stats.vertices -= range->vertices.count;
|
||||
}
|
||||
|
||||
r_geometry_range_lock_t R_GeometryRangeLock(const r_geometry_range_t *range) {
|
||||
@ -121,6 +134,9 @@ qboolean R_GeometryBufferAllocOnceAndLock(r_geometry_buffer_lock_t *lock, int ve
|
||||
};
|
||||
}
|
||||
|
||||
g_geom.stats.dyn_vertices += vertex_count;
|
||||
g_geom.stats.dyn_indices += index_count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -144,6 +160,12 @@ qboolean R_GeometryBuffer_Init(void) {
|
||||
|
||||
#define EXPECTED_ALLOCS 1024
|
||||
R_BlocksCreate(&g_geom.alloc, GEOMETRY_BUFFER_SIZE, GEOMETRY_BUFFER_DYNAMIC_SIZE, EXPECTED_ALLOCS);
|
||||
|
||||
R_SPEEDS_METRIC(g_geom.alloc.allocated_long, "used", kSpeedsMetricBytes);
|
||||
R_SPEEDS_METRIC(g_geom.stats.vertices, "vertices", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_geom.stats.indices, "indices", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_geom.stats.dyn_vertices, "dyn_vertices", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_geom.stats.dyn_indices, "dyn_indices", kSpeedsMetricCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -106,15 +106,15 @@ qboolean VK_LightsInit( void ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
R_SPEEDS_METRIC(g_lights_.stats.dirty_cells, "dirty_cells", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.stats.dirty_cells_size, "dirty_cells_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_METRIC(g_lights_.stats.ranges_uploaded, "ranges_uploaded", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.num_polygons, "polygons", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.num_point_lights, "points", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.stats.dynamic_polygons, "polygons_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.stats.dynamic_points, "points_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.stats.dlights, "dlights", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_lights_.stats.elights, "elights", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.dirty_cells, "dirty_cells", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.dirty_cells_size, "dirty_cells_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.ranges_uploaded, "ranges_uploaded", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.num_polygons, "polygons", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.num_point_lights, "points", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.dynamic_polygons, "polygons_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.dynamic_points, "points_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.dlights, "dlights", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_lights_.stats.elights, "elights", kSpeedsMetricCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -390,8 +390,8 @@ qboolean RT_VkAccelInit(void) {
|
||||
|
||||
g_accel.accels_buffer_alloc = aloPoolCreate(MAX_ACCELS_BUFFER, MAX_INSTANCES, /* why */ 256);
|
||||
|
||||
R_SPEEDS_METRIC(g_accel.stats.instances_count, "instances", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_accel.stats.accels_built, "built", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_accel.stats.instances_count, "instances", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_accel.stats.accels_built, "built", kSpeedsMetricCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -338,8 +338,8 @@ qboolean VK_RenderInit( void ) {
|
||||
if (!createPipelines())
|
||||
return false;
|
||||
|
||||
R_SPEEDS_METRIC(g_render.stats.dynamic_model_count, "models_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_render.stats.models_count, "models", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_render.stats.dynamic_model_count, "models_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_render.stats.models_count, "models", kSpeedsMetricCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ static void destroyQuadModel(void) {
|
||||
}
|
||||
|
||||
qboolean R_SpriteInit(void) {
|
||||
R_SPEEDS_METRIC(g_sprite.stats.sprites, "count", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_sprite.stats.sprites, "count", kSpeedsMetricCount);
|
||||
|
||||
return true;
|
||||
// TODO return createQuadModel();
|
||||
|
@ -64,12 +64,12 @@ qboolean R_VkStagingInit(void) {
|
||||
|
||||
R_FlippingBuffer_Init(&g_staging.buffer_alloc, DEFAULT_STAGING_SIZE);
|
||||
|
||||
R_SPEEDS_METRIC(g_staging.stats.total_size, "total_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_METRIC(g_staging.stats.buffers_size, "buffers_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_METRIC(g_staging.stats.images_size, "images_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_COUNTER(g_staging.stats.total_size, "total_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_COUNTER(g_staging.stats.buffers_size, "buffers_size", kSpeedsMetricBytes);
|
||||
R_SPEEDS_COUNTER(g_staging.stats.images_size, "images_size", kSpeedsMetricBytes);
|
||||
|
||||
R_SPEEDS_METRIC(g_staging.stats.buffer_chunks, "buffer_chunks", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_staging.stats.images, "images", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_staging.stats.buffer_chunks, "buffer_chunks", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_staging.stats.images, "images", kSpeedsMetricCount);
|
||||
|
||||
g_staging.buffer_upload_scope_id = R_VkGpuScope_Register("staging_buffers");
|
||||
g_staging.image_upload_scope_id = R_VkGpuScope_Register("staging_images");
|
||||
|
@ -189,6 +189,7 @@ void R_StudioCacheClear( void ) {
|
||||
}
|
||||
|
||||
static const r_studio_model_cache_entry_t *findSubModelInCacheForEntity(const mstudiomodel_t *submodel, const cl_entity_t *ent) {
|
||||
// FIXME hash table, there are hundreds of entries
|
||||
for (int i = 0; i < g_studio_cache.entries_count; ++i) {
|
||||
const r_studio_model_cache_entry_t *const entry = g_studio_cache.entries + i;
|
||||
if (entry->key_submodel == submodel && (entry->key_entity == NULL || entry->key_entity == ent))
|
||||
@ -209,10 +210,12 @@ void R_StudioInit( void )
|
||||
g_studio.framecount = 0;
|
||||
m_fDoRemap = false;
|
||||
|
||||
R_SPEEDS_METRIC(g_studio_stats.models_count, "models", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_studio_stats.submodels_total, "submodels_total", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_studio_stats.submodels_static, "submodels_static", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_studio_stats.submodels_dynamic, "submodels_dynamic", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_studio_stats.models_count, "models", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_studio_stats.submodels_total, "submodels_total", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_studio_stats.submodels_static, "submodels_static", kSpeedsMetricCount);
|
||||
R_SPEEDS_COUNTER(g_studio_stats.submodels_dynamic, "submodels_dynamic", kSpeedsMetricCount);
|
||||
|
||||
R_SPEEDS_METRIC(g_studio_cache.entries_count, "cached_submodels", kSpeedsMetricCount);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user