From 97c9b9e4f715eceea0734bdcc740b2c7d65867dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 12:01:24 +0100 Subject: [PATCH] Break out PollReplacement from TextureCacheCommon::FindReplacement --- GPU/Common/ReplacedTexture.cpp | 2 +- GPU/Common/ReplacedTexture.h | 2 +- GPU/Common/TextureCacheCommon.cpp | 36 ++++++++++++++++++------------- GPU/Common/TextureCacheCommon.h | 8 ++++++- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 293d7c1a76..9461a08141 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -145,7 +145,7 @@ void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) { } // This can only return true if ACTIVE or NOT_FOUND. -bool ReplacedTexture::IsReady(double budget) { +bool ReplacedTexture::Poll(double budget) { _assert_(vfs_ != nullptr); double now = time_now_d(); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index eaeb5ed230..b4716c8b64 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -161,7 +161,7 @@ public: return (u8)alphaStatus_; } - bool IsReady(double budget); + bool Poll(double budget); bool CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch); std::string logId_; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index e7a4b87012..c2359efa67 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -531,7 +531,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { int w0 = gstate.getTextureWidth(0); int h0 = gstate.getTextureHeight(0); int d0 = 1; - ReplacedTexture *replaced = FindReplacement(entry, w0, h0, d0); + ReplacedTexture *replaced = FindReplacement(entry, &w0, &h0, &d0); if (replaced) { // This texture is pending a replacement load. // So check the replacer if it's reached a conclusion. @@ -1502,8 +1502,8 @@ u32 TextureCacheCommon::EstimateTexMemoryUsage(const TexCacheEntry *entry) { return pixelSize << (dimW + dimH); } -ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d) { - if (d != 1) { +ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int *w, int *h, int *d) { + if (*d != 1) { // We don't yet support replacing 3D textures. return nullptr; } @@ -1519,23 +1519,30 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & return nullptr; } - // Allow some delay to reduce pop-in. - constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0; - double replaceStart = time_now_d(); u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; - ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); + ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, *w, *h); + replacementTimeThisFrame_ += time_now_d() - replaceStart; if (!replaced) { // TODO: Remove the flag here? // entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; - replacementTimeThisFrame_ += time_now_d() - replaceStart; return nullptr; } + entry->replacedTexture = replaced; // we know it's non-null here. + PollReplacement(entry, w, h, d); + return replaced; +} + +void TextureCacheCommon::PollReplacement(TexCacheEntry *entry, int *w, int *h, int *d) { + // Allow some delay to reduce pop-in. + constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0; double budget = std::min(MAX_BUDGET_PER_TEX, replacementFrameBudget_ - replacementTimeThisFrame_); - if (replaced->IsReady(budget)) { - if (replaced->State() == ReplacementState::ACTIVE) { - replaced->GetSize(0, &w, &h); + + double replaceStart = time_now_d(); + if (entry->replacedTexture->Poll(budget)) { + if (entry->replacedTexture->State() == ReplacementState::ACTIVE) { + entry->replacedTexture->GetSize(0, w, h); // Consider it already "scaled.". entry->status |= TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED; } @@ -1543,8 +1550,9 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & // Remove the flag, even if it was invalid. entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; } + replacementTimeThisFrame_ += time_now_d() - replaceStart; - switch (replaced->State()) { + switch (entry->replacedTexture->State()) { case ReplacementState::UNLOADED: case ReplacementState::PENDING: // Make sure we keep polling. @@ -1553,8 +1561,6 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & default: break; } - replacementTimeThisFrame_ += time_now_d() - replaceStart; - return replaced; } // This is only used in the GLES backend, where we don't point these to video memory. @@ -2822,7 +2828,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (canReplace) { // This is the "trigger point" for replacement. - plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); + plan.replaced = FindReplacement(entry, &plan.w, &plan.h, &plan.depth); plan.doReplace = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false; } else { plan.replaced = nullptr; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 67e78c6f47..ba97bb135b 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -105,12 +105,18 @@ struct TextureDefinition { GETextureFormat format; }; -// TODO: Shrink this struct. There is some fluff. +// Texture replacement state machine: +// Call FindReplacement during PrepareBuild. +// If replacedTexture gets set: If not found, -> STATUS_TO_REPLACE, otherwise directly -> STATUS_IS_SCALED. +// If replacedTexture is null, leave it at null. +// If replacedTexture is set in SetTexture and STATUS_IS_SCALED is not set, query status. If ready rebuild texture, which will set STATUS_IS_SCALED. // NOTE: These only handle textures loaded directly from PSP memory contents. // Framebuffer textures do not have entries, we bind the framebuffers directly. // At one point we might merge the concepts of framebuffers and textures, but that // moment is far away. + +// TODO: Shrink this struct. There is some fluff. struct TexCacheEntry { ~TexCacheEntry() { if (texturePtr || textureName || vkTex)