Free Unused Image and Models only if we are near to limit

This commit is contained in:
Denis Pauk 2020-12-23 21:35:27 +02:00
parent b0cc97e6f3
commit 2c00502b0b
3 changed files with 176 additions and 24 deletions

View file

@ -232,9 +232,15 @@ void Vk_TextureMode( char *string );
void Vk_LmapTextureMode( char *string );
void Vk_ImageList_f (void);
void Vk_BuildPolygonFromSurface(msurface_t *fa, model_t *currentmodel);
void Vk_CreateSurfaceLightmap (msurface_t *surf);
void Vk_EndBuildingLightmaps (void);
void Vk_BeginBuildingLightmaps (model_t *m);
void Vk_InitImages (void);
void Vk_ShutdownImages (void);
void Vk_FreeUnusedImages (void);
qboolean Vk_ImageHasFreeSpace(void);
void RE_BeginRegistration (char *model);
struct model_s *RE_RegisterModel (char *name);

View file

@ -21,7 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "header/local.h"
image_t vktextures[MAX_VKTEXTURES];
int numvktextures;
int numvktextures = 0;
static int img_loaded = 0;
static int image_max = 0;
// texture for storing raw image data (cinematics, endscreens, etc.)
qvktexture_t vk_rawTexture = QVVKTEXTURE_INIT;
@ -530,17 +533,26 @@ Vk_ImageList_f
*/
void Vk_ImageList_f (void)
{
int i;
int i, used, texels;
image_t *image;
int texels;
R_Printf(PRINT_ALL, "------------------\n");
texels = 0;
used = 0;
for (i = 0, image = vktextures; i < numvktextures; i++, image++)
{
char *in_use = "";
if (image->vk_texture.resource.image == VK_NULL_HANDLE)
continue;
if (image->registration_sequence == registration_sequence)
{
in_use = "*";
used++;
}
texels += image->upload_width*image->upload_height;
switch (image->type)
{
@ -561,11 +573,12 @@ void Vk_ImageList_f (void)
break;
}
R_Printf(PRINT_ALL, " %4i %4i RGB: %s (%dx%d)\n",
R_Printf(PRINT_ALL, " %4i %4i RGB: %s (%dx%d) %s\n",
image->upload_width, image->upload_height, image->name,
image->width, image->height);
image->width, image->height, in_use);
}
R_Printf(PRINT_ALL, "Total texel count (not counting mipmaps): %i\n", texels);
R_Printf(PRINT_ALL, "Total texel count (not counting mipmaps): %i in %d images\n", texels, img_loaded);
R_Printf(PRINT_ALL, "Used %d of %d images.\n", used, image_max);
}
typedef struct
@ -978,6 +991,12 @@ Vk_LoadPic(char *name, byte *pic, int width, int realwidth,
image->width = realwidth;
image->height = realheight;
image->type = type;
// update count of loaded images
img_loaded ++;
if (vk_validation->value)
{
R_Printf(PRINT_ALL, "%s: Load %s[%d]\n", __func__, image->name, img_loaded);
}
if (type == it_skin && bits == 8)
FloodFillSkin(pic, width, height);
@ -1310,6 +1329,31 @@ struct image_s *RE_RegisterSkin (char *name)
return Vk_FindImage (name, it_skin);
}
qboolean Vk_ImageHasFreeSpace(void)
{
int i, used;
image_t *image;
used = 0;
for (i = 0, image = vktextures; i < numvktextures; i++, image++)
{
if (!image->name[0])
continue;
if (image->registration_sequence == registration_sequence)
{
used ++;
}
}
if (image_max < used)
{
image_max = used;
}
// should same size of free slots as currently used
return (img_loaded + used) < MAX_VKTEXTURES;
}
/*
================
@ -1324,6 +1368,12 @@ void Vk_FreeUnusedImages (void)
int i;
image_t *image;
if (Vk_ImageHasFreeSpace())
{
// should be enough space for load next images
return;
}
// never free r_notexture or particle texture
r_notexture->registration_sequence = registration_sequence;
r_particletexture->registration_sequence = registration_sequence;
@ -1337,9 +1387,21 @@ void Vk_FreeUnusedImages (void)
continue; // free image_t slot
if (image->type == it_pic)
continue; // don't free pics
if (vk_validation->value)
{
R_Printf(PRINT_ALL, "%s: Unload %s[%d]\n", __func__, image->name, img_loaded);
}
// free it
QVk_ReleaseTexture(&image->vk_texture);
memset(image, 0, sizeof(*image));
img_loaded --;
if (img_loaded < 0)
{
ri.Sys_Error (ERR_DROP, "%s: Broken unload", __func__);
}
}
// free all unused blocks
@ -1396,6 +1458,9 @@ void Vk_InitImages (void)
int i;
float overbright;
numvktextures = 0;
img_loaded = 0;
image_max = 0;
registration_sequence = 1;
// init intensity conversions
@ -1455,8 +1520,19 @@ void Vk_ShutdownImages (void)
if (!image->registration_sequence)
continue; // free image_t slot
if (vk_validation->value)
{
R_Printf(PRINT_ALL, "%s: Unload %s[%d]\n", __func__, image->name, img_loaded);
}
QVk_ReleaseTexture(&image->vk_texture);
memset(image, 0, sizeof(*image));
img_loaded --;
if (img_loaded < 0)
{
ri.Sys_Error (ERR_DROP, "%s: Broken unload", __func__);
}
}
QVk_ReleaseTexture(&vk_rawTexture);

View file

@ -25,11 +25,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
YQ2_ALIGNAS_TYPE(int) static byte mod_novis[MAX_MAP_LEAFS/8];
#define MAX_MOD_KNOWN 512
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
static model_t mod_known[MAX_MOD_KNOWN];
static int mod_numknown = 0;
static int mod_loaded = 0;
static int mod_max = 0;
// the inline * models from the current map are kept seperate
model_t mod_inline[MAX_MOD_KNOWN];
static model_t mod_inline[MAX_MOD_KNOWN];
int registration_sequence;
@ -43,7 +45,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
mnode_t *node;
if (!model || !model->nodes)
ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
ri.Sys_Error (ERR_DROP, "%s: bad model", __func__);
node = model->nodes;
while (1)
@ -90,20 +92,31 @@ Mod_Modellist_f
*/
void Mod_Modellist_f (void)
{
int i;
int i, total, used;
model_t *mod;
int total;
total = 0;
used = 0;
R_Printf(PRINT_ALL,"Loaded models:\n");
for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
{
char *in_use = "";
if (mod->registration_sequence == registration_sequence)
{
in_use = "*";
used ++;
}
if (!mod->name[0])
continue;
R_Printf(PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
R_Printf(PRINT_ALL, "%8i : %s %s\n",
mod->extradatasize, mod->name, in_use);
total += mod->extradatasize;
}
R_Printf(PRINT_ALL, "Total resident: %i\n", total);
R_Printf(PRINT_ALL, "Total resident: %i in %d models\n", total, mod_loaded);
R_Printf(PRINT_ALL, "Used %d of %d models.\n", used, mod_max);
}
/*
@ -114,6 +127,9 @@ Mod_Init
void Mod_Init (void)
{
memset (mod_novis, 0xff, sizeof(mod_novis));
mod_numknown = 0;
mod_loaded = 0;
mod_max = 0;
}
/*
@ -123,8 +139,25 @@ Mod_Free
*/
static void Mod_Free (model_t *mod)
{
if (!mod->extradata)
{
// looks as empty model
memset (mod, 0, sizeof(*mod));
return;
}
if (vk_validation->value)
{
R_Printf(PRINT_ALL, "%s: Unload %s[%d]\n", __func__, mod->name, mod_loaded);
}
Hunk_Free (mod->extradata);
memset (mod, 0, sizeof(*mod));
mod_loaded --;
if (mod_loaded < 0)
{
ri.Sys_Error (ERR_DROP, "%s: Broken unload", __func__);
}
}
/*
@ -435,12 +468,6 @@ static void CalcSurfaceExtents (model_t *loadmodel, msurface_t *s)
}
}
void Vk_BuildPolygonFromSurface(msurface_t *fa, model_t *currentmodel);
void Vk_CreateSurfaceLightmap (msurface_t *surf);
void Vk_EndBuildingLightmaps (void);
void Vk_BeginBuildingLightmaps (model_t *m);
static int calcTexinfoAndFacesSize(const lump_t *fl, byte *mod_base, const lump_t *tl)
{
dface_t* face_in = (void *)(mod_base + fl->fileofs);
@ -1207,7 +1234,7 @@ Mod_ForName
Loads in a model for the given name
==================
*/
static model_t *Mod_ForName (char *name, qboolean crash)
static model_t *Mod_ForName (char *name, model_t *parent_model, qboolean crash)
{
model_t *mod;
unsigned *buf;
@ -1224,7 +1251,7 @@ static model_t *Mod_ForName (char *name, qboolean crash)
if (name[0] == '*')
{
i = atoi(name+1);
if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
if (i < 1 || !parent_model || i >= parent_model->numsubmodels)
ri.Sys_Error (ERR_DROP, "bad inline model number");
return &mod_inline[i];
}
@ -1268,10 +1295,21 @@ static model_t *Mod_ForName (char *name, qboolean crash)
__func__, mod->name);
}
if (vk_validation->value)
{
R_Printf(PRINT_ALL, "%s: Can't load %s\n", __func__, mod->name);
}
memset (mod->name, 0, sizeof(mod->name));
return NULL;
}
// update count of loaded models
mod_loaded ++;
if (vk_validation->value)
{
R_Printf(PRINT_ALL, "%s: Load %s[%d]\n", __func__, mod->name, mod_loaded);
}
//
// fill it in
//
@ -1328,7 +1366,7 @@ RE_BeginRegistration (char *model)
flushmap = ri.Cvar_Get ("flushmap", "0", 0);
if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
Mod_Free (&mod_known[0]);
r_worldmodel = Mod_ForName(fullname, true);
r_worldmodel = Mod_ForName(fullname, NULL, true);
r_viewcluster = -1;
}
@ -1343,7 +1381,7 @@ struct model_s *RE_RegisterModel (char *name)
{
model_t *mod;
mod = Mod_ForName (name, false);
mod = Mod_ForName (name, r_worldmodel, false);
if (mod)
{
int i;
@ -1379,6 +1417,32 @@ struct model_s *RE_RegisterModel (char *name)
return mod;
}
static qboolean
Mod_HasFreeSpace(void)
{
int i, used;
model_t *mod;
used = 0;
for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
{
if (!mod->name[0])
continue;
if (mod->registration_sequence == registration_sequence)
{
used ++;
}
}
if (mod_max < used)
{
mod_max = used;
}
// should same size of free slots as currently used
return (mod_loaded + mod_max) < MAX_MOD_KNOWN;
}
/*
=====================
@ -1391,6 +1455,12 @@ void RE_EndRegistration (void)
int i;
model_t *mod;
if (Mod_HasFreeSpace() && Vk_ImageHasFreeSpace())
{
// should be enough space for load next maps
return;
}
for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
{
if (!mod->name[0])