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 all 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
34 changes: 11 additions & 23 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 @@ -158,7 +153,7 @@ private Process RunInPrefix(ProcessStartInfo psi, string workingDirectory, IDict

var wineEnviromentVariables = new Dictionary<string, string>();
wineEnviromentVariables.Add("WINEPREFIX", Settings.Prefix.FullName);
wineEnviromentVariables.Add("WINEDLLOVERRIDES", $"msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi={(wineD3D ? "b" : "n")}");
wineEnviromentVariables.Add("WINEDLLOVERRIDES", $"msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi={(DxvkSettings.Enabled && !wineD3D ? "n" : "b")}");

if (!string.IsNullOrEmpty(Settings.DebugVars))
{
Expand All @@ -168,21 +163,14 @@ 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"))
if (gamemodeOn && !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 (var 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 +278,4 @@ public void Kill()

Process.Start(psi);
}
}
}
48 changes: 39 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,14 @@ 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)
{
var dxvkPath = Path.Combine(installDirectory.FullName, DXVK_NAME, "x64");
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 +27,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 +46,40 @@ 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", "The version of DXVK originally used with XIVLauncher.Core 1.0.3. Safe to use.")]
v1_10_1,

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

[SettingsDescription("1.10.3 (default)", "Current version of 1.10 branch of DXVK.")]
v1_10_3,

[SettingsDescription("2.0", "Newer version of DXVK. Last version with Async patch")]
v2_0,

[SettingsDescription("2.1 (No Async)", "Newer version of DXVK, using graphics pipeline library. No Async patch.")]
v2_1,

[SettingsDescription("2.2 (No Async)", "Newest version of DXVK, using graphics pipeline library. No Async patch.")]
v2_2,
}
}
}
142 changes: 142 additions & 0 deletions src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#nullable enable
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace XIVLauncher.Common.Unix.Compatibility;

public class DxvkSettings
{
public bool Enabled { get; }

public string DownloadURL { get; }

public string FolderName { get; }

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

public Dxvk.DxvkHudType DxvkHud { get; }

public Dxvk.DxvkVersion DxvkVersion { get; }

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, DirectoryInfo corePath, Dxvk.DxvkVersion version, bool enabled = true, string? dxvkHudCustom = null, FileInfo? mangoHudConfig = null, bool async = true,
int maxFrameRate = 0)
{
Enabled = enabled;
DxvkHud = hud;
var dxvkConfigPath = new DirectoryInfo(Path.Combine(corePath.FullName, "compatibilitytool", "dxvk"));
if (!dxvkConfigPath.Exists)
dxvkConfigPath.Create();
DxvkVars = new Dictionary<string, string>
{
{ "DXVK_LOG_PATH", Path.Combine(corePath.FullName, "logs") },
{ "DXVK_CONFIG_FILE", Path.Combine(dxvkConfigPath.FullName, "dxvk.conf") },
{ "DXVK_FRAME_RATE", (maxFrameRate).ToString() }
};
DxvkVersion = version;
var release = 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",
Dxvk.DxvkVersion.v2_1 => "2.1",
Dxvk.DxvkVersion.v2_2 => "2.2",
_ => throw new ArgumentOutOfRangeException(),
};
if (new[] {"1.10.1", "1.10.2", "1.10.3", "2.0"}.Contains(release))
{
DownloadURL = $"https://github.com/Sporif/dxvk-async/releases/download/{release}/dxvk-async-{release}.tar.gz";
FolderName = $"dxvk-async-{release}";
DxvkVars.Add("DXVK_ASYNC", async ? "1" : "0");
}
else
{
DownloadURL = $"https://github.com/doitsujin/dxvk/releases/download/v{release}/dxvk-{release}.tar.gz";
FolderName = $"dxvk-{release}";
}

var dxvkCachePath = new DirectoryInfo(Path.Combine(dxvkConfigPath.FullName, "cache"));
if (!dxvkCachePath.Exists) dxvkCachePath.Create();
this.DxvkVars.Add("DXVK_STATE_CACHE_PATH", Path.Combine(dxvkCachePath.FullName, release + (async ? "-async" : "")));

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 (mangoHudConfig is null)
{
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var conf1 = Path.Combine(corePath.FullName, "MangoHud.conf");
var conf2 = Path.Combine(home, ".config", "MangoHud", "wine-ffxiv_dx11.conf");
var conf3 = Path.Combine(home, ".config", "MangoHud", "MangoHud.conf");
if (File.Exists(conf1))
mangoHudConfig = new FileInfo(conf1);
else if (File.Exists(conf2))
mangoHudConfig = new FileInfo(conf2);
else if (File.Exists(conf3))
mangoHudConfig = new FileInfo(conf3);
}

if (mangoHudConfig != null && mangoHudConfig.Exists)
DxvkVars.Add("MANGOHUD_CONFIGFILE", mangoHudConfig.FullName);
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;

case Dxvk.DxvkHudType.None:
break;

default:
throw new ArgumentOutOfRangeException();
}
}

public static bool CheckDxvkHudString(string? customHud)
{
if (string.IsNullOrWhiteSpace(customHud)) return false;
if (customHud == "1") return true;
if (!Regex.IsMatch(customHud,ALLOWED_CHARS)) return false;

string[] hudvars = customHud.Split(",");

return hudvars.All(hudvar => Regex.IsMatch(hudvar, ALLOWED_WORDS));
}
}