summaryrefslogtreecommitdiffstats
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2021-08-15 15:35:53 +0200
committerFernando Sahmkow <fsahmkow27@gmail.com>2021-08-28 17:54:12 +0200
commitd540d284b5711f044678191bbab858de626103a9 (patch)
tree42839b218c848973c1886c7b288d2708821130a5 /src/video_core/texture_cache
parentMerge pull request #6929 from yuzu-emu/revert-6870-trace-back-stack-back-stack-back (diff)
downloadyuzu-d540d284b5711f044678191bbab858de626103a9.tar
yuzu-d540d284b5711f044678191bbab858de626103a9.tar.gz
yuzu-d540d284b5711f044678191bbab858de626103a9.tar.bz2
yuzu-d540d284b5711f044678191bbab858de626103a9.tar.lz
yuzu-d540d284b5711f044678191bbab858de626103a9.tar.xz
yuzu-d540d284b5711f044678191bbab858de626103a9.tar.zst
yuzu-d540d284b5711f044678191bbab858de626103a9.zip
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/image_base.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h89
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h8
3 files changed, 37 insertions, 62 deletions
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h
index ff1feda9b..662089e3d 100644
--- a/src/video_core/texture_cache/image_base.h
+++ b/src/video_core/texture_cache/image_base.h
@@ -80,7 +80,7 @@ struct ImageBase {
VAddr cpu_addr_end = 0;
u64 modification_tick = 0;
- u64 frame_tick = 0;
+ size_t lru_index = ~0;
std::array<u32, MAX_MIP_LEVELS> mip_level_offsets{};
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index a087498ff..c16cc0838 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -43,8 +43,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
void(slot_image_views.insert(runtime, NullImageParams{}));
void(slot_samplers.insert(runtime, sampler_descriptor));
- deletion_iterator = slot_images.begin();
-
if constexpr (HAS_DEVICE_MEMORY_INFO) {
const auto device_memory = runtime.GetDeviceLocalMemory();
const u64 possible_expected_memory = (device_memory * 3) / 10;
@@ -64,65 +62,33 @@ template <class P>
void TextureCache<P>::RunGarbageCollector() {
const bool high_priority_mode = total_used_memory >= expected_memory;
const bool aggressive_mode = total_used_memory >= critical_memory;
- const u64 ticks_to_destroy = high_priority_mode ? 60 : 100;
- int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64);
- for (; num_iterations > 0; --num_iterations) {
- if (deletion_iterator == slot_images.end()) {
- deletion_iterator = slot_images.begin();
- if (deletion_iterator == slot_images.end()) {
- break;
- }
+ const u64 ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 50ULL : 100ULL;
+ size_t num_iterations = aggressive_mode ? 10000 : (high_priority_mode ? 50 : 5);
+ const auto clean_up = [this, &num_iterations, high_priority_mode](ImageId image_id) {
+ if (num_iterations == 0) {
+ return true;
}
- auto [image_id, image_tmp] = *deletion_iterator;
- Image* image = image_tmp; // fix clang error.
- const bool is_alias = True(image->flags & ImageFlagBits::Alias);
- const bool is_bad_overlap = True(image->flags & ImageFlagBits::BadOverlap);
- const bool must_download = image->IsSafeDownload();
- bool should_care = is_bad_overlap || is_alias || (high_priority_mode && !must_download);
- const u64 ticks_needed =
- is_bad_overlap
- ? ticks_to_destroy >> 4
- : ((should_care && aggressive_mode) ? ticks_to_destroy >> 1 : ticks_to_destroy);
- should_care |= aggressive_mode;
- if (should_care && image->frame_tick + ticks_needed < frame_tick) {
- if (is_bad_overlap) {
- const bool overlap_check = std::ranges::all_of(
- image->overlapping_images, [&, image](const ImageId& overlap_id) {
- auto& overlap = slot_images[overlap_id];
- return overlap.frame_tick >= image->frame_tick;
- });
- if (!overlap_check) {
- ++deletion_iterator;
- continue;
- }
- }
- if (!is_bad_overlap && must_download) {
- const bool alias_check = std::ranges::none_of(
- image->aliased_images, [&, image](const AliasedImage& alias) {
- auto& alias_image = slot_images[alias.id];
- return (alias_image.frame_tick < image->frame_tick) ||
- (alias_image.modification_tick < image->modification_tick);
- });
-
- if (alias_check) {
- auto map = runtime.DownloadStagingBuffer(image->unswizzled_size_bytes);
- const auto copies = FullDownloadCopies(image->info);
- image->DownloadMemory(map, copies);
- runtime.Finish();
- SwizzleImage(gpu_memory, image->gpu_addr, image->info, copies, map.mapped_span);
- }
- }
- if (True(image->flags & ImageFlagBits::Tracked)) {
- UntrackImage(*image, image_id);
- }
- UnregisterImage(image_id);
- DeleteImage(image_id);
- if (is_bad_overlap) {
- ++num_iterations;
- }
+ --num_iterations;
+ auto& image = slot_images[image_id];
+ const bool must_download = image.IsSafeDownload();
+ if (!high_priority_mode && must_download) {
+ return false;
}
- ++deletion_iterator;
- }
+ if (must_download) {
+ auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes);
+ const auto copies = FullDownloadCopies(image.info);
+ image.DownloadMemory(map, copies);
+ runtime.Finish();
+ SwizzleImage(gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span);
+ }
+ if (True(image.flags & ImageFlagBits::Tracked)) {
+ UntrackImage(image, image_id);
+ }
+ UnregisterImage(image_id);
+ DeleteImage(image_id);
+ return false;
+ };
+ lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, clean_up);
}
template <class P>
@@ -1078,6 +1044,8 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format);
}
total_used_memory += Common::AlignUp(tentative_size, 1024);
+ image.lru_index = lru_cache.Insert(image_id, frame_tick);
+
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
[this, image_id](u64 page) { gpu_page_table[page].push_back(image_id); });
if (False(image.flags & ImageFlagBits::Sparse)) {
@@ -1115,6 +1083,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format);
}
total_used_memory -= Common::AlignUp(tentative_size, 1024);
+ lru_cache.Free(image.lru_index);
const auto& clear_page_table =
[this, image_id](
u64 page,
@@ -1384,7 +1353,7 @@ void TextureCache<P>::PrepareImage(ImageId image_id, bool is_modification, bool
if (is_modification) {
MarkModification(image);
}
- image.frame_tick = frame_tick;
+ lru_cache.Touch(image.lru_index, frame_tick);
}
template <class P>
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index e4ae351cb..d7528ed24 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -14,6 +14,7 @@
#include "common/common_types.h"
#include "common/literals.h"
+#include "common/lru_cache.h"
#include "video_core/compatible_formats.h"
#include "video_core/delayed_destruction_ring.h"
#include "video_core/engines/fermi_2d.h"
@@ -370,6 +371,12 @@ private:
std::vector<ImageId> uncommitted_downloads;
std::queue<std::vector<ImageId>> committed_downloads;
+ struct LRUItemParams {
+ using ObjectType = ImageId;
+ using TickType = u64;
+ };
+ Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
+
static constexpr size_t TICKS_TO_DESTROY = 6;
DelayedDestructionRing<Image, TICKS_TO_DESTROY> sentenced_images;
DelayedDestructionRing<ImageView, TICKS_TO_DESTROY> sentenced_image_view;
@@ -379,7 +386,6 @@ private:
u64 modification_tick = 0;
u64 frame_tick = 0;
- typename SlotVector<Image>::Iterator deletion_iterator;
};
} // namespace VideoCommon