- fixed texture layer management so that each material layer can decide for itself if it wants to allow upscaling.

- rewrote the hardware texture precacher to use the new texture management to properly track the data to delete.
This commit is contained in:
Christoph Oelckers 2020-04-19 10:08:24 +02:00
parent cedc95c2a5
commit b2281c38e1
20 changed files with 190 additions and 135 deletions

View file

@ -145,7 +145,7 @@ public:
bool isFullbrightDisabled() const { return !!(flags & GTexf_DisableFullbrightSprites); }
bool isFullbright() const { return !!(flags & GTexf_RenderFullbright); }
bool isFullNameTexture() const { return !!(flags & GTexf_FullNameTexture); }
bool expandSprites() const { return !!expandSprite; }
bool expandSprites() { return expandSprite == -1? ShouldExpandSprite() : !!expandSprite; }
bool useWorldPanning() const { return !!(flags & GTexf_WorldPanning); }
void SetWorldPanning(bool on) { if (on) flags |= GTexf_WorldPanning; else flags &= ~GTexf_WorldPanning; }
bool allowNoDecals() const { return !!(flags & GTexf_NoDecals); }
@ -269,6 +269,19 @@ public:
void CleanHardwareData(bool full = true);
void GetLayers(TArray<FTexture*>& layers)
{
layers.Clear();
for (auto tex : { Base.get(), Brightmap.get(), Detailmap.get(), Glowmap.get(), Normal.get(), Specular.get(), Metallic.get(), Roughness.get(), AmbientOcclusion.get() })
{
if (tex != nullptr) layers.Push(tex);
}
for (auto& tex : CustomShaderTextures)
{
if (tex != nullptr) layers.Push(tex.get());
}
}
};
inline FGameTexture* MakeGameTexture(FTexture* tex, const char *name, ETextureType useType)

View file

@ -41,7 +41,8 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
{
mShaderIndex = SHADER_Default;
sourcetex = tx;
imgtex = tx->GetTexture();
auto imgtex = tx->GetTexture();
mTextureLayers.Push({ imgtex, scaleflags });
if (tx->GetUseType() == ETextureType::SWCanvas && static_cast<FWrapperTexture*>(imgtex)->GetColorFormat() == 0)
{
@ -66,7 +67,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
{
for (auto &texture : { tx->Normal.get(), tx->Specular.get() })
{
mTextureLayers.Push(texture);
mTextureLayers.Push({ texture, 0 });
}
mShaderIndex = SHADER_Specular;
}
@ -74,7 +75,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
{
for (auto &texture : { tx->Normal.get(), tx->Metallic.get(), tx->Roughness.get(), tx->AmbientOcclusion.get() })
{
mTextureLayers.Push(texture);
mTextureLayers.Push({ texture, 0 });
}
mShaderIndex = SHADER_PBR;
}
@ -84,30 +85,30 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
auto placeholder = TexMan.GameByIndex(1);
if (tx->Brightmap.get())
{
mTextureLayers.Push(tx->Brightmap.get());
mTextureLayers.Push({ tx->Brightmap.get(), scaleflags });
mLayerFlags |= TEXF_Brightmap;
}
else
{
mTextureLayers.Push(placeholder->GetTexture());
mTextureLayers.Push({ placeholder->GetTexture(), 0 });
}
if (tx->Detailmap.get())
{
mTextureLayers.Push(tx->Detailmap.get());
mTextureLayers.Push({ tx->Detailmap.get(), 0 });
mLayerFlags |= TEXF_Detailmap;
}
else
{
mTextureLayers.Push(placeholder->GetTexture());
mTextureLayers.Push({ placeholder->GetTexture(), 0 });
}
if (tx->Glowmap.get())
{
mTextureLayers.Push(tx->Glowmap.get());
mTextureLayers.Push({ tx->Glowmap.get(), scaleflags });
mLayerFlags |= TEXF_Glowmap;
}
else
{
mTextureLayers.Push(placeholder->GetTexture());
mTextureLayers.Push({ placeholder->GetTexture(), 0 });
}
auto index = tx->GetShaderIndex();
@ -119,7 +120,7 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags)
for (auto &texture : tx->CustomShaderTextures)
{
if (texture == nullptr) continue;
mTextureLayers.Push(texture.get());
mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable.
}
mShaderIndex = index;
}
@ -149,12 +150,12 @@ FMaterial::~FMaterial()
//
//===========================================================================
IHardwareTexture *FMaterial::GetLayer(int i, int translation, FTexture **pLayer) const
IHardwareTexture *FMaterial::GetLayer(int i, int translation, MaterialLayerInfo **pLayer) const
{
FTexture *layer = i == 0 ? imgtex : mTextureLayers[i - 1];
if (pLayer) *pLayer = layer;
auto &layer = mTextureLayers[i];
if (pLayer) *pLayer = &layer;
if (layer) return layer->GetHardwareTexture(translation, mScaleFlags);
if (layer.layerTexture) return layer.layerTexture->GetHardwareTexture(translation, layer.scaleFlags);
return nullptr;
}
@ -169,7 +170,7 @@ FMaterial * FMaterial::ValidateTexture(FGameTexture * gtex, int scaleflags, bool
{
if (gtex && gtex->isValid())
{
if (!gtex->ShouldExpandSprite()) scaleflags &= ~CTF_Expand;
if (!gtex->expandSprites()) scaleflags &= ~CTF_Expand;
FMaterial *hwtex = gtex->Material[scaleflags];
if (hwtex == NULL && create)

View file

@ -8,6 +8,12 @@
struct FRemapTable;
class IHardwareTexture;
struct MaterialLayerInfo
{
FTexture* layerTexture;
int scaleFlags;
};
//===========================================================================
//
// this is the material class for OpenGL.
@ -17,14 +23,13 @@ class IHardwareTexture;
class FMaterial
{
private:
TArray<FTexture*> mTextureLayers;
TArray<MaterialLayerInfo> mTextureLayers; // the only layers allowed to scale are the brightmap and the glowmap.
int mShaderIndex;
int mLayerFlags = 0;
int mScaleFlags;
public:
FGameTexture *sourcetex; // the owning texture.
FTexture* imgtex; // the first layer's texture image - should be moved into the array
FMaterial(FGameTexture *tex, int scaleflags);
virtual ~FMaterial();
@ -37,27 +42,22 @@ public:
{
return sourcetex;
}
FTexture* BaseLayer() const
void AddTextureLayer(FTexture *tex, bool allowscale)
{
// Only for spftpoly!
return imgtex;
}
void AddTextureLayer(FTexture *tex)
{
//ValidateTexture(tex, false);
mTextureLayers.Push(tex);
mTextureLayers.Push({ tex, allowscale });
}
int GetLayers() const
int NumLayers() const
{
return mTextureLayers.Size() + 1;
return mTextureLayers.Size();
}
IHardwareTexture *GetLayer(int i, int translation, FTexture **pLayer = nullptr) const;
IHardwareTexture *GetLayer(int i, int translation, MaterialLayerInfo **pLayer = nullptr) const;
static FMaterial *ValidateTexture(FGameTexture * tex, int scaleflags, bool create = true);
const TArray<FTexture*> &GetLayerArray() const
const TArray<MaterialLayerInfo> &GetLayerArray() const
{
return mTextureLayers;
}

View file

@ -29,6 +29,7 @@ private:
{
IHardwareTexture *hwTexture = nullptr;
int translation = 0;
bool precacheMarker; // This is used to check whether a texture has been hit by the precacher, so that the cleanup code can delete the unneeded ones.
void Delete()
{
@ -40,6 +41,16 @@ private:
{
Delete();
}
void MarkForPrecache(bool on)
{
precacheMarker = on;
}
bool isMarkedForPreache() const
{
return precacheMarker;
}
};
private:
@ -99,25 +110,44 @@ public:
//===========================================================================
//
// Deletes all allocated resources and considers translations
// This will only be called for sprites
//
//===========================================================================
void CleanUnused(SpriteHits &usedtranslations, int scaleflags)
void CleanUnused()
{
if (usedtranslations.CheckKey(0) == nullptr)
for (auto& tt : hwDefTex)
{
hwDefTex[scaleflags].Delete();
if (!tt.isMarkedForPreache()) tt.Delete();
}
for (int i = hwTex_Translated.Size()-1; i>= 0; i--)
{
if (usedtranslations.CheckKey(hwTex_Translated[i].translation & 0xffffff) == nullptr)
auto& tt = hwTex_Translated[i];
if (!tt.isMarkedForPreache())
{
hwTex_Translated.Delete(i);
}
}
}
void UnmarkAll()
{
for (auto& tt : hwDefTex)
{
if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false);
}
for (auto& tt : hwTex_Translated)
{
if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false);
}
}
void MarkForPrecache(int translation, int scaleflags)
{
auto tt = GetTexID(translation, scaleflags);
tt->MarkForPrecache(true);
}
template<class T>
void Iterate(T callback)
{

View file

@ -397,12 +397,6 @@ bool FTexture::DetermineTranslucency()
return !!bTranslucent;
}
void FTexture::CleanHardwareTextures()
{
SystemTextures.Clean();
}
//===========================================================================
//
// the default just returns an empty texture.

View file

@ -226,7 +226,26 @@ public:
IHardwareTexture* GetHardwareTexture(int translation, int scaleflags);
virtual FImageSource *GetImage() const { return nullptr; }
void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly);
void CleanHardwareTextures();
void CleanHardwareTextures()
{
SystemTextures.Clean();
}
void CleanPrecacheMarker()
{
SystemTextures.UnmarkAll();
}
void MarkForPrecache(int translation, int scaleflags)
{
SystemTextures.MarkForPrecache(translation, scaleflags);
}
void CleanUnused()
{
SystemTextures.CleanUnused();
}
int GetWidth() { return Width; }
int GetHeight() { return Height; }