From fb7f57cf6a49ad4c49de6812cf7d8c75a0f06e61 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 3 Aug 2024 10:56:37 +0300 Subject: [PATCH] engine: client: switch efrags to dynamic allocation (as suggested on insideqc by @mh) --- common/com_model.h | 1 - engine/client/cl_efrag.c | 88 +++++++++++++++++++++++++++------------- engine/client/cl_tent.c | 20 --------- engine/client/client.h | 1 - 4 files changed, 60 insertions(+), 50 deletions(-) diff --git a/common/com_model.h b/common/com_model.h index 71212b70..cabf46cb 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -532,7 +532,6 @@ typedef struct #define MAX_MOVIES 8 #define MAX_CDTRACKS 32 #define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client) -#define MAX_EFRAGS 8192 // Arcane Dimensions required #define MAX_REQUESTS 64 #if ! XASH_64BIT diff --git a/engine/client/cl_efrag.c b/engine/client/cl_efrag.c index 668c12da..9416fe39 100644 --- a/engine/client/cl_efrag.c +++ b/engine/client/cl_efrag.c @@ -28,10 +28,51 @@ GNU General Public License for more details. =============================================================================== */ +#define NUM_EFRAGS_ALLOC 64 // alloc 64 efrags (1-2kb each alloc) + static efrag_t **lastlink; static mnode_t *r_pefragtopnode; static vec3_t r_emins, r_emaxs; static cl_entity_t *r_addent; +static int cl_efrags_num; +static efrag_t *cl_efrags; + +static efrag_t *CL_AllocEfrags( int num ) +{ + int i; + efrag_t *efrags; + + if( !cl.worldmodel ) + { + Host_Error( "%s: called with NULL world\n", __func__ ); + return NULL; + } + + if( num == 0 ) + return NULL; + + // set world to be the owner, so it will get automatically cleaned up + efrags = Mem_Calloc( cl.worldmodel->mempool, sizeof( *efrags ) * num ); + + // initialize linked list + for( i = 0; i < num - 1; i++ ) + efrags[i].entnext = &efrags[i + 1]; + + cl_efrags_num += num; + + return efrags; +} + +/* +============== +CL_ClearEfrags +============== +*/ +void CL_ClearEfrags( void ) +{ + cl_efrags_num = 0; + cl_efrags = NULL; +} /* =================== @@ -56,14 +97,11 @@ static void R_SplitEntityOnNode( mnode_t *node ) leaf = (mleaf_t *)node; // grab an efrag off the free list - ef = clgame.free_efrags; + ef = cl_efrags; if( !ef ) - { - Con_Printf( S_ERROR "too many efrags!\n" ); - return; // no free fragments... - } + ef = CL_AllocEfrags( NUM_EFRAGS_ALLOC ); - clgame.free_efrags = ef->entnext; + cl_efrags = ef->entnext; ef->entity = r_addent; // add the entity link @@ -133,35 +171,29 @@ R_StoreEfrags */ void R_StoreEfrags( efrag_t **ppefrag, int framecount ) { - cl_entity_t *pent; - model_t *clmodel; - efrag_t *pefrag; + const efrag_t *pefrag; + cl_entity_t *pent; + model_t *clmodel; while(( pefrag = *ppefrag ) != NULL ) { pent = pefrag->entity; clmodel = pent->model; - switch( clmodel->type ) - { - case mod_alias: - case mod_brush: - case mod_studio: - case mod_sprite: - if( pent->visframe != framecount ) - { - if( CL_AddVisibleEntity( pent, ET_FRAGMENTED )) - { - // mark that we've recorded this entity for this frame - pent->curstate.messagenum = cl.parsecount; - pent->visframe = framecount; - } - } + // how this could happen? + if( unlikely( clmodel->type < mod_brush || clmodel->type > mod_studio )) + continue; - ppefrag = &pefrag->leafnext; - break; - default: - break; + if( pent->visframe != framecount ) + { + if( CL_AddVisibleEntity( pent, ET_FRAGMENTED )) + { + // mark that we've recorded this entity for this frame + pent->curstate.messagenum = cl.parsecount; + pent->visframe = framecount; + } } + + ppefrag = &pefrag->leafnext; } } diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 355a9aea..a12112af 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -3064,26 +3064,6 @@ EFRAGS MANAGEMENT ============================================================== */ -efrag_t cl_efrags[MAX_EFRAGS]; - -/* -============== -CL_ClearEfrags -============== -*/ -void CL_ClearEfrags( void ) -{ - int i; - - memset( cl_efrags, 0, sizeof( cl_efrags )); - - // allocate the efrags and chain together into a free list - clgame.free_efrags = cl_efrags; - for( i = 0; i < MAX_EFRAGS - 1; i++ ) - clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1]; - clgame.free_efrags[i].entnext = NULL; -} - /* ======================= R_ClearStaticEntities diff --git a/engine/client/client.h b/engine/client/client.h index c9d97810..06076292 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -501,7 +501,6 @@ typedef struct net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more - efrag_t *free_efrags; // linked efrags cl_entity_t viewent; // viewmodel qboolean client_dll_uses_sdl;