- implemented model precaching.

This commit is contained in:
Christoph Oelckers 2016-05-03 18:14:16 +02:00
parent 534500f36d
commit b6af4677f3
5 changed files with 129 additions and 29 deletions

View file

@ -34,6 +34,7 @@ public:
virtual int FindFrame(const char * name) = 0; virtual int FindFrame(const char * name) = 0;
virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0; virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0;
virtual void BuildVertexBuffer() = 0; virtual void BuildVertexBuffer() = 0;
virtual void AddSkins(BYTE *hitlist) = 0;
void DestroyVertexBuffer() void DestroyVertexBuffer()
{ {
delete mVBuf; delete mVBuf;
@ -155,6 +156,8 @@ public:
virtual int FindFrame(const char * name); virtual int FindFrame(const char * name);
virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0);
virtual void LoadGeometry(); virtual void LoadGeometry();
virtual void AddSkins(BYTE *hitlist);
void UnloadGeometry(); void UnloadGeometry();
void BuildVertexBuffer(); void BuildVertexBuffer();
@ -260,6 +263,7 @@ public:
virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0);
void LoadGeometry(); void LoadGeometry();
void BuildVertexBuffer(); void BuildVertexBuffer();
virtual void AddSkins(BYTE *hitlist);
}; };
struct FVoxelVertexHash struct FVoxelVertexHash
@ -312,6 +316,7 @@ public:
void Initialize(); void Initialize();
virtual int FindFrame(const char * name); virtual int FindFrame(const char * name);
virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0);
virtual void AddSkins(BYTE *hitlist);
FTextureID GetPaletteTexture() const { return mPalette; } FTextureID GetPaletteTexture() const { return mPalette; }
void BuildVertexBuffer(); void BuildVertexBuffer();
float getAspectFactor(); float getAspectFactor();

View file

@ -336,7 +336,22 @@ void FDMDModel::BuildVertexBuffer()
} }
} }
//===========================================================================
//
// for skin precaching
//
//===========================================================================
void FDMDModel::AddSkins(BYTE *hitlist)
{
for (int i = 0; i < info.numSkins; i++)
{
if (skins[i].isValid())
{
hitlist[skins[i].GetIndex()] |= FTexture::TEX_Flat;
}
}
}
//=========================================================================== //===========================================================================
// //

View file

@ -309,6 +309,27 @@ void FMD3Model::BuildVertexBuffer()
} }
//===========================================================================
//
// for skin precaching
//
//===========================================================================
void FMD3Model::AddSkins(BYTE *hitlist)
{
for (int i = 0; i < numSurfaces; i++)
{
MD3Surface * surf = &surfaces[i];
for (int j = 0; j < surf->numSkins; j++)
{
if (surf->skins[j].isValid())
{
hitlist[surf->skins[j].GetIndex()] |= FTexture::TEX_Flat;
}
}
}
}
//=========================================================================== //===========================================================================
// //
// //

View file

@ -397,6 +397,17 @@ void FVoxelModel::BuildVertexBuffer()
} }
//===========================================================================
//
// for skin precaching
//
//===========================================================================
void FVoxelModel::AddSkins(BYTE *hitlist)
{
hitlist[mPalette.GetIndex()] |= FTexture::TEX_Flat;
}
//=========================================================================== //===========================================================================
// //
// //

View file

@ -1019,23 +1019,10 @@ bool FGLInterface::UsesColormap() const
void FGLInterface::PrecacheTexture(FTexture *tex, int cache) void FGLInterface::PrecacheTexture(FTexture *tex, int cache)
{ {
if (tex != NULL) if (cache & (FTextureManager::HIT_Wall | FTextureManager::HIT_Flat | FTextureManager::HIT_Sky))
{ {
if (cache) FMaterial * gltex = FMaterial::ValidateTexture(tex, false);
{ if (gltex) gltex->Precache();
if (gl_precache)
{
if (cache & (FTextureManager::HIT_Wall | FTextureManager::HIT_Flat | FTextureManager::HIT_Sky))
{
FMaterial * gltex = FMaterial::ValidateTexture(tex, false);
if (gltex) gltex->Precache();
}
}
}
else
{
if (tex->gl_info.Material[0]) tex->gl_info.Material[0]->Clean(true);
}
} }
} }
@ -1047,15 +1034,8 @@ void FGLInterface::PrecacheTexture(FTexture *tex, int cache)
void FGLInterface::PrecacheSprite(FTexture *tex, SpriteHits &hits) void FGLInterface::PrecacheSprite(FTexture *tex, SpriteHits &hits)
{ {
if (hits.CountUsed() == 0) FMaterial * gltex = FMaterial::ValidateTexture(tex, true);
{ if (gltex) gltex->PrecacheList(hits);
if (tex->gl_info.Material[1]) tex->gl_info.Material[1]->Clean(true);
}
else
{
FMaterial * gltex = FMaterial::ValidateTexture(tex, true);
if (gltex) gltex->PrecacheList(hits);
}
} }
//========================================================================== //==========================================================================
@ -1070,6 +1050,8 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhit
SpriteHits **spritehitlist = new SpriteHits*[TexMan.NumTextures()]; SpriteHits **spritehitlist = new SpriteHits*[TexMan.NumTextures()];
TMap<PClassActor*, bool>::Iterator it(actorhitlist); TMap<PClassActor*, bool>::Iterator it(actorhitlist);
TMap<PClassActor*, bool>::Pair *pair; TMap<PClassActor*, bool>::Pair *pair;
BYTE *modellist = new BYTE[Models.Size()];
memset(modellist, 0, Models.Size());
memset(spritehitlist, 0, sizeof(SpriteHits**) * TexMan.NumTextures()); memset(spritehitlist, 0, sizeof(SpriteHits**) * TexMan.NumTextures());
// this isn't done by the main code so it needs to be done here first: // this isn't done by the main code so it needs to be done here first:
@ -1095,6 +1077,9 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhit
} }
} }
// Check all used actors.
// 1. mark all sprites associated with its states
// 2. mark all model data and skins associated with its states
while (it.NextPair(pair)) while (it.NextPair(pair))
{ {
PClassActor *cls = pair->Key; PClassActor *cls = pair->Key;
@ -1103,11 +1088,29 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhit
for (int i = 0; i < cls->NumOwnedStates; i++) for (int i = 0; i < cls->NumOwnedStates; i++)
{ {
spritelist[cls->OwnedStates[i].sprite].Insert(gltrans, true); spritelist[cls->OwnedStates[i].sprite].Insert(gltrans, true);
FSpriteModelFrame * smf = gl_FindModelFrame(cls, cls->OwnedStates[i].sprite, cls->OwnedStates[i].Frame, false);
if (smf != NULL)
{
for (int i = 0; i < MAX_MODELS_PER_FRAME; i++)
{
if (smf->skinIDs[i].isValid())
{
texhitlist[smf->skinIDs[i].GetIndex()] |= FTexture::TEX_Flat;
}
else if (smf->modelIDs[i] != -1)
{
Models[smf->modelIDs[i]]->AddSkins(texhitlist);
}
if (smf->modelIDs[i] != -1)
{
modellist[smf->modelIDs[i]] = 1;
}
}
}
} }
} }
// Precache textures (and sprites). // mark all sprite textures belonging to the marked sprites.
for (int i = (int)(sprites.Size() - 1); i >= 0; i--) for (int i = (int)(sprites.Size() - 1); i >= 0; i--)
{ {
if (spritelist[i].CountUsed()) if (spritelist[i].CountUsed())
@ -1129,14 +1132,59 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhit
} }
} }
// delete everything unused before creating any new resources to avoid memory usage peaks.
// delete unused models
for (unsigned i = 0; i < Models.Size(); i++)
{
if (!modellist[i]) Models[i]->DestroyVertexBuffer();
}
// delete unused textures
int cnt = TexMan.NumTextures(); int cnt = TexMan.NumTextures();
for (int i = cnt - 1; i >= 0; i--) for (int i = cnt - 1; i >= 0; i--)
{ {
PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]); FTexture *tex = TexMan.ByIndex(i);
if (spritehitlist[i] != nullptr) PrecacheSprite(TexMan.ByIndex(i), *spritehitlist[i]); if (tex != nullptr)
{
if (!texhitlist[i])
{
if (tex->gl_info.Material[0]) tex->gl_info.Material[0]->Clean(true);
}
if (spritehitlist[i] == nullptr || (*spritehitlist[i]).CountUsed() == 0)
{
if (tex->gl_info.Material[1]) tex->gl_info.Material[1]->Clean(true);
}
}
} }
if (gl_precache)
{
// cache all used textures
for (int i = cnt - 1; i >= 0; i--)
{
FTexture *tex = TexMan.ByIndex(i);
if (tex != nullptr)
{
PrecacheTexture(tex, texhitlist[i]);
if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CountUsed() > 0)
{
PrecacheSprite(tex, *spritehitlist[i]);
}
}
}
// cache all used models
for (unsigned i = 0; i < Models.Size(); i++)
{
if (modellist[i])
Models[i]->BuildVertexBuffer();
}
}
delete[] spritehitlist; delete[] spritehitlist;
delete[] spritelist; delete[] spritelist;
delete[] modellist;
} }