Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[xlcore][feature] Dxvk settings rework #1205

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fe921f6
fix: Launcher.cs changed to work with xlcore
rankynbass Dec 5, 2022
72bd2e4
feat: add DxvkSettings & related
rankynbass Dec 6, 2022
001ff3e
feat: add frame rate limit support
rankynbass Dec 6, 2022
7cc2a5a
feat: add backend for dxvkhud custom string
rankynbass Dec 6, 2022
c0f50f7
feat: add support for MangoHud
rankynbass Dec 6, 2022
8381d03
fix: disable MangoHud when using DXVK Hud
rankynbass Dec 6, 2022
aad9315
fix: use Path.Combine in MangoHud Custom
rankynbass Dec 7, 2022
435396e
fix: make sure mangohud.conf exists
rankynbass Dec 8, 2022
5dba7dc
fix: basic validity checking added for custom huds
rankynbass Dec 10, 2022
e4c4a4b
fix: improve dxvkhud checking with regex.
rankynbass Dec 10, 2022
d3fed4d
fix: add "1" as valid value for dxvkhud
rankynbass Dec 10, 2022
665abf2
fix: mangohud.conf logic was broken, now fixed.
rankynbass Dec 10, 2022
e31bf46
fix: flatpak breaks using fallback method
rankynbass Dec 10, 2022
f7b7aad
Update CompatibilityTools.cs
rankynbass Dec 10, 2022
bf0fb66
Update Launcher.cs
rankynbass Dec 10, 2022
ad34feb
Update DxvkSettings.cs
rankynbass Dec 10, 2022
87282c6
Update Dxvk.cs
rankynbass Dec 10, 2022
f47ddca
feat: Add dxvk log, cache, config
rankynbass Dec 10, 2022
84ed999
fix: Make sure to create .dxvk folder
rankynbass Dec 10, 2022
df1a3be
fix: Fixed directory create function.
rankynbass Dec 10, 2022
a4a7b38
fix: keep aync/async shader cache separate
rankynbass Dec 10, 2022
c138a3a
fix: use DirectoryInfo for xlcore path
rankynbass Dec 10, 2022
f58c2f6
DxvkSettings refactor and formatting
marzent Dec 11, 2022
391cc43
Merge remote-tracking branch 'goat_origin/master' into dxvk-settings-…
marzent Dec 11, 2022
b33dc79
add DXVK enabled switch
marzent Dec 11, 2022
d7139c4
Apply suggestions from code review
rankynbass Dec 12, 2022
90849ae
Update src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs
rankynbass Dec 12, 2022
1b05cda
Apply suggestions from code review
rankynbass Dec 12, 2022
84b9637
Merge pull request #13 from marzent/dxvk-settings-rework2
rankynbass Dec 12, 2022
810bcc9
fix: get rid of useless function
rankynbass Dec 13, 2022
a5f6ffd
update: dxvk version to 1.10.3
rankynbass Jan 5, 2023
26b704c
Add dxvk 2.1 support (no async)
rankynbass Jan 27, 2023
62fee28
Update for Dxvk 2.2
rankynbass Jun 2, 2023
3726cde
Fix a couple of minor style issues in code
rankynbass Jun 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 10 additions & 21 deletions src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,15 @@ public class CompatibilityTools

public bool IsToolDownloaded => File.Exists(Wine64Path) && Settings.Prefix.Exists;

private readonly Dxvk.DxvkHudType hudType;
public DxvkSettings DxvkSettings { get; private set; }

private readonly bool gamemodeOn;
private readonly string dxvkAsyncOn;

