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.ShadersDumpPath = ConfigurationState.Instance.Graphics.ShadersDumpPath;
GraphicsConfig.EnableShaderCache = ConfigurationState.Instance.Graphics.EnableShaderCache;
GraphicsConfig.EnableTextureRecompression = ConfigurationState.Instance.Graphics.EnableTextureRecompression;
}
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
};
}
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;
private Func<Instance, Vk, SurfaceKHR> GetSurface;
private Func<string[]> GetRequiredExtensions;
private readonly Func<Instance, Vk, SurfaceKHR> _getSurface;
private readonly Func<string[]> _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<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;
GetRequiredExtensions = requiredExtensionsFunc;
_getSurface = surfaceFunc;
_getRequiredExtensions = requiredExtensionsFunc;
_preferredGpuId = preferredGpuId;
Shaders = new HashSet<ShaderCollection>();
Textures = new HashSet<ITexture>();
Samplers = new HashSet<SamplerHolder>();
@ -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);
}
}
}

View file

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

View file

@ -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.")]

View file

@ -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
{

View file

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

View file

@ -411,11 +411,21 @@ namespace Ryujinx.Ui.Common.Configuration
/// </summary>
public ReactiveObject<bool> EnableShaderCache { get; private set; }
/// <summary>
/// Enables or disables texture recompression
/// </summary>
public ReactiveObject<bool> EnableTextureRecompression { get; private set; }
/// <summary>
/// Graphics backend
/// </summary>
public ReactiveObject<GraphicsBackend> GraphicsBackend { get; private set; }
/// <summary>
/// Preferred GPU
/// </summary>
public ReactiveObject<string> PreferredGpu { get; private set; }
public GraphicsSection()
{
BackendThreading = new ReactiveObject<BackendThreading>();
@ -433,8 +443,12 @@ namespace Ryujinx.Ui.Common.Configuration
EnableVsync.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableVsync));
EnableShaderCache = new ReactiveObject<bool>();
EnableShaderCache.Event += static (sender, e) => LogValueChange(sender, e, nameof(EnableShaderCache));
EnableTextureRecompression = new ReactiveObject<bool>();
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));
}
}
@ -534,6 +548,7 @@ namespace Ryujinx.Ui.Common.Configuration
HideCursorOnIdle = HideCursorOnIdle,
EnableVsync = Graphics.EnableVsync,
EnableShaderCache = Graphics.EnableShaderCache,
EnableTextureRecompression = Graphics.EnableTextureRecompression,
EnablePtc = System.EnablePtc,
EnableInternetAccess = System.EnableInternetAccess,
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
@ -554,7 +569,7 @@ 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
{
@ -580,6 +595,7 @@ namespace Ryujinx.Ui.Common.Configuration
ControllerConfig = new List<object>(),
InputConfig = Hid.InputConfig,
GraphicsBackend = Graphics.GraphicsBackend,
PreferredGpu = Graphics.PreferredGpu
};
return configurationFile;
@ -594,6 +610,7 @@ namespace Ryujinx.Ui.Common.Configuration
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;
@ -616,6 +633,7 @@ namespace Ryujinx.Ui.Common.Configuration
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;
@ -1113,6 +1131,7 @@ namespace Ryujinx.Ui.Common.Configuration
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;
@ -1134,6 +1153,7 @@ namespace Ryujinx.Ui.Common.Configuration
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;

View file

@ -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;
@ -1038,6 +1043,7 @@ namespace Ryujinx.Ui
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()

View file

@ -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";
@ -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()
{
//Bind system time events
@ -511,6 +556,7 @@ namespace Ryujinx.Ui.Windows
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;
@ -531,6 +577,7 @@ namespace Ryujinx.Ui.Windows
ConfigurationState.Instance.Graphics.AspectRatio.Value = Enum.Parse<AspectRatio>(_aspectRatio.ActiveId);
ConfigurationState.Instance.Graphics.BackendThreading.Value = backendThreading;
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = Enum.Parse<GraphicsBackend>(_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;

View file

@ -1897,7 +1897,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">1</property>
<property name="position">0</property>
</packing>
</child>
<child>
@ -1945,6 +1945,47 @@
<property name="position">1</property>
</packing>
</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>
<packing>
<property name="expand">False</property>
@ -2011,6 +2052,24 @@
<property name="position">0</property>
</packing>
</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>
<object class="GtkBox">
<property name="visible">True</property>
@ -2072,7 +2131,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
@ -2120,7 +2179,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">1</property>
<property name="position">3</property>
</packing>
</child>
<child>
@ -2169,7 +2228,7 @@
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
</object>