diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 04da286c..a7a266c7 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 04da286ca9442133724a3611172737c24fb97ef4 +Subproject commit a7a266c7356cbe3fab6dbeb2510cc02e780110a8 diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index a8374345..aabdee9a 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -32,6 +32,18 @@ public SettingsTabDxvk() CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED", }, + new DictionarySettingsEntry("Enable DLSS (Dxvk-Nvapi)", $"Choose which version of dxvk-nvapi to use. Wine >= 9.0 or Valve Wine (wine-ge/valvebe) >= 8.x are needed for DLSS.", Dxvk.NvapiVersions, () => Program.Config.NvapiVersion ?? Dxvk.GetDefaultNvapiVersion(), s => Program.Config.NvapiVersion = s, Dxvk.GetDefaultVersion()) + { + CheckWarning = s => + { + if (s == "DISABLED") return null; + if (!DxvkSettings.DxvkAllowsNvapi(dxvkVersionSetting.Value)) + return "Nvapi/DLSS requires DXVK 2.0 or greater."; + return null; + }, + CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED" && CoreEnvironmentSettings.IsDLSSAvailable, + }, + dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with DXVK. MangoHud must be installed separately.\nFlatpak users need the flatpak version of MangoHud.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) { CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED", diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs index f51f9a0c..bd411164 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs @@ -38,7 +38,7 @@ public override void Draw() Program.ClearPrefix(); } - ImGui.Text("\nClear the managed Wine and DXVK installs. Custom versions won't be touched."); + ImGui.Text("\nClear the managed Wine and DXVK installs."); if (ImGui.Button("Clear Wine & DXVK")) { Program.ClearTools(true); diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index 05e1e8a5..2c9adea5 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -59,6 +59,17 @@ public SettingsTabWine() } }, + new SettingsEntry("Extra WINEDLLOVERRIDES", "Do not use msquic, mscoree, d3d9, d3d10core, d3d11, or dxgi. These are already set.", () => Program.Config.WineDLLOverrides ?? "", s => Program.Config.WineDLLOverrides = s) + { + CheckValidity = s => + { + if (!WineSettings.WineDLLOverrideIsValid(s)) + return "Not a valid WINEDLLOVERRIDE string"; + + return null; + } + }, + new SettingsEntry("WINEDEBUG Variables", "Configure debug logging for wine. Useful for troubleshooting.", () => Program.Config.WineDebugVars ?? string.Empty, s => Program.Config.WineDebugVars = s) }; } diff --git a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs index 9fef0eb1..2790ba42 100644 --- a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs +++ b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs @@ -77,6 +77,8 @@ public interface ILauncherConfig public string? DxvkVersion { get; set; } + public string? NvapiVersion { get; set; } + public int? DxvkFrameRateLimit { get; set; } public DxvkHud? DxvkHud { get; set; } @@ -89,6 +91,8 @@ public interface ILauncherConfig public string? MangoHudCustomFile { get; set; } + public string? WineDLLOverrides { get; set; } + public string? WineDebugVars { get; set; } public bool? FixLocale { get; set; } diff --git a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs index e17b66f3..5cb1dd3d 100644 --- a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs +++ b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs @@ -21,6 +21,8 @@ public static class CoreEnvironmentSettings public static bool IsSteamCompatTool => CheckEnvBool("XL_SCT"); public static uint AltAppID => GetAltAppId(System.Environment.GetEnvironmentVariable("XL_APPID")); + public static bool ForceDLSS => CheckEnvBool("XL_FORCE_DLSS"); // Don't search for nvngx.dll. Assume it's already in the game directory. + private static bool CheckEnvBool(string key) { string val = (System.Environment.GetEnvironmentVariable(key) ?? string.Empty).ToLower(); @@ -82,4 +84,44 @@ static public bool IsGameModeInstalled() gameModeInstalled = false; return gameModeInstalled ?? false; } + + static private string? nvngxPath = ForceDLSS ? "" : Environment.GetEnvironmentVariable("XL_NVNGXPATH"); + + static public bool IsDLSSAvailable => !string.IsNullOrEmpty(NvidiaWineDLLPath()) || ForceDLSS; + + static public string NvidiaWineDLLPath() + { + if (nvngxPath is not null) + { + if (!File.Exists(Path.Combine(nvngxPath, "nvngx.dll"))) + nvngxPath = ""; + return nvngxPath; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + string[] targets = { Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".xlcore", "compatibilitytool", "nvidia"), "/lib64", "/lib", "/usr/lib64", "/usr/lib" }; + foreach (var target in targets) + { + var psi = new ProcessStartInfo("/bin/find"); + psi.Arguments = $"-L {target} -name \"nvngx.dll\""; + psi.RedirectStandardOutput = true; + var findCmd = new Process(); + findCmd.StartInfo = psi; + findCmd.Start(); + + var output = findCmd.StandardOutput.ReadToEnd(); + if (!string.IsNullOrWhiteSpace(output)) + { + var nvngx = new FileInfo(output.Split('\n', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()); + nvngxPath = nvngx.DirectoryName; + break; + } + } + } + else + nvngxPath = ""; + nvngxPath ??= ""; // If nvngxPath is still null, set it to empty string to prevent an infinite loop. + return nvngxPath ?? ""; + } } diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index c23c9002..f031911b 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -131,12 +131,15 @@ private static void LoadConfig(Storage storage) Config.WineType ??= WineType.Managed; if (!Wine.Versions.ContainsKey(Config.WineVersion ?? "")) - Config.WineVersion = "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; + Config.WineVersion = Wine.GetDefaultVersion(); Config.WineBinaryPath ??= "/usr/bin"; + Config.WineDLLOverrides ??= ""; Config.WineDebugVars ??= "-all"; if (!Dxvk.Versions.ContainsKey(Config.DxvkVersion ?? "")) - Config.DxvkVersion = "dxvk-async-1.10.3"; + Config.DxvkVersion = Dxvk.GetDefaultVersion(); + if (!Dxvk.NvapiVersions.ContainsKey(Config.NvapiVersion ?? "")) + Config.NvapiVersion = Dxvk.GetDefaultNvapiVersion(); Config.DxvkAsyncEnabled ??= true; Config.DxvkFrameRateLimit ??= 0; Config.DxvkHud ??= DxvkHud.None; @@ -379,10 +382,10 @@ private static void Main(string[] args) public static void CreateCompatToolsInstance() { - var dxvkSettings = new DxvkSettings(Dxvk.FolderName, Dxvk.DownloadUrl, storage.Root.FullName, Dxvk.AsyncEnabled, Dxvk.FrameRateLimit, Dxvk.DxvkHudEnabled, Dxvk.DxvkHudString, Dxvk.MangoHudEnabled, Dxvk.MangoHudCustomIsFile, Dxvk.MangoHudString, Dxvk.Enabled); - var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, storage.Root, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); + var dxvkSettings = new DxvkSettings(Dxvk.FolderName, Dxvk.DownloadUrl, storage.Root.FullName, Dxvk.AsyncEnabled, Dxvk.FrameRateLimit, Dxvk.DxvkHudEnabled, Dxvk.DxvkHudString, Dxvk.MangoHudEnabled, Dxvk.MangoHudCustomIsFile, Dxvk.MangoHudString, Dxvk.Enabled, Dxvk.NvapiFolderName, Dxvk.NvapiDownloadUrl, Dxvk.NvngxFolderName); + var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, Wine.ExtraWineDLLOverrides, storage.Root, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); var toolsFolder = storage.GetFolder("compatibilitytool"); - CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder, OSInfo.IsFlatpak); + CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder, Config.GamePath, OSInfo.IsFlatpak); } public static void ShowWindow() diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index db389e25..b3e127f2 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -8,6 +8,7 @@ using Serilog; using XIVLauncher.Common; using XIVLauncher.Common.Unix.Compatibility; +using XIVLauncher.Core; namespace XIVLauncher.Core.UnixCompatibility; @@ -17,7 +18,15 @@ public static class Dxvk public static string FolderName => Program.Config.DxvkVersion ?? GetDefaultVersion(); - public static string DownloadUrl => GetDownloadUrl(Program.Config.DxvkVersion); + public static string DownloadUrl => GetDownloadUrl(FolderName); + + public static string NvapiFolderName => NvapiEnabled ? Program.Config.NvapiVersion ?? GetDefaultNvapiVersion() : ""; + + public static string NvapiDownloadUrl => NvapiEnabled ? GetNvapiDownloadUrl(NvapiFolderName) : ""; + + public static string NvngxFolderName => NvapiEnabled ? CoreEnvironmentSettings.NvidiaWineDLLPath() : ""; + + public static bool NvapiEnabled => CoreEnvironmentSettings.IsDLSSAvailable && Program.Config.NvapiVersion != "DISABLED"; public static int FrameRateLimit => Program.Config.DxvkFrameRateLimit ?? 0; @@ -59,9 +68,12 @@ public static class Dxvk public static Dictionary> Versions { get; private set; } + public static Dictionary> NvapiVersions { get; private set; } + static Dxvk() { Versions = new Dictionary>(); + NvapiVersions = new Dictionary>(); MangoHudInstalled = DxvkSettings.MangoHudIsInstalled(); } @@ -92,6 +104,26 @@ public static void Initialize() {"label", "Disabled"} }; + NvapiVersions["dxvk-nvapi-v0.7.1"] = new Dictionary() + { + {"name", "dxvk-nvapi 0.7.1"}, {"desc", "dxvk-nvapi 0.7.1. Latest version, should be compatible with latest Nvidia drivers." }, + {"label", "Current"}, {"url", "https://github.com/jp7677/dxvk-nvapi/releases/download/v0.7.1/dxvk-nvapi-v0.7.1.tar.gz"}, + {"mark", "download"} + }; + + NvapiVersions["dxvk-nvapi-v0.6.4"] = new Dictionary() + { + {"name", "dxvk-nvapi 0.6.4"}, {"desc", "dxvk-nvapi 0.6.4. Try this if 0.7.1 doesn't work." }, + {"label", "Current"}, {"url", "https://github.com/jp7677/dxvk-nvapi/releases/download/v0.6.4/dxvk-nvapi-v0.6.4.tar.gz"}, + {"mark", "download"} + }; + + NvapiVersions["DISABLED"] = new Dictionary() + { + {"name", "Disabled"}, {"desc", "Don't use Dxvk-nvapi. DLSS will not be available. (FSR2 mod still works)"}, + {"label", "DLSS Off"} + }; + var toolDirectory = new DirectoryInfo(Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "dxvk")); if (!toolDirectory.Exists) @@ -104,15 +136,27 @@ public static void Initialize() { if (Directory.Exists(Path.Combine(dxvkDir.FullName, "x64")) && Directory.Exists(Path.Combine(dxvkDir.FullName, "x32"))) { - if (Versions.ContainsKey(dxvkDir.Name)) + if (dxvkDir.Name.Contains("nvapi")) { - if (dxvkDir.Name == "DISABLED") - Log.Error("Cannot use custom DXVK with folder name DISABLED. Skipping."); - else - Versions[dxvkDir.Name].Remove("mark"); - continue; + if (NvapiVersions.ContainsKey(dxvkDir.Name)) + { + NvapiVersions[dxvkDir.Name].Remove("mark"); + continue; + } + NvapiVersions[dxvkDir.Name] = new Dictionary() { {"label", "Custom"} }; + } + else + { + if (Versions.ContainsKey(dxvkDir.Name)) + { + if (dxvkDir.Name == "DISABLED") + Log.Error("Cannot use custom DXVK with folder name DISABLED. Skipping."); + else + Versions[dxvkDir.Name].Remove("mark"); + continue; + } + Versions[dxvkDir.Name] = new Dictionary() { {"label", "Custom"} }; } - Versions[dxvkDir.Name] = new Dictionary() { {"label", "Custom"} }; } } } @@ -134,6 +178,21 @@ public static string GetDefaultVersion() return Versions.First().Key; } + public static string GetNvapiDownloadUrl(string? name) + { + name ??= GetDefaultNvapiVersion(); + if (NvapiVersions.ContainsKey(name)) + return NvapiVersions[name].ContainsKey("url") ? NvapiVersions[name]["url"] : ""; + return Versions[GetDefaultNvapiVersion()].ContainsKey("url") ? Versions[GetDefaultNvapiVersion()]["url"] : ""; + } + + public static string GetDefaultNvapiVersion() + { + if (NvapiVersions.ContainsKey("dxvk-nvapi-v0.7.1")) + return "dxvk-nvapi-v0.7.1"; + return NvapiVersions.First().Key; + } + } public enum DxvkHud diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 3d34dfe7..0a5e628e 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -30,6 +30,8 @@ public static class Wine public static bool FSyncEnabled => Program.Config.FSyncEnabled ?? false; + public static string ExtraWineDLLOverrides => WineSettings.WineDLLOverrideIsValid(Program.Config.WineDLLOverrides) ? Program.Config.WineDLLOverrides ?? "" : ""; + public static Dictionary> Versions { get; private set; } static Wine() @@ -52,6 +54,13 @@ public static void Initialize() {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz"}, {"mark", "Download"} }; + // Beta version for testing. Needed for DLSS. + Versions["wine-xiv-staging-fsync-git-9.17.r0.g27b121f2"] = new Dictionary() + { + {"name", "Wine-XIV 9.17"}, {"desc", "Patched version of Wine Staging 9.17. Now with wayland and lsteamclient support added."}, + {"label", "Testing"}, {"url", $"https://github.com/rankynbass/unofficial-wine-xiv-git/releases/download/beta-9.17.r0.g27b121f2/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-9.17.r0.g27b121f2.tar.xz"}, + {"mark", "Download"} + }; var toolDirectory = new DirectoryInfo(Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "wine")); @@ -86,6 +95,8 @@ private static string GetDownloadUrl(string? name) public static string GetDefaultVersion() { + if (Versions.ContainsKey("wine-xiv-staging-fsync-git-9.17.r0.g27b121f2")) + return "wine-xiv-staging-fsync-git-9.17.r0.g27b121f2"; if (Versions.ContainsKey("wine-xiv-staging-fsync-git-8.5.r4.g4211bac7")) return "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; if (Versions.ContainsKey("wine-xiv-staging-fsync-git-7.10.r3.g560db77d"))