public CompatibilityTools(WineSettings wineSettings, Dxvk.DxvkHudType hudType, bool? gamemodeOn, bool? dxvkAsyncOn, DirectoryInfo toolsFolder)
public CompatibilityTools(WineSettings wineSettings, DxvkSettings dxvkSettings, bool? gamemodeOn, DirectoryInfo toolsFolder)
{
this.Settings = wineSettings;
this.hudType = hudType;
this.DxvkSettings = dxvkSettings;
this.gamemodeOn = gamemodeOn ?? false;
this.dxvkAsyncOn = (dxvkAsyncOn ?? false) ? "1" : "0";

this.toolDirectory = new DirectoryInfo(Path.Combine(toolsFolder.FullName, "beta"));
this.dxvkDirectory = new DirectoryInfo(Path.Combine(toolsFolder.FullName, "dxvk"));

Expand All @@ -67,9 +65,6 @@ public CompatibilityTools(WineSettings wineSettings, Dxvk.DxvkHudType hudType, b
if (!this.dxvkDirectory.Exists)
this.dxvkDirectory.Create();
}

if (!wineSettings.Prefix.Exists)
wineSettings.Prefix.Create();
}

public async Task EnsureTool(DirectoryInfo tempPath)
Expand All @@ -81,7 +76,7 @@ public async Task EnsureTool(DirectoryInfo tempPath)
}

EnsurePrefix();
await Dxvk.InstallDxvk(Settings.Prefix, dxvkDirectory).ConfigureAwait(false);
await Dxvk.InstallDxvk(Settings.Prefix, dxvkDirectory, DxvkSettings).ConfigureAwait(false);

IsToolReady = true;
}
Expand Down Expand Up @@ -168,21 +163,15 @@ private Process RunInPrefix(ProcessStartInfo psi, string workingDirectory, IDict
wineEnviromentVariables.Add("XL_WINEONLINUX", "true");
string ldPreload = Environment.GetEnvironmentVariable("LD_PRELOAD") ?? "";

string dxvkHud = hudType switch
{
Dxvk.DxvkHudType.None => "0",
Dxvk.DxvkHudType.Fps => "fps",
Dxvk.DxvkHudType.Full => "full",
_ => throw new ArgumentOutOfRangeException()
};

if (this.gamemodeOn == true && !ldPreload.Contains("libgamemodeauto.so.0"))
{
ldPreload = ldPreload.Equals("") ? "libgamemodeauto.so.0" : ldPreload + ":libgamemodeauto.so.0";
}

wineEnviromentVariables.Add("DXVK_HUD", dxvkHud);
wineEnviromentVariables.Add("DXVK_ASYNC", dxvkAsyncOn);
foreach(KeyValuePair<string,string> dxvkVar in DxvkSettings.DxvkVars)
{
wineEnviromentVariables.Add(dxvkVar.Key, dxvkVar.Value);
}
wineEnviromentVariables.Add("WINEESYNC", Settings.EsyncOn);
wineEnviromentVariables.Add("WINEFSYNC", Settings.FsyncOn);

Expand Down Expand Up @@ -290,4 +279,4 @@ public void Kill()

Process.Start(psi);
}
}
}
43 changes: 34 additions & 9 deletions src/XIVLauncher.Common.Unix/Compatibility/Dxvk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ namespace XIVLauncher.Common.Unix.Compatibility;

public static class Dxvk
{
private const string DXVK_DOWNLOAD = "https://github.com/Sporif/dxvk-async/releases/download/1.10.1/dxvk-async-1.10.1.tar.gz";
private const string DXVK_NAME = "dxvk-async-1.10.1";

public static async Task InstallDxvk(DirectoryInfo prefix, DirectoryInfo installDirectory)
public static async Task InstallDxvk(DirectoryInfo prefix, DirectoryInfo installDirectory, DxvkSettings? dxvkSettings = null)
{
var dxvkPath = Path.Combine(installDirectory.FullName, DXVK_NAME, "x64");
dxvkSettings ??= new DxvkSettings();
var dxvkPath = Path.Combine(installDirectory.FullName, dxvkSettings.FolderName, "x64");

if (!Directory.Exists(dxvkPath))
{
Log.Information("DXVK does not exist, downloading");
await DownloadDxvk(installDirectory).ConfigureAwait(false);
await DownloadDxvk(installDirectory, dxvkSettings.DownloadURL).ConfigureAwait(false);
}

var system32 = Path.Combine(prefix.FullName, "drive_c", "windows", "system32");
Expand All @@ -30,12 +28,12 @@ public static async Task InstallDxvk(DirectoryInfo prefix, DirectoryInfo install
}
}

private static async Task DownloadDxvk(DirectoryInfo installDirectory)
private static async Task DownloadDxvk(DirectoryInfo installDirectory, string downloadURL)
{
using var client = new HttpClient();
var tempPath = Path.GetTempFileName();

File.WriteAllBytes(tempPath, await client.GetByteArrayAsync(DXVK_DOWNLOAD));
File.WriteAllBytes(tempPath, await client.GetByteArrayAsync(downloadURL));
PlatformHelpers.Untar(tempPath, installDirectory.FullName);

File.Delete(tempPath);
Expand All @@ -49,7 +47,34 @@ public enum DxvkHudType
[SettingsDescription("FPS", "Only show FPS")]
Fps,

[SettingsDescription("DXVK Hud Custom", "Use a custom DXVK_HUD string")]
Custom,

[SettingsDescription("Full", "Show everything")]
Full,

[SettingsDescription("MangoHud Default", "Uses no config file.")]
MangoHud,

[SettingsDescription("MangoHud Custom", "Specify a custom config file")]
MangoHudCustom,

[SettingsDescription("MangoHud Full", "Show (almost) everything")]
MangoHudFull,
}

public enum DxvkVersion
{
[SettingsDescription("1.10.1 (default)", "The default version of DXVK used with XIVLauncher.Core.")]
v1_10_1,

[SettingsDescription("1.10.2", "Newer version of 1.10 branch of DXVK. Safe to use.")]
v1_10_2,

[SettingsDescription("1.10.3", "Newer version of 1.10 branch of DXVK. Safe to use.")]
v1_10_3,

[SettingsDescription("2.0 (might break Dalamud, GShade)", "Newest version of DXVK. May be faster, but not stable yet.")]
v2_0,
}
}
}
121 changes: 121 additions & 0 deletions src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace XIVLauncher.Common.Unix.Compatibility;

public class DxvkSettings
{
public string DownloadURL { get; private set; }

public string FolderName { get; private set; }

public Dictionary<string, string> DxvkVars { get; private set; }

public Dxvk.DxvkHudType DxvkHud { get; private set; }

public Dxvk.DxvkVersion DxvkVersion { get; private set; }

private const string ALLOWED_CHARS = "^[0-9a-zA-Z,=.]+$";
private const string ALLOWED_WORDS = "^(?:devinfo|fps|frametimes|submissions|drawcalls|pipelines|descriptors|memory|gpuload|version|api|cs|compiler|samplers|scale=(?:[0-9])*(?:.(?:[0-9])+)?)$";

public DxvkSettings(Dxvk.DxvkHudType hud = Dxvk.DxvkHudType.None, string dxvkHudCustom="",
string mangoHudPath="", bool? async = true, int? frameRate = 0,
Dxvk.DxvkVersion version = Dxvk.DxvkVersion.v1_10_1, string? corePath = null)
{
this.DxvkHud = hud;
string home = Environment.GetEnvironmentVariable("HOME");
corePath ??= Path.Combine(home,".xlcore");
string dxvkConfigPath = Path.Combine(corePath,".dxvk");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is cleaner to pass a DirectoryInfo into the cctor here as well, just in case the base xlcore storage path will change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's just the default. You can pass in the correct path to the constructor; it just defaults to null and sets the default to ~/.xlcore in that case. XL Core's Program.cs creates a DxvkSettings object, and I've passed it in there. But I could change it to pass in a DirectoryInfo. It's probably more "correct". So now the storage.Root object can be passed in from XL Core, instead of the string storage.Root.FullName.

if (!Directory.Exists(dxvkConfigPath))
Directory.CreateDirectory(dxvkConfigPath);
this.DxvkVars = new Dictionary<string, string> ();
this.DxvkVars.Add("DXVK_LOG_PATH",Path.Combine(corePath,"logs"));
this.DxvkVars.Add("DXVK_CONFIG_FILE",Path.Combine(dxvkConfigPath,"dxvk.conf"));
this.DxvkVars.Add("DXVK_ASYNC", ((async ?? false) ? "1" : "0"));
frameRate ??= 0;
if (frameRate > 0) this.DxvkVars.Add("DXVK_FRAME_RATE", (frameRate).ToString());
this.DxvkVersion = version;
string release = this.DxvkVersion switch
{
Dxvk.DxvkVersion.v1_10_1 => "1.10.1",
Dxvk.DxvkVersion.v1_10_2 => "1.10.2",
Dxvk.DxvkVersion.v1_10_3 => "1.10.3",
Dxvk.DxvkVersion.v2_0 => "2.0",
_ => throw new ArgumentOutOfRangeException(),
};
this.DownloadURL = $"https://github.com/Sporif/dxvk-async/releases/download/{release}/dxvk-async-{release}.tar.gz";
this.FolderName = $"dxvk-async-{release}";
string dxvkCacheSync = release + ((async ?? false) ? "-async" : "");
this.DxvkVars.Add("DXVK_STATE_CACHE_PATH",Path.Combine(dxvkConfigPath,dxvkCacheSync));
switch(this.DxvkHud)
{
case Dxvk.DxvkHudType.Fps:
DxvkVars.Add("DXVK_HUD","fps");
DxvkVars.Add("MANGOHUD","0");
break;
case Dxvk.DxvkHudType.Custom:
if (!CheckDxvkHudString(dxvkHudCustom)) dxvkHudCustom = "fps,frametimes,gpuload,version";
DxvkVars.Add("DXVK_HUD",dxvkHudCustom);
DxvkVars.Add("MANGOHUD","0");
break;
case Dxvk.DxvkHudType.Full:
DxvkVars.Add("DXVK_HUD","full");
DxvkVars.Add("MANGOHUD","0");
break;
case Dxvk.DxvkHudType.MangoHud:
DxvkVars.Add("DXVK_HUD","0");
DxvkVars.Add("MANGOHUD","1");
DxvkVars.Add("MANGOHUD_CONFIG", "");
break;
case Dxvk.DxvkHudType.MangoHudCustom:
DxvkVars.Add("DXVK_HUD","0");
DxvkVars.Add("MANGOHUD","1");
if (mangoHudPath == "")
{
string conf1 = Path.Combine(corePath,"MangoHud.conf");
string conf2 = Path.Combine(home,".config","MangoHud","wine-ffxiv_dx11.conf");
string conf3 = Path.Combine(home,".config","MangoHud","MangoHud.conf");
if (CheckMangoHudPath(conf1))
mangoHudPath = conf1;
else if (CheckMangoHudPath(conf2))
mangoHudPath = conf2;
else if (CheckMangoHudPath(conf3))
mangoHudPath = conf3;
}
if (CheckMangoHudPath(mangoHudPath))
DxvkVars.Add("MANGOHUD_CONFIGFILE",mangoHudPath);
else
DxvkVars.Add("MANGOHUD_CONFIG","");
break;
case Dxvk.DxvkHudType.MangoHudFull:
DxvkVars.Add("DXVK_HUD","0");
DxvkVars.Add("MANGOHUD","1");
DxvkVars.Add("MANGOHUD_CONFIG","full");
break;
// If DxvkHudType is None, or undefined, don't set anything.
default:
break;
}
}

public static bool CheckDxvkHudString(string customHud)
{
if (customHud == "1") return true;
if (string.IsNullOrWhiteSpace(customHud)) return false;
if (!Regex.IsMatch(customHud,ALLOWED_CHARS)) return false;
string[] hudvars = customHud.Split(",");
foreach (var hudvar in hudvars)
{
if (!Regex.IsMatch(hudvar,ALLOWED_WORDS))
return false;
}
return true;
}

public static bool CheckMangoHudPath(string mangoPath)
{
return (File.Exists(mangoPath)) ? true : false;
}
}