diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 38c44a0622..d92fb9e037 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -31,6 +31,7 @@ #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" #include "Common/Thread/ParallelLoop.h" +#include "Common/TimeUtil.h" #include "Core/Config.h" #include "Core/Host.h" #include "Core/System.h" @@ -621,6 +622,15 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl savedCache_[replacementKey] = saved; } +void TextureReplacer::Decimate(bool forcePressure) { + // Allow replacements to be cached for a long time, although they're large. + const double age = forcePressure ? 90.0 : 1800.0; + const double threshold = time_now_d() - age; + for (auto &item : cache_) { + item.second.PurgeIfOlder(threshold); + } +} + template static typename std::unordered_map::const_iterator LookupWildcard(const std::unordered_map &map, Key &key, u64 cachekey, u32 hash, bool ignoreAddress) { auto alias = map.find(key); @@ -734,7 +744,33 @@ float TextureReplacer::LookupReduceHashRange(int& w, int& h) { } bool ReplacedTexture::IsReady(double budget) { - return true; + lastUsed_ = time_now_d(); + + if (levelData_.size() == levels_.size()) + return true; + if (budget <= 0.0) + return false; + + double deadline = lastUsed_ + budget; + for (int i = (int)levelData_.size(); i <= MaxLevel(); ++i) { + levelData_.resize(i + 1); + PrepareData(i); + if (time_now_d() >= deadline) { + break; + } + } + // If we finished all the levels, we're done. + return levelData_.size() == levels_.size(); +} + +void ReplacedTexture::PrepareData(int level) { + // TODO +} + +void ReplacedTexture::PurgeIfOlder(double t) { + if (lastUsed_ < t) { + levelData_.clear(); + } } bool ReplacedTexture::Load(int level, void *out, int rowPitch) { diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 110f9df57b..46ee4c58be 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -158,8 +158,13 @@ struct ReplacedTexture { bool Load(int level, void *out, int rowPitch); protected: + void PrepareData(int level); + void PurgeIfOlder(double t); + std::vector levels_; + std::vector> levelData_; ReplacedTextureAlpha alphaStatus_; + double lastUsed_ = 0.0; friend TextureReplacer; }; @@ -193,6 +198,8 @@ public: void NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h); + void Decimate(bool forcePressure); + static bool GenerateIni(const std::string &gameID, Path &generatedFilename); protected: diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 8661018007..04c6bfae2c 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -724,6 +724,7 @@ void TextureCacheCommon::Decimate(bool forcePressure) { } DecimateVideos(); + replacer_.Decimate(forcePressure); } void TextureCacheCommon::DecimateVideos() {