texture_cache: count evictions that download; EDEN_NX2_TC_MIN_AGE knob

The collector's periodic log now also counts evictions that downloaded the image first
(each a full GPU wait). EDEN_NX2_TC_MIN_AGE=<frames> keeps images used more recently
than that (a VRAM thrash test on 8 GB: 120 frames made no difference over three runs).
This commit is contained in:
Takoroka 2026-10-29 07:05:03 -04:00
commit 39dd849e24
2 changed files with 11 additions and 2 deletions

View file

@ -129,6 +129,12 @@ void TextureCache<P>::RunGarbageCollector() {
high_priority_mode = total_used_memory >= expected_memory;
aggressive_mode = allow_aggressive && total_used_memory >= critical_memory;
ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
// EDEN_NX2_TC_MIN_AGE=<frames>: never evict images used more recently (thrash tests).
static const u64 min_age = [] {
const char* value = std::getenv("EDEN_NX2_TC_MIN_AGE");
return value != nullptr ? std::strtoull(value, nullptr, 10) : 0ULL;
}();
ticks_to_destroy = (std::max)(ticks_to_destroy, min_age);
num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10);
};
const auto Cleanup = [this, &num_iterations, &high_priority_mode, &aggressive_mode](ImageId image_id) {
@ -150,6 +156,7 @@ void TextureCache<P>::RunGarbageCollector() {
image.DownloadMemory(map, copies);
runtime.Finish();
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span, swizzle_data_buffer);
++gc_download_deletes;
}
if (True(image.flags & ImageFlagBits::Tracked)) {
UntrackImage(image, image_id);
@ -269,8 +276,9 @@ void TextureCache<P>::TickFrame() {
if constexpr (requires { runtime.LogMemoryStatistics(); }) {
runtime.LogMemoryStatistics();
}
LOG_INFO(HW_GPU, "Texture cache last 600 frames: created {} images, deleted {} (collector {}, {} costly), {} async decodes, ASTC {} opaque / {} alpha",
LOG_INFO(HW_GPU, "Texture cache last 600 frames: created {} images, deleted {} (collector {}, {} costly, {} downloaded), {} async decodes, ASTC {} opaque / {} alpha",
images_created, images_deleted, gc_deletes + gc_costly_deletes, gc_costly_deletes,
gc_download_deletes,
async_decodes_queued, astc_opaque_images, astc_alpha_images);
astc_opaque_images = astc_alpha_images = 0;
std::vector<std::pair<u32, u64>> shapes;
@ -284,7 +292,7 @@ void TextureCache<P>::TickFrame() {
created_shapes[key].second);
}
created_shapes.clear();
gc_deletes = gc_costly_deletes = async_decodes_queued = 0;
gc_deletes = gc_costly_deletes = gc_download_deletes = async_decodes_queued = 0;
images_created = images_deleted = 0;
}
if (total_used_memory > minimum_memory) {

View file

@ -125,6 +125,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
// Periodic statistics (TickFrame).
u64 gc_deletes{};
u64 gc_costly_deletes{};
u64 gc_download_deletes{}; ///< Evictions that downloaded the image first (a full GPU wait)
u64 async_decodes_queued{};
u64 images_created{};
bool native_thresholds_applied{};