feat(video_core): implement comprehensive VRAM management system

Add automatic VRAM leak prevention with configurable garbage collection
to prevent device loss crashes during extended play sessions.

New Settings:
- vram_limit_mb: Configurable VRAM limit (0 = auto-detect 80%)
- gc_aggressiveness: Off/Light/Moderate/Heavy/Extreme levels
- texture_eviction_frames: Frames before texture eviction (default 2)
- buffer_eviction_frames: Frames before buffer eviction (default 5)
- sparse_texture_priority_eviction: Prioritize large sparse textures
- log_vram_usage: Enable VRAM statistics logging

Core Changes:
- Enhanced texture cache with LRU eviction and sparse texture priority
- Enhanced buffer cache with configurable eviction thresholds
- Added VRAM pressure monitoring using VK_EXT_memory_budget
- Emergency GC triggers at 90%/95% VRAM usage thresholds

Platform Support:
- Desktop: Settings in Graphics > Advanced tab
- Android: Settings in Zep Zone category

Fixes VRAM climbing steadily during gameplay until device loss.
Target: Stable VRAM usage below configured limit for 2+ hours.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2026-01-25 15:21:02 +10:00
parent 44f9cb6347
commit 3e2137a470
16 changed files with 938 additions and 48 deletions

View File

@@ -66,6 +66,7 @@ SWITCHABLE(AstcDecodeMode, true);
SWITCHABLE(AstcRecompression, true);
SWITCHABLE(AudioMode, true);
SWITCHABLE(ExtendedDynamicState, true);
SWITCHABLE(GCAggressiveness, true);
SWITCHABLE(CpuBackend, true);
SWITCHABLE(CpuAccuracy, true);
SWITCHABLE(FullscreenMode, true);
@@ -501,6 +502,61 @@ struct Values {
VramUsageMode::Insane,
"vram_usage_mode",
Category::RendererAdvanced};
// FIXED: VRAM leak prevention - New memory management settings
// VRAM limit in MB (0 = auto-detect based on GPU, default 6144 for 6GB limit)
SwitchableSetting<u32, true> vram_limit_mb{linkage,
0, // 0 = auto-detect (80% of available VRAM)
0, // min: 0 (auto)
32768, // max: 32GB
"vram_limit_mb",
Category::RendererAdvanced,
Specialization::Default,
true,
true};
// GC aggressiveness level for texture/buffer cache eviction
SwitchableSetting<GCAggressiveness, true> gc_aggressiveness{linkage,
GCAggressiveness::Moderate,
GCAggressiveness::Off,
GCAggressiveness::Extreme,
"gc_aggressiveness",
Category::RendererAdvanced,
Specialization::Default,
true,
true};
// Number of frames before unused textures are evicted (default 2)
SwitchableSetting<u32, true> texture_eviction_frames{linkage,
2, // default: 2 frames
1, // min: 1 frame
60, // max: 60 frames (1 second at 60fps)
"texture_eviction_frames",
Category::RendererAdvanced,
Specialization::Default,
true,
true};
// Number of frames before unused buffers are evicted (default 5)
SwitchableSetting<u32, true> buffer_eviction_frames{linkage,
5, // default: 5 frames
1, // min: 1 frame
120, // max: 120 frames (2 seconds at 60fps)
"buffer_eviction_frames",
Category::RendererAdvanced,
Specialization::Default,
true,
true};
// Enable sparse texture priority eviction (evict large unmapped pages first)
SwitchableSetting<bool> sparse_texture_priority_eviction{linkage, true,
"sparse_texture_priority_eviction",
Category::RendererAdvanced};
// Enable VRAM usage logging for debugging
SwitchableSetting<bool> log_vram_usage{linkage, false, "log_vram_usage",
Category::RendererAdvanced};
SwitchableSetting<bool> async_presentation{linkage,
#ifdef ANDROID
true,

View File

@@ -880,6 +880,32 @@ inline u32 EnumMetadata<ExtendedDynamicState>::Index() {
return 26;
}
// FIXED: VRAM leak prevention - GC aggressiveness levels
enum class GCAggressiveness : u32 {
Off = 0, // Disable automatic GC (not recommended)
Light = 1, // Light GC - only evict very old textures
Moderate = 2, // Moderate GC - balanced eviction (default)
Heavy = 3, // Heavy GC - aggressive eviction for low VRAM systems
Extreme = 4, // Extreme GC - maximum eviction for 4GB VRAM systems
};
template <>
inline std::vector<std::pair<std::string, GCAggressiveness>>
EnumMetadata<GCAggressiveness>::Canonicalizations() {
return {
{"Off", GCAggressiveness::Off},
{"Light", GCAggressiveness::Light},
{"Moderate", GCAggressiveness::Moderate},
{"Heavy", GCAggressiveness::Heavy},
{"Extreme", GCAggressiveness::Extreme},
};
}
template <>
inline u32 EnumMetadata<GCAggressiveness>::Index() {
return 27;
}
template <typename Type>
inline std::string CanonicalizeEnum(Type id) {