Migrate Graphics to SettingsGraphicsViewModel

This commit is contained in:
Isaac Marovitz 2024-04-19 15:53:40 -04:00
parent 7e19054de1
commit ae97783459
No known key found for this signature in database
GPG key ID: 97250B2B09A132E1
5 changed files with 362 additions and 259 deletions

View file

@ -0,0 +1,321 @@
using Avalonia.Controls;
using Avalonia.Threading;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.UI.Common.Configuration;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.ViewModels.Settings
{
public class SettingsGraphicsViewModel: BaseModel
{
public event Action DirtyEvent;
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
public bool ColorSpacePassthroughAvailable => OperatingSystem.IsMacOS();
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
public bool IsVulkanSelected => GraphicsBackendIndex == 0;
public string ScalingFilterLevelText => ScalingFilterLevel.ToString("0");
private readonly List<string> _gpuIds = new();
private int _graphicsBackendIndex;
public int GraphicsBackendIndex
{
get => _graphicsBackendIndex;
set
{
_graphicsBackendIndex = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsVulkanSelected));
DirtyEvent?.Invoke();
}
}
private int _preferredGpuIndex;
public int PreferredGpuIndex
{
get => _preferredGpuIndex;
set
{
_preferredGpuIndex = value;
OnPropertyChanged();
DirtyEvent?.Invoke();
}
}
private bool _isVulkanAvailable = true;
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged();
}
}
private bool _enableShaderCache;
public bool EnableShaderCache
{
get => _enableShaderCache;
set
{
_enableShaderCache = value;
DirtyEvent?.Invoke();
}
}
private bool _enableTextureRecompression;
public bool EnableTextureRecompression
{
get => _enableTextureRecompression;
set
{
_enableTextureRecompression = value;
DirtyEvent?.Invoke();
}
}
private bool _enableMacroHLE;
public bool EnableMacroHLE
{
get => _enableMacroHLE;
set
{
_enableMacroHLE = value;
DirtyEvent?.Invoke();
}
}
private bool _enableColorSpacePassthrough;
public bool EnableColorSpacePassthrough
{
get => _enableColorSpacePassthrough;
set
{
_enableColorSpacePassthrough = value;
DirtyEvent?.Invoke();
}
}
private int _resolutionScale;
public int ResolutionScale
{
get => _resolutionScale;
set
{
_resolutionScale = value;
OnPropertyChanged(nameof(CustomResolutionScale));
OnPropertyChanged(nameof(IsCustomResolutionScaleActive));
DirtyEvent?.Invoke();
}
}
private float _customResolutionScale;
public float CustomResolutionScale
{
get => _customResolutionScale;
set
{
_customResolutionScale = MathF.Round(value, 1);
OnPropertyChanged();
DirtyEvent?.Invoke();
}
}
private int _maxAnisotropy;
public int MaxAnisotropy
{
get => _maxAnisotropy;
set
{
_maxAnisotropy = value;
DirtyEvent?.Invoke();
}
}
private int _aspectRatio;
public int AspectRatio
{
get => _aspectRatio;
set
{
_aspectRatio = value;
DirtyEvent?.Invoke();
}
}
private int _graphicsBackendMultithreadingIndex;
public int GraphicsBackendMultithreadingIndex
{
get => _graphicsBackendMultithreadingIndex;
set
{
_graphicsBackendMultithreadingIndex = value;
OnPropertyChanged();
DirtyEvent?.Invoke();
}
}
private string _shaderDumpPath;
public string ShaderDumpPath
{
get => _shaderDumpPath;
set
{
_shaderDumpPath = value;
DirtyEvent?.Invoke();
}
}
private int _antiAliasingEffect;
public int AntiAliasingEffect
{
get => _antiAliasingEffect;
set
{
_antiAliasingEffect = value;
DirtyEvent?.Invoke();
}
}
private int _scalingFilter;
public int ScalingFilter
{
get => _scalingFilter;
set
{
_scalingFilter = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsScalingFilterActive));
DirtyEvent?.Invoke();
}
}
private int _scalingFilterLevel;
public int ScalingFilterLevel
{
get => _scalingFilterLevel;
set
{
_scalingFilterLevel = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ScalingFilterLevelText));
DirtyEvent?.Invoke();
}
}
public SettingsGraphicsViewModel()
{
AvailableGpus = new ObservableCollection<ComboBoxItem>();
ConfigurationState config = ConfigurationState.Instance;
GraphicsBackendIndex = (int)config.Graphics.GraphicsBackend.Value;
// Physical devices are queried asynchronously hence the preferred index config value is loaded in LoadAvailableGpus().
EnableShaderCache = config.Graphics.EnableShaderCache;
EnableTextureRecompression = config.Graphics.EnableTextureRecompression;
EnableMacroHLE = config.Graphics.EnableMacroHLE;
EnableColorSpacePassthrough = config.Graphics.EnableColorSpacePassthrough;
ResolutionScale = config.Graphics.ResScale == -1 ? 4 : config.Graphics.ResScale - 1;
CustomResolutionScale = config.Graphics.ResScaleCustom;
MaxAnisotropy = config.Graphics.MaxAnisotropy == -1 ? 0 : (int)(MathF.Log2(config.Graphics.MaxAnisotropy));
AspectRatio = (int)config.Graphics.AspectRatio.Value;
AntiAliasingEffect = (int)config.Graphics.AntiAliasing.Value;
ScalingFilter = (int)config.Graphics.ScalingFilter.Value;
ScalingFilterLevel = config.Graphics.ScalingFilterLevel.Value;
GraphicsBackendMultithreadingIndex = (int)config.Graphics.BackendThreading.Value;
ShaderDumpPath = config.Graphics.ShadersDumpPath;
if (Program.PreviewerDetached)
{
Task.Run(LoadAvailableGpus);
}
}
private async Task LoadAvailableGpus()
{
AvailableGpus.Clear();
var devices = VulkanRenderer.GetPhysicalDevices();
if (devices.Length == 0)
{
IsVulkanAvailable = false;
GraphicsBackendIndex = 1;
}
else
{
foreach (var device in devices)
{
await Dispatcher.UIThread.InvokeAsync(() =>
{
_gpuIds.Add(device.Id);
AvailableGpus.Add(new ComboBoxItem { Content = $"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}" });
});
}
}
// GPU configuration needs to be loaded during the async method or it will always return 0.
PreferredGpuIndex = _gpuIds.Contains(ConfigurationState.Instance.Graphics.PreferredGpu) ?
_gpuIds.IndexOf(ConfigurationState.Instance.Graphics.PreferredGpu) : 0;
}
public bool CheckIfModified(ConfigurationState config)
{
bool isDirty = false;
isDirty |= config.Graphics.GraphicsBackend.Value != (GraphicsBackend)GraphicsBackendIndex;
isDirty |= config.Graphics.PreferredGpu.Value != _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
isDirty |= config.Graphics.EnableShaderCache.Value != EnableShaderCache;
isDirty |= config.Graphics.EnableTextureRecompression.Value != EnableTextureRecompression;
isDirty |= config.Graphics.EnableMacroHLE.Value != EnableMacroHLE;
isDirty |= config.Graphics.EnableColorSpacePassthrough.Value != EnableColorSpacePassthrough;
isDirty |= config.Graphics.ResScale.Value != (ResolutionScale == 4 ? -1 : ResolutionScale + 1);
isDirty |= config.Graphics.ResScaleCustom.Value != CustomResolutionScale;
isDirty |= config.Graphics.MaxAnisotropy.Value != (MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy));
isDirty |= config.Graphics.AspectRatio.Value != (AspectRatio)AspectRatio;
isDirty |= config.Graphics.AntiAliasing.Value != (AntiAliasing)AntiAliasingEffect;
isDirty |= config.Graphics.ScalingFilter.Value != (ScalingFilter)ScalingFilter;
isDirty |= config.Graphics.ScalingFilterLevel.Value != ScalingFilterLevel;
isDirty |= config.Graphics.BackendThreading.Value != (BackendThreading)GraphicsBackendMultithreadingIndex;
isDirty |= config.Graphics.ShadersDumpPath.Value != ShaderDumpPath;
return isDirty;
}
public void Save(ConfigurationState config)
{
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
config.Graphics.EnableShaderCache.Value = EnableShaderCache;
config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression;
config.Graphics.EnableMacroHLE.Value = EnableMacroHLE;
config.Graphics.EnableColorSpacePassthrough.Value = EnableColorSpacePassthrough;
config.Graphics.ResScale.Value = ResolutionScale == 4 ? -1 : ResolutionScale + 1;
config.Graphics.ResScaleCustom.Value = CustomResolutionScale;
config.Graphics.MaxAnisotropy.Value = MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy);
config.Graphics.AspectRatio.Value = (AspectRatio)AspectRatio;
config.Graphics.AntiAliasing.Value = (AntiAliasing)AntiAliasingEffect;
config.Graphics.ScalingFilter.Value = (ScalingFilter)ScalingFilter;
config.Graphics.ScalingFilterLevel.Value = ScalingFilterLevel;
config.Graphics.BackendThreading.Value = (BackendThreading)GraphicsBackendMultithreadingIndex;
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
if (config.Graphics.BackendThreading != (BackendThreading)GraphicsBackendMultithreadingIndex)
{
DriverUtilities.ToggleOGLThreading(GraphicsBackendMultithreadingIndex == (int)BackendThreading.Off);
}
}
}
}

View file

@ -1,22 +1,17 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Time.TimeZone; using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using Ryujinx.UI.Common.Configuration; using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Configuration.System; using Ryujinx.UI.Common.Configuration.System;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -35,15 +30,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
private readonly Dictionary<string, string> _networkInterfaces; private readonly Dictionary<string, string> _networkInterfaces;
private float _customResolutionScale;
private int _resolutionScale;
private int _graphicsBackendMultithreadingIndex;
private bool _isVulkanAvailable = true;
private bool _directoryChanged; private bool _directoryChanged;
private readonly List<string> _gpuIds = new();
private int _graphicsBackendIndex;
private int _scalingFilter;
private int _scalingFilterLevel;
private int _networkInterfaceIndex; private int _networkInterfaceIndex;
private int _multiplayerModeIndex; private int _multiplayerModeIndex;
@ -64,64 +52,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
public event Action<bool> DirtyEvent; public event Action<bool> DirtyEvent;
public event Action<bool> ToggleButtons; public event Action<bool> ToggleButtons;
public int ResolutionScale
{
get => _resolutionScale;
set
{
_resolutionScale = value;
OnPropertyChanged(nameof(CustomResolutionScale));
OnPropertyChanged(nameof(IsCustomResolutionScaleActive));
}
}
public int GraphicsBackendMultithreadingIndex
{
get => _graphicsBackendMultithreadingIndex;
set
{
_graphicsBackendMultithreadingIndex = value;
if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value)
{
Dispatcher.UIThread.InvokeAsync(() =>
ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
"",
"",
LocaleManager.Instance[LocaleKeys.InputDialogOk],
LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle])
);
}
OnPropertyChanged();
}
}
public float CustomResolutionScale
{
get => _customResolutionScale;
set
{
_customResolutionScale = MathF.Round(value, 1);
OnPropertyChanged();
}
}
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged();
}
}
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
public bool IsHypervisorAvailable => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64; public bool IsHypervisorAvailable => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
public bool DirectoryChanged public bool DirectoryChanged
@ -247,102 +177,15 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
} }
} }
private bool _enableShaderCache;
public bool EnableShaderCache
{
get => _enableShaderCache;
set
{
_enableShaderCache = value;
CheckIfModified();
}
}
private bool _enableTextureRecompression;
public bool EnableTextureRecompression
{
get => _enableTextureRecompression;
set
{
_enableTextureRecompression = value;
CheckIfModified();
}
}
private bool _enableMacroHLE;
public bool EnableMacroHLE
{
get => _enableMacroHLE;
set
{
_enableMacroHLE = value;
CheckIfModified();
}
}
private bool _enableColorSpacePassthrough;
public bool EnableColorSpacePassthrough
{
get => _enableColorSpacePassthrough;
set
{
_enableColorSpacePassthrough = value;
CheckIfModified();
}
}
public bool ColorSpacePassthroughAvailable => IsMacOS;
public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
public bool IsVulkanSelected => GraphicsBackendIndex == 0;
public bool UseHypervisor { get; set; } public bool UseHypervisor { get; set; }
public string TimeZone { get; set; } public string TimeZone { get; set; }
public string ShaderDumpPath { get; set; }
public int Language { get; set; } public int Language { get; set; }
public int Region { get; set; } public int Region { get; set; }
public int MaxAnisotropy { get; set; }
public int AspectRatio { get; set; }
public int AntiAliasingEffect { get; set; }
public string ScalingFilterLevelText => ScalingFilterLevel.ToString("0");
public int ScalingFilterLevel
{
get => _scalingFilterLevel;
set
{
_scalingFilterLevel = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ScalingFilterLevelText));
}
}
public int MemoryMode { get; set; } public int MemoryMode { get; set; }
public int BaseStyleIndex { get; set; } public int BaseStyleIndex { get; set; }
public int GraphicsBackendIndex
{
get => _graphicsBackendIndex;
set
{
_graphicsBackendIndex = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsVulkanSelected));
}
}
public int ScalingFilter
{
get => _scalingFilter;
set
{
_scalingFilter = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsScalingFilterActive));
}
}
public int PreferredGpuIndex { get; set; }
private readonly SettingsGraphicsViewModel _graphicsViewModel;
private readonly SettingsAudioViewModel _audioViewModel; private readonly SettingsAudioViewModel _audioViewModel;
private readonly SettingsLoggingViewModel _loggingViewModel; private readonly SettingsLoggingViewModel _loggingViewModel;
@ -351,7 +194,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
internal AvaloniaList<TimeZone> TimeZones { get; set; } internal AvaloniaList<TimeZone> TimeZones { get; set; }
public AvaloniaList<string> GameDirectories { get; set; } public AvaloniaList<string> GameDirectories { get; set; }
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
public AvaloniaList<string> NetworkInterfaceList public AvaloniaList<string> NetworkInterfaceList
{ {
@ -384,15 +226,18 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
VirtualFileSystem virtualFileSystem, VirtualFileSystem virtualFileSystem,
ContentManager contentManager, ContentManager contentManager,
SettingsAudioViewModel audioViewModel, SettingsAudioViewModel audioViewModel,
SettingsGraphicsViewModel graphicsViewModel,
SettingsLoggingViewModel loggingViewModel) : this() SettingsLoggingViewModel loggingViewModel) : this()
{ {
_virtualFileSystem = virtualFileSystem; _virtualFileSystem = virtualFileSystem;
_contentManager = contentManager; _contentManager = contentManager;
_audioViewModel = audioViewModel; _audioViewModel = audioViewModel;
_graphicsViewModel = graphicsViewModel;
_loggingViewModel = loggingViewModel; _loggingViewModel = loggingViewModel;
_audioViewModel.DirtyEvent += CheckIfModified; _audioViewModel.DirtyEvent += CheckIfModified;
_graphicsViewModel.DirtyEvent += CheckIfModified;
_loggingViewModel.DirtyEvent += CheckIfModified; _loggingViewModel.DirtyEvent += CheckIfModified;
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
@ -405,7 +250,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
{ {
GameDirectories = new AvaloniaList<string>(); GameDirectories = new AvaloniaList<string>();
TimeZones = new AvaloniaList<TimeZone>(); TimeZones = new AvaloniaList<TimeZone>();
AvailableGpus = new ObservableCollection<ComboBoxItem>();
_validTzRegions = new List<string>(); _validTzRegions = new List<string>();
_networkInterfaces = new Dictionary<string, string>(); _networkInterfaces = new Dictionary<string, string>();
@ -413,7 +257,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
{ {
Task.Run(LoadAvailableGpus);
LoadCurrentConfiguration(); LoadCurrentConfiguration();
} }
} }
@ -456,29 +299,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
isDirty |= config.System.MemoryManagerMode.Value != (MemoryManagerMode)MemoryMode; isDirty |= config.System.MemoryManagerMode.Value != (MemoryManagerMode)MemoryMode;
isDirty |= config.System.UseHypervisor.Value != UseHypervisor; isDirty |= config.System.UseHypervisor.Value != UseHypervisor;
// Graphics if (_graphicsViewModel != null)
isDirty |= config.Graphics.GraphicsBackend.Value != (GraphicsBackend)GraphicsBackendIndex;
isDirty |= config.Graphics.PreferredGpu.Value != _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
isDirty |= config.Graphics.EnableShaderCache.Value != EnableShaderCache;
isDirty |= config.Graphics.EnableTextureRecompression.Value != EnableTextureRecompression;
isDirty |= config.Graphics.EnableMacroHLE.Value != EnableMacroHLE;
isDirty |= config.Graphics.EnableColorSpacePassthrough.Value != EnableColorSpacePassthrough;
isDirty |= config.Graphics.ResScale.Value != (ResolutionScale == 4 ? -1 : ResolutionScale + 1);
isDirty |= config.Graphics.ResScaleCustom.Value != CustomResolutionScale;
isDirty |= config.Graphics.MaxAnisotropy.Value != (MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy));
isDirty |= config.Graphics.AspectRatio.Value != (AspectRatio)AspectRatio;
isDirty |= config.Graphics.AntiAliasing.Value != (AntiAliasing)AntiAliasingEffect;
isDirty |= config.Graphics.ScalingFilter.Value != (ScalingFilter)ScalingFilter;
isDirty |= config.Graphics.ScalingFilterLevel.Value != ScalingFilterLevel;
if (ConfigurationState.Instance.Graphics.BackendThreading != (BackendThreading)GraphicsBackendMultithreadingIndex)
{ {
DriverUtilities.ToggleOGLThreading(GraphicsBackendMultithreadingIndex == (int)BackendThreading.Off); isDirty |= _graphicsViewModel.CheckIfModified(config);
} }
isDirty |= config.Graphics.BackendThreading.Value != (BackendThreading)GraphicsBackendMultithreadingIndex;
isDirty |= config.Graphics.ShadersDumpPath.Value != ShaderDumpPath;
if (_audioViewModel != null) if (_audioViewModel != null)
{ {
isDirty |= _audioViewModel.CheckIfModified(config); isDirty |= _audioViewModel.CheckIfModified(config);
@ -497,39 +322,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
IsModified = isDirty; IsModified = isDirty;
} }
private async Task LoadAvailableGpus()
{
AvailableGpus.Clear();
var devices = VulkanRenderer.GetPhysicalDevices();
if (devices.Length == 0)
{
IsVulkanAvailable = false;
GraphicsBackendIndex = 1;
}
else
{
foreach (var device in devices)
{
await Dispatcher.UIThread.InvokeAsync(() =>
{
_gpuIds.Add(device.Id);
AvailableGpus.Add(new ComboBoxItem { Content = $"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}" });
});
}
}
// GPU configuration needs to be loaded during the async method or it will always return 0.
PreferredGpuIndex = _gpuIds.Contains(ConfigurationState.Instance.Graphics.PreferredGpu) ?
_gpuIds.IndexOf(ConfigurationState.Instance.Graphics.PreferredGpu) : 0;
Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex)));
}
public async Task LoadTimeZones() public async Task LoadTimeZones()
{ {
_timeZoneContentManager = new TimeZoneContentManager(); _timeZoneContentManager = new TimeZoneContentManager();
@ -619,23 +411,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
MemoryMode = (int)config.System.MemoryManagerMode.Value; MemoryMode = (int)config.System.MemoryManagerMode.Value;
UseHypervisor = config.System.UseHypervisor; UseHypervisor = config.System.UseHypervisor;
// Graphics
GraphicsBackendIndex = (int)config.Graphics.GraphicsBackend.Value;
// Physical devices are queried asynchronously hence the prefered index config value is loaded in LoadAvailableGpus().
EnableShaderCache = config.Graphics.EnableShaderCache;
EnableTextureRecompression = config.Graphics.EnableTextureRecompression;
EnableMacroHLE = config.Graphics.EnableMacroHLE;
EnableColorSpacePassthrough = config.Graphics.EnableColorSpacePassthrough;
ResolutionScale = config.Graphics.ResScale == -1 ? 4 : config.Graphics.ResScale - 1;
CustomResolutionScale = config.Graphics.ResScaleCustom;
MaxAnisotropy = config.Graphics.MaxAnisotropy == -1 ? 0 : (int)(MathF.Log2(config.Graphics.MaxAnisotropy));
AspectRatio = (int)config.Graphics.AspectRatio.Value;
GraphicsBackendMultithreadingIndex = (int)config.Graphics.BackendThreading.Value;
ShaderDumpPath = config.Graphics.ShadersDumpPath;
AntiAliasingEffect = (int)config.Graphics.AntiAliasing.Value;
ScalingFilter = (int)config.Graphics.ScalingFilter.Value;
ScalingFilterLevel = config.Graphics.ScalingFilterLevel.Value;
// Network // Network
EnableInternetAccess = config.System.EnableInternetAccess; EnableInternetAccess = config.System.EnableInternetAccess;
// LAN interface index is loaded asynchronously in PopulateNetworkInterfaces() // LAN interface index is loaded asynchronously in PopulateNetworkInterfaces()
@ -684,29 +459,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode; config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
config.System.UseHypervisor.Value = UseHypervisor; config.System.UseHypervisor.Value = UseHypervisor;
// Graphics _graphicsViewModel?.Save(config);
config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
config.Graphics.EnableShaderCache.Value = EnableShaderCache;
config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression;
config.Graphics.EnableMacroHLE.Value = EnableMacroHLE;
config.Graphics.EnableColorSpacePassthrough.Value = EnableColorSpacePassthrough;
config.Graphics.ResScale.Value = ResolutionScale == 4 ? -1 : ResolutionScale + 1;
config.Graphics.ResScaleCustom.Value = CustomResolutionScale;
config.Graphics.MaxAnisotropy.Value = MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy);
config.Graphics.AspectRatio.Value = (AspectRatio)AspectRatio;
config.Graphics.AntiAliasing.Value = (AntiAliasing)AntiAliasingEffect;
config.Graphics.ScalingFilter.Value = (ScalingFilter)ScalingFilter;
config.Graphics.ScalingFilterLevel.Value = ScalingFilterLevel;
if (ConfigurationState.Instance.Graphics.BackendThreading != (BackendThreading)GraphicsBackendMultithreadingIndex)
{
DriverUtilities.ToggleOGLThreading(GraphicsBackendMultithreadingIndex == (int)BackendThreading.Off);
}
config.Graphics.BackendThreading.Value = (BackendThreading)GraphicsBackendMultithreadingIndex;
config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
_audioViewModel?.Save(config); _audioViewModel?.Save(config);
// Network // Network
@ -726,7 +479,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Settings
_directoryChanged = false; _directoryChanged = false;
} }
public void ApplyButton() public void ApplyButton()
{ {
SaveSettings(); SaveSettings();

View file

@ -10,9 +10,9 @@
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Settings" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Settings"
Design.Width="1000" Design.Width="1000"
mc:Ignorable="d" mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel"> x:DataType="viewModels:SettingsGraphicsViewModel">
<Design.DataContext> <Design.DataContext>
<viewModels:SettingsViewModel /> <viewModels:SettingsGraphicsViewModel />
</Design.DataContext> </Design.DataContext>
<ScrollViewer <ScrollViewer
Name="GraphicsPage" Name="GraphicsPage"
@ -265,6 +265,7 @@
<ComboBox Width="350" <ComboBox Width="350"
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
ToolTip.Tip="{locale:Locale GalThreadingTooltip}" ToolTip.Tip="{locale:Locale GalThreadingTooltip}"
SelectionChanged="GraphicsBackendMultithreadingIndex_OnSelectionChanged"
SelectedIndex="{Binding GraphicsBackendMultithreadingIndex}"> SelectedIndex="{Binding GraphicsBackendMultithreadingIndex}">
<ComboBoxItem> <ComboBoxItem>
<TextBlock Text="{locale:Locale CommonAuto}" /> <TextBlock Text="{locale:Locale CommonAuto}" />

View file

@ -1,12 +1,40 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels.Settings;
using Ryujinx.UI.Common.Configuration;
namespace Ryujinx.Ava.UI.Views.Settings namespace Ryujinx.Ava.UI.Views.Settings
{ {
public partial class SettingsGraphicsView : UserControl public partial class SettingsGraphicsView : UserControl
{ {
public SettingsGraphicsViewModel ViewModel;
public SettingsGraphicsView() public SettingsGraphicsView()
{ {
DataContext = ViewModel = new SettingsGraphicsViewModel();
InitializeComponent(); InitializeComponent();
} }
private void GraphicsBackendMultithreadingIndex_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source is not ComboBox comboBox)
{
return;
}
if (comboBox.SelectedIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value)
{
Dispatcher.UIThread.InvokeAsync(() =>
ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
"",
"",
LocaleManager.Instance[LocaleKeys.InputDialogOk],
LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle],
parent: this.VisualRoot as Window)
);
}
}
} }
} }

View file

@ -30,12 +30,14 @@ namespace Ryujinx.Ava.UI.Windows
Title = $"{LocaleManager.Instance[LocaleKeys.Settings]}"; Title = $"{LocaleManager.Instance[LocaleKeys.Settings]}";
AudioPage = new SettingsAudioView(); AudioPage = new SettingsAudioView();
GraphicsPage = new SettingsGraphicsView();
LoggingPage = new SettingsLoggingView(); LoggingPage = new SettingsLoggingView();
ViewModel = new SettingsViewModel( ViewModel = new SettingsViewModel(
virtualFileSystem, virtualFileSystem,
contentManager, contentManager,
AudioPage.ViewModel, AudioPage.ViewModel,
GraphicsPage.ViewModel,
LoggingPage.ViewModel); LoggingPage.ViewModel);
UiPage = new SettingsUiView(ViewModel); UiPage = new SettingsUiView(ViewModel);
@ -43,7 +45,6 @@ namespace Ryujinx.Ava.UI.Windows
HotkeysPage = new SettingsHotkeysView(ViewModel); HotkeysPage = new SettingsHotkeysView(ViewModel);
SystemPage = new SettingsSystemView(ViewModel); SystemPage = new SettingsSystemView(ViewModel);
CpuPage = new SettingsCPUView(); CpuPage = new SettingsCPUView();
GraphicsPage = new SettingsGraphicsView();
NetworkPage = new SettingsNetworkView(); NetworkPage = new SettingsNetworkView();
DataContext = ViewModel; DataContext = ViewModel;