Break out PollReplacement from TextureCacheCommon::FindReplacement

This commit is contained in:
Henrik Rydgård
2023-03-18 12:01:24 +01:00
parent 75bcb9b10c
commit 97c9b9e4f7
4 changed files with 30 additions and 18 deletions
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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_;
+21 -15
View File
@@ -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;
+7 -1
View File
@@ -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)