From d9bc9efe3dc660686c8cbf857cd42d89362dfa42 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 17 May 2026 20:58:54 -0400 Subject: [PATCH] added toggle in UI --- assets/Locales/Root.json | 50 +++++++++++++++++++ src/Ryujinx/Systems/AppHost.cs | 30 ++++++++++- .../Configuration/ConfigurationFileFormat.cs | 7 ++- .../ConfigurationState.Migration.cs | 4 +- .../Configuration/ConfigurationState.Model.cs | 7 +++ .../Configuration/ConfigurationState.cs | 1 + .../UI/ViewModels/SettingsViewModel.cs | 3 ++ .../UI/Views/Settings/SettingsCPUView.axaml | 5 ++ 8 files changed, 103 insertions(+), 4 deletions(-) diff --git a/assets/Locales/Root.json b/assets/Locales/Root.json index 757ddeec8..db84fd3ae 100644 --- a/assets/Locales/Root.json +++ b/assets/Locales/Root.json @@ -200,6 +200,31 @@ "zh_TW": "使用 Hypervisor" } }, + { + "ID": "SettingsTabSystemGCLowLatency", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Use Low-latency Garbage Collector", + "es_ES": "Usa recolección de basura de baja latencia", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "MenuBarFile", "Translations": { @@ -16500,6 +16525,31 @@ "zh_TW": "變更客體記憶體的映射和存取方式。這會極大地影響模擬 CPU 效能。\n\n如果不確定,請設定為主體略過檢查模式。" } }, + { + "ID": "GCLowLatencyTooltip", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Sets the garbage collector for the CLR to low-latency mode.\n\nThis may decrease stuttering at the cost of performance.\n\nLeave OFF if unsure.", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "MemoryManagerSoftwareTooltip", "Translations": { diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index afad7bc7b..627e486d2 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -580,7 +580,12 @@ namespace Ryujinx.Ava.Systems { _isActive = false; _playTimer.Stop(); + GCSettings.LatencyMode = GCLatencyMode.Interactive; + if (ConfigurationState.Instance.System.GCLowLatency) + { + Logger.Info?.Print(LogClass.Application, "Garbage collector set to interactive mode."); + } } private void Exit() @@ -664,7 +669,12 @@ namespace Ryujinx.Ava.Systems _chrono.Stop(); _playTimer.Stop(); + GCSettings.LatencyMode = GCLatencyMode.Interactive; + if (ConfigurationState.Instance.System.GCLowLatency) + { + Logger.Info?.Print(LogClass.Application, "Garbage collector set to interactive mode."); + } } public void DisposeGpu() @@ -918,8 +928,14 @@ namespace Ryujinx.Ava.Systems ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, appMetadata => appMetadata.UpdatePreGame() ); + _playTimer.Start(); - GCSettings.LatencyMode = GCLatencyMode.LowLatency; + + if (ConfigurationState.Instance.System.GCLowLatency) + { + GCSettings.LatencyMode = GCLatencyMode.LowLatency; + Logger.Info?.Print(LogClass.Application, "Garbage collector set to low latency mode."); + } } internal void Resume() @@ -930,7 +946,12 @@ namespace Ryujinx.Ava.Systems _playTimer.Start(); _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI); Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed."); - GCSettings.LatencyMode = GCLatencyMode.LowLatency; + + if (ConfigurationState.Instance.System.GCLowLatency) + { + GCSettings.LatencyMode = GCLatencyMode.LowLatency; + Logger.Info?.Print(LogClass.Application, "Garbage collector set to low latency mode."); + } } internal void Pause() @@ -941,7 +962,12 @@ namespace Ryujinx.Ava.Systems _playTimer.Stop(); _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]); Logger.Info?.Print(LogClass.Emulation, "Emulation was paused."); + GCSettings.LatencyMode = GCLatencyMode.Interactive; + if (ConfigurationState.Instance.System.GCLowLatency) + { + Logger.Info?.Print(LogClass.Application, "Garbage collector set to interactive mode."); + } } private void InitEmulatedSwitch() diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs index 0b451eacb..55b2d2cac 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationFileFormat.cs @@ -17,7 +17,7 @@ namespace Ryujinx.Ava.Systems.Configuration /// /// The current version of the file format /// - public const int CurrentVersion = 72; + public const int CurrentVersion = 73; /// /// Version of the configuration file format @@ -470,6 +470,11 @@ namespace Ryujinx.Ava.Systems.Configuration /// Uses Hypervisor over JIT if available /// public bool UseHypervisor { get; set; } + + /// + /// Enable or disable low-latency mode for garbage collection + /// + public bool GCLowLatency { get; set; } /// /// Enables or disables the GDB stub diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs index 90a045a67..8890055ac 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Migration.cs @@ -112,6 +112,7 @@ namespace Ryujinx.Ava.Systems.Configuration System.IgnoreControllerApplet.Value = cff.IgnoreApplet; System.SkipUserProfilesManager.Value = cff.SkipUserProfiles; System.UseHypervisor.Value = cff.UseHypervisor; + System.GCLowLatency.Value = cff.GCLowLatency; UI.GuiColumns.FavColumn.Value = shouldLoadFromFile ? cff.GuiColumns.FavColumn : UI.GuiColumns.FavColumn.Value; UI.GuiColumns.IconColumn.Value = shouldLoadFromFile ? cff.GuiColumns.IconColumn : UI.GuiColumns.IconColumn.Value; @@ -534,7 +535,8 @@ namespace Ryujinx.Ava.Systems.Configuration { if (cff.AudioBackend is AudioBackend.SDL2) cff.AudioBackend = AudioBackend.SDL3; - }) + }), + (72, static cff => cff.GCLowLatency = false) ); } } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs index 7775125d4..c66f74ed5 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.Model.cs @@ -417,6 +417,11 @@ namespace Ryujinx.Ava.Systems.Configuration /// Uses Hypervisor over JIT if available /// public ReactiveObject UseHypervisor { get; private set; } + + /// + /// Enable or disable low-latency garbage collection + /// + public ReactiveObject GCLowLatency { get; private set; } public SystemSection() { @@ -471,6 +476,8 @@ namespace Ryujinx.Ava.Systems.Configuration AudioVolume.LogChangesToValue(nameof(AudioVolume)); UseHypervisor = new ReactiveObject(); UseHypervisor.LogChangesToValue(nameof(UseHypervisor)); + GCLowLatency = new ReactiveObject(); + GCLowLatency.LogChangesToValue(nameof(GCLowLatency)); } } diff --git a/src/Ryujinx/Systems/Configuration/ConfigurationState.cs b/src/Ryujinx/Systems/Configuration/ConfigurationState.cs index e4874963d..b4b5e8029 100644 --- a/src/Ryujinx/Systems/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Systems/Configuration/ConfigurationState.cs @@ -87,6 +87,7 @@ namespace Ryujinx.Ava.Systems.Configuration IgnoreApplet = System.IgnoreControllerApplet, SkipUserProfiles = System.SkipUserProfilesManager, UseHypervisor = System.UseHypervisor, + GCLowLatency = System.GCLowLatency, GuiColumns = new GuiColumns { FavColumn = UI.GuiColumns.FavColumn, diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 6904d4ebc..d4532e8ca 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -286,6 +286,7 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsVulkanSelected => GraphicsBackendIndex == 1 || (GraphicsBackendIndex == 0 && !OperatingSystem.IsMacOS()); public bool UseHypervisor { get; set; } + public bool GCLowLatency { get; set; } public bool DisableP2P { get; set; } public bool ShowDirtyHacks => ConfigurationState.Instance.Hacks.ShowDirtyHacks; @@ -689,6 +690,7 @@ namespace Ryujinx.Ava.UI.ViewModels EnableLowPowerPptc = config.System.EnableLowPowerPtc; MemoryMode = (int)config.System.MemoryManagerMode.Value; UseHypervisor = config.System.UseHypervisor; + GCLowLatency = config.System.GCLowLatency; TurboMultiplier = config.System.TickScalar; // Graphics @@ -800,6 +802,7 @@ namespace Ryujinx.Ava.UI.ViewModels config.System.EnableLowPowerPtc.Value = EnableLowPowerPptc; config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode; config.System.UseHypervisor.Value = UseHypervisor; + config.System.GCLowLatency.Value = GCLowLatency; config.System.TickScalar.Value = TurboMultiplier; // Graphics diff --git a/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml index 2424aca97..c253c1aa0 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsCPUView.axaml @@ -71,6 +71,11 @@ + + +