vk: studio: clear submodule cache at appropriate times
Add render refcount to submodels to diagnose when it can't properly clear things due to them being used somewhere still. Also add `speeds.submodels_cache_{dynamic,static}` counters to show how many submodels render models have been allocated.
This commit is contained in:
parent
03fc537d54
commit
45a141aa36
|
@ -22,6 +22,7 @@
|
|||
#include "vk_sprite.h"
|
||||
#include "vk_beams.h"
|
||||
#include "vk_combuf.h"
|
||||
#include "vk_entity_data.h"
|
||||
|
||||
// FIXME move this rt-specific stuff out
|
||||
#include "vk_light.h"
|
||||
|
@ -810,6 +811,8 @@ qboolean R_VkInit( void )
|
|||
void R_VkShutdown( void ) {
|
||||
XVK_CHECK(vkDeviceWaitIdle(vk_core.device));
|
||||
|
||||
VK_EntityDataClear();
|
||||
|
||||
R_SpriteShutdown();
|
||||
|
||||
if (vk_core.rtx)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "camera.h"
|
||||
#include "vk_mapents.h"
|
||||
#include "profiler.h"
|
||||
#include "vk_entity_data.h"
|
||||
|
||||
#include "com_strings.h"
|
||||
#include "ref_params.h"
|
||||
|
@ -85,6 +86,7 @@ static void loadLights( const model_t *const map ) {
|
|||
|
||||
// Clears all old map data
|
||||
static void mapLoadBegin( const model_t *const map ) {
|
||||
VK_EntityDataClear();
|
||||
R_StudioCacheClear();
|
||||
R_GeometryBuffer_MapClear();
|
||||
|
||||
|
|
|
@ -6,16 +6,6 @@
|
|||
|
||||
#define MODULE_NAME "studio"
|
||||
|
||||
// FIXME:
|
||||
// - [ ] (CRASH) Cache coherence: entities are reused between frames for different studio models. Catch and handle it.
|
||||
// If it was literally reused between sequential frames, then we're screwed, because we can't delete the previous one, as it might be still in use on GPU. Needs refcounts infrastructure.
|
||||
// Currently we just push render_submodels being released back into cache. And we don't destroy them ever.
|
||||
// This needs to change.
|
||||
// TODO add clearing cache function. Also make sure that it is called on shutdown.
|
||||
|
||||
// TODO Potential optimization: (MIGHT STILL NEED THIS FOR DENOISER MOVE VECTORS)
|
||||
// Keep last generated verts. Compare new verts with previous ones. If they are the same, do not rebuild the BLAS.
|
||||
|
||||
typedef struct {
|
||||
const studiohdr_t *studio_header_key;
|
||||
r_studio_model_info_t info;
|
||||
|
@ -25,6 +15,9 @@ static struct {
|
|||
#define MAX_STUDIO_MODELS 256
|
||||
r_studio_model_info_entry_t models[MAX_STUDIO_MODELS];
|
||||
int models_count;
|
||||
|
||||
int submodels_cached_dynamic;
|
||||
int submodels_cached_static;
|
||||
} g_studio_cache;
|
||||
|
||||
void studioRenderSubmodelDestroy( r_studio_submodel_render_t *submodel ) {
|
||||
|
@ -35,6 +28,9 @@ void studioRenderSubmodelDestroy( r_studio_submodel_render_t *submodel ) {
|
|||
}
|
||||
|
||||
static void studioSubmodelInfoDestroy(r_studio_submodel_info_t *subinfo) {
|
||||
// Not zero means that something still holds a cached render submodel instance somewhere
|
||||
ASSERT(subinfo->render_refcount == 0);
|
||||
|
||||
while (subinfo->cached_head) {
|
||||
r_studio_submodel_render_t *render = subinfo->cached_head;
|
||||
subinfo->cached_head = subinfo->cached_head->_.next;
|
||||
|
@ -53,6 +49,8 @@ void R_StudioCacheClear( void ) {
|
|||
Mem_Free(info->submodels);
|
||||
}
|
||||
g_studio_cache.models_count = 0;
|
||||
|
||||
g_studio_cache.submodels_cached_dynamic = g_studio_cache.submodels_cached_static = 0;
|
||||
}
|
||||
|
||||
static struct {
|
||||
|
@ -219,7 +217,8 @@ r_studio_model_info_t *getStudioModelInfo(model_t *model) {
|
|||
}
|
||||
|
||||
void VK_StudioModelInit(void) {
|
||||
// FIXME R_SPEEDS_METRIC(g_studio_cache.entries_count, "cached_submodels", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_studio_cache.submodels_cached_static, "submodels_cached_static", kSpeedsMetricCount);
|
||||
R_SPEEDS_METRIC(g_studio_cache.submodels_cached_dynamic, "submodels_cached_dynamic", kSpeedsMetricCount);
|
||||
}
|
||||
|
||||
r_studio_submodel_render_t *studioSubmodelRenderModelAcquire(r_studio_submodel_info_t *subinfo) {
|
||||
|
@ -230,15 +229,21 @@ r_studio_submodel_render_t *studioSubmodelRenderModelAcquire(r_studio_submodel_i
|
|||
subinfo->cached_head = render->_.next;
|
||||
render->_.next = NULL;
|
||||
}
|
||||
subinfo->render_refcount++;
|
||||
return render;
|
||||
}
|
||||
|
||||
render = Mem_Calloc(vk_core.pool, sizeof(*render));
|
||||
render->_.info = subinfo;
|
||||
|
||||
if (!subinfo->is_dynamic)
|
||||
if (!subinfo->is_dynamic) {
|
||||
subinfo->cached_head = render;
|
||||
++g_studio_cache.submodels_cached_static;
|
||||
} else {
|
||||
++g_studio_cache.submodels_cached_dynamic;
|
||||
}
|
||||
|
||||
subinfo->render_refcount++;
|
||||
return render;
|
||||
}
|
||||
|
||||
|
@ -246,6 +251,9 @@ void studioSubmodelRenderModelRelease(r_studio_submodel_render_t *render_submode
|
|||
if (!render_submodel)
|
||||
return;
|
||||
|
||||
ASSERT(render_submodel->_.info->render_refcount > 0);
|
||||
render_submodel->_.info->render_refcount--;
|
||||
|
||||
if (!render_submodel->_.info->is_dynamic)
|
||||
return;
|
||||
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
#include "vk_geometry.h"
|
||||
|
||||
struct r_studio_submodel_info_s;
|
||||
|
||||
// Submodel render data that is enough to render given submodel
|
||||
// Included render model (that also incapsulates BLAS)
|
||||
// This can be static (built once), or dynamic (updated frequently)
|
||||
// Lives in per-model-info submodel cache
|
||||
typedef struct r_studio_submodel_render_s {
|
||||
vk_render_model_t model;
|
||||
r_geometry_range_t geometry_range;
|
||||
|
@ -21,6 +26,7 @@ typedef struct r_studio_submodel_render_s {
|
|||
} _;
|
||||
} r_studio_submodel_render_t;
|
||||
|
||||
// Submodel metadata and render-model cache
|
||||
typedef struct r_studio_submodel_info_s {
|
||||
const mstudiomodel_t *submodel_key;
|
||||
qboolean is_dynamic;
|
||||
|
@ -28,8 +34,12 @@ typedef struct r_studio_submodel_info_s {
|
|||
// TODO int verts_count; for prev_verts
|
||||
|
||||
r_studio_submodel_render_t *cached_head;
|
||||
|
||||
// Mostly for debug: how many cached render models were acquired and not given back
|
||||
int render_refcount;
|
||||
} r_studio_submodel_info_t;
|
||||
|
||||
// Submodel cache functions, used in vk_studio.c
|
||||
r_studio_submodel_render_t *studioSubmodelRenderModelAcquire(r_studio_submodel_info_t *info);
|
||||
void studioSubmodelRenderModelRelease(r_studio_submodel_render_t *render_submodel);
|
||||
|
||||
|
@ -38,7 +48,7 @@ typedef struct {
|
|||
r_studio_submodel_info_t *submodels;
|
||||
} r_studio_model_info_t;
|
||||
|
||||
void VK_StudioModelInit(void);
|
||||
r_studio_model_info_t *getStudioModelInfo(model_t *model);
|
||||
|
||||
// Entity model cache/pool
|
||||
typedef struct {
|
||||
|
@ -52,12 +62,5 @@ typedef struct {
|
|||
r_studio_submodel_render_t **bodyparts;
|
||||
} r_studio_entity_model_t;
|
||||
|
||||
//r_studio_entity_model_t *studioEntityModelGet(const cl_entity_t *ent);
|
||||
|
||||
// TOOD manual cleanup function? free unused?
|
||||
|
||||
//void studioEntityModelClear(void);
|
||||
|
||||
void studioRenderSubmodelDestroy( r_studio_submodel_render_t *submodel );
|
||||
|
||||
r_studio_model_info_t *getStudioModelInfo(model_t *model);
|
||||
void VK_StudioModelInit(void);
|
||||
//void VK_StudioModelShutdown(void);
|
||||
|
|
Loading…
Reference in New Issue