From b5bec371ae9c117c1ebfcfd4d02dcee9b0a0a51a Mon Sep 17 00:00:00 2001 From: MrPurple666 Date: Wed, 30 Apr 2025 03:41:46 -0300 Subject: [PATCH] Add toggle for LRU --- .../features/settings/model/BooleanSetting.kt | 3 +- .../settings/model/view/SettingsItem.kt | 7 ++++ .../settings/ui/SettingsFragmentPresenter.kt | 8 ++++ .../app/src/main/jni/android_settings.h | 4 ++ .../app/src/main/res/values/strings.xml | 4 ++ src/common/settings.h | 1 + src/core/arm/nce/lru_cache.h | 40 +++++++++++++++---- src/core/arm/nce/patcher.h | 5 ++- 8 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 31f8a62397..ec2759edd5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -36,7 +36,8 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { SHOW_APP_RAM_USAGE("show_app_ram_usage"), SHOW_SYSTEM_RAM_USAGE("show_system_ram_usage"), SHOW_BAT_TEMPERATURE("show_bat_temperature"), - OVERLAY_BACKGROUND("overlay_background"),; + OVERLAY_BACKGROUND("overlay_background"), + USE_LRU_CACHE("use_lru_cache"),; external fun isFrameSkippingEnabled(): Boolean external fun isFrameInterpolationEnabled(): Boolean diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index a0ace00c0b..7ccc6500c2 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -119,6 +119,13 @@ abstract class SettingsItem( // List of all general val settingsItems = HashMap().apply { put(StringInputSetting(StringSetting.DEVICE_NAME, titleId = R.string.device_name)) + put( + SwitchSetting( + BooleanSetting.USE_LRU_CACHE, + titleId = R.string.use_lru_cache, + descriptionId = R.string.use_lru_cache_description + ) + ) put( SwitchSetting( BooleanSetting.RENDERER_USE_SPEED_LIMIT, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index cfdfce7276..4a33b176d7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -251,6 +251,7 @@ class SettingsFragmentPresenter( add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key) add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key) add(IntSetting.RENDERER_VRAM_USAGE_MODE.key) + add(BooleanSetting.USE_LRU_CACHE.key) } } @@ -471,6 +472,13 @@ class SettingsFragmentPresenter( descriptionId = R.string.frame_skipping_description ) ) + add( + SwitchSetting( + BooleanSetting.USE_LRU_CACHE, + titleId = R.string.use_lru_cache, + descriptionId = R.string.use_lru_cache_description + ) + ) add(ByteSetting.RENDERER_DYNA_STATE.key) add( SwitchSetting( diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h index a47803604a..ff569d1981 100644 --- a/src/android/app/src/main/jni/android_settings.h +++ b/src/android/app/src/main/jni/android_settings.h @@ -49,6 +49,10 @@ struct Values { Settings::SwitchableSetting driver_path{linkage, "", "driver_path", Settings::Category::GpuDriver}; + // LRU Cache + Settings::SwitchableSetting use_lru_cache{linkage, true, "use_lru_cache", + Settings::Category::System}; + Settings::Setting theme{linkage, 0, "theme", Settings::Category::Android}; Settings::Setting theme_mode{linkage, -1, "theme_mode", Settings::Category::Android}; Settings::Setting black_backgrounds{linkage, false, "black_backgrounds", diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index e47d1df498..28f18e1596 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -655,6 +655,10 @@ 3X (2160p/3240p) (Slow) 4X (2880p/4320p) (Slow) + + Enable LRU Cache + Enable or disable the Least Recently Used (LRU) cache for improved performance + Immediate (Off) Mailbox diff --git a/src/common/settings.h b/src/common/settings.h index b16106985b..ec627b744d 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -218,6 +218,7 @@ struct Values { // Memory SwitchableSetting use_gpu_memory_manager{linkage, false, "Use GPU Memory Manager", Category::Core}; SwitchableSetting enable_memory_snapshots{linkage, false, "Enable Memory Snapshots", Category::Core}; + SwitchableSetting lru_cache_enabled{linkage, true, "use_lru_cache", Category::System}; // Cpu SwitchableSetting cpu_backend{linkage, diff --git a/src/core/arm/nce/lru_cache.h b/src/core/arm/nce/lru_cache.h index 4150e76a69..70f5163947 100644 --- a/src/core/arm/nce/lru_cache.h +++ b/src/core/arm/nce/lru_cache.h @@ -6,13 +6,21 @@ template class LRUCache { +private: + bool enabled = true; + size_t capacity; + std::list cache_list; + std::unordered_map::iterator, ValueType>> cache_map; + public: - explicit LRUCache(size_t capacity) : capacity(capacity) { + explicit LRUCache(size_t capacity, bool enabled = true) : enabled(enabled), capacity(capacity) { cache_map.reserve(capacity); } // Returns pointer to value if found, nullptr otherwise ValueType* get(const KeyType& key) { + if (!enabled) return nullptr; + auto it = cache_map.find(key); if (it == cache_map.end()) { return nullptr; @@ -25,12 +33,16 @@ public: // Returns pointer to value if found (without promoting it), nullptr otherwise ValueType* peek(const KeyType& key) const { + if (!enabled) return nullptr; + auto it = cache_map.find(key); return it != cache_map.end() ? &(it->second.second) : nullptr; } // Inserts or updates a key-value pair void put(const KeyType& key, const ValueType& value) { + if (!enabled) return; + auto it = cache_map.find(key); if (it != cache_map.end()) { @@ -52,6 +64,19 @@ public: cache_map[key] = {cache_list.begin(), value}; } + // Enable or disable the LRU cache + void setEnabled(bool state) { + enabled = state; + if (!enabled) { + clear(); + } + } + + // Check if the cache is enabled + bool isEnabled() const { + return enabled; + } + // Attempts to get value, returns std::nullopt if not found std::optional try_get(const KeyType& key) { auto* val = get(key); @@ -60,16 +85,18 @@ public: // Checks if key exists in cache bool contains(const KeyType& key) const { + if (!enabled) return false; return cache_map.find(key) != cache_map.end(); } // Removes a key from the cache if it exists bool erase(const KeyType& key) { + if (!enabled) return false; + auto it = cache_map.find(key); if (it == cache_map.end()) { return false; } - cache_list.erase(it->second.first); cache_map.erase(it); return true; @@ -83,7 +110,7 @@ public: // Returns current number of elements in cache size_t size() const { - return cache_map.size(); + return enabled ? cache_map.size() : 0; } // Returns maximum capacity of cache @@ -93,6 +120,8 @@ public: // Resizes the cache, evicting LRU items if new capacity is smaller void resize(size_t new_capacity) { + if (!enabled) return; + capacity = new_capacity; while (cache_map.size() > capacity) { auto last = cache_list.back(); @@ -101,9 +130,4 @@ public: } cache_map.reserve(capacity); } - -private: - size_t capacity; - std::list cache_list; - std::unordered_map::iterator, ValueType>> cache_map; }; \ No newline at end of file diff --git a/src/core/arm/nce/patcher.h b/src/core/arm/nce/patcher.h index 21ea7fd2a1..c8c2ac7326 100644 --- a/src/core/arm/nce/patcher.h +++ b/src/core/arm/nce/patcher.h @@ -10,6 +10,7 @@ #include #include "common/common_types.h" +#include "common/settings.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/k_typed_address.h" #include "core/hle/kernel/physical_memory.h" @@ -61,8 +62,8 @@ private: void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg); private: - static constexpr size_t CACHE_SIZE = 1024; // Cache size for patch entries - LRUCache patch_cache{CACHE_SIZE}; + static constexpr size_t CACHE_SIZE = 4096; // Cache size for patch entries + LRUCache patch_cache{CACHE_SIZE, Settings::values.lru_cache_enabled.GetValue()}; void BranchToPatch(uintptr_t module_dest) { // Try to get existing patch entry from cache