From 4252036d8920bff98aa831920136efe074b334d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 29 Aug 2020 22:25:50 +0200 Subject: [PATCH] Apply the scoring model when creating/updating framebuffers too. Reuses the same mechanism. This is the second part of the Test Drive fix. --- GPU/Common/TextureCacheCommon.cpp | 38 +++++++++++++++++++------------ GPU/Common/TextureCacheCommon.h | 8 +++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 9fcfd3ce12..bad64c09bf 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -550,12 +550,6 @@ void TextureCacheCommon::SetTexture(bool force) { bool TextureCacheCommon::AttachFramebufferToEntry(TexCacheEntry *entry, u32 texAddrOffset) { bool success = false; - struct AttachCandidate { - FramebufferMatchInfo match; - TexCacheEntry *entry; - VirtualFramebuffer *fb; - }; - std::vector candidates; bool anyIgnores = false; @@ -565,7 +559,7 @@ bool TextureCacheCommon::AttachFramebufferToEntry(TexCacheEntry *entry, u32 texA auto framebuffer = fbCache_[i]; FramebufferMatchInfo match = MatchFramebuffer(entry, framebuffer->fb_address, framebuffer, texAddrOffset, channel); if (match.match != FramebufferMatch::IGNORE && match.match != FramebufferMatch::NO_MATCH) { - candidates.push_back(AttachCandidate{ match, entry, framebuffer }); + candidates.push_back(AttachCandidate{ match, entry, framebuffer, channel }); } else if (match.match == FramebufferMatch::IGNORE) { anyIgnores = true; } @@ -585,9 +579,15 @@ bool TextureCacheCommon::AttachFramebufferToEntry(TexCacheEntry *entry, u32 texA return false; } + return AttachBestCandidate(candidates); +} + +bool TextureCacheCommon::AttachBestCandidate(const std::vector &candidates) { + _dbg_assert_(!candidates.empty()); + if (candidates.size() == 1) { VirtualFramebuffer *framebuffer = candidates[0].fb; - return ApplyFramebufferMatch(candidates[0].match, entry, framebuffer->fb_address, framebuffer, channel); + return ApplyFramebufferMatch(candidates[0].match, candidates[0].entry, framebuffer->fb_address, framebuffer, candidates[0].channel); } // OK, multiple possible candidates. Will need to figure out which one is the most relevant. @@ -608,7 +608,7 @@ bool TextureCacheCommon::AttachFramebufferToEntry(TexCacheEntry *entry, u32 texA } // Bonus point for matching stride. - if (channel == NOTIFY_FB_COLOR && candidate.fb->fb_stride == candidate.entry->bufw) { + if (candidate.channel == NOTIFY_FB_COLOR && candidate.fb->fb_stride == candidate.entry->bufw) { relevancy += 10; } @@ -619,10 +619,9 @@ bool TextureCacheCommon::AttachFramebufferToEntry(TexCacheEntry *entry, u32 texA } VirtualFramebuffer *framebuffer = candidates[bestIndex].fb; - return ApplyFramebufferMatch(candidates[bestIndex].match, candidates[bestIndex].entry, framebuffer->fb_address, framebuffer, channel); + return ApplyFramebufferMatch(candidates[bestIndex].match, candidates[bestIndex].entry, framebuffer->fb_address, framebuffer, candidates[bestIndex].channel); } - // Removes old textures. void TextureCacheCommon::Decimate(bool forcePressure) { if (--decimationCounter_ <= 0) { @@ -737,6 +736,7 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram switch (msg) { case NOTIFY_FB_CREATED: case NOTIFY_FB_UPDATED: + { // Try to match the new framebuffer to existing textures. // Backwards from the "usual" texturing case so can't share a utility function. @@ -748,11 +748,15 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram fbCache_.push_back(framebuffer); } + std::vector candidates; + // TODO: Rework this to not try to "apply" all matches, only the best one. for (auto it = cache_.lower_bound(cacheKey), end = cache_.upper_bound(cacheKeyEnd); it != end; ++it) { TexCacheEntry *entry = it->second.get(); FramebufferMatchInfo match = MatchFramebuffer(entry, addr, framebuffer, 0, channel); - ApplyFramebufferMatch(match, entry, addr, framebuffer, channel); + if (match.match != FramebufferMatch::IGNORE && match.match != FramebufferMatch::NO_MATCH) { + candidates.push_back(AttachCandidate{ match, entry, framebuffer, channel }); + } } // Let's assume anything in mirrors is fair game to check. @@ -763,11 +767,17 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram if (mirrorlessKey >= cacheKey && mirrorlessKey <= cacheKeyEnd) { TexCacheEntry *entry = it->second.get(); FramebufferMatchInfo match = MatchFramebuffer(entry, addr, framebuffer, 0, channel); - ApplyFramebufferMatch(match, entry, addr, framebuffer, channel); + if (match.match != FramebufferMatch::IGNORE && match.match != FramebufferMatch::NO_MATCH) { + candidates.push_back(AttachCandidate{ match, entry, framebuffer, channel }); + } } } - break; + if (!candidates.empty()) { + AttachBestCandidate(candidates); + } + break; + } case NOTIFY_FB_DESTROYED: fbCache_.erase(std::remove(fbCache_.begin(), fbCache_.end(), framebuffer), fbCache_.end()); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index f699e55026..630ef43fa9 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -207,6 +207,13 @@ struct FramebufferMatchInfo { u32 yOffset; }; +struct AttachCandidate { + FramebufferMatchInfo match; + TexCacheEntry *entry; + VirtualFramebuffer *fb; + FramebufferNotificationChannel channel; +}; + class TextureCacheCommon { public: TextureCacheCommon(Draw::DrawContext *draw); @@ -278,6 +285,7 @@ protected: // Temporary utility during conversion bool ApplyFramebufferMatch(FramebufferMatchInfo match, TexCacheEntry *entry, u32 address, VirtualFramebuffer *framebuffer, FramebufferNotificationChannel channel); + bool AttachBestCandidate(const std::vector &candidates); void AttachFramebufferValid(TexCacheEntry *entry, VirtualFramebuffer *framebuffer, const FramebufferMatchInfo &fbInfo, FramebufferNotificationChannel channel); void AttachFramebufferInvalid(TexCacheEntry *entry, VirtualFramebuffer *framebuffer, const FramebufferMatchInfo &fbInfo, FramebufferNotificationChannel channel);