Fix up texture precaching + add Opengl texture precaching #160

Merged
alufolie91 merged 18 commits from oglprecache into Saturn-Next 2025-04-23 10:28:23 +02:00
11 changed files with 396 additions and 65 deletions

No files matched your search

+1 -5
View File
@@ -2968,9 +2968,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
CON_LogMessage(M_GetText("Speeding off to level...\n"));
}
if (demo.playback && !demo.timing)
precache = false;
if (resetplayer)
{
if (!FLS || (netgame || multiplayer))
@@ -2986,8 +2983,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING;
demo.savebutton = 0;
G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene);
if (demo.playback && !demo.timing)
precache = true;
if (demo.timing)
G_DoneLevelLoad();
-3
View File
@@ -541,9 +541,6 @@ extern FILE *debugfile;
extern INT32 debugload;
#endif
// if true, load all graphics at level load
extern boolean precache;
// wipegamestate can be set to -1
// to force a wipe on the next draw
extern gamestate_t wipegamestate;
-2
View File
@@ -330,8 +330,6 @@ static struct {
// There is no conflict here.
demoghost *ghosts = NULL;
boolean precache = true; // if true, load all graphics at start
INT16 prevmap, nextmap;
// save if director is enabled
+257
View File
@@ -29,6 +29,9 @@
#include "../r_draw.h"
#include "../r_main.h"
#include "../r_patch.h" // patch rotation
#include "../p_setup.h" // levelflats
#include "../p_spec.h" // anim_t
#include "../r_sky.h"
INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes
INT32 textureformat = GL_TEXFMT_P_8; // use chromakey for hole
@@ -546,6 +549,260 @@ void HWR_FreeTextureCache(void)
gl_numtextures = 0;
}
static void HWR_PrecacheLevelFlats(void)
{
levelflat_t levelflat;
lumpnum_t lump;
size_t i, j;
INT32 k;
// special case for encore
#ifdef GLENCORE
if (encoremode)
{
// go through all sectors to determine if it should be remapped for encore
for (i = 0; i < numsectors; i++)
{
sector_t *sec = &sectors[i];
// sector checked already?
if (sec->validcount == validcount)
continue;
sec->validcount = validcount;
// gotta check sector floor and ceiling
for (j = 0; j < 2; j++)
{
const boolean ceiling = (j == 1);
INT32 pic = ceiling ? sec->ceilingpic : sec->floorpic;
levelflat = levelflats[pic];
lump = levelflat.lumpnum;
HWR_GetFlat(lump, R_NoEncore(sec, ceiling));
if (levelflat.speed) // it is an animated flat
{
for (k = 1; k < levelflat.numpics; k++)
{
lump = levelflat.baselumpnum + k;
HWR_GetFlat(lump, R_NoEncore(sec, ceiling));
}
}
}
}
}
else
#endif
{
// on non encore we have it simple
// just load every flat in the level
for (i = 0; i < numlevelflats; i++)
{
levelflat = levelflats[i];
lump = levelflat.lumpnum;
HWR_GetFlat(lump, false);
if (levelflat.speed) // it is an animated flat
{
for (k = 1; k < levelflat.numpics; k++)
{
lump = levelflat.baselumpnum + k;
HWR_GetFlat(lump, false);
}
}
}
}
}
static void HWR_PrecacheLevelTextures(void)
{
char *texturepresent;
anim_t *anim;
size_t i, j;
INT32 h;
texturepresent = calloc(numtextures, sizeof (*texturepresent));
if (texturepresent == NULL) I_Error("%s: Out of memory looking up textures", "HWR_PrecacheLevel");
for (i = 0; i < numlines; i++)
{
line_t *line = &lines[i];
#ifdef GLENCORE
const int noencoremap = ((line->flags & ML_TFERLINE) ? 2 : 1);
#else
const int noencoremap = 1;
#endif
// line checked already?
if (line->validcount == validcount)
continue;
line->validcount = validcount;
// two sides
for (j = 0; j < 2; j++)
{
side_t *side = &sides[line->sidenum[j]];
// Single-side linedef
if (line->sidenum[j] == 0xffff)
continue;
if (side->toptexture >= 0 && side->toptexture < numtextures)
{
texturepresent[side->toptexture] = 1|noencoremap;
}
if (side->midtexture >= 0 && side->midtexture < numtextures)
{
texturepresent[side->midtexture] = 1|noencoremap;
}
if (side->bottomtexture >= 0 && side->bottomtexture < numtextures)
{
texturepresent[side->bottomtexture] = 1|noencoremap;
}
}
}
// check for animated textures
for (anim = anims; anim < lastanim; anim++)
{
if (!anim->istexture)
continue;
const char texpresent = texturepresent[anim->basepic];
if (!texpresent)
continue;
if (texpresent & 1)
{
for (h = 1; h < anim->numpics; h++)
{
HWR_GetTexture(anim->basepic+h, false);
}
}
#ifdef GLENCORE
if (texpresent & 2)
{
for (h = 1; h < anim->numpics; h++)
{
HWR_GetTexture(anim->basepic+h, true);
}
}
#endif
}
// Sky texture is always present.
// Note that F_SKY1 is the name used to indicate a sky floor/ceiling as a flat,
// while the sky texture is stored like a wall texture, with a skynum dependent name.
texturepresent[skytexture] = 1;
for (i = 0; i < (unsigned)numtextures; i++)
{
const char texpresent = texturepresent[i];
if (!texpresent)
continue;
if (texpresent & 1)
{
HWR_GetTexture(i, false);
}
#ifdef GLENCORE
if (texpresent & 2)
{
HWR_GetTexture(i, true);
}
#endif
}
free(texturepresent);
}
static void HWR_PrecacheLevelSprites(void)
{
GLPatch_t *spritepatch;
char *spritepresent;
size_t i, j, k;
lumpnum_t lump;
thinker_t *th;
mobj_t *mo;
spriteframe_t *sf;
spritepresent = calloc(numsprites, sizeof (*spritepresent));
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "HWR_PrecacheLevel");
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
// ogl is weird
// for some reason it does not want to preload sprites with colormaps
// so just save us the work
if (mo->color || mo->colorized)
continue;
spritepresent[mo->sprite] = 1;
}
for (i = 0; i < numsprites; i++)
{
if (!spritepresent[i])
continue;
for (j = 0; j < sprites[i].numframes; j++)
{
sf = &sprites[i].spriteframes[j];
#define cacheang(a) {\
lump = sf->lumppat[a];\
spritepatch = (GLPatch_t *)W_CachePatchNum(lump, PU_CACHE);\
if (spritepatch != NULL)\
HWR_GetPatch(spritepatch);\
}
// see R_InitSprites for more about lumppat,lumpid
switch (sf->rotate)
{
case SRF_SINGLE:
cacheang(0);
break;
case SRF_2D:
cacheang(2);
cacheang(6);
break;
default:
k = 8;
while (k--)
cacheang(k);
break;
}
#undef cacheang
}
}
free(spritepresent);
}
void HWR_PrecacheLevel(void)
{
if (rendermode != render_opengl)
return;
// Precache flats.
HWR_PrecacheLevelFlats();
// Precache textures.
HWR_PrecacheLevelTextures();
// Precache sprites.
HWR_PrecacheLevelSprites();
}
void HWR_LoadTextures(size_t pnumtextures)
{
// we must free it since numtextures changed
+4 -1
View File
@@ -49,13 +49,16 @@ typedef struct gl_vissprite_s
extern extrasubsector_t *extrasubsectors;
extern size_t addsubsector;
void HWR_FreeExtraSubsectors(void);
// --------
// hw_cache.c
// --------
void HWR_InitTextureCache(void);
void HWR_FreeTextureCache(void);
void HWR_FreeMipmapCache(void);
void HWR_FreeExtraSubsectors(void);
void HWR_PrecacheLevel(void);
void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap);
// ^ some flats must NOT be remapped to encore, since we remap them as we cache them for ease, adding a toggle here seems wise.
+18 -2
View File
@@ -586,16 +586,30 @@ levelflat_t *levelflats;
//SoM: Other files want this info.
size_t P_PrecacheLevelFlats(void)
{
levelflat_t levelflat;
lumpnum_t lump;
size_t i, flatmem = 0;
INT32 k;
//SoM: 4/18/2000: New flat code to make use of levelflats.
for (i = 0; i < numlevelflats; i++)
{
lump = levelflats[i].lumpnum;
levelflat = levelflats[i];
lump = levelflat.lumpnum;
if (devparm)
flatmem += W_LumpLength(lump);
R_GetFlat(lump);
if (levelflat.speed) // it is an animated flat
{
for (k = 1; k < levelflat.numpics; k++)
{
lump = levelflat.baselumpnum + k;
if (devparm)
flatmem += W_LumpLength(lump);
R_GetFlat(lump);
}
}
}
return flatmem;
@@ -624,6 +638,7 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->baselumpnum = LUMPERROR;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
@@ -668,6 +683,7 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
// store the flat lump number
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->baselumpnum = LUMPERROR;
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
@@ -2970,7 +2986,7 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate)
if (rendermode != render_none && !reloadinggamestate)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
if (precache || dedicated)
if (cv_precachetextures.value)
R_PrecacheLevel();
nextmapoverride = 0;
+2 -15
View File
@@ -51,19 +51,6 @@ mobj_t *skyboxmo[2];
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
#define MAXFLATSIZE (2048<<FRACBITS)
/** Animated texture descriptor
* This keeps track of an animated texture or an animated flat.
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
*/
typedef struct
{
SINT8 istexture; ///< ::true for a texture, ::false for a flat
INT32 picnum; ///< The end flat number
INT32 basepic; ///< The start flat number
INT32 numpics; ///< Number of frames in the animation
tic_t speed; ///< Number of tics for which each frame is shown
} anim_t;
#if defined(_MSC_VER)
#pragma pack(1)
#endif
@@ -113,8 +100,8 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer);
//SoM: 3/7/2000: New sturcture without limits.
static anim_t *lastanim;
static anim_t *anims = NULL; /// \todo free leak
anim_t *lastanim;
anim_t *anims = NULL; /// \todo free leak
static size_t maxanims;
//
+16
View File
@@ -25,6 +25,22 @@ extern mobj_t *skyboxmo[2];
//
#define GETSECSPECIAL(i,j) ((i >> ((j-1)*4))&15)
/** Animated texture descriptor
* This keeps track of an animated texture or an animated flat.
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
*/
typedef struct
{
SINT8 istexture; ///< ::true for a texture, ::false for a flat
INT32 picnum; ///< The end flat number
INT32 basepic; ///< The start flat number
INT32 numpics; ///< Number of frames in the animation
tic_t speed; ///< Number of tics for which each frame is shown
} anim_t;
extern anim_t *lastanim;
extern anim_t *anims;
// at game start
void P_InitPicAnims(void);
+92 -37
View File
@@ -1618,33 +1618,13 @@ INT32 R_TextureNumForName(const char *name)
return i;
}
//
// R_PrecacheLevel
//
// Preloads all relevant graphics for the level.
//
void R_PrecacheLevel(void)
static void R_PrecacheLevelTextures(void)
{
char *texturepresent, *spritepresent;
size_t i, j, k;
lumpnum_t lump;
char *texturepresent;
anim_t *anim;
size_t j;
INT32 h;
thinker_t *th;
spriteframe_t *sf;
if (demo.playback)
return;
// do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap()
if (rendermode != render_soft)
return;
// Precache flats.
flatmemory = P_PrecacheLevelFlats();
//
// Precache textures.
//
// no need to precache all software textures in 3D mode
// (note they are still used with the reference software view)
texturepresent = calloc(numtextures, sizeof (*texturepresent));
@@ -1661,6 +1641,22 @@ void R_PrecacheLevel(void)
texturepresent[sides[j].bottomtexture] = 1;
}
// check for animated textures
for (anim = anims; anim < lastanim; anim++)
{
if (!anim->istexture)
continue;
if (!texturepresent[anim->basepic])
continue;
for (h = 1; h < anim->numpics; h++)
{
if (!texturecache[anim->basepic+h])
R_GenerateTexture(anim->basepic+h);
}
}
// Sky texture is always present.
// Note that F_SKY1 is the name used to indicate a sky floor/ceiling as a flat,
// while the sky texture is stored like a wall texture, with a skynum dependent name.
@@ -1678,16 +1674,27 @@ void R_PrecacheLevel(void)
// since we cache entire composite textures
}
free(texturepresent);
}
static void R_PrecacheLevelSprites(void)
{
char *spritepresent;
size_t i, j, k;
lumpnum_t lump;
thinker_t *th;
spriteframe_t *sf;
//
// Precache sprites.
//
spritepresent = calloc(numsprites, sizeof (*spritepresent));
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel");
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
spritepresent[((mobj_t *)th)->sprite] = 1;
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
spritepresent[((mobj_t *)th)->sprite] = 1;
}
spritememory = 0;
for (i = 0; i < numsprites; i++)
@@ -1698,17 +1705,65 @@ void R_PrecacheLevel(void)
for (j = 0; j < sprites[i].numframes; j++)
{
sf = &sprites[i].spriteframes[j];
for (k = 0; k < 8; k++)
{
// see R_InitSprites for more about lumppat,lumpid
lump = sf->lumppat[k];
if (devparm)
spritememory += W_LumpLength(lump);
W_CachePatchNum(lump, PU_CACHE);
#define cacheang(a) {\
lump = sf->lumppat[a];\
if (devparm)\
spritememory += W_LumpLength(lump);\
W_CachePatchNum(lump, PU_CACHE);\
}
// see R_InitSprites for more about lumppat,lumpid
switch (sf->rotate)
{
case SRF_SINGLE:
cacheang(0);
break;
case SRF_2D:
cacheang(2);
cacheang(6);
break;
default:
k = 8;
while (k--)
cacheang(k);
break;
}
#undef cacheang
}
}
free(spritepresent);
}
//
// R_PrecacheLevel
//
// Preloads all relevant graphics for the level.
//
void R_PrecacheLevel(void)
{
// do not flush the memory, Z_Malloc twice with same user will cause error in Z_CheckHeap()
if (rendermode == render_none)
return;
if (demo.playback)
return;
#ifdef HWRENDER
if (rendermode == render_opengl)
{
HWR_PrecacheLevel();
return;
}
#endif
// Precache flats.
flatmemory = P_PrecacheLevelFlats();
// Precache textures.
R_PrecacheLevelTextures();
// Precache sprites.
R_PrecacheLevelSprites();
// FIXME: this is no longer correct with OpenGL render mode
CONS_Debug(DBG_SETUP, "Precache level done:\n"
+5
View File
@@ -164,6 +164,9 @@ static void Precipstuff_OnChange(void);
consvar_t cv_tailspickup = {"tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// if enabled, load all graphics at level load
consvar_t cv_precachetextures = {"precachetextures", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS] = {
{"chasecam", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL},
{"chasecam2", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL},
@@ -1532,6 +1535,8 @@ void R_RegisterEngineStuff(void)
if (dedicated)
return;
CV_RegisterVar(&cv_precachetextures);
CV_RegisterVar(&cv_translucency);
CV_RegisterVar(&cv_drawdist);
CV_RegisterVar(&cv_drawdist_precip);
+1
View File
@@ -174,6 +174,7 @@ extern ps_metric_t ps_numpolyobjects;
// REFRESH - the actual rendering functions.
//
extern consvar_t cv_precachetextures;
extern consvar_t cv_showhud, cv_translucenthud, cv_uncappedhud;
extern consvar_t cv_homremoval;
extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS];