Add custom refresh rate mode to VSync option (#238)

Rebased @jcm93's refreshinterval branch:
https://github.com/jcm93/Ryujinx/tree/refreshinterval

The option is placed under System/Hacks. Disabled, it's the default
Ryujinx behavior. Enabled, the behavior is shown in the attached
screenshots. If a framerate is too high or low, you can adjust the value
where you normally toggle VSync on and off. It will also cycle through
the default on/off toggles.

Also, in order to reduce clutter, I made an adjustment to remove the
target FPS and only show the percentage.

---------

Co-authored-by: jcm <6864788+jcm93@users.noreply.github.com>
This commit is contained in:
Keaton 2024-11-25 13:39:09 -06:00 committed by GitHub
parent 7e16fccfc1
commit 2e6794e69b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 678 additions and 110 deletions

View file

@ -63,6 +63,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private string _searchText;
private Timer _searchTimer;
private string _dockedStatusText;
private string _vSyncModeText;
private string _fifoStatusText;
private string _gameStatusText;
private string _volumeStatusText;
@ -80,7 +81,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool _showStatusSeparator;
private Brush _progressBarForegroundColor;
private Brush _progressBarBackgroundColor;
private Brush _vsyncColor;
private Brush _vSyncModeColor;
private byte[] _selectedIcon;
private bool _isAppletMenuActive;
private int _statusBarProgressMaximum;
@ -111,6 +112,8 @@ namespace Ryujinx.Ava.UI.ViewModels
private WindowState _windowState;
private double _windowWidth;
private double _windowHeight;
private int _customVSyncInterval;
private int _customVSyncIntervalPercentageProxy;
private bool _isActive;
private bool _isSubMenuOpen;
@ -145,6 +148,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Volume = ConfigurationState.Instance.System.AudioVolume;
}
CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value;
}
public void Initialize(
@ -447,17 +451,87 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public Brush VsyncColor
public Brush VSyncModeColor
{
get => _vsyncColor;
get => _vSyncModeColor;
set
{
_vsyncColor = value;
_vSyncModeColor = value;
OnPropertyChanged();
}
}
public bool ShowCustomVSyncIntervalPicker
{
get
{
if (_isGameRunning)
{
return AppHost.Device.VSyncMode ==
VSyncMode.Custom;
}
else
{
return false;
}
}
set
{
OnPropertyChanged();
}
}
public int CustomVSyncIntervalPercentageProxy
{
get => _customVSyncIntervalPercentageProxy;
set
{
int newInterval = (int)((value / 100f) * 60);
_customVSyncInterval = newInterval;
_customVSyncIntervalPercentageProxy = value;
if (_isGameRunning)
{
AppHost.Device.CustomVSyncInterval = newInterval;
AppHost.Device.UpdateVSyncInterval();
}
OnPropertyChanged((nameof(CustomVSyncInterval)));
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
}
}
public string CustomVSyncIntervalPercentageText
{
get
{
string text = CustomVSyncIntervalPercentageProxy.ToString() + "%";
return text;
}
set
{
}
}
public int CustomVSyncInterval
{
get => _customVSyncInterval;
set
{
_customVSyncInterval = value;
int newPercent = (int)((value / 60f) * 100);
_customVSyncIntervalPercentageProxy = newPercent;
if (_isGameRunning)
{
AppHost.Device.CustomVSyncInterval = value;
AppHost.Device.UpdateVSyncInterval();
}
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged();
}
}
public byte[] SelectedIcon
{
get => _selectedIcon;
@ -578,6 +652,17 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public string VSyncModeText
{
get => _vSyncModeText;
set
{
_vSyncModeText = value;
OnPropertyChanged();
}
}
public string DockedStatusText
{
get => _dockedStatusText;
@ -1292,17 +1377,18 @@ namespace Ryujinx.Ava.UI.ViewModels
{
Dispatcher.UIThread.InvokeAsync(() =>
{
Application.Current!.Styles.TryGetResource(args.VSyncEnabled
? "VsyncEnabled"
: "VsyncDisabled",
Application.Current!.Styles.TryGetResource(args.VSyncMode,
Application.Current.ActualThemeVariant,
out object color);
if (color is Color clr)
{
VsyncColor = new SolidColorBrush(clr);
VSyncModeColor = new SolidColorBrush(clr);
}
VSyncModeText = args.VSyncMode == "Custom" ? "Custom" : "VSync";
ShowCustomVSyncIntervalPicker =
args.VSyncMode == VSyncMode.Custom.ToString();
DockedStatusText = args.DockedMode;
AspectRatioStatusText = args.AspectRatio;
GameStatusText = args.GameStatus;
@ -1495,6 +1581,27 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public void ToggleVSyncMode()
{
AppHost.VSyncModeToggle();
OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker));
}
public void VSyncModeSettingChanged()
{
if (_isGameRunning)
{
AppHost.Device.CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value;
AppHost.Device.UpdateVSyncInterval();
}
CustomVSyncInterval = ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value;
OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged(nameof(CustomVSyncInterval));
}
public async Task ExitCurrentState()
{
if (WindowState is WindowState.FullScreen)

View file

@ -52,6 +52,10 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _graphicsBackendIndex;
private int _scalingFilter;
private int _scalingFilterLevel;
private int _customVSyncInterval;
private bool _enableCustomVSyncInterval;
private int _customVSyncIntervalPercentageProxy;
private VSyncMode _vSyncMode;
public event Action CloseWindow;
public event Action SaveSettingsEvent;
@ -154,7 +158,74 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableDockedMode { get; set; }
public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; }
public bool EnableVsync { get; set; }
public VSyncMode VSyncMode
{
get => _vSyncMode;
set
{
if (value == VSyncMode.Custom ||
value == VSyncMode.Switch ||
value == VSyncMode.Unbounded)
{
_vSyncMode = value;
OnPropertyChanged();
}
}
}
public int CustomVSyncIntervalPercentageProxy
{
get => _customVSyncIntervalPercentageProxy;
set
{
int newInterval = (int)((value / 100f) * 60);
_customVSyncInterval = newInterval;
_customVSyncIntervalPercentageProxy = value;
OnPropertyChanged((nameof(CustomVSyncInterval)));
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
}
}
public string CustomVSyncIntervalPercentageText
{
get
{
string text = CustomVSyncIntervalPercentageProxy.ToString() + "%";
return text;
}
}
public bool EnableCustomVSyncInterval
{
get => _enableCustomVSyncInterval;
set
{
_enableCustomVSyncInterval = value;
if (_vSyncMode == VSyncMode.Custom && !value)
{
VSyncMode = VSyncMode.Switch;
}
else if (value)
{
VSyncMode = VSyncMode.Custom;
}
OnPropertyChanged();
}
}
public int CustomVSyncInterval
{
get => _customVSyncInterval;
set
{
_customVSyncInterval = value;
int newPercent = (int)((value / 60f) * 100);
_customVSyncIntervalPercentageProxy = newPercent;
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged();
}
}
public bool EnablePptc { get; set; }
public bool EnableLowPowerPptc { get; set; }
public bool EnableInternetAccess { get; set; }
@ -484,7 +555,9 @@ namespace Ryujinx.Ava.UI.ViewModels
CurrentDate = currentDateTime.Date;
CurrentTime = currentDateTime.TimeOfDay;
EnableVsync = config.Graphics.EnableVsync;
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval.Value;
CustomVSyncInterval = config.Graphics.CustomVSyncInterval;
VSyncMode = config.Graphics.VSyncMode;
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
DramSize = config.System.DramSize;
IgnoreMissingServices = config.System.IgnoreMissingServices;
@ -590,7 +663,9 @@ namespace Ryujinx.Ava.UI.ViewModels
}
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
config.Graphics.EnableVsync.Value = EnableVsync;
config.Graphics.VSyncMode.Value = VSyncMode;
config.Graphics.EnableCustomVSyncInterval.Value = EnableCustomVSyncInterval;
config.Graphics.CustomVSyncInterval.Value = CustomVSyncInterval;
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
config.System.DramSize.Value = DramSize;
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
@ -660,6 +735,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
MainWindow.UpdateGraphicsConfig();
MainWindow.MainWindowViewModel.VSyncModeSettingChanged();
SaveSettingsEvent?.Invoke();