- 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; } void SetNull() { texnum = 0; }
bool operator ==(const FTextureID &other) const { return texnum == other.texnum; } bool operator ==(const FTextureID &other) const { return texnum == other.texnum; }
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! 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! 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 (!isValid()) return *this;
if (texnum + offset >= TexMan.NumTextures()) return FTextureID(-1); if (texnum + offset >= TexMan.NumTextures()) return FTextureID(-1);

View file

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

View file

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