- optimized storage for animation definitions.

Instead of allocating everything on the heap as single blocks, use a value TArray and allocate the frame arrays from the texture manager's memory arena, since lifetime of the data is identical.
Most importantly this avoids using a variable size array at the end of the struct.
This commit is contained in:
Christoph Oelckers 2022-07-17 10:14:37 +02:00
parent 89f5428a9a
commit 6d635ce715
5 changed files with 44 additions and 48 deletions

View file

@ -35,7 +35,7 @@ public:
void SetNull() { texnum = 0; }
bool operator ==(const FTextureID &other) const { return texnum == other.texnum; }
bool operator !=(const FTextureID &other) const { return texnum != other.texnum; }
FTextureID operator +(int offset) throw();
FTextureID operator +(int offset) const noexcept(true);
int GetIndex() const { return texnum; } // Use this only if you absolutely need the index!
void SetIndex(int index) { texnum = index; } // Use this only if you absolutely need the index!

View file

@ -1615,7 +1615,7 @@ void FTextureManager::AddAlias(const char* name, FGameTexture* tex)
//
//==========================================================================
FTextureID FTextureID::operator +(int offset) throw()
FTextureID FTextureID::operator +(int offset) const noexcept(true)
{
if (!isValid()) return *this;
if (texnum + offset >= TexMan.NumTextures()) return FTextureID(-1);

View file

@ -43,6 +43,7 @@
#include "serializer.h"
#include "animations.h"
#include "texturemanager.h"
#include "image.h"
// MACROS ------------------------------------------------------------------
@ -61,14 +62,6 @@ static FRandom pr_animatepictures ("AnimatePics");
void FTextureAnimator::DeleteAll()
{
for (unsigned i = 0; i < mAnimations.Size(); i++)
{
if (mAnimations[i] != NULL)
{
M_Free(mAnimations[i]);
mAnimations[i] = NULL;
}
}
mAnimations.Clear();
for (unsigned i = 0; i < mSwitchDefs.Size(); i++)
@ -101,22 +94,21 @@ void FTextureAnimator::DeleteAll()
//
//==========================================================================
FAnimDef *FTextureAnimator::AddAnim (FAnimDef *anim)
FAnimDef *FTextureAnimator::AddAnim (FAnimDef& anim)
{
// Search for existing duplicate.
for (unsigned int i = 0; i < mAnimations.Size(); ++i)
{
if (mAnimations[i]->BasePic == anim->BasePic)
if (mAnimations[i].BasePic == anim.BasePic)
{
// Found one!
M_Free (mAnimations[i]);
mAnimations[i] = anim;
return anim;
return &anim;
}
}
// Didn't find one, so add it at the end.
mAnimations.Push (anim);
return anim;
return &anim;
}
//==========================================================================
@ -132,19 +124,20 @@ FAnimDef *FTextureAnimator::AddSimpleAnim (FTextureID picnum, int animcount, uin
{
if (TexMan.AreTexturesCompatible(picnum, picnum + (animcount - 1)))
{
FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef));
anim->CurFrame = 0;
anim->BasePic = picnum;
anim->NumFrames = animcount;
anim->AnimType = FAnimDef::ANIM_Forward;
anim->bDiscrete = false;
anim->SwitchTime = 0;
anim->Frames[0].SpeedMin = speedmin;
anim->Frames[0].SpeedRange = speedrange;
anim->Frames[0].FramePic = anim->BasePic;
FAnimDef anim;
anim.CurFrame = 0;
anim.BasePic = picnum;
anim.NumFrames = animcount;
anim.AnimType = FAnimDef::ANIM_Forward;
anim.bDiscrete = false;
anim.SwitchTime = 0;
anim.Frames = (FAnimDef::FAnimFrame*)ImageArena.Alloc(sizeof(FAnimDef::FAnimFrame));
anim.Frames[0].SpeedMin = speedmin;
anim.Frames[0].SpeedRange = speedrange;
anim.Frames[0].FramePic = anim.BasePic;
return AddAnim (anim);
}
return NULL;
return nullptr;
}
//==========================================================================
@ -157,14 +150,15 @@ FAnimDef *FTextureAnimator::AddSimpleAnim (FTextureID picnum, int animcount, uin
FAnimDef *FTextureAnimator::AddComplexAnim (FTextureID picnum, const TArray<FAnimDef::FAnimFrame> &frames)
{
FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef) + (frames.Size()-1) * sizeof(frames[0]));
anim->BasePic = picnum;
anim->NumFrames = frames.Size();
anim->CurFrame = 0;
anim->AnimType = FAnimDef::ANIM_Forward;
anim->bDiscrete = true;
anim->SwitchTime = 0;
memcpy (&anim->Frames[0], &frames[0], frames.Size() * sizeof(frames[0]));
FAnimDef anim;
anim.BasePic = picnum;
anim.NumFrames = frames.Size();
anim.CurFrame = 0;
anim.AnimType = FAnimDef::ANIM_Forward;
anim.bDiscrete = true;
anim.SwitchTime = 0;
anim.Frames = (FAnimDef::FAnimFrame*)ImageArena.Alloc(frames.Size() * sizeof(frames[0]));
memcpy (&anim.Frames[0], &frames[0], frames.Size() * sizeof(frames[0]));
return AddAnim (anim);
}
@ -783,7 +777,7 @@ void FTextureAnimator::FixAnimations ()
for (i = 0; i < mAnimations.Size(); ++i)
{
FAnimDef *anim = mAnimations[i];
const FAnimDef *anim = &mAnimations[i];
if (!anim->bDiscrete)
{
bool nodecals;
@ -928,7 +922,7 @@ void FTextureAnimator::UpdateAnimations (uint64_t mstime)
{
for (unsigned int j = 0; j < mAnimations.Size(); ++j)
{
FAnimDef *anim = mAnimations[j];
FAnimDef *anim = &mAnimations[j];
// If this is the first time through R_UpdateAnimations, just
// initialize the anim's switch time without actually animating.

View file

@ -7,18 +7,20 @@
struct FAnimDef
{
struct FAnimFrame
{
uint32_t SpeedMin; // Speeds are in ms, not tics
uint32_t SpeedRange;
FTextureID FramePic;
};
FTextureID BasePic;
uint16_t NumFrames;
uint16_t CurFrame;
uint8_t AnimType;
bool bDiscrete; // taken out of AnimType to have better control
uint64_t SwitchTime; // Time to advance to next frame
struct FAnimFrame
{
uint32_t SpeedMin; // Speeds are in ms, not tics
uint32_t SpeedRange;
FTextureID FramePic;
} Frames[1];
FAnimFrame* Frames;
enum
{
ANIM_Forward,
@ -59,7 +61,7 @@ struct FDoorAnimation
class FTextureAnimator
{
TArray<FAnimDef*> mAnimations;
TArray<FAnimDef> mAnimations;
TArray<FSwitchDef*> mSwitchDefs;
TArray<FDoorAnimation> mAnimatedDoors;
@ -88,7 +90,7 @@ public:
}
// Animation stuff
FAnimDef* AddAnim(FAnimDef* anim);
FAnimDef* AddAnim(FAnimDef& anim);
void DeleteAll();
FAnimDef* AddSimpleAnim(FTextureID picnum, int animcount, uint32_t speedmin, uint32_t speedrange = 0);
@ -98,7 +100,7 @@ public:
FDoorAnimation* FindAnimatedDoor(FTextureID picnum);
void UpdateAnimations(uint64_t mstime);
const TArray<FAnimDef*>& GetAnimations() const { return mAnimations; }
const TArray<FAnimDef>& GetAnimations() const { return mAnimations; }
void Init()
{

View file

@ -102,11 +102,11 @@ static void AddToList(uint8_t *hitlist, FTextureID texid, int bitmask)
const auto addAnimations = [hitlist, bitmask](const FTextureID texid)
{
for (auto anim : TexAnim.GetAnimations())
for (auto& anim : TexAnim.GetAnimations())
{
if (texid == anim->BasePic || (!anim->bDiscrete && anim->BasePic < texid && texid < anim->BasePic + anim->NumFrames))
if (texid == anim.BasePic || (!anim.bDiscrete && anim.BasePic < texid && texid < anim.BasePic + anim.NumFrames))
{
for (int i = anim->BasePic.GetIndex(); i < anim->BasePic.GetIndex() + anim->NumFrames; i++)
for (int i = anim.BasePic.GetIndex(); i < anim.BasePic.GetIndex() + anim.NumFrames; i++)
{
hitlist[i] |= (uint8_t)bitmask;
}