From d31360e7dab8cbf3ab3ae3e5dba1d27f70d64d09 Mon Sep 17 00:00:00 2001 From: gdk Date: Sat, 11 Jun 2022 20:33:07 -0300 Subject: [PATCH] Implement GPU selector and expose texture recompression on the UI and config --- Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs | 1 + Ryujinx.Graphics.GAL/DeviceInfo.cs | 18 + Ryujinx.Graphics.Vulkan/Vendor.cs | 21 + .../VulkanGraphicsDevice.cs | 101 ++-- .../VulkanInitialization.cs | 86 +++- Ryujinx.Headless.SDL2/Options.cs | 6 + Ryujinx.Headless.SDL2/Program.cs | 27 +- .../Configuration/ConfigurationFileFormat.cs | 12 +- .../Configuration/ConfigurationState.cs | 438 +++++++++--------- Ryujinx/Ui/MainWindow.cs | 18 +- Ryujinx/Ui/Windows/SettingsWindow.cs | 129 ++++-- Ryujinx/Ui/Windows/SettingsWindow.glade | 67 ++- 12 files changed, 602 insertions(+), 322 deletions(-) create mode 100644 Ryujinx.Graphics.GAL/DeviceInfo.cs diff --git a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs index 07c18a447..2199e46ec 100644 --- a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs @@ -544,6 +544,7 @@ namespace Ryujinx.Ava.Ui.Windows GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache; + GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression; } public void LoadHotKeys() diff --git a/Ryujinx.Graphics.GAL/DeviceInfo.cs b/Ryujinx.Graphics.GAL/DeviceInfo.cs new file mode 100644 index 000000000..c525eb601 --- /dev/null +++ b/Ryujinx.Graphics.GAL/DeviceInfo.cs @@ -0,0 +1,18 @@ +namespace Ryujinx.Graphics.GAL +{ + public struct DeviceInfo + { + public readonly string Id; + public readonly string Vendor; + public readonly string Name; + public readonly bool IsDiscrete; + + public DeviceInfo(string id, string vendor, string name, bool isDiscrete) + { + Id = id; + Vendor = vendor; + Name = name; + IsDiscrete = isDiscrete; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Vulkan/Vendor.cs b/Ryujinx.Graphics.Vulkan/Vendor.cs index 228b304ab..0fd44c10d 100644 --- a/Ryujinx.Graphics.Vulkan/Vendor.cs +++ b/Ryujinx.Graphics.Vulkan/Vendor.cs @@ -22,5 +22,26 @@ namespace Ryujinx.Graphics.Vulkan _ => Vendor.Unknown }; } + + public static string GetNameFromId(uint id) + { + return id switch + { + 0x1002 => "AMD", + 0x1010 => "ImgTec", + 0x10DE => "NVIDIA", + 0x13B5 => "ARM", + 0x1AE0 => "Google", + 0x5143 => "Qualcomm", + 0x8086 => "Intel", + 0x10001 => "Vivante", + 0x10002 => "VeriSilicon", + 0x10003 => "Kazan", + 0x10004 => "Codeplay Software Ltd.", + 0x10005 => "Mesa", + 0x10006 => "PoCL", + _ => $"0x{id:X}" + }; + } } } diff --git a/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs b/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs index 3cf155c51..4eec06824 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs @@ -74,8 +74,9 @@ namespace Ryujinx.Graphics.Vulkan public IWindow Window => _window; - private Func GetSurface; - private Func GetRequiredExtensions; + private readonly Func _getSurface; + private readonly Func _getRequiredExtensions; + private readonly string _preferredGpuId; internal Vendor Vendor { get; private set; } internal bool IsAmdWindows { get; private set; } @@ -88,10 +89,11 @@ namespace Ryujinx.Graphics.Vulkan public event EventHandler ScreenCaptured; - public VulkanGraphicsDevice(Func surfaceFunc, Func requiredExtensionsFunc) + public VulkanGraphicsDevice(Func surfaceFunc, Func requiredExtensionsFunc, string preferredGpuId) { - GetSurface = surfaceFunc; - GetRequiredExtensions = requiredExtensionsFunc; + _getSurface = surfaceFunc; + _getRequiredExtensions = requiredExtensionsFunc; + _preferredGpuId = preferredGpuId; Shaders = new HashSet(); Textures = new HashSet(); Samplers = new HashSet(); @@ -239,7 +241,7 @@ namespace Ryujinx.Graphics.Vulkan Api = api; - _instance = VulkanInitialization.CreateInstance(api, logLevel, GetRequiredExtensions(), out ExtDebugReport debugReport, out _debugReportCallback); + _instance = VulkanInitialization.CreateInstance(api, logLevel, _getRequiredExtensions(), out ExtDebugReport debugReport, out _debugReportCallback); DebugReportApi = debugReport; @@ -248,8 +250,8 @@ namespace Ryujinx.Graphics.Vulkan SurfaceApi = surfaceApi; } - _surface = GetSurface(_instance, api); - _physicalDevice = VulkanInitialization.FindSuitablePhysicalDevice(api, _instance, _surface); + _surface = _getSurface(_instance, api); + _physicalDevice = VulkanInitialization.FindSuitablePhysicalDevice(api, _instance, _surface, _preferredGpuId); var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(api, _physicalDevice, _surface, out uint maxQueueCount); var supportedExtensions = VulkanInitialization.GetSupportedExtensions(api, _physicalDevice); @@ -435,6 +437,11 @@ namespace Ryujinx.Graphics.Vulkan return new HardwareInfo(GpuVendor, GpuRenderer); } + public static DeviceInfo[] GetPhysicalDevices() + { + return VulkanInitialization.GetSuitablePhysicalDevices(Vk.GetApi()); + } + private static string ParseStandardVulkanVersion(uint version) { return $"{version >> 22}.{(version >> 12) & 0x3FF}.{version & 0xFFF}"; @@ -459,23 +466,7 @@ namespace Ryujinx.Graphics.Vulkan { Api.GetPhysicalDeviceProperties(_physicalDevice, out var properties); - string vendorName = properties.VendorID switch - { - 0x1002 => "AMD", - 0x1010 => "ImgTec", - 0x10DE => "NVIDIA", - 0x13B5 => "ARM", - 0x1AE0 => "Google", - 0x5143 => "Qualcomm", - 0x8086 => "Intel", - 0x10001 => "Vivante", - 0x10002 => "VeriSilicon", - 0x10003 => "Kazan", - 0x10004 => "Codeplay Software Ltd.", - 0x10005 => "Mesa", - 0x10006 => "PoCL", - _ => $"0x{properties.VendorID:X}" - }; + string vendorName = VendorUtils.GetNameFromId(properties.VendorID); Vendor = VendorUtils.FromId(properties.VendorID); @@ -528,6 +519,36 @@ namespace Ryujinx.Graphics.Vulkan _counters.Update(); } + public void BackgroundContextAction(Action action, bool alwaysBackground = false) + { + action(); + } + + public void CreateSync(ulong id) + { + _syncManager.Create(id); + } + + public IProgram LoadProgramBinary(byte[] programBinary, bool isFragment, ShaderInfo info) + { + throw new NotImplementedException(); + } + + public void WaitSync(ulong id) + { + _syncManager.Wait(id); + } + + public void Screenshot() + { + _window.ScreenCaptureRequested = true; + } + + public void OnScreenCaptured(ScreenCaptureImageInfo bitmap) + { + ScreenCaptured?.Invoke(this, bitmap); + } + public unsafe void Dispose() { CommandBufferPool.Dispose(); @@ -572,35 +593,5 @@ namespace Ryujinx.Graphics.Vulkan Api.DestroyInstance(_instance, null); } } - - public void BackgroundContextAction(Action action, bool alwaysBackground = false) - { - action(); - } - - public void CreateSync(ulong id) - { - _syncManager.Create(id); - } - - public IProgram LoadProgramBinary(byte[] programBinary, bool isFragment, ShaderInfo info) - { - throw new NotImplementedException(); - } - - public void WaitSync(ulong id) - { - _syncManager.Wait(id); - } - - public void Screenshot() - { - _window.ScreenCaptureRequested = true; - } - - public void OnScreenCaptured(ScreenCaptureImageInfo bitmap) - { - ScreenCaptured?.Invoke(this, bitmap); - } } } diff --git a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index fd3578e2d..e1d818701 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; using Silk.NET.Vulkan.Extensions.EXT; using Silk.NET.Vulkan.Extensions.KHR; @@ -188,7 +189,7 @@ namespace Ryujinx.Graphics.Vulkan return 0; } - internal static PhysicalDevice FindSuitablePhysicalDevice(Vk api, Instance instance, SurfaceKHR surface) + internal static PhysicalDevice FindSuitablePhysicalDevice(Vk api, Instance instance, SurfaceKHR surface, string preferredGpuId) { uint physicalDeviceCount; @@ -201,11 +202,16 @@ namespace Ryujinx.Graphics.Vulkan api.EnumeratePhysicalDevices(instance, &physicalDeviceCount, pPhysicalDevices).ThrowOnError(); } - if (physicalDevices.Length > 1) + // First we try to pick the the user preferred GPU. + for (int i = 0; i < physicalDevices.Length; i++) { - return physicalDevices[0]; + if (IsPreferredAndSuitableDevice(api, physicalDevices[i], surface, preferredGpuId)) + { + return physicalDevices[i]; + } } + // If we fail to do that, just use the first compatible GPU. for (int i = 0; i < physicalDevices.Length; i++) { if (IsSuitableDevice(api, physicalDevices[i], surface)) @@ -217,6 +223,80 @@ namespace Ryujinx.Graphics.Vulkan throw new VulkanException("Initialization failed, none of the available GPUs meets the minimum requirements."); } + internal static DeviceInfo[] GetSuitablePhysicalDevices(Vk api) + { + var appName = Marshal.StringToHGlobalAnsi(AppName); + + var applicationInfo = new ApplicationInfo + { + PApplicationName = (byte*)appName, + ApplicationVersion = 1, + PEngineName = (byte*)appName, + EngineVersion = 1, + ApiVersion = Vk.Version12.Value + }; + + var instanceCreateInfo = new InstanceCreateInfo + { + SType = StructureType.InstanceCreateInfo, + PApplicationInfo = &applicationInfo, + PpEnabledExtensionNames = null, + PpEnabledLayerNames = null, + EnabledExtensionCount = 0, + EnabledLayerCount = 0 + }; + + api.CreateInstance(in instanceCreateInfo, null, out var instance).ThrowOnError(); + + Marshal.FreeHGlobal(appName); + + uint physicalDeviceCount; + + api.EnumeratePhysicalDevices(instance, &physicalDeviceCount, null).ThrowOnError(); + + PhysicalDevice[] physicalDevices = new PhysicalDevice[physicalDeviceCount]; + + fixed (PhysicalDevice* pPhysicalDevices = physicalDevices) + { + api.EnumeratePhysicalDevices(instance, &physicalDeviceCount, pPhysicalDevices).ThrowOnError(); + } + + DeviceInfo[] devices = new DeviceInfo[physicalDevices.Length]; + + for (int i = 0; i < physicalDevices.Length; i++) + { + var physicalDevice = physicalDevices[i]; + api.GetPhysicalDeviceProperties(physicalDevice, out var properties); + + devices[i] = new DeviceInfo( + StringFromIdPair(properties.VendorID, properties.DeviceID), + VendorUtils.GetNameFromId(properties.VendorID), + Marshal.PtrToStringAnsi((IntPtr)properties.DeviceName), + properties.DeviceType == PhysicalDeviceType.DiscreteGpu); + } + + api.DestroyInstance(instance, null); + + return devices; + } + + private static string StringFromIdPair(uint vendorId, uint deviceId) + { + return $"0x{vendorId:X}_0x{deviceId:X}"; + } + + private static bool IsPreferredAndSuitableDevice(Vk api, PhysicalDevice physicalDevice, SurfaceKHR surface, string preferredGpuId) + { + api.GetPhysicalDeviceProperties(physicalDevice, out var properties); + + if (StringFromIdPair(properties.VendorID, properties.DeviceID) != preferredGpuId) + { + return false; + } + + return IsSuitableDevice(api, physicalDevice, surface); + } + private static bool IsSuitableDevice(Vk api, PhysicalDevice physicalDevice, SurfaceKHR surface) { int extensionMatches = 0; diff --git a/Ryujinx.Headless.SDL2/Options.cs b/Ryujinx.Headless.SDL2/Options.cs index 806fcd71e..956941798 100644 --- a/Ryujinx.Headless.SDL2/Options.cs +++ b/Ryujinx.Headless.SDL2/Options.cs @@ -94,6 +94,9 @@ namespace Ryujinx.Headless.SDL2 [Option("enable-shader-cache", Required = false, Default = true, HelpText = "Enables Shader cache.")] public bool? EnableShaderCache { get; set; } + [Option("enable-texture-recompression", Required = false, Default = false, HelpText = "Enables Texture recompression.")] + public bool? EnableTextureRecompression { get; set; } + [Option("enable-docked-mode", Required = false, Default = true, HelpText = "Enables Docked Mode.")] public bool? EnableDockedMode { get; set; } @@ -167,6 +170,9 @@ namespace Ryujinx.Headless.SDL2 [Option("graphics-backend", Required = false, Default = GraphicsBackend.OpenGl, HelpText = "Change Graphics Backend to use.")] public GraphicsBackend GraphicsBackend { get; set; } + [Option("preferred-gpu-vendor", Required = false, Default = "", HelpText = "When using the Vulkan backend, prefer using the GPU from the specified vendor.")] + public string PreferredGpuVendor { get; set; } + // Hacks [Option("expand-ram", Required = false, Default = false, HelpText = "Expands the RAM amount on the emulated system from 4GB to 6GB.")] diff --git a/Ryujinx.Headless.SDL2/Program.cs b/Ryujinx.Headless.SDL2/Program.cs index 05eac2e2e..deb34d051 100644 --- a/Ryujinx.Headless.SDL2/Program.cs +++ b/Ryujinx.Headless.SDL2/Program.cs @@ -406,7 +406,8 @@ namespace Ryujinx.Headless.SDL2 } // Setup graphics configuration - GraphicsConfig.EnableShaderCache = (bool)option.EnableShaderCache && option.GraphicsBackend != GraphicsBackend.Vulkan; + GraphicsConfig.EnableShaderCache = (bool)option.EnableShaderCache; + GraphicsConfig.EnableTextureRecompression = (bool)option.EnableTextureRecompression; GraphicsConfig.ResScale = option.ResScale; GraphicsConfig.MaxAnisotropy = option.MaxAnisotropy; GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath; @@ -461,8 +462,28 @@ namespace Ryujinx.Headless.SDL2 { VulkanWindow vulkanWindow = new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, (bool)options.EnableMouse); window = vulkanWindow; - renderer = new VulkanGraphicsDevice((instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))), - vulkanWindow.GetRequiredInstanceExtensions); + + string preferredGpuId = string.Empty; + + if (!string.IsNullOrEmpty(options.PreferredGpuVendor)) + { + string preferredGpuVendor = options.PreferredGpuVendor.ToLowerInvariant(); + var devices = VulkanGraphicsDevice.GetPhysicalDevices(); + + foreach (var device in devices) + { + if (device.Vendor.ToLowerInvariant() == preferredGpuVendor) + { + preferredGpuId = device.Id; + break; + } + } + } + + renderer = new VulkanGraphicsDevice( + (instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))), + vulkanWindow.GetRequiredInstanceExtensions, + preferredGpuId); } else { diff --git a/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs index 918a52d95..8b5355b1c 100644 --- a/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs +++ b/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs @@ -80,7 +80,7 @@ namespace Ryujinx.Ui.Common.Configuration /// Enables printing error log messages /// public bool LoggingEnableError { get; set; } - + /// /// Enables printing trace log messages /// @@ -161,6 +161,11 @@ namespace Ryujinx.Ui.Common.Configuration /// public bool EnableShaderCache { get; set; } + /// + /// Enables or disables texture recompression + /// + public bool EnableTextureRecompression { get; set; } + /// /// Enables or disables profiled translation cache persistency /// @@ -315,6 +320,11 @@ namespace Ryujinx.Ui.Common.Configuration /// public GraphicsBackend GraphicsBackend { get; set; } + /// + /// Preferred GPU + /// + public string PreferredGpu { get; set; } + /// /// Loads a configuration file from disk /// diff --git a/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs b/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs index 9f011cc63..1ec8895d7 100644 --- a/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs +++ b/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs @@ -310,7 +310,7 @@ namespace Ryujinx.Ui.Common.Configuration EnableDockedMode = new ReactiveObject(); EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode)); EnablePtc = new ReactiveObject(); - EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc)); + EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc)); EnableInternetAccess = new ReactiveObject(); EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess)); EnableFsIntegrityChecks = new ReactiveObject(); @@ -411,30 +411,44 @@ namespace Ryujinx.Ui.Common.Configuration /// public ReactiveObject EnableShaderCache { get; private set; } + /// + /// Enables or disables texture recompression + /// + public ReactiveObject EnableTextureRecompression { get; private set; } + /// /// Graphics backend /// public ReactiveObject GraphicsBackend { get; private set; } + /// + /// Preferred GPU + /// + public ReactiveObject PreferredGpu { get; private set; } + public GraphicsSection() { - BackendThreading = new ReactiveObject(); - BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading)); - ResScale = new ReactiveObject(); - ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale)); - ResScaleCustom = new ReactiveObject(); - ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom)); - MaxAnisotropy = new ReactiveObject(); - MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy)); - AspectRatio = new ReactiveObject(); - AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio)); - ShadersDumpPath = new ReactiveObject(); - EnableVsync = new ReactiveObject(); - EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync)); - EnableShaderCache = new ReactiveObject(); - EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache)); - GraphicsBackend = new ReactiveObject(); - GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend)); + BackendThreading = new ReactiveObject(); + BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading)); + ResScale = new ReactiveObject(); + ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale)); + ResScaleCustom = new ReactiveObject(); + ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom)); + MaxAnisotropy = new ReactiveObject(); + MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy)); + AspectRatio = new ReactiveObject(); + AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio)); + ShadersDumpPath = new ReactiveObject(); + EnableVsync = new ReactiveObject(); + EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync)); + EnableShaderCache = new ReactiveObject(); + EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache)); + EnableTextureRecompression = new ReactiveObject(); + EnableTextureRecompression.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableTextureRecompression)); + GraphicsBackend = new ReactiveObject(); + GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend)); + PreferredGpu = new ReactiveObject(); + PreferredGpu.Event += static (sender, e) => LogValueChange(sender, e, nameof(PreferredGpu)); } } @@ -505,45 +519,46 @@ namespace Ryujinx.Ui.Common.Configuration { ConfigurationFileFormat configurationFile = new ConfigurationFileFormat { - Version = ConfigurationFileFormat.CurrentVersion, - BackendThreading = Graphics.BackendThreading, - EnableFileLog = Logger.EnableFileLog, - ResScale = Graphics.ResScale, - ResScaleCustom = Graphics.ResScaleCustom, - MaxAnisotropy = Graphics.MaxAnisotropy, - AspectRatio = Graphics.AspectRatio, - GraphicsShadersDumpPath = Graphics.ShadersDumpPath, - LoggingEnableDebug = Logger.EnableDebug, - LoggingEnableStub = Logger.EnableStub, - LoggingEnableInfo = Logger.EnableInfo, - LoggingEnableWarn = Logger.EnableWarn, - LoggingEnableError = Logger.EnableError, - LoggingEnableTrace = Logger.EnableTrace, - LoggingEnableGuest = Logger.EnableGuest, - LoggingEnableFsAccessLog = Logger.EnableFsAccessLog, - LoggingFilteredClasses = Logger.FilteredClasses, - LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel, - SystemLanguage = System.Language, - SystemRegion = System.Region, - SystemTimeZone = System.TimeZone, - SystemTimeOffset = System.SystemTimeOffset, - DockedMode = System.EnableDockedMode, - EnableDiscordIntegration = EnableDiscordIntegration, - CheckUpdatesOnStart = CheckUpdatesOnStart, - ShowConfirmExit = ShowConfirmExit, - HideCursorOnIdle = HideCursorOnIdle, - EnableVsync = Graphics.EnableVsync, - EnableShaderCache = Graphics.EnableShaderCache, - EnablePtc = System.EnablePtc, - EnableInternetAccess = System.EnableInternetAccess, - EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, - FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, - AudioBackend = System.AudioBackend, - AudioVolume = System.AudioVolume, - MemoryManagerMode = System.MemoryManagerMode, - ExpandRam = System.ExpandRam, - IgnoreMissingServices = System.IgnoreMissingServices, - GuiColumns = new GuiColumns + Version = ConfigurationFileFormat.CurrentVersion, + BackendThreading = Graphics.BackendThreading, + EnableFileLog = Logger.EnableFileLog, + ResScale = Graphics.ResScale, + ResScaleCustom = Graphics.ResScaleCustom, + MaxAnisotropy = Graphics.MaxAnisotropy, + AspectRatio = Graphics.AspectRatio, + GraphicsShadersDumpPath = Graphics.ShadersDumpPath, + LoggingEnableDebug = Logger.EnableDebug, + LoggingEnableStub = Logger.EnableStub, + LoggingEnableInfo = Logger.EnableInfo, + LoggingEnableWarn = Logger.EnableWarn, + LoggingEnableError = Logger.EnableError, + LoggingEnableTrace = Logger.EnableTrace, + LoggingEnableGuest = Logger.EnableGuest, + LoggingEnableFsAccessLog = Logger.EnableFsAccessLog, + LoggingFilteredClasses = Logger.FilteredClasses, + LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel, + SystemLanguage = System.Language, + SystemRegion = System.Region, + SystemTimeZone = System.TimeZone, + SystemTimeOffset = System.SystemTimeOffset, + DockedMode = System.EnableDockedMode, + EnableDiscordIntegration = EnableDiscordIntegration, + CheckUpdatesOnStart = CheckUpdatesOnStart, + ShowConfirmExit = ShowConfirmExit, + HideCursorOnIdle = HideCursorOnIdle, + EnableVsync = Graphics.EnableVsync, + EnableShaderCache = Graphics.EnableShaderCache, + EnableTextureRecompression = Graphics.EnableTextureRecompression, + EnablePtc = System.EnablePtc, + EnableInternetAccess = System.EnableInternetAccess, + EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, + FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, + AudioBackend = System.AudioBackend, + AudioVolume = System.AudioVolume, + MemoryManagerMode = System.MemoryManagerMode, + ExpandRam = System.ExpandRam, + IgnoreMissingServices = System.IgnoreMissingServices, + GuiColumns = new GuiColumns { FavColumn = Ui.GuiColumns.FavColumn, IconColumn = Ui.GuiColumns.IconColumn, @@ -554,32 +569,33 @@ namespace Ryujinx.Ui.Common.Configuration LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn, FileExtColumn = Ui.GuiColumns.FileExtColumn, FileSizeColumn = Ui.GuiColumns.FileSizeColumn, - PathColumn = Ui.GuiColumns.PathColumn, + PathColumn = Ui.GuiColumns.PathColumn }, - ColumnSort = new ColumnSort + ColumnSort = new ColumnSort { SortColumnId = Ui.ColumnSort.SortColumnId, SortAscending = Ui.ColumnSort.SortAscending }, - GameDirs = Ui.GameDirs, - LanguageCode = Ui.LanguageCode, - EnableCustomTheme = Ui.EnableCustomTheme, - CustomThemePath = Ui.CustomThemePath, - BaseStyle = Ui.BaseStyle, - GameListViewMode = Ui.GameListViewMode, - ShowNames = Ui.ShowNames, - GridSize = Ui.GridSize, - ApplicationSort = Ui.ApplicationSort, - IsAscendingOrder = Ui.IsAscendingOrder, - StartFullscreen = Ui.StartFullscreen, - ShowConsole = Ui.ShowConsole, - EnableKeyboard = Hid.EnableKeyboard, - EnableMouse = Hid.EnableMouse, - Hotkeys = Hid.Hotkeys, - KeyboardConfig = new List(), - ControllerConfig = new List(), - InputConfig = Hid.InputConfig, - GraphicsBackend = Graphics.GraphicsBackend, + GameDirs = Ui.GameDirs, + LanguageCode = Ui.LanguageCode, + EnableCustomTheme = Ui.EnableCustomTheme, + CustomThemePath = Ui.CustomThemePath, + BaseStyle = Ui.BaseStyle, + GameListViewMode = Ui.GameListViewMode, + ShowNames = Ui.ShowNames, + GridSize = Ui.GridSize, + ApplicationSort = Ui.ApplicationSort, + IsAscendingOrder = Ui.IsAscendingOrder, + StartFullscreen = Ui.StartFullscreen, + ShowConsole = Ui.ShowConsole, + EnableKeyboard = Hid.EnableKeyboard, + EnableMouse = Hid.EnableMouse, + Hotkeys = Hid.Hotkeys, + KeyboardConfig = new List(), + ControllerConfig = new List(), + InputConfig = Hid.InputConfig, + GraphicsBackend = Graphics.GraphicsBackend, + PreferredGpu = Graphics.PreferredGpu }; return configurationFile; @@ -587,70 +603,72 @@ namespace Ryujinx.Ui.Common.Configuration public void LoadDefault() { - Logger.EnableFileLog.Value = true; - Graphics.BackendThreading.Value = BackendThreading.Auto; - Graphics.ResScale.Value = 1; - Graphics.ResScaleCustom.Value = 1.0f; - Graphics.MaxAnisotropy.Value = -1.0f; - Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; - Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl; - Graphics.ShadersDumpPath.Value = ""; - Logger.EnableDebug.Value = false; - Logger.EnableStub.Value = true; - Logger.EnableInfo.Value = true; - Logger.EnableWarn.Value = true; - Logger.EnableError.Value = true; - Logger.EnableTrace.Value = false; - Logger.EnableGuest.Value = true; - Logger.EnableFsAccessLog.Value = false; - Logger.FilteredClasses.Value = Array.Empty(); - Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None; - System.Language.Value = Language.AmericanEnglish; - System.Region.Value = Region.USA; - System.TimeZone.Value = "UTC"; - System.SystemTimeOffset.Value = 0; - System.EnableDockedMode.Value = true; - EnableDiscordIntegration.Value = true; - CheckUpdatesOnStart.Value = true; - ShowConfirmExit.Value = true; - HideCursorOnIdle.Value = false; - Graphics.EnableVsync.Value = true; - Graphics.EnableShaderCache.Value = true; - System.EnablePtc.Value = true; - System.EnableInternetAccess.Value = false; - System.EnableFsIntegrityChecks.Value = true; - System.FsGlobalAccessLogMode.Value = 0; - System.AudioBackend.Value = AudioBackend.SDL2; - System.AudioVolume.Value = 1; - System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe; - System.ExpandRam.Value = false; - System.IgnoreMissingServices.Value = false; - Ui.GuiColumns.FavColumn.Value = true; - Ui.GuiColumns.IconColumn.Value = true; - Ui.GuiColumns.AppColumn.Value = true; - Ui.GuiColumns.DevColumn.Value = true; - Ui.GuiColumns.VersionColumn.Value = true; - Ui.GuiColumns.TimePlayedColumn.Value = true; - Ui.GuiColumns.LastPlayedColumn.Value = true; - Ui.GuiColumns.FileExtColumn.Value = true; - Ui.GuiColumns.FileSizeColumn.Value = true; - Ui.GuiColumns.PathColumn.Value = true; - Ui.ColumnSort.SortColumnId.Value = 0; - Ui.ColumnSort.SortAscending.Value = false; - Ui.GameDirs.Value = new List(); - Ui.EnableCustomTheme.Value = false; - Ui.LanguageCode.Value = "en_US"; - Ui.CustomThemePath.Value = ""; - Ui.BaseStyle.Value = "Dark"; - Ui.GameListViewMode.Value = 0; - Ui.ShowNames.Value = true; - Ui.GridSize.Value = 2; - Ui.ApplicationSort.Value = 0; - Ui.IsAscendingOrder.Value = true; - Ui.StartFullscreen.Value = false; - Ui.ShowConsole.Value = true; - Hid.EnableKeyboard.Value = false; - Hid.EnableMouse.Value = false; + Logger.EnableFileLog.Value = true; + Graphics.BackendThreading.Value = BackendThreading.Auto; + Graphics.ResScale.Value = 1; + Graphics.ResScaleCustom.Value = 1.0f; + Graphics.MaxAnisotropy.Value = -1.0f; + Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; + Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl; + Graphics.PreferredGpu.Value = ""; + Graphics.ShadersDumpPath.Value = ""; + Logger.EnableDebug.Value = false; + Logger.EnableStub.Value = true; + Logger.EnableInfo.Value = true; + Logger.EnableWarn.Value = true; + Logger.EnableError.Value = true; + Logger.EnableTrace.Value = false; + Logger.EnableGuest.Value = true; + Logger.EnableFsAccessLog.Value = false; + Logger.FilteredClasses.Value = Array.Empty(); + Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None; + System.Language.Value = Language.AmericanEnglish; + System.Region.Value = Region.USA; + System.TimeZone.Value = "UTC"; + System.SystemTimeOffset.Value = 0; + System.EnableDockedMode.Value = true; + EnableDiscordIntegration.Value = true; + CheckUpdatesOnStart.Value = true; + ShowConfirmExit.Value = true; + HideCursorOnIdle.Value = false; + Graphics.EnableVsync.Value = true; + Graphics.EnableShaderCache.Value = true; + Graphics.EnableTextureRecompression.Value = false; + System.EnablePtc.Value = true; + System.EnableInternetAccess.Value = false; + System.EnableFsIntegrityChecks.Value = true; + System.FsGlobalAccessLogMode.Value = 0; + System.AudioBackend.Value = AudioBackend.SDL2; + System.AudioVolume.Value = 1; + System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe; + System.ExpandRam.Value = false; + System.IgnoreMissingServices.Value = false; + Ui.GuiColumns.FavColumn.Value = true; + Ui.GuiColumns.IconColumn.Value = true; + Ui.GuiColumns.AppColumn.Value = true; + Ui.GuiColumns.DevColumn.Value = true; + Ui.GuiColumns.VersionColumn.Value = true; + Ui.GuiColumns.TimePlayedColumn.Value = true; + Ui.GuiColumns.LastPlayedColumn.Value = true; + Ui.GuiColumns.FileExtColumn.Value = true; + Ui.GuiColumns.FileSizeColumn.Value = true; + Ui.GuiColumns.PathColumn.Value = true; + Ui.ColumnSort.SortColumnId.Value = 0; + Ui.ColumnSort.SortAscending.Value = false; + Ui.GameDirs.Value = new List(); + Ui.EnableCustomTheme.Value = false; + Ui.LanguageCode.Value = "en_US"; + Ui.CustomThemePath.Value = ""; + Ui.BaseStyle.Value = "Dark"; + Ui.GameListViewMode.Value = 0; + Ui.ShowNames.Value = true; + Ui.GridSize.Value = 2; + Ui.ApplicationSort.Value = 0; + Ui.IsAscendingOrder.Value = true; + Ui.StartFullscreen.Value = false; + Ui.ShowConsole.Value = true; + Hid.EnableKeyboard.Value = false; + Hid.EnableMouse.Value = false; Hid.Hotkeys.Value = new KeyboardHotkeys { ToggleVsync = Key.Tab, @@ -976,7 +994,7 @@ namespace Ryujinx.Ui.Common.Configuration if (configurationFileFormat.Version < 29) { Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29."); - + configurationFileFormat.Hotkeys = new KeyboardHotkeys { ToggleVsync = Key.Tab, @@ -1105,72 +1123,74 @@ namespace Ryujinx.Ui.Common.Configuration configurationFileUpdated = true; } - Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; - Graphics.ResScale.Value = configurationFileFormat.ResScale; - Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; - Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; - Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio; - Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; - Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading; - Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend; - Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; - Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; - Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo; - Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn; - Logger.EnableError.Value = configurationFileFormat.LoggingEnableError; - Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace; - Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest; - Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog; - Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses; - Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel; - System.Language.Value = configurationFileFormat.SystemLanguage; - System.Region.Value = configurationFileFormat.SystemRegion; - System.TimeZone.Value = configurationFileFormat.SystemTimeZone; - System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; - System.EnableDockedMode.Value = configurationFileFormat.DockedMode; - EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; - CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; - ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; - HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; - Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; - Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; - System.EnablePtc.Value = configurationFileFormat.EnablePtc; - System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess; - System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; - System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; - System.AudioBackend.Value = configurationFileFormat.AudioBackend; - System.AudioVolume.Value = configurationFileFormat.AudioVolume; - System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode; - System.ExpandRam.Value = configurationFileFormat.ExpandRam; - System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; - Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; - Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; - Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; - Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn; - Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn; - Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn; - Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn; - Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn; - Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn; - Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn; - Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; - Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; - Ui.GameDirs.Value = configurationFileFormat.GameDirs; - Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; - Ui.LanguageCode.Value = configurationFileFormat.LanguageCode; - Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; - Ui.BaseStyle.Value = configurationFileFormat.BaseStyle; - Ui.GameListViewMode.Value = configurationFileFormat.GameListViewMode; - Ui.ShowNames.Value = configurationFileFormat.ShowNames; - Ui.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder; - Ui.GridSize.Value = configurationFileFormat.GridSize; - Ui.ApplicationSort.Value = configurationFileFormat.ApplicationSort; - Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen; - Ui.ShowConsole.Value = configurationFileFormat.ShowConsole; - Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; - Hid.EnableMouse.Value = configurationFileFormat.EnableMouse; - Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; - Hid.InputConfig.Value = configurationFileFormat.InputConfig; + Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; + Graphics.ResScale.Value = configurationFileFormat.ResScale; + Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; + Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; + Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio; + Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; + Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading; + Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend; + Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu; + Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; + Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; + Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo; + Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn; + Logger.EnableError.Value = configurationFileFormat.LoggingEnableError; + Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace; + Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest; + Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog; + Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses; + Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel; + System.Language.Value = configurationFileFormat.SystemLanguage; + System.Region.Value = configurationFileFormat.SystemRegion; + System.TimeZone.Value = configurationFileFormat.SystemTimeZone; + System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; + System.EnableDockedMode.Value = configurationFileFormat.DockedMode; + EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; + CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; + ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; + HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; + Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; + Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; + Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression; + System.EnablePtc.Value = configurationFileFormat.EnablePtc; + System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess; + System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; + System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; + System.AudioBackend.Value = configurationFileFormat.AudioBackend; + System.AudioVolume.Value = configurationFileFormat.AudioVolume; + System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode; + System.ExpandRam.Value = configurationFileFormat.ExpandRam; + System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; + Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; + Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; + Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; + Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn; + Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn; + Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn; + Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn; + Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn; + Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn; + Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn; + Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; + Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; + Ui.GameDirs.Value = configurationFileFormat.GameDirs; + Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; + Ui.LanguageCode.Value = configurationFileFormat.LanguageCode; + Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; + Ui.BaseStyle.Value = configurationFileFormat.BaseStyle; + Ui.GameListViewMode.Value = configurationFileFormat.GameListViewMode; + Ui.ShowNames.Value = configurationFileFormat.ShowNames; + Ui.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder; + Ui.GridSize.Value = configurationFileFormat.GridSize; + Ui.ApplicationSort.Value = configurationFileFormat.ApplicationSort; + Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen; + Ui.ShowConsole.Value = configurationFileFormat.ShowConsole; + Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; + Hid.EnableMouse.Value = configurationFileFormat.EnableMouse; + Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; + Hid.InputConfig.Value = configurationFileFormat.InputConfig; if (Hid.InputConfig.Value == null) { diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index be7956437..e8e200db7 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -410,8 +410,8 @@ namespace Ryujinx.Ui if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan) { - renderer = new VulkanGraphicsDevice((instance, vk) => new SurfaceKHR((ulong)((VKRenderer)RendererWidget).CreateWindowSurface(instance.Handle)), - VulkanHelper.GetRequiredInstanceExtensions); + string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value; + renderer = new VulkanGraphicsDevice(CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu); } else { @@ -582,6 +582,11 @@ namespace Ryujinx.Ui _emulationContext = new HLE.Switch(configuration); } + private SurfaceKHR CreateVulkanSurface(Instance instance, Vk vk) + { + return new SurfaceKHR((ulong)((VKRenderer)RendererWidget).CreateWindowSurface(instance.Handle)); + } + private void SetupProgressUiHandlers() { Ptc.PtcStateChanged -= ProgressHandler; @@ -1034,10 +1039,11 @@ namespace Ryujinx.Ui int resScale = ConfigurationState.Instance.Graphics.ResScale; float resScaleCustom = ConfigurationState.Instance.Graphics.ResScaleCustom; - Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale; - Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; - Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; - Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache; + Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale; + Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; + Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; + Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache; + Graphics.Gpu.GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression; } public void SaveConfig() diff --git a/Ryujinx/Ui/Windows/SettingsWindow.cs b/Ryujinx/Ui/Windows/SettingsWindow.cs index 5ab9b61a3..c339ed124 100644 --- a/Ryujinx/Ui/Windows/SettingsWindow.cs +++ b/Ryujinx/Ui/Windows/SettingsWindow.cs @@ -6,6 +6,7 @@ using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.GraphicsDriver; +using Ryujinx.Graphics.Vulkan; using Ryujinx.Ui.Common.Configuration; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Time.TimeZone; @@ -53,6 +54,7 @@ namespace Ryujinx.Ui.Windows [GUI] CheckButton _hideCursorOnIdleToggle; [GUI] CheckButton _vSyncToggle; [GUI] CheckButton _shaderCacheToggle; + [GUI] CheckButton _textureRecompressionToggle; [GUI] CheckButton _ptcToggle; [GUI] CheckButton _internetToggle; [GUI] CheckButton _fsicToggle; @@ -92,6 +94,7 @@ namespace Ryujinx.Ui.Windows [GUI] ComboBoxText _anisotropy; [GUI] ComboBoxText _aspectRatio; [GUI] ComboBoxText _graphicsBackend; + [GUI] ComboBoxText _preferredGpu; [GUI] ComboBoxText _resScaleCombo; [GUI] Entry _resScaleText; [GUI] ToggleButton _configureController1; @@ -230,6 +233,11 @@ namespace Ryujinx.Ui.Windows _shaderCacheToggle.Click(); } + if (ConfigurationState.Instance.Graphics.EnableTextureRecompression) + { + _textureRecompressionToggle.Click(); + } + if (ConfigurationState.Instance.System.EnablePtc) { _ptcToggle.Click(); @@ -324,6 +332,10 @@ namespace Ryujinx.Ui.Windows _aspectRatio.SetActiveId(((int)ConfigurationState.Instance.Graphics.AspectRatio.Value).ToString()); _graphicsBackend.SetActiveId(((int)ConfigurationState.Instance.Graphics.GraphicsBackend.Value).ToString()); + UpdatePreferredGpuComboBox(); + + _graphicsBackend.Changed += (sender, e) => UpdatePreferredGpuComboBox(); + _custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath; _resScaleText.Buffer.Text = ConfigurationState.Instance.Graphics.ResScaleCustom.Value.ToString(); _resScaleText.Visible = _resScaleCombo.ActiveId == "-1"; @@ -347,7 +359,7 @@ namespace Ryujinx.Ui.Windows _browseThemePath.Sensitive = false; } - //Setup system time spinners + // Setup system time spinners UpdateSystemTimeSpinners(); _audioBackendStore = new ListStore(typeof(string), typeof(AudioBackend)); @@ -421,6 +433,39 @@ namespace Ryujinx.Ui.Windows }); } + private void UpdatePreferredGpuComboBox() + { + _preferredGpu.RemoveAll(); + + if (Enum.Parse(_graphicsBackend.ActiveId) == GraphicsBackend.Vulkan) + { + var devices = VulkanGraphicsDevice.GetPhysicalDevices(); + string preferredGpuIdFromConfig = ConfigurationState.Instance.Graphics.PreferredGpu.Value; + string preferredGpuId = preferredGpuIdFromConfig; + bool noGpuId = string.IsNullOrEmpty(preferredGpuIdFromConfig); + + foreach (var device in devices) + { + string dGPU = device.IsDiscrete ? " (dGPU)" : ""; + _preferredGpu.Append(device.Id, $"{device.Name}{dGPU}"); + + // If there's no GPU selected yet, we just pick the first GPU. + // If there's a discrete GPU available, we always prefer that over the previous selection, + // as it is likely to have better performance and more features. + // If the configuration file already has a GPU selection, we always prefer that instead. + if (noGpuId && (string.IsNullOrEmpty(preferredGpuId) || device.IsDiscrete)) + { + preferredGpuId = device.Id; + } + } + + if (!string.IsNullOrEmpty(preferredGpuId)) + { + _preferredGpu.SetActiveId(preferredGpuId); + } + } + } + private void UpdateSystemTimeSpinners() { //Bind system time events @@ -494,46 +539,48 @@ namespace Ryujinx.Ui.Windows DriverUtilities.ToggleOGLThreading(backendThreading == BackendThreading.Off); } - ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active; - ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active; - ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active; - ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active; - ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active; - ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active; - ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active; - ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active; - ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active; - ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse(_graphicsDebugLevel.ActiveId); - ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active; - ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; - ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active; - ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active; - ConfigurationState.Instance.HideCursorOnIdle.Value = _hideCursorOnIdleToggle.Active; - ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; - ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active; - ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active; - ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active; - ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active; - ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode; - ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active; - ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active; - ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active; - ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active; - ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active; - ConfigurationState.Instance.System.Language.Value = Enum.Parse(_systemLanguageSelect.ActiveId); - ConfigurationState.Instance.System.Region.Value = Enum.Parse(_systemRegionSelect.ActiveId); - ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset; - ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text; - ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text; - ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs; - ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value; - ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture); - ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse(_aspectRatio.ActiveId); - ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading; - ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse(_graphicsBackend.ActiveId); - ConfigurationState.Instance.Graphics.ResScale.Value = int.Parse(_resScaleCombo.ActiveId); - ConfigurationState.Instance.Graphics.ResScaleCustom.Value = resScaleCustom; - ConfigurationState.Instance.System.AudioVolume.Value = (float)_audioVolumeSlider.Value / 100.0f; + ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active; + ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active; + ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active; + ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active; + ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active; + ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active; + ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active; + ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active; + ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active; + ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse(_graphicsDebugLevel.ActiveId); + ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active; + ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; + ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active; + ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active; + ConfigurationState.Instance.HideCursorOnIdle.Value = _hideCursorOnIdleToggle.Active; + ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; + ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active; + ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active; + ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active; + ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active; + ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active; + ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode; + ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active; + ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active; + ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active; + ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active; + ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active; + ConfigurationState.Instance.System.Language.Value = Enum.Parse(_systemLanguageSelect.ActiveId); + ConfigurationState.Instance.System.Region.Value = Enum.Parse(_systemRegionSelect.ActiveId); + ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset; + ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text; + ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text; + ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs; + ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value; + ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture); + ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse(_aspectRatio.ActiveId); + ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading; + ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse(_graphicsBackend.ActiveId); + ConfigurationState.Instance.Graphics.PreferredGpu.Value = _preferredGpu.ActiveId; + ConfigurationState.Instance.Graphics.ResScale.Value = int.Parse(_resScaleCombo.ActiveId); + ConfigurationState.Instance.Graphics.ResScaleCustom.Value = resScaleCustom; + ConfigurationState.Instance.System.AudioVolume.Value = (float)_audioVolumeSlider.Value / 100.0f; _previousVolumeLevel = ConfigurationState.Instance.System.AudioVolume.Value; diff --git a/Ryujinx/Ui/Windows/SettingsWindow.glade b/Ryujinx/Ui/Windows/SettingsWindow.glade index f573ac709..ecd59e727 100644 --- a/Ryujinx/Ui/Windows/SettingsWindow.glade +++ b/Ryujinx/Ui/Windows/SettingsWindow.glade @@ -1897,7 +1897,7 @@ False True 5 - 1 + 0 @@ -1945,6 +1945,47 @@ 1 + + + True + False + 5 + 5 + + + True + False + Preferred GPU (Vulkan only) + Preferred GPU: + + + False + True + 5 + 0 + + + + + True + False + Preferred GPU (Vulkan only) + -1 + + + False + True + 1 + + + + + False + True + 5 + 2 + + False @@ -2011,6 +2052,24 @@ 0 + + + Enable Texture Recompression + True + True + False + Enables or disables Texture Recompression. Reduces VRAM usage at the cost of texture quality, and may also increase stuttering + start + 5 + 5 + True + + + False + True + 1 + + True @@ -2072,7 +2131,7 @@ False True 5 - 1 + 2 @@ -2120,7 +2179,7 @@ False True 5 - 1 + 3 @@ -2169,7 +2228,7 @@ False True 5 - 3 + 4