Browse Source

ref: Improve model unloading, fix texture leak

pull/2/head
mittorn 6 years ago
parent
commit
8339096ad8
  1. 4
      engine/client/cl_game.c
  2. 4
      engine/client/cl_parse.c
  3. 6
      engine/client/ref_common.c
  4. 36
      engine/common/mod_bmodel.c
  5. 2
      engine/common/mod_local.h
  6. 26
      engine/common/mod_sprite.c
  7. 19
      engine/common/mod_studio.c
  8. 30
      engine/common/model.c
  9. 3
      engine/ref_api.h
  10. 17
      ref_gl/gl_alias.c
  11. 62
      ref_gl/gl_context.c
  12. 5
      ref_gl/gl_local.h
  13. 4
      ref_gl/gl_sprite.c
  14. 2
      ref_gl/gl_studio.c

4
engine/client/cl_game.c

@ -1226,7 +1226,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
else else
{ {
Con_Reportf( S_ERROR "Could not load HUD sprite %s\n", szSpriteName ); Con_Reportf( S_ERROR "Could not load HUD sprite %s\n", szSpriteName );
ref.dllFuncs.Mod_UnloadModel( m_pSprite ); Mod_FreeModel( m_pSprite );
return false; return false;
} }
} }
@ -1242,7 +1242,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
if( !loaded ) if( !loaded )
{ {
ref.dllFuncs.Mod_UnloadModel( m_pSprite ); Mod_FreeModel( m_pSprite );
return false; return false;
} }

4
engine/client/cl_parse.c

@ -1561,7 +1561,7 @@ void CL_RegisterResources( sizebuf_t *msg )
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ ) for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{ {
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name )) if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
ref.dllFuncs.Mod_UnloadModel( mod ); Mod_FreeModel( mod );
} }
Mod_FreeUnused (); Mod_FreeUnused ();
@ -3145,7 +3145,7 @@ void CL_LegacyPrecache_f( void )
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ ) for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{ {
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name )) if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
ref.dllFuncs.Mod_UnloadModel( mod ); Mod_FreeModel( mod );
} }
// Mod_FreeUnused (); // Mod_FreeUnused ();

6
engine/client/ref_common.c

@ -403,6 +403,7 @@ static void R_UnloadProgs( void )
ref.hInstance = NULL; ref.hInstance = NULL;
memset( &refState, 0, sizeof( refState )); memset( &refState, 0, sizeof( refState ));
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG ); Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
Cmd_Unlink( CMD_REFDLL ); Cmd_Unlink( CMD_REFDLL );
@ -507,10 +508,13 @@ void R_Shutdown( void )
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ ) for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{ {
if( !mod->name[0] ) continue; if( !mod->name[0] ) continue;
Mod_UnloadSpriteModel( mod ); Mod_FreeModel( mod );
} }
memset( clgame.sprites, 0, sizeof( clgame.sprites )); memset( clgame.sprites, 0, sizeof( clgame.sprites ));
// correctly free all models before render unload
// change this if need add online render changing
Mod_FreeAll();
R_UnloadProgs(); R_UnloadProgs();
ref.initialized = false; ref.initialized = false;
} }

36
engine/common/mod_bmodel.c

@ -2797,42 +2797,6 @@ void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded )
if( loaded ) *loaded = true; // all done if( loaded ) *loaded = true; // all done
} }
/*
=================
Mod_UnloadBrushModel
Release all uploaded textures
=================
*/
void Mod_UnloadBrushModel( model_t *mod )
{
texture_t *tx;
int i;
Assert( mod != NULL );
if( mod->type != mod_brush )
return; // not a bmodel
if( mod->name[0] != '*' )
{
#ifndef XASH_DEDICATED
for( i = 0; i < mod->numtextures; i++ )
{
tx = mod->textures[i];
if( !tx || tx->gl_texturenum == ref.dllFuncs.R_GetBuiltinTexture( REF_DEFAULT_TEXTURE ) )
continue; // free slot
ref.dllFuncs.GL_FreeTexture( tx->gl_texturenum ); // main texture
ref.dllFuncs.GL_FreeTexture( tx->fb_texturenum ); // luma texture
}
#endif
Mem_FreePool( &mod->mempool );
}
memset( mod, 0, sizeof( *mod ));
}
/* /*
================== ==================
Mod_CheckLump Mod_CheckLump

2
engine/common/mod_local.h

@ -118,6 +118,7 @@ extern convar_t *r_showhull;
// model.c // model.c
// //
void Mod_Init( void ); void Mod_Init( void );
void Mod_FreeModel( model_t *mod );
void Mod_FreeAll( void ); void Mod_FreeAll( void );
void Mod_Shutdown( void ); void Mod_Shutdown( void );
void Mod_ClearUserData( void ); void Mod_ClearUserData( void );
@ -189,7 +190,6 @@ void Mod_ClearStudioCache( void );
// mod_sprite.c // mod_sprite.c
// //
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ); void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
void Mod_UnloadSpriteModel( model_t *mod );
#endif #endif
#endif//MOD_LOCAL_H #endif//MOD_LOCAL_H

26
engine/common/mod_sprite.c

@ -113,29 +113,3 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
ref.dllFuncs.Mod_LoadModel( mod_sprite, mod, buffer, loaded, texFlags ); ref.dllFuncs.Mod_LoadModel( mod_sprite, mod, buffer, loaded, texFlags );
#endif #endif
} }
/*
====================
Mod_UnloadSpriteModel
release sprite model and frames
====================
*/
void Mod_UnloadSpriteModel( model_t *mod )
{
Assert( mod != NULL );
if( mod->type == mod_sprite )
{
#ifndef XASH_DEDICATED
if( host.type != HOST_DEDICATED )
{
ref.dllFuncs.Mod_UnloadModel( mod );
}
#endif
Mem_FreePool( &mod->mempool );
memset( mod, 0, sizeof( *mod ));
}
}

19
engine/common/mod_studio.c

@ -1139,25 +1139,6 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
if( loaded ) *loaded = true; if( loaded ) *loaded = true;
} }
/*
=================
Mod_UnloadStudioModel
=================
*/
void Mod_UnloadStudioModel( model_t *mod )
{
Assert( mod != NULL );
if( mod->type != mod_studio )
return; // not a studio
if( Host_IsDedicated() )
ref.dllFuncs.Mod_StudioUnloadTextures( mod->cache.data );
Mem_FreePool( &mod->mempool );
memset( mod, 0, sizeof( *mod ));
}
static sv_blending_interface_t gBlendAPI = static sv_blending_interface_t gBlendAPI =
{ {
SV_BLENDING_INTERFACE_VERSION, SV_BLENDING_INTERFACE_VERSION,

30
engine/common/model.c

@ -102,37 +102,21 @@ static void Mod_FreeUserData( model_t *mod )
Mod_FreeModel Mod_FreeModel
================ ================
*/ */
static void Mod_FreeModel( model_t *mod ) void Mod_FreeModel( model_t *mod )
{ {
// already freed? // already freed?
if( !mod || !mod->name[0] ) if( !mod || !mod->name[0] )
return; return;
if( mod->name[0] != '*' ) if( mod->type != mod_brush || mod->name[0] != '*' )
Mod_FreeUserData( mod );
// notify renderer about unloading
if( ref.dllFuncs.Mod_UnloadModel )
ref.dllFuncs.Mod_UnloadModel( mod );
switch( mod->type )
{ {
case mod_studio: Mod_FreeUserData( mod );
Mod_UnloadStudioModel( mod ); #ifndef XASH_DEDICATED
break; ref.dllFuncs.Mod_UnloadTextures( mod );
case mod_alias: #endif
// REFTODO: Mem_FreePool( &mod->mempool );
// Mod_UnloadAliasModel( mod );
break;
case mod_sprite:
Mod_UnloadSpriteModel( mod );
break;
case mod_brush:
Mod_UnloadBrushModel( mod );
break;
} }
memset( mod, 0, sizeof( *mod )); memset( mod, 0, sizeof( *mod ));
} }

3
engine/ref_api.h

@ -520,9 +520,8 @@ typedef struct ref_interface_s
// flags ignored for everything except spritemodels // flags ignored for everything except spritemodels
void (*Mod_LoadModel)( modtype_t desiredType, model_t *mod, const byte *buf, qboolean *loaded, int flags ); void (*Mod_LoadModel)( modtype_t desiredType, model_t *mod, const byte *buf, qboolean *loaded, int flags );
void (*Mod_LoadMapSprite)( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded ); void (*Mod_LoadMapSprite)( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded );
void (*Mod_UnloadModel)( model_t *mod ); void (*Mod_UnloadTextures)( model_t *mod );
void (*Mod_StudioLoadTextures)( model_t *mod, void *data ); void (*Mod_StudioLoadTextures)( model_t *mod, void *data );
void (*Mod_StudioUnloadTextures)( void *data );
// efx implementation // efx implementation
void (*CL_DrawParticles)( double frametime, particle_t *particles, float partsize ); void (*CL_DrawParticles)( double frametime, particle_t *particles, float partsize );

17
ref_gl/gl_alias.c

@ -729,22 +729,12 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
if( loaded ) *loaded = true; // done if( loaded ) *loaded = true; // done
} }
/* void Mod_AliasUnloadTextures( void *data )
=================
Mod_UnloadAliasModel
=================
*/
void Mod_UnloadAliasModel( model_t *mod )
{ {
aliashdr_t *palias; aliashdr_t *palias;
int i, j; int i, j;
Assert( mod != NULL ); palias = data;
if( mod->type != mod_alias )
return; // not an alias
palias = mod->cache.data;
if( !palias ) return; // already freed if( !palias ) return; // already freed
for( i = 0; i < MAX_SKINS; i++ ) for( i = 0; i < MAX_SKINS; i++ )
@ -758,9 +748,6 @@ void Mod_UnloadAliasModel( model_t *mod )
GL_FreeTexture( palias->fb_texturenum[i][j] ); GL_FreeTexture( palias->fb_texturenum[i][j] );
} }
} }
Mem_FreePool( &mod->mempool );
memset( mod, 0, sizeof( *mod ));
} }
/* /*

62
ref_gl/gl_context.c

@ -164,26 +164,6 @@ static void Mod_LoadModel( modtype_t desiredType, model_t *mod, const byte *buf,
} }
} }
static void Mod_UnloadModel( model_t *mod )
{
switch( mod->type )
{
case mod_studio:
// Mod_UnloadStudioModel( mod );
break;
case mod_alias:
Mod_UnloadAliasModel( mod );
break;
case mod_brush:
// Mod_UnloadBrushModel( mod );
break;
case mod_sprite:
Mod_UnloadSpriteModel( mod );
break;
default: gEngfuncs.Host_Error( "Mod_UnloadModel: unsupported type %d\n", mod->type );
}
}
static int GL_RenderGetParm( int parm, int arg ) static int GL_RenderGetParm( int parm, int arg )
{ {
gl_texture_t *glt; gl_texture_t *glt;
@ -320,6 +300,45 @@ const byte *GL_TextureData( unsigned int texnum )
return NULL; return NULL;
} }
void Mod_BrushUnloadTextures( model_t *mod )
{
int i;
for( i = 0; i < mod->numtextures; i++ )
{
texture_t *tx = mod->textures[i];
if( !tx || tx->gl_texturenum == tr.defaultTexture )
continue; // free slot
GL_FreeTexture( tx->gl_texturenum ); // main texture
GL_FreeTexture( tx->fb_texturenum ); // luma texture
}
}
void Mod_UnloadTextures( model_t *mod )
{
int i, j;
Assert( mod != NULL );
switch( mod->type )
{
case mod_studio:
Mod_StudioUnloadTextures( mod->cache.data );
break;
case mod_alias:
Mod_AliasUnloadTextures( mod->cache.data );
break;
case mod_brush:
Mod_BrushUnloadTextures( mod );
break;
case mod_sprite:
Mod_SpriteUnloadTextures( mod->cache.data );
break;
default: gEngfuncs.Host_Error( "Mod_UnloadModel: unsupported type %d\n", mod->type );
}
}
ref_interface_t gReffuncs = ref_interface_t gReffuncs =
{ {
R_Init, R_Init,
@ -390,9 +409,8 @@ ref_interface_t gReffuncs =
Mod_LoadModel, Mod_LoadModel,
Mod_LoadMapSprite, Mod_LoadMapSprite,
Mod_UnloadModel, Mod_UnloadTextures,
Mod_StudioLoadTextures, Mod_StudioLoadTextures,
Mod_StudioUnloadTextures,
CL_DrawParticles, CL_DrawParticles,
CL_DrawTracers, CL_DrawTracers,

5
ref_gl/gl_local.h

@ -541,10 +541,9 @@ int R_WorldToScreen( const vec3_t point, vec3_t screen );
void R_ScreenToWorld( const vec3_t screen, vec3_t point ); void R_ScreenToWorld( const vec3_t screen, vec3_t point );
qboolean R_AddEntity( struct cl_entity_s *pRefEntity, int entityType ); qboolean R_AddEntity( struct cl_entity_s *pRefEntity, int entityType );
void Mod_LoadMapSprite( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded ); void Mod_LoadMapSprite( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded );
void Mod_UnloadSpriteModel( struct model_s *mod ); void Mod_SpriteUnloadTextures( void *data );
void Mod_UnloadStudioModel( struct model_s *mod );
void Mod_UnloadBrushModel( struct model_s *mod );
void Mod_UnloadAliasModel( struct model_s *mod ); void Mod_UnloadAliasModel( struct model_s *mod );
void Mod_AliasUnloadTextures( void *data );
void GL_SetRenderMode( int mode ); void GL_SetRenderMode( int mode );
void R_RunViewmodelEvents( void ); void R_RunViewmodelEvents( void );
void R_DrawViewModel( void ); void R_DrawViewModel( void );

4
ref_gl/gl_sprite.c

@ -356,14 +356,14 @@ Mod_UnloadSpriteModel
release sprite model and frames release sprite model and frames
==================== ====================
*/ */
void Mod_UnloadSpriteModel( model_t *mod ) void Mod_SpriteUnloadTextures( void *data )
{ {
msprite_t *psprite; msprite_t *psprite;
mspritegroup_t *pspritegroup; mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe; mspriteframe_t *pspriteframe;
int i, j; int i, j;
psprite = mod->cache.data; psprite = data;
if( psprite ) if( psprite )
{ {

2
ref_gl/gl_studio.c

@ -3584,7 +3584,7 @@ void Mod_StudioLoadTextures( model_t *mod, void *data )
/* /*
================= =================
Mod_StudioLoadTextures Mod_StudioUnloadTextures
================= =================
*/ */
void Mod_StudioUnloadTextures( void *data ) void Mod_StudioUnloadTextures( void *data )

Loading…
Cancel
Save