From 0160841dde496462badfae2b0ac0a603bd34225d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Dec 2018 18:17:21 +0100 Subject: [PATCH] - reverse the order of the texture list before resolving it. Since this deletes the resolved elements one by one and needs to start at the front to ensure consistency, it is better to reverse the order so that the deletions take place at the end of the list which requires a lot less data movement. On Total Chaos this slowed down texture setup to the point where the mod was basically unlaunchable. --- src/tarray.h | 18 +++++++++++++++++- src/textures/formats/multipatchtexture.h | 22 ++++++++++++++++++++++ src/textures/multipatchtexturebuilder.cpp | 13 +++++++++++-- src/zstring.h | 5 +++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/tarray.h b/src/tarray.h index 524c0942e..1c5faca43 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -497,6 +497,14 @@ public: Array = nullptr; } } + + void Swap(TArray &other) + { + std::swap(Array, other.Array); + std::swap(Count, other.Count); + std::swap(Most, other.Most); + } + private: T *Array; unsigned int Count; @@ -760,6 +768,7 @@ struct FMap hash_t NumUsed; }; + template class TMapIterator; template class TMapConstIterator; @@ -947,6 +956,14 @@ public: DelKey(key); } + void Swap(MyType &other) + { + std::swap(Nodes, other.Nodes); + std::swap(LastFree, other.LastFree); + std::swap(Size, other.Size); + std::swap(NumUsed, other.NumUsed); + } + protected: struct IPair // This must be the same as Pair above, but with a { // non-const Key. @@ -1518,4 +1535,3 @@ private: T *Array; unsigned int Count; }; - diff --git a/src/textures/formats/multipatchtexture.h b/src/textures/formats/multipatchtexture.h index 3d7800832..8337ffe6c 100644 --- a/src/textures/formats/multipatchtexture.h +++ b/src/textures/formats/multipatchtexture.h @@ -89,8 +89,30 @@ struct BuildInfo int LeftOffset[2] = {}; int TopOffset[2] = {}; FImageTexture *tex = nullptr; + + void swap(BuildInfo &other) + { + Name.Swap(other.Name); + Parts.Swap(other.Parts); + Inits.Swap(other.Inits); + std::swap(Width, other.Width); + std::swap(Height, other.Height); + std::swap(Scale, other.Scale); + std::swap(bWorldPanning, other.bWorldPanning); + std::swap(DefinitionLump, other.DefinitionLump); + std::swap(bComplex, bComplex); + std::swap(textual, other.textual); + std::swap(bNoDecals, other.bNoDecals); + std::swap(LeftOffset[0], other.LeftOffset[0]); + std::swap(LeftOffset[1], other.LeftOffset[1]); + std::swap(TopOffset[0], other.TopOffset[0]); + std::swap(TopOffset[1], other.TopOffset[1]); + std::swap(tex, other.tex); + } }; + + class FMultipatchTextureBuilder { FTextureManager &TexMan; diff --git a/src/textures/multipatchtexturebuilder.cpp b/src/textures/multipatchtexturebuilder.cpp index 7be8a69e5..4675220f5 100644 --- a/src/textures/multipatchtexturebuilder.cpp +++ b/src/textures/multipatchtexturebuilder.cpp @@ -922,11 +922,21 @@ void FMultipatchTextureBuilder::ResolveAllPatches() } // Now try to resolve the images. We only can do this at the end when all multipatch textures are set up. int i = 0; + + // reverse the list so that the Delete operation in the loop below deletes at the end. + // For normal sized lists this is of no real concern, but Total Chaos has over 250000 textures where this becomes a performance issue. + for (unsigned i = 0; i < BuiltTextures.Size() / 2; i++) + { + // std::swap is VERY inefficient here... + BuiltTextures[i].swap(BuiltTextures[BuiltTextures.Size() - 1 - i]); + } + + while (BuiltTextures.Size() > 0) { bool donesomething = false; - for (unsigned i = 0; i < BuiltTextures.Size(); i++) + for (int i = BuiltTextures.Size()-1; i>= 0; i--) { auto &buildinfo = BuiltTextures[i]; bool hasEmpty = false; @@ -969,7 +979,6 @@ void FMultipatchTextureBuilder::ResolveAllPatches() } BuiltTextures.Delete(i); - i--; donesomething = true; } } diff --git a/src/zstring.h b/src/zstring.h index 67fef4a18..334fbcb1f 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -148,6 +148,11 @@ public: char *LockBuffer(); // Obtain write access to the character buffer void UnlockBuffer(); // Allow shared access to the character buffer + void Swap(FString &other) + { + std::swap(Chars, other.Chars); + } + operator const char *() const { return Chars; } const char *GetChars() const { return Chars; }