Implement GPU selector and expose texture recompression on the UI and config

This commit is contained in:
gdk 2022-06-11 20:33:07 -03:00 committed by riperiperi
parent c98b61ade8
commit d31360e7da
12 changed files with 602 additions and 322 deletions

View file

@ -544,6 +544,7 @@ namespace Ryujinx.Ava.Ui.Windows
GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache; GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
} }
public void LoadHotKeys() public void LoadHotKeys()

View file

@ -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;
}
}
}

View file

@ -22,5 +22,26 @@ namespace Ryujinx.Graphics.Vulkan
_ => Vendor.Unknown _ => 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}"
};
}
} }
} }

View file

@ -74,8 +74,9 @@ namespace Ryujinx.Graphics.Vulkan
public IWindow Window => _window; public IWindow Window => _window;
private Func<Instance, Vk, SurfaceKHR> GetSurface; private readonly Func<Instance, Vk, SurfaceKHR> _getSurface;
private Func<string[]> GetRequiredExtensions; private readonly Func<string[]> _getRequiredExtensions;
private readonly string _preferredGpuId;
internal Vendor Vendor { get; private set; } internal Vendor Vendor { get; private set; }
internal bool IsAmdWindows { get; private set; } internal bool IsAmdWindows { get; private set; }
@ -88,10 +89,11 @@ namespace Ryujinx.Graphics.Vulkan
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured; public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
public VulkanGraphicsDevice(Func<Instance, Vk, SurfaceKHR> surfaceFunc, Func<string[]> requiredExtensionsFunc) public VulkanGraphicsDevice(Func<Instance, Vk, SurfaceKHR> surfaceFunc, Func<string[]> requiredExtensionsFunc, string preferredGpuId)
{ {
GetSurface = surfaceFunc; _getSurface = surfaceFunc;
GetRequiredExtensions = requiredExtensionsFunc; _getRequiredExtensions = requiredExtensionsFunc;
_preferredGpuId = preferredGpuId;
Shaders = new HashSet<ShaderCollection>(); Shaders = new HashSet<ShaderCollection>();
Textures = new HashSet<ITexture>(); Textures = new HashSet<ITexture>();
Samplers = new HashSet<SamplerHolder>(); Samplers = new HashSet<SamplerHolder>();
@ -239,7 +241,7 @@ namespace Ryujinx.Graphics.Vulkan
Api = api; 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; DebugReportApi = debugReport;
@ -248,8 +250,8 @@ namespace Ryujinx.Graphics.Vulkan
SurfaceApi = surfaceApi; SurfaceApi = surfaceApi;
} }
_surface = GetSurface(_instance, api); _surface = _getSurface(_instance, api);
_physicalDevice = VulkanInitialization.FindSuitablePhysicalDevice(api, _instance, _surface); _physicalDevice = VulkanInitialization.FindSuitablePhysicalDevice(api, _instance, _surface, _preferredGpuId);
var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(api, _physicalDevice, _surface, out uint maxQueueCount); var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(api, _physicalDevice, _surface, out uint maxQueueCount);
var supportedExtensions = VulkanInitialization.GetSupportedExtensions(api, _physicalDevice); var supportedExtensions = VulkanInitialization.GetSupportedExtensions(api, _physicalDevice);
@ -435,6 +437,11 @@ namespace Ryujinx.Graphics.Vulkan
return new HardwareInfo(GpuVendor, GpuRenderer); return new HardwareInfo(GpuVendor, GpuRenderer);
} }
public static DeviceInfo[] GetPhysicalDevices()
{
return VulkanInitialization.GetSuitablePhysicalDevices(Vk.GetApi());
}
private static string ParseStandardVulkanVersion(uint version) private static string ParseStandardVulkanVersion(uint version)
{ {
return $"{version >> 22}.{(version >> 12) & 0x3FF}.{version & 0xFFF}"; return $"{version >> 22}.{(version >> 12) & 0x3FF}.{version & 0xFFF}";
@ -459,23 +466,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
Api.GetPhysicalDeviceProperties(_physicalDevice, out var properties); Api.GetPhysicalDeviceProperties(_physicalDevice, out var properties);
string vendorName = properties.VendorID switch string vendorName = VendorUtils.GetNameFromId(properties.VendorID);
{
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}"
};
Vendor = VendorUtils.FromId(properties.VendorID); Vendor = VendorUtils.FromId(properties.VendorID);
@ -528,6 +519,36 @@ namespace Ryujinx.Graphics.Vulkan
_counters.Update(); _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() public unsafe void Dispose()
{ {
CommandBufferPool.Dispose(); CommandBufferPool.Dispose();
@ -572,35 +593,5 @@ namespace Ryujinx.Graphics.Vulkan
Api.DestroyInstance(_instance, null); 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);
}
} }
} }

View file

@ -1,5 +1,6 @@
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.EXT; using Silk.NET.Vulkan.Extensions.EXT;
using Silk.NET.Vulkan.Extensions.KHR; using Silk.NET.Vulkan.Extensions.KHR;
@ -188,7 +189,7 @@ namespace Ryujinx.Graphics.Vulkan
return 0; 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; uint physicalDeviceCount;
@ -201,11 +202,16 @@ namespace Ryujinx.Graphics.Vulkan
api.EnumeratePhysicalDevices(instance, &physicalDeviceCount, pPhysicalDevices).ThrowOnError(); 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++) for (int i = 0; i < physicalDevices.Length; i++)
{ {
if (IsSuitableDevice(api, physicalDevices[i], surface)) 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."); 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) private static bool IsSuitableDevice(Vk api, PhysicalDevice physicalDevice, SurfaceKHR surface)
{ {
int extensionMatches = 0; int extensionMatches = 0;

View file

@ -94,6 +94,9 @@ namespace Ryujinx.Headless.SDL2
[Option("enable-shader-cache", Required = false, Default = true, HelpText = "Enables Shader cache.")] [Option("enable-shader-cache", Required = false, Default = true, HelpText = "Enables Shader cache.")]
public bool? EnableShaderCache { get; set; } 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.")] [Option("enable-docked-mode", Required = false, Default = true, HelpText = "Enables Docked Mode.")]
public bool? EnableDockedMode { get; set; } 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.")] [Option("graphics-backend", Required = false, Default = GraphicsBackend.OpenGl, HelpText = "Change Graphics Backend to use.")]
public GraphicsBackend GraphicsBackend { get; set; } 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 // Hacks
[Option("expand-ram", Required = false, Default = false, HelpText = "Expands the RAM amount on the emulated system from 4GB to 6GB.")] [Option("expand-ram", Required = false, Default = false, HelpText = "Expands the RAM amount on the emulated system from 4GB to 6GB.")]

View file

@ -406,7 +406,8 @@ namespace Ryujinx.Headless.SDL2
} }
// Setup graphics configuration // 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.ResScale = option.ResScale;
GraphicsConfig.MaxAnisotropy = option.MaxAnisotropy; GraphicsConfig.MaxAnisotropy = option.MaxAnisotropy;
GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath; GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
@ -461,8 +462,28 @@ namespace Ryujinx.Headless.SDL2
{ {
VulkanWindow vulkanWindow = new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, (bool)options.EnableMouse); VulkanWindow vulkanWindow = new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, (bool)options.EnableMouse);
window = vulkanWindow; 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 else
{ {

View file

@ -80,7 +80,7 @@ namespace Ryujinx.Ui.Common.Configuration
/// Enables printing error log messages /// Enables printing error log messages
/// </summary> /// </summary>
public bool LoggingEnableError { get; set; } public bool LoggingEnableError { get; set; }
/// <summary> /// <summary>
/// Enables printing trace log messages /// Enables printing trace log messages
/// </summary> /// </summary>
@ -161,6 +161,11 @@ namespace Ryujinx.Ui.Common.Configuration
/// </summary> /// </summary>
public bool EnableShaderCache { get; set; } public bool EnableShaderCache { get; set; }
/// <summary>
/// Enables or disables texture recompression
/// </summary>
public bool EnableTextureRecompression { get; set; }
/// <summary> /// <summary>
/// Enables or disables profiled translation cache persistency /// Enables or disables profiled translation cache persistency
/// </summary> /// </summary>
@ -315,6 +320,11 @@ namespace Ryujinx.Ui.Common.Configuration
/// </summary> /// </summary>
public GraphicsBackend GraphicsBackend { get; set; } public GraphicsBackend GraphicsBackend { get; set; }
/// <summary>
/// Preferred GPU
/// </summary>
public string PreferredGpu { get; set; }
/// <summary> /// <summary>
/// Loads a configuration file from disk /// Loads a configuration file from disk
/// </summary> /// </summary>

View file

@ -310,7 +310,7 @@ namespace Ryujinx.Ui.Common.Configuration
EnableDockedMode = new ReactiveObject<bool>(); EnableDockedMode = new ReactiveObject<bool>();
EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode)); EnableDockedMode.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableDockedMode));
EnablePtc = new ReactiveObject<bool>(); EnablePtc = new ReactiveObject<bool>();
EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc)); EnablePtc.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnablePtc));
EnableInternetAccess = new ReactiveObject<bool>(); EnableInternetAccess = new ReactiveObject<bool>();
EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess)); EnableInternetAccess.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableInternetAccess));
EnableFsIntegrityChecks = new ReactiveObject<bool>(); EnableFsIntegrityChecks = new ReactiveObject<bool>();
@ -411,30 +411,44 @@ namespace Ryujinx.Ui.Common.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> EnableShaderCache { get; private set; } public ReactiveObject<bool> EnableShaderCache { get; private set; }
/// <summary>
/// Enables or disables texture recompression
/// </summary>
public ReactiveObject<bool> EnableTextureRecompression { get; private set; }
/// <summary> /// <summary>
/// Graphics backend /// Graphics backend
/// </summary> /// </summary>
public ReactiveObject<GraphicsBackend> GraphicsBackend { get; private set; } public ReactiveObject<GraphicsBackend> GraphicsBackend { get; private set; }
/// <summary>
/// Preferred GPU
/// </summary>
public ReactiveObject<string> PreferredGpu { get; private set; }
public GraphicsSection() public GraphicsSection()
{ {
BackendThreading = new ReactiveObject<BackendThreading>(); BackendThreading = new ReactiveObject<BackendThreading>();
BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading)); BackendThreading.Event += static (sender, e) => LogValueChange(sender, e, nameof(BackendThreading));
ResScale = new ReactiveObject<int>(); ResScale = new ReactiveObject<int>();
ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale)); ResScale.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScale));
ResScaleCustom = new ReactiveObject<float>(); ResScaleCustom = new ReactiveObject<float>();
ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom)); ResScaleCustom.Event += static (sender, e) => LogValueChange(sender, e, nameof(ResScaleCustom));
MaxAnisotropy = new ReactiveObject<float>(); MaxAnisotropy = new ReactiveObject<float>();
MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy)); MaxAnisotropy.Event += static (sender, e) => LogValueChange(sender, e, nameof(MaxAnisotropy));
AspectRatio = new ReactiveObject<AspectRatio>(); AspectRatio = new ReactiveObject<AspectRatio>();
AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio)); AspectRatio.Event += static (sender, e) => LogValueChange(sender, e, nameof(AspectRatio));
ShadersDumpPath = new ReactiveObject<string>(); ShadersDumpPath = new ReactiveObject<string>();
EnableVsync = new ReactiveObject<bool>(); EnableVsync = new ReactiveObject<bool>();
EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync)); EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync));
EnableShaderCache = new ReactiveObject<bool>(); EnableShaderCache = new ReactiveObject<bool>();
EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache)); EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache));
GraphicsBackend = new ReactiveObject<GraphicsBackend>(); EnableTextureRecompression = new ReactiveObject<bool>();
GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend)); EnableTextureRecompression.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableTextureRecompression));
GraphicsBackend = new ReactiveObject<GraphicsBackend>();
GraphicsBackend.Event += static (sender, e) => LogValueChange(sender, e, nameof(GraphicsBackend));
PreferredGpu = new ReactiveObject<string>();
PreferredGpu.Event += static (sender, e) => LogValueChange(sender, e, nameof(PreferredGpu));
} }
} }
@ -505,45 +519,46 @@ namespace Ryujinx.Ui.Common.Configuration
{ {
ConfigurationFileFormat configurationFile = new ConfigurationFileFormat ConfigurationFileFormat configurationFile = new ConfigurationFileFormat
{ {
Version = ConfigurationFileFormat.CurrentVersion, Version = ConfigurationFileFormat.CurrentVersion,
BackendThreading = Graphics.BackendThreading, BackendThreading = Graphics.BackendThreading,
EnableFileLog = Logger.EnableFileLog, EnableFileLog = Logger.EnableFileLog,
ResScale = Graphics.ResScale, ResScale = Graphics.ResScale,
ResScaleCustom = Graphics.ResScaleCustom, ResScaleCustom = Graphics.ResScaleCustom,
MaxAnisotropy = Graphics.MaxAnisotropy, MaxAnisotropy = Graphics.MaxAnisotropy,
AspectRatio = Graphics.AspectRatio, AspectRatio = Graphics.AspectRatio,
GraphicsShadersDumpPath = Graphics.ShadersDumpPath, GraphicsShadersDumpPath = Graphics.ShadersDumpPath,
LoggingEnableDebug = Logger.EnableDebug, LoggingEnableDebug = Logger.EnableDebug,
LoggingEnableStub = Logger.EnableStub, LoggingEnableStub = Logger.EnableStub,
LoggingEnableInfo = Logger.EnableInfo, LoggingEnableInfo = Logger.EnableInfo,
LoggingEnableWarn = Logger.EnableWarn, LoggingEnableWarn = Logger.EnableWarn,
LoggingEnableError = Logger.EnableError, LoggingEnableError = Logger.EnableError,
LoggingEnableTrace = Logger.EnableTrace, LoggingEnableTrace = Logger.EnableTrace,
LoggingEnableGuest = Logger.EnableGuest, LoggingEnableGuest = Logger.EnableGuest,
LoggingEnableFsAccessLog = Logger.EnableFsAccessLog, LoggingEnableFsAccessLog = Logger.EnableFsAccessLog,
LoggingFilteredClasses = Logger.FilteredClasses, LoggingFilteredClasses = Logger.FilteredClasses,
LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel, LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel,
SystemLanguage = System.Language, SystemLanguage = System.Language,
SystemRegion = System.Region, SystemRegion = System.Region,
SystemTimeZone = System.TimeZone, SystemTimeZone = System.TimeZone,
SystemTimeOffset = System.SystemTimeOffset, SystemTimeOffset = System.SystemTimeOffset,
DockedMode = System.EnableDockedMode, DockedMode = System.EnableDockedMode,
EnableDiscordIntegration = EnableDiscordIntegration, EnableDiscordIntegration = EnableDiscordIntegration,
CheckUpdatesOnStart = CheckUpdatesOnStart, CheckUpdatesOnStart = CheckUpdatesOnStart,
ShowConfirmExit = ShowConfirmExit, ShowConfirmExit = ShowConfirmExit,
HideCursorOnIdle = HideCursorOnIdle, HideCursorOnIdle = HideCursorOnIdle,
EnableVsync = Graphics.EnableVsync, EnableVsync = Graphics.EnableVsync,
EnableShaderCache = Graphics.EnableShaderCache, EnableShaderCache = Graphics.EnableShaderCache,
EnablePtc = System.EnablePtc, EnableTextureRecompression = Graphics.EnableTextureRecompression,
EnableInternetAccess = System.EnableInternetAccess, EnablePtc = System.EnablePtc,
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, EnableInternetAccess = System.EnableInternetAccess,
FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
AudioBackend = System.AudioBackend, FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
AudioVolume = System.AudioVolume, AudioBackend = System.AudioBackend,
MemoryManagerMode = System.MemoryManagerMode, AudioVolume = System.AudioVolume,
ExpandRam = System.ExpandRam, MemoryManagerMode = System.MemoryManagerMode,
IgnoreMissingServices = System.IgnoreMissingServices, ExpandRam = System.ExpandRam,
GuiColumns = new GuiColumns IgnoreMissingServices = System.IgnoreMissingServices,
GuiColumns = new GuiColumns
{ {
FavColumn = Ui.GuiColumns.FavColumn, FavColumn = Ui.GuiColumns.FavColumn,
IconColumn = Ui.GuiColumns.IconColumn, IconColumn = Ui.GuiColumns.IconColumn,
@ -554,32 +569,33 @@ namespace Ryujinx.Ui.Common.Configuration
LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn, LastPlayedColumn = Ui.GuiColumns.LastPlayedColumn,
FileExtColumn = Ui.GuiColumns.FileExtColumn, FileExtColumn = Ui.GuiColumns.FileExtColumn,
FileSizeColumn = Ui.GuiColumns.FileSizeColumn, FileSizeColumn = Ui.GuiColumns.FileSizeColumn,
PathColumn = Ui.GuiColumns.PathColumn, PathColumn = Ui.GuiColumns.PathColumn
}, },
ColumnSort = new ColumnSort ColumnSort = new ColumnSort
{ {
SortColumnId = Ui.ColumnSort.SortColumnId, SortColumnId = Ui.ColumnSort.SortColumnId,
SortAscending = Ui.ColumnSort.SortAscending SortAscending = Ui.ColumnSort.SortAscending
}, },
GameDirs = Ui.GameDirs, GameDirs = Ui.GameDirs,
LanguageCode = Ui.LanguageCode, LanguageCode = Ui.LanguageCode,
EnableCustomTheme = Ui.EnableCustomTheme, EnableCustomTheme = Ui.EnableCustomTheme,
CustomThemePath = Ui.CustomThemePath, CustomThemePath = Ui.CustomThemePath,
BaseStyle = Ui.BaseStyle, BaseStyle = Ui.BaseStyle,
GameListViewMode = Ui.GameListViewMode, GameListViewMode = Ui.GameListViewMode,
ShowNames = Ui.ShowNames, ShowNames = Ui.ShowNames,
GridSize = Ui.GridSize, GridSize = Ui.GridSize,
ApplicationSort = Ui.ApplicationSort, ApplicationSort = Ui.ApplicationSort,
IsAscendingOrder = Ui.IsAscendingOrder, IsAscendingOrder = Ui.IsAscendingOrder,
StartFullscreen = Ui.StartFullscreen, StartFullscreen = Ui.StartFullscreen,
ShowConsole = Ui.ShowConsole, ShowConsole = Ui.ShowConsole,
EnableKeyboard = Hid.EnableKeyboard, EnableKeyboard = Hid.EnableKeyboard,
EnableMouse = Hid.EnableMouse, EnableMouse = Hid.EnableMouse,
Hotkeys = Hid.Hotkeys, Hotkeys = Hid.Hotkeys,
KeyboardConfig = new List<object>(), KeyboardConfig = new List<object>(),
ControllerConfig = new List<object>(), ControllerConfig = new List<object>(),
InputConfig = Hid.InputConfig, InputConfig = Hid.InputConfig,
GraphicsBackend = Graphics.GraphicsBackend, GraphicsBackend = Graphics.GraphicsBackend,
PreferredGpu = Graphics.PreferredGpu
}; };
return configurationFile; return configurationFile;
@ -587,70 +603,72 @@ namespace Ryujinx.Ui.Common.Configuration
public void LoadDefault() public void LoadDefault()
{ {
Logger.EnableFileLog.Value = true; Logger.EnableFileLog.Value = true;
Graphics.BackendThreading.Value = BackendThreading.Auto; Graphics.BackendThreading.Value = BackendThreading.Auto;
Graphics.ResScale.Value = 1; Graphics.ResScale.Value = 1;
Graphics.ResScaleCustom.Value = 1.0f; Graphics.ResScaleCustom.Value = 1.0f;
Graphics.MaxAnisotropy.Value = -1.0f; Graphics.MaxAnisotropy.Value = -1.0f;
Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; Graphics.AspectRatio.Value = AspectRatio.Fixed16x9;
Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl; Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
Graphics.ShadersDumpPath.Value = ""; Graphics.PreferredGpu.Value = "";
Logger.EnableDebug.Value = false; Graphics.ShadersDumpPath.Value = "";
Logger.EnableStub.Value = true; Logger.EnableDebug.Value = false;
Logger.EnableInfo.Value = true; Logger.EnableStub.Value = true;
Logger.EnableWarn.Value = true; Logger.EnableInfo.Value = true;
Logger.EnableError.Value = true; Logger.EnableWarn.Value = true;
Logger.EnableTrace.Value = false; Logger.EnableError.Value = true;
Logger.EnableGuest.Value = true; Logger.EnableTrace.Value = false;
Logger.EnableFsAccessLog.Value = false; Logger.EnableGuest.Value = true;
Logger.FilteredClasses.Value = Array.Empty<LogClass>(); Logger.EnableFsAccessLog.Value = false;
Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None; Logger.FilteredClasses.Value = Array.Empty<LogClass>();
System.Language.Value = Language.AmericanEnglish; Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None;
System.Region.Value = Region.USA; System.Language.Value = Language.AmericanEnglish;
System.TimeZone.Value = "UTC"; System.Region.Value = Region.USA;
System.SystemTimeOffset.Value = 0; System.TimeZone.Value = "UTC";
System.EnableDockedMode.Value = true; System.SystemTimeOffset.Value = 0;
EnableDiscordIntegration.Value = true; System.EnableDockedMode.Value = true;
CheckUpdatesOnStart.Value = true; EnableDiscordIntegration.Value = true;
ShowConfirmExit.Value = true; CheckUpdatesOnStart.Value = true;
HideCursorOnIdle.Value = false; ShowConfirmExit.Value = true;
Graphics.EnableVsync.Value = true; HideCursorOnIdle.Value = false;
Graphics.EnableShaderCache.Value = true; Graphics.EnableVsync.Value = true;
System.EnablePtc.Value = true; Graphics.EnableShaderCache.Value = true;
System.EnableInternetAccess.Value = false; Graphics.EnableTextureRecompression.Value = false;
System.EnableFsIntegrityChecks.Value = true; System.EnablePtc.Value = true;
System.FsGlobalAccessLogMode.Value = 0; System.EnableInternetAccess.Value = false;
System.AudioBackend.Value = AudioBackend.SDL2; System.EnableFsIntegrityChecks.Value = true;
System.AudioVolume.Value = 1; System.FsGlobalAccessLogMode.Value = 0;
System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe; System.AudioBackend.Value = AudioBackend.SDL2;
System.ExpandRam.Value = false; System.AudioVolume.Value = 1;
System.IgnoreMissingServices.Value = false; System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe;
Ui.GuiColumns.FavColumn.Value = true; System.ExpandRam.Value = false;
Ui.GuiColumns.IconColumn.Value = true; System.IgnoreMissingServices.Value = false;
Ui.GuiColumns.AppColumn.Value = true; Ui.GuiColumns.FavColumn.Value = true;
Ui.GuiColumns.DevColumn.Value = true; Ui.GuiColumns.IconColumn.Value = true;
Ui.GuiColumns.VersionColumn.Value = true; Ui.GuiColumns.AppColumn.Value = true;
Ui.GuiColumns.TimePlayedColumn.Value = true; Ui.GuiColumns.DevColumn.Value = true;
Ui.GuiColumns.LastPlayedColumn.Value = true; Ui.GuiColumns.VersionColumn.Value = true;
Ui.GuiColumns.FileExtColumn.Value = true; Ui.GuiColumns.TimePlayedColumn.Value = true;
Ui.GuiColumns.FileSizeColumn.Value = true; Ui.GuiColumns.LastPlayedColumn.Value = true;
Ui.GuiColumns.PathColumn.Value = true; Ui.GuiColumns.FileExtColumn.Value = true;
Ui.ColumnSort.SortColumnId.Value = 0; Ui.GuiColumns.FileSizeColumn.Value = true;
Ui.ColumnSort.SortAscending.Value = false; Ui.GuiColumns.PathColumn.Value = true;
Ui.GameDirs.Value = new List<string>(); Ui.ColumnSort.SortColumnId.Value = 0;
Ui.EnableCustomTheme.Value = false; Ui.ColumnSort.SortAscending.Value = false;
Ui.LanguageCode.Value = "en_US"; Ui.GameDirs.Value = new List<string>();
Ui.CustomThemePath.Value = ""; Ui.EnableCustomTheme.Value = false;
Ui.BaseStyle.Value = "Dark"; Ui.LanguageCode.Value = "en_US";
Ui.GameListViewMode.Value = 0; Ui.CustomThemePath.Value = "";
Ui.ShowNames.Value = true; Ui.BaseStyle.Value = "Dark";
Ui.GridSize.Value = 2; Ui.GameListViewMode.Value = 0;
Ui.ApplicationSort.Value = 0; Ui.ShowNames.Value = true;
Ui.IsAscendingOrder.Value = true; Ui.GridSize.Value = 2;
Ui.StartFullscreen.Value = false; Ui.ApplicationSort.Value = 0;
Ui.ShowConsole.Value = true; Ui.IsAscendingOrder.Value = true;
Hid.EnableKeyboard.Value = false; Ui.StartFullscreen.Value = false;
Hid.EnableMouse.Value = false; Ui.ShowConsole.Value = true;
Hid.EnableKeyboard.Value = false;
Hid.EnableMouse.Value = false;
Hid.Hotkeys.Value = new KeyboardHotkeys Hid.Hotkeys.Value = new KeyboardHotkeys
{ {
ToggleVsync = Key.Tab, ToggleVsync = Key.Tab,
@ -976,7 +994,7 @@ namespace Ryujinx.Ui.Common.Configuration
if (configurationFileFormat.Version < 29) if (configurationFileFormat.Version < 29)
{ {
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29."); Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys configurationFileFormat.Hotkeys = new KeyboardHotkeys
{ {
ToggleVsync = Key.Tab, ToggleVsync = Key.Tab,
@ -1105,72 +1123,74 @@ namespace Ryujinx.Ui.Common.Configuration
configurationFileUpdated = true; configurationFileUpdated = true;
} }
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio; Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio;
Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading; Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend; Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend;
Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu;
Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo; Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub;
Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn; Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
Logger.EnableError.Value = configurationFileFormat.LoggingEnableError; Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace; Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest; Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog; Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses; Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel; Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
System.Language.Value = configurationFileFormat.SystemLanguage; Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
System.Region.Value = configurationFileFormat.SystemRegion; System.Language.Value = configurationFileFormat.SystemLanguage;
System.TimeZone.Value = configurationFileFormat.SystemTimeZone; System.Region.Value = configurationFileFormat.SystemRegion;
System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
System.EnableDockedMode.Value = configurationFileFormat.DockedMode; System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle; ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; HideCursorOnIdle.Value = configurationFileFormat.HideCursorOnIdle;
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync;
System.EnablePtc.Value = configurationFileFormat.EnablePtc; Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess; Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; System.EnablePtc.Value = configurationFileFormat.EnablePtc;
System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
System.AudioBackend.Value = configurationFileFormat.AudioBackend; System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
System.AudioVolume.Value = configurationFileFormat.AudioVolume; System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode; System.AudioBackend.Value = configurationFileFormat.AudioBackend;
System.ExpandRam.Value = configurationFileFormat.ExpandRam; System.AudioVolume.Value = configurationFileFormat.AudioVolume;
System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode;
Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; System.ExpandRam.Value = configurationFileFormat.ExpandRam;
Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; Ui.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn;
Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn; Ui.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn;
Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn; Ui.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn;
Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn; Ui.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn;
Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn; Ui.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn;
Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn; Ui.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn;
Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn; Ui.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn;
Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn; Ui.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn;
Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; Ui.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn;
Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; Ui.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn;
Ui.GameDirs.Value = configurationFileFormat.GameDirs; Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId;
Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending;
Ui.LanguageCode.Value = configurationFileFormat.LanguageCode; Ui.GameDirs.Value = configurationFileFormat.GameDirs;
Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme;
Ui.BaseStyle.Value = configurationFileFormat.BaseStyle; Ui.LanguageCode.Value = configurationFileFormat.LanguageCode;
Ui.GameListViewMode.Value = configurationFileFormat.GameListViewMode; Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
Ui.ShowNames.Value = configurationFileFormat.ShowNames; Ui.BaseStyle.Value = configurationFileFormat.BaseStyle;
Ui.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder; Ui.GameListViewMode.Value = configurationFileFormat.GameListViewMode;
Ui.GridSize.Value = configurationFileFormat.GridSize; Ui.ShowNames.Value = configurationFileFormat.ShowNames;
Ui.ApplicationSort.Value = configurationFileFormat.ApplicationSort; Ui.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder;
Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen; Ui.GridSize.Value = configurationFileFormat.GridSize;
Ui.ShowConsole.Value = configurationFileFormat.ShowConsole; Ui.ApplicationSort.Value = configurationFileFormat.ApplicationSort;
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
Hid.EnableMouse.Value = configurationFileFormat.EnableMouse; Ui.ShowConsole.Value = configurationFileFormat.ShowConsole;
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
Hid.InputConfig.Value = configurationFileFormat.InputConfig; Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
Hid.InputConfig.Value = configurationFileFormat.InputConfig;
if (Hid.InputConfig.Value == null) if (Hid.InputConfig.Value == null)
{ {

View file

@ -410,8 +410,8 @@ namespace Ryujinx.Ui
if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan) if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan)
{ {
renderer = new VulkanGraphicsDevice((instance, vk) => new SurfaceKHR((ulong)((VKRenderer)RendererWidget).CreateWindowSurface(instance.Handle)), string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
VulkanHelper.GetRequiredInstanceExtensions); renderer = new VulkanGraphicsDevice(CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
} }
else else
{ {
@ -582,6 +582,11 @@ namespace Ryujinx.Ui
_emulationContext = new HLE.Switch(configuration); _emulationContext = new HLE.Switch(configuration);
} }
private SurfaceKHR CreateVulkanSurface(Instance instance, Vk vk)
{
return new SurfaceKHR((ulong)((VKRenderer)RendererWidget).CreateWindowSurface(instance.Handle));
}
private void SetupProgressUiHandlers() private void SetupProgressUiHandlers()
{ {
Ptc.PtcStateChanged -= ProgressHandler; Ptc.PtcStateChanged -= ProgressHandler;
@ -1034,10 +1039,11 @@ namespace Ryujinx.Ui
int resScale = ConfigurationState.Instance.Graphics.ResScale; int resScale = ConfigurationState.Instance.Graphics.ResScale;
float resScaleCustom = ConfigurationState.Instance.Graphics.ResScaleCustom; float resScaleCustom = ConfigurationState.Instance.Graphics.ResScaleCustom;
Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale; Graphics.Gpu.GraphicsConfig.ResScale = (resScale == -1) ? resScaleCustom : resScale;
Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy; Graphics.Gpu.GraphicsConfig.MaxAnisotropy = ConfigurationState.Instance.Graphics.MaxAnisotropy;
Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath; Graphics.Gpu.GraphicsConfig.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache; Graphics.Gpu.GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
Graphics.Gpu.GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
} }
public void SaveConfig() public void SaveConfig()

View file

@ -6,6 +6,7 @@ using Ryujinx.Audio.Backends.SoundIo;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Time.TimeZone; using Ryujinx.HLE.HOS.Services.Time.TimeZone;
@ -53,6 +54,7 @@ namespace Ryujinx.Ui.Windows
[GUI] CheckButton _hideCursorOnIdleToggle; [GUI] CheckButton _hideCursorOnIdleToggle;
[GUI] CheckButton _vSyncToggle; [GUI] CheckButton _vSyncToggle;
[GUI] CheckButton _shaderCacheToggle; [GUI] CheckButton _shaderCacheToggle;
[GUI] CheckButton _textureRecompressionToggle;
[GUI] CheckButton _ptcToggle; [GUI] CheckButton _ptcToggle;
[GUI] CheckButton _internetToggle; [GUI] CheckButton _internetToggle;
[GUI] CheckButton _fsicToggle; [GUI] CheckButton _fsicToggle;
@ -92,6 +94,7 @@ namespace Ryujinx.Ui.Windows
[GUI] ComboBoxText _anisotropy; [GUI] ComboBoxText _anisotropy;
[GUI] ComboBoxText _aspectRatio; [GUI] ComboBoxText _aspectRatio;
[GUI] ComboBoxText _graphicsBackend; [GUI] ComboBoxText _graphicsBackend;
[GUI] ComboBoxText _preferredGpu;
[GUI] ComboBoxText _resScaleCombo; [GUI] ComboBoxText _resScaleCombo;
[GUI] Entry _resScaleText; [GUI] Entry _resScaleText;
[GUI] ToggleButton _configureController1; [GUI] ToggleButton _configureController1;
@ -230,6 +233,11 @@ namespace Ryujinx.Ui.Windows
_shaderCacheToggle.Click(); _shaderCacheToggle.Click();
} }
if (ConfigurationState.Instance.Graphics.EnableTextureRecompression)
{
_textureRecompressionToggle.Click();
}
if (ConfigurationState.Instance.System.EnablePtc) if (ConfigurationState.Instance.System.EnablePtc)
{ {
_ptcToggle.Click(); _ptcToggle.Click();
@ -324,6 +332,10 @@ namespace Ryujinx.Ui.Windows
_aspectRatio.SetActiveId(((int)ConfigurationState.Instance.Graphics.AspectRatio.Value).ToString()); _aspectRatio.SetActiveId(((int)ConfigurationState.Instance.Graphics.AspectRatio.Value).ToString());
_graphicsBackend.SetActiveId(((int)ConfigurationState.Instance.Graphics.GraphicsBackend.Value).ToString()); _graphicsBackend.SetActiveId(((int)ConfigurationState.Instance.Graphics.GraphicsBackend.Value).ToString());
UpdatePreferredGpuComboBox();
_graphicsBackend.Changed += (sender, e) => UpdatePreferredGpuComboBox();
_custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath; _custThemePath.Buffer.Text = ConfigurationState.Instance.Ui.CustomThemePath;
_resScaleText.Buffer.Text = ConfigurationState.Instance.Graphics.ResScaleCustom.Value.ToString(); _resScaleText.Buffer.Text = ConfigurationState.Instance.Graphics.ResScaleCustom.Value.ToString();
_resScaleText.Visible = _resScaleCombo.ActiveId == "-1"; _resScaleText.Visible = _resScaleCombo.ActiveId == "-1";
@ -347,7 +359,7 @@ namespace Ryujinx.Ui.Windows
_browseThemePath.Sensitive = false; _browseThemePath.Sensitive = false;
} }
//Setup system time spinners // Setup system time spinners
UpdateSystemTimeSpinners(); UpdateSystemTimeSpinners();
_audioBackendStore = new ListStore(typeof(string), typeof(AudioBackend)); _audioBackendStore = new ListStore(typeof(string), typeof(AudioBackend));
@ -421,6 +433,39 @@ namespace Ryujinx.Ui.Windows
}); });
} }
private void UpdatePreferredGpuComboBox()
{
_preferredGpu.RemoveAll();
if (Enum.Parse<GraphicsBackend>(_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() private void UpdateSystemTimeSpinners()
{ {
//Bind system time events //Bind system time events
@ -494,46 +539,48 @@ namespace Ryujinx.Ui.Windows
DriverUtilities.ToggleOGLThreading(backendThreading == BackendThreading.Off); DriverUtilities.ToggleOGLThreading(backendThreading == BackendThreading.Off);
} }
ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active; ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active; ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active;
ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active; ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active;
ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active; ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active;
ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active; ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active;
ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active; ConfigurationState.Instance.Logger.EnableDebug.Value = _debugLogToggle.Active;
ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active; ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active;
ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active; ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active;
ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active; ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active;
ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse<GraphicsDebugLevel>(_graphicsDebugLevel.ActiveId); ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse<GraphicsDebugLevel>(_graphicsDebugLevel.ActiveId);
ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active; ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active; ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active; ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active;
ConfigurationState.Instance.HideCursorOnIdle.Value = _hideCursorOnIdleToggle.Active; ConfigurationState.Instance.HideCursorOnIdle.Value = _hideCursorOnIdleToggle.Active;
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active; ConfigurationState.Instance.Graphics.EnableShaderCache.Value = _shaderCacheToggle.Active;
ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active; ConfigurationState.Instance.Graphics.EnableTextureRecompression.Value = _textureRecompressionToggle.Active;
ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active; ConfigurationState.Instance.System.EnablePtc.Value = _ptcToggle.Active;
ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active; ConfigurationState.Instance.System.EnableInternetAccess.Value = _internetToggle.Active;
ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode; ConfigurationState.Instance.System.EnableFsIntegrityChecks.Value = _fsicToggle.Active;
ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active; ConfigurationState.Instance.System.MemoryManagerMode.Value = memoryMode;
ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active; ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active;
ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active; ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active;
ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active; ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active;
ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active; ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active;
ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId); ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active;
ConfigurationState.Instance.System.Region.Value = Enum.Parse<Common.Configuration.System.Region>(_systemRegionSelect.ActiveId); ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId);
ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset; ConfigurationState.Instance.System.Region.Value = Enum.Parse<Common.Configuration.System.Region>(_systemRegionSelect.ActiveId);
ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text; ConfigurationState.Instance.System.SystemTimeOffset.Value = _systemTimeOffset;
ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text; ConfigurationState.Instance.Ui.CustomThemePath.Value = _custThemePath.Buffer.Text;
ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs; ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = _graphicsShadersDumpPath.Buffer.Text;
ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value; ConfigurationState.Instance.Ui.GameDirs.Value = gameDirs;
ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture); ConfigurationState.Instance.System.FsGlobalAccessLogMode.Value = (int)_fsLogSpinAdjustment.Value;
ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId); ConfigurationState.Instance.Graphics.MaxAnisotropy.Value = float.Parse(_anisotropy.ActiveId, CultureInfo.InvariantCulture);
ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading; ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId);
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId); ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading;
ConfigurationState.Instance.Graphics.ResScale.Value = int.Parse(_resScaleCombo.ActiveId); ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId);
ConfigurationState.Instance.Graphics.ResScaleCustom.Value = resScaleCustom; ConfigurationState.Instance.Graphics.PreferredGpu.Value = _preferredGpu.ActiveId;
ConfigurationState.Instance.System.AudioVolume.Value = (float)_audioVolumeSlider.Value / 100.0f; 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; _previousVolumeLevel = ConfigurationState.Instance.System.AudioVolume.Value;

View file

@ -1897,7 +1897,7 @@
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="padding">5</property> <property name="padding">5</property>
<property name="position">1</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -1945,6 +1945,47 @@
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Preferred GPU (Vulkan only)</property>
<property name="label" translatable="yes">Preferred GPU:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="_preferredGpu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Preferred GPU (Vulkan only)</property>
<property name="active-id">-1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">2</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -2011,6 +2052,24 @@
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="_textureRecompressionToggle">
<property name="label" translatable="yes">Enable Texture Recompression</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="tooltip-text" translatable="yes">Enables or disables Texture Recompression. Reduces VRAM usage at the cost of texture quality, and may also increase stuttering</property>
<property name="halign">start</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@ -2072,7 +2131,7 @@
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="padding">5</property> <property name="padding">5</property>
<property name="position">1</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -2120,7 +2179,7 @@
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="padding">5</property> <property name="padding">5</property>
<property name="position">1</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -2169,7 +2228,7 @@
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="padding">5</property> <property name="padding">5</property>
<property name="position">3</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
</object> </object>