Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refreshinterval #3

Merged
merged 3 commits into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 92 additions & 10 deletions src/Ryujinx.Ava/AppHost.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ARMeilleure.Translation;
using ARMeilleure.Translation;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
Expand Down Expand Up @@ -58,6 +58,7 @@
using IRenderer = Ryujinx.Graphics.GAL.IRenderer;
using Key = Ryujinx.Input.Key;
using MouseButton = Ryujinx.Input.MouseButton;
using PresentIntervalState = Ryujinx.Common.Configuration.PresentIntervalState;
using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
using Size = Avalonia.Size;
using Switch = Ryujinx.HLE.Switch;
Expand Down Expand Up @@ -189,6 +190,9 @@ public AppHost(
ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Event += UpdateColorSpacePassthrough;
ConfigurationState.Instance.Graphics.PresentIntervalState.Event += UpdatePresentIntervalState;
ConfigurationState.Instance.Graphics.CustomPresentInterval.Event += UpdateCustomPresentIntervalValue;
ConfigurationState.Instance.Graphics.EnableCustomPresentInterval.Event += UpdateCustomPresentIntervalEnabled;

ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
ConfigurationState.Instance.Multiplayer.Mode.Event += UpdateMultiplayerModeState;
Expand Down Expand Up @@ -235,6 +239,37 @@ private void UpdateColorSpacePassthrough(object sender, ReactiveEventArgs<bool>
_renderer.Window?.SetColorSpacePassthrough((bool)ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Value);
}

private void UpdatePresentIntervalState(object sender, ReactiveEventArgs<PresentIntervalState> e)
{
if (Device != null)
{
Device.PresentIntervalState = e.NewValue;
Device.UpdatePresentInterval();
}
//vulkan present mode may change in response, so recreate the swapchain
_renderer.Window?.ChangePresentIntervalState((Ryujinx.Graphics.GAL.PresentIntervalState)e.NewValue);
ConfigurationState.Instance.Graphics.PresentIntervalState.Value = e.NewValue;
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
}

private void UpdateCustomPresentIntervalValue(object sender, ReactiveEventArgs<int> e)
{
if (Device != null)
{
Device.TargetPresentInterval = e.NewValue;
Device.UpdatePresentInterval();
}
}

private void UpdateCustomPresentIntervalEnabled(object sender, ReactiveEventArgs<bool> e)
{
if (Device != null)
{
Device.CustomPresentIntervalEnabled = e.NewValue;
Device.UpdatePresentInterval();
}
}

private void ShowCursor()
{
Dispatcher.UIThread.Post(() =>
Expand Down Expand Up @@ -516,6 +551,12 @@ private void HideCursorState_Changed(object sender, ReactiveEventArgs<HideCursor
}
}

public void UpdatePresentInterval(PresentIntervalState presentIntervalState)
{
PresentIntervalState oldState = ConfigurationState.Instance.Graphics.PresentIntervalState.Value;
UpdatePresentIntervalState(this, new ReactiveEventArgs<PresentIntervalState>(oldState, presentIntervalState));
}

public async Task<bool> LoadGuestApplication()
{
InitializeSwitchInstance();
Expand Down Expand Up @@ -775,7 +816,7 @@ private void InitializeSwitchInstance()
_viewModel.UiHandler,
(SystemLanguage)ConfigurationState.Instance.System.Language.Value,
(RegionCode)ConfigurationState.Instance.System.Region.Value,
ConfigurationState.Instance.Graphics.EnableVsync,
ConfigurationState.Instance.Graphics.PresentIntervalState,
ConfigurationState.Instance.System.EnableDockedMode,
ConfigurationState.Instance.System.EnablePtc,
ConfigurationState.Instance.System.EnableInternetAccess,
Expand All @@ -789,7 +830,8 @@ private void InitializeSwitchInstance()
ConfigurationState.Instance.System.AudioVolume,
ConfigurationState.Instance.System.UseHypervisor,
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value,
ConfigurationState.Instance.Multiplayer.Mode);
ConfigurationState.Instance.Multiplayer.Mode,
ConfigurationState.Instance.Graphics.CustomPresentInterval.Value);

Device = new Switch(configuration);
}
Expand Down Expand Up @@ -915,7 +957,7 @@ private void RenderLoop()
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
Translator.IsReadyForTranslation.Set();

_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
_renderer.Window.ChangePresentIntervalState((Ryujinx.Graphics.GAL.PresentIntervalState)Device.PresentIntervalState);

while (_isActive)
{
Expand Down Expand Up @@ -963,14 +1005,15 @@ public void UpdateStatus()
{
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued.
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance[LocaleKeys.Docked] : LocaleManager.Instance[LocaleKeys.Handheld];
string presentIntervalState = Device.PresentIntervalState.ToString();

if (GraphicsConfig.ResScale != 1)
{
dockedMode += $" ({GraphicsConfig.ResScale}x)";
}

StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.EnableDeviceVsync,
presentIntervalState,
LocaleManager.Instance[LocaleKeys.VolumeShort] + $": {(int)(Device.GetVolume() * 100)}%",
ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan ? "Vulkan" : "OpenGL",
dockedMode,
Expand Down Expand Up @@ -1062,9 +1105,40 @@ private bool UpdateFrame()
{
switch (currentHotkeyState)
{
case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;

//todo default
case KeyboardHotkeyState.TogglePresentIntervalState:
PresentIntervalState oldState = Device.PresentIntervalState;
PresentIntervalState newState;
if (oldState == PresentIntervalState.Switch)
{
newState = PresentIntervalState.Unbounded;
}
else if (oldState == PresentIntervalState.Unbounded)
{
if (ConfigurationState.Instance.Graphics.EnableCustomPresentInterval)
{
newState = PresentIntervalState.Custom;
}
else
{
newState = PresentIntervalState.Switch;
}
}
else
{
newState = PresentIntervalState.Switch;
}
UpdatePresentIntervalState(this, new ReactiveEventArgs<PresentIntervalState>(oldState, newState));
_viewModel.ShowCustomPresentIntervalPicker =
(newState == PresentIntervalState.Custom);
break;
case KeyboardHotkeyState.CustomPresentIntervalDecrement:
Device.DecrementCustomPresentInterval();
_viewModel.CustomPresentInterval -= 1;
break;
case KeyboardHotkeyState.CustomPresentIntervalIncrement:
Device.IncrementCustomPresentInterval();
_viewModel.CustomPresentInterval += 1;
break;
case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true;
Expand Down Expand Up @@ -1150,9 +1224,9 @@ private KeyboardHotkeyState GetHotkeyState()
{
KeyboardHotkeyState state = KeyboardHotkeyState.None;

if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync))
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.PresentIntervalState))
{
state = KeyboardHotkeyState.ToggleVSync;
state = KeyboardHotkeyState.TogglePresentIntervalState;
}
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
{
Expand Down Expand Up @@ -1186,6 +1260,14 @@ private KeyboardHotkeyState GetHotkeyState()
{
state = KeyboardHotkeyState.VolumeDown;
}
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.CustomPresentIntervalIncrement))
{
state = KeyboardHotkeyState.CustomPresentIntervalIncrement;
}
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.CustomPresentIntervalDecrement))
{
state = KeyboardHotkeyState.CustomPresentIntervalDecrement;
}

return state;
}
Expand Down
19 changes: 16 additions & 3 deletions src/Ryujinx.Ava/Assets/Locales/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,27 @@
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "Latin American Spanish",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "Simplified Chinese",
"SettingsTabSystemSystemLanguageTraditionalChinese": "Traditional Chinese",
"SettingsTabSystemSystemTimeZone": "System TimeZone:",
"SettingsTabSystemSystemTimeZone": "System Time Zone:",
"SettingsTabSystemSystemTime": "System Time:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemPresentIntervalState": "VSync:",
"SettingsTabSystemEnableCustomPresentInterval": "Enable custom refresh rate (Experimental)",
"SettingsTabSystemPresentIntervalStateSwitch": "On",
"SettingsTabSystemPresentIntervalStateUnbounded": "Off",
"SettingsTabSystemPresentIntervalStateCustom": "Custom Refresh Rate",
"SettingsTabSystemPresentIntervalStateTooltip": "Emulated Vertical Sync. 'On' emulates the Switch's refresh rate of 60Hz. 'Off' is an unbounded refresh rate.",
"SettingsTabSystemPresentIntervalStateTooltipCustom": "Emulated Vertical Sync. 'On' emulates the Switch's refresh rate of 60Hz. 'Off' is an unbounded refresh rate. 'Custom' emulates the specified custom refresh rate.",
"SettingsTabSystemEnableCustomPresentIntervalTooltip": "Allows the user to specify an emulated refresh rate. In some titles, this may speed up or slow down the rate of gameplay logic. In other titles, it may allow for capping FPS at some multiple of the refresh rate, or lead to unpredictable behavior. This is an experimental feature, with no guarantees for how gameplay will be affected. \n\nLeave OFF if unsure.",
"SettingsTabSystemCustomPresentIntervalValueTooltip": "The custom refresh rate target value.",
"SettingsTabSystemCustomPresentIntervalSliderTooltip": "The custom refresh rate, as a percentage of the normal Switch refresh rate.",
"SettingsTabSystemCustomPresentIntervalValue": "Custom Refresh Rate Value:",
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integrity Checks",
"SettingsTabSystemAudioBackend": "Audio Backend:",
"SettingsTabSystemAudioBackendDummy": "Dummy",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemCustomPresentInterval": "Interval",
"SettingsTabSystemHacks": "Hacks",
"SettingsTabSystemHacksNote": "May cause instability",
"SettingsTabSystemExpandDramSize": "Use alternative memory layout (Developers)",
Expand Down Expand Up @@ -571,11 +582,13 @@
"RyujinxUpdater": "Ryujinx Updater",
"SettingsTabHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:",
"SettingsTabHotkeysTogglePresentIntervalStateHotkey": "Toggle Present Interval state:",
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
"SettingsTabHotkeysShowUiHotkey": "Show UI:",
"SettingsTabHotkeysPauseHotkey": "Pause:",
"SettingsTabHotkeysToggleMuteHotkey": "Mute:",
"SettingsTabHotkeysIncrementCustomPresentIntervalHotkey": "Raise custom refresh interval",
"SettingsTabHotkeysDecrementCustomPresentIntervalHotkey": "Lower custom refresh interval",
"ControllerMotionTitle": "Motion Control Settings",
"ControllerRumbleTitle": "Rumble Settings",
"SettingsSelectThemeFileDialogTitle": "Select Theme File",
Expand Down
5 changes: 3 additions & 2 deletions src/Ryujinx.Ava/Assets/Styles/Themes.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
<Color x:Key="AppListBackgroundColor">#b3ffffff</Color>
<Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color>
<Color x:Key="SecondaryTextColor">#A0000000</Color>
<Color x:Key="VsyncEnabled">#FF2EEAC9</Color>
<Color x:Key="VsyncDisabled">#FFFF4554</Color>
<Color x:Key="Switch">#FF2EEAC9</Color>
<Color x:Key="Unbounded">#FFFF4554</Color>
<Color x:Key="Custom">#6483F5</Color>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
Expand Down
4 changes: 3 additions & 1 deletion src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public enum KeyboardHotkeyState
{
None,
ToggleVSync,
TogglePresentIntervalState,
Screenshot,
ShowUi,
Pause,
Expand All @@ -12,5 +12,7 @@ public enum KeyboardHotkeyState
ResScaleDown,
VolumeUp,
VolumeDown,
CustomPresentIntervalIncrement,
CustomPresentIntervalDecrement,
}
}
6 changes: 3 additions & 3 deletions src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Ryujinx.Ava.UI.Models
{
internal class StatusUpdatedEventArgs : EventArgs
{
public bool VSyncEnabled { get; }
public string PresentIntervalState { get; }
public string VolumeStatus { get; }
public string GpuBackend { get; }
public string AspectRatio { get; }
Expand All @@ -13,9 +13,9 @@ internal class StatusUpdatedEventArgs : EventArgs
public string GameStatus { get; }
public string GpuName { get; }

public StatusUpdatedEventArgs(bool vSyncEnabled, string volumeStatus, string gpuBackend, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, string gpuName)
public StatusUpdatedEventArgs(string presentIntervalState, string volumeStatus, string gpuBackend, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, string gpuName)
{
VSyncEnabled = vSyncEnabled;
PresentIntervalState = presentIntervalState;
VolumeStatus = volumeStatus;
GpuBackend = gpuBackend;
DockedMode = dockedMode;
Expand Down
Loading
Loading