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

WIP: feat: add dlss preset chooser #357

Open
wants to merge 1 commit into
base: feature/dlss_presets
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions src/Converters/ListNotEmptyConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml.Data;

namespace DLSS_Swapper.Converters
{
internal class ListNotEmptyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return (value is IEnumerable list) && list.Cast<object>().Any();
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}
1 change: 1 addition & 0 deletions src/DLSS Swapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250108002" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="Serilog" Version="4.2.0" />
Expand Down
10 changes: 10 additions & 0 deletions src/Data/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public abstract partial class Game : ObservableObject, IComparable<Game>, IEquat
[Column("cover_image")]
public partial string? CoverImage { get; set; } = null;

[ObservableProperty]
[Column("dlss_preset")]
public partial string? DlssPreset { get; set; } = "0x00000000";

/*
[ObservableProperty]
[property: Column("base_dlss_version")]
Expand Down Expand Up @@ -1195,6 +1199,12 @@ protected bool ParentUpdateFromGame(Game game)
didChange = true;
}

if (DlssPreset != game.DlssPreset)
{
DlssPreset = game.DlssPreset;
didChange = true;
}

if (CurrentDLSS_G != game.CurrentDLSS_G)
{
CurrentDLSS_G = game.CurrentDLSS_G;
Expand Down
4 changes: 3 additions & 1 deletion src/Data/GameManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.WinUI.Collections;
using DLSS_Swapper.Helpers;
using DLSS_Swapper.Interfaces;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
Expand Down Expand Up @@ -248,7 +249,6 @@ public ICollectionView GetGameCollection()
}
}


public Game AddGame(Game game, bool scrollIntoView = false)
{
lock (gameLock)
Expand All @@ -258,6 +258,7 @@ public Game AddGame(Game game, bool scrollIntoView = false)
// This probably checks the game collection twice looking for the game.
// We could do away with this, but in theory this if is never hit
var oldGame = _synchronisedAllGames.First(x => x.Equals(game));
oldGame.DlssPreset = NVAPIHelper.Instance.GetGameDLSSPreset(oldGame.Title);

App.CurrentApp.RunOnUIThread(() =>
{
Expand All @@ -270,6 +271,7 @@ public Game AddGame(Game game, bool scrollIntoView = false)
else
{
Debug.WriteLine($"Adding new game: {game.Title}");
game.DlssPreset = NVAPIHelper.Instance.GetGameDLSSPreset(game.Title);

_synchronisedAllGames.Add(game);

Expand Down
38 changes: 38 additions & 0 deletions src/Helpers/CommonHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DLSS_Swapper.Helpers
{
internal class CommonHelpers
{
public static int LevenshteinDistance(string s, string t)
{
if (string.IsNullOrEmpty(s)) return t?.Length ?? 0;
if (string.IsNullOrEmpty(t)) return s.Length;

int[,] dp = new int[s.Length + 1, t.Length + 1];

for (int i = 0; i <= s.Length; i++)
dp[i, 0] = i;
for (int j = 0; j <= t.Length; j++)
dp[0, j] = j;

for (int i = 1; i <= s.Length; i++)
{
for (int j = 1; j <= t.Length; j++)
{
int cost = s[i - 1] == t[j - 1] ? 0 : 1;
dp[i, j] = Math.Min(
Math.Min(dp[i - 1, j] + 1, dp[i, j - 1] + 1),
dp[i - 1, j - 1] + cost);
}
}

return dp[s.Length, t.Length];
}
}
}

113 changes: 113 additions & 0 deletions src/Helpers/NVAPIHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using ABI.Windows.ApplicationModel.Activation;
using DLSS_Swapper.Data;
using NvAPIWrapper.DRS;

namespace DLSS_Swapper.Helpers
{

internal class NVAPIHelper
{
private static readonly Dictionary<string, uint> PresetMap = new Dictionary<string, uint>
{
["Default"] = 0x00000000,
["Preset J"] = 0x0000000A,
["Preset K"] = 0x0000000B,
};

public List<DlssPresetOption> DlssPresetOptions { get; } = PresetMap
.Select(kvp => new DlssPresetOption
{
Value = $"0x{kvp.Value:X8}",
Label = kvp.Key == "Preset 0" ? "Default" : kvp.Key
})
.ToList();

public static NVAPIHelper Instance { get; private set; } = new NVAPIHelper();
private readonly NvAPIWrapper.DRS.DriverSettingsSession nvapiSession;
private Dictionary<string, DriverSettingsProfile> cachedProfiles = new Dictionary<string, DriverSettingsProfile>();

private NVAPIHelper()
{
nvapiSession = NvAPIWrapper.DRS.DriverSettingsSession.CreateAndLoad();
cachedProfiles = nvapiSession.Profiles.AsParallel().ToDictionary(profile => profile.Name);
Logger.Info("" + cachedProfiles.First());
}

private DriverSettingsProfile FindClosestTitle(string title)
{
if (cachedProfiles.TryGetValue(title, out var exactProfile))
return exactProfile;
return cachedProfiles
.OrderBy(entry => CommonHelpers.LevenshteinDistance(entry.Key, title))
.Select(entry => entry.Value)
.FirstOrDefault();
}

public string GetGameDLSSPreset(string title)
{
try
{
var closestProfile = FindClosestTitle(title);
if (closestProfile is null)
{
return "0x00000000";
}
var settings = closestProfile.Settings;
var dlssPreset = settings.FirstOrDefault(x => x.SettingId == 283385331);

if (dlssPreset is not null)
{
return $"0x{dlssPreset.CurrentValue:X8}";

}
else
{
return "0x00000000";
}

}
catch (Exception err)
{
Logger.Error(err.Message);
return "0x00000000";
}
}

public void SetGameDLSSPreset(Game game)
{
try
{
var closestProfile = FindClosestTitle(game.Title);
if (closestProfile is null)
{
throw new Exception("There was an error finding a matching Profile");
}
var preset = game.DlssPreset;
if (preset.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
{
preset = preset.Substring(2);
}

uint value = uint.Parse(preset, NumberStyles.HexNumber);
closestProfile.SetSetting(283385331, value);
nvapiSession.Save();
Logger.Info("Set Profile for: " + game.Title + " to " + game.DlssPreset);
}
catch (Exception err)
{
Logger.Error(err.Message);
}
}
}
}

public class DlssPresetOption
{
public string Value { get; set; }
public string Label { get; set; }
}
18 changes: 15 additions & 3 deletions src/UserControls/GameControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
VerticalAlignment="Stretch">

<usercontrols:FakeContentDialog.Resources>

<ct_converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" TrueValue="Visible" FalseValue="Collapsed" />
<ct_converters:BoolNegationConverter x:Key="BoolNegationConverter" />
<ct_converters:BoolToVisibilityConverter x:Key="BoolToInvisibilityConverter" TrueValue="Collapsed" FalseValue="Visible" />
<ct_converters:BoolNegationConverter x:Key="BoolNegationConverter" />
<ct_converters:BoolToObjectConverter x:Key="FavouriteTextConverter" TrueValue="Favourited" FalseValue="Click to favourite" />
<ct_converters:BoolToObjectConverter x:Key="FavouriteGlyphConverter" TrueValue="&#xE735;" FalseValue="&#xE734;" />
<ct_converters:EmptyObjectToObjectConverter x:Key="NullObjectToBoolConverter" NotEmptyValue="True" EmptyValue="False" />

<ct_converters:EmptyCollectionToObjectConverter x:Key="EmptyCollectionToObjectConverter" NotEmptyValue="True" EmptyValue="False" />

<converters:DLSSStateVisibilityConverter x:Key="IsDownloadingConverter" DesierdState="Downloading" />
<converters:DLSSStateVisibilityConverter x:Key="IsDownloadedConverter" DesierdState="Downloaded" />
<converters:DLSSStateVisibilityConverter x:Key="IsNotFoundConverter" DesierdState="NotFound" />
Expand Down Expand Up @@ -156,6 +157,17 @@
<TextBlock Grid.Column="0" Grid.Row="3" Text="DLSS Ray Reconstruction" FontWeight="Bold" />
<Button Grid.Column="0" Grid.Row="4" IsEnabled="{x:Bind ViewModel.Game.CurrentDLSS_D, Converter={StaticResource NullObjectToBoolConverter}}" Content="{x:Bind ViewModel.Game.CurrentDLSS_D.DisplayName, FallbackValue='Not found', Mode=OneWay}" Command="{x:Bind ViewModel.ChangeRecordCommand}" CommandParameter="{x:Bind data:GameAssetType.DLSS_D}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" />

<StackPanel Grid.Column="1" Grid.Row="3" Orientation="Horizontal">
<TextBlock Text="DLSS Preset" FontWeight="Bold"/>
<FontIcon Glyph="&#xE73E;" Visibility="{x:Bind ViewModel.IsDlssPresetSaved, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter }}" Margin="5,0,0,0"/>
<ProgressRing Visibility="{x:Bind ViewModel.IsDlssPresetSaved, Mode=OneWay, Converter={StaticResource BoolToInvisibilityConverter }}" Width="16" Height="16" Margin="5,0,0,0"/>
</StackPanel>
<ComboBox Grid.Column="1" Grid.Row="4"
ItemsSource="{x:Bind ViewModel.DlssPresetOptions}"
SelectedItem="{x:Bind ViewModel.SelectedDlssPreset, Mode=TwoWay}"
DisplayMemberPath="Label"
IsEnabled="{x:Bind ViewModel.DlssPresetOptions, Mode=OneWay, Converter={StaticResource EmptyCollectionToObjectConverter}}"
/>
</Grid>


Expand Down
62 changes: 62 additions & 0 deletions src/UserControls/GameControlModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Diagnostics;
using System.IO;
using System.ComponentModel;
using DLSS_Swapper.Helpers;

namespace DLSS_Swapper.UserControls;

Expand All @@ -26,6 +27,34 @@ public partial class GameControlModel : ObservableObject
[NotifyPropertyChangedFor(nameof(GameTitleHasChanged))]
public partial string GameTitle { get; set; }

public List<DlssPresetOption> DlssPresetOptions;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(DlssPresetHasChanged))]
public partial string DlssPreset { get; set; }

[ObservableProperty]
private DlssPresetOption selectedDlssPreset;

[ObservableProperty]
private bool canSelectDlssPreset = false;

[ObservableProperty]
private bool isDlssPresetSaved = true;

// Declare and implement the partial method
partial void OnSelectedDlssPresetChanged(DlssPresetOption value)
{
// This code executes whenever SelectedDlssPreset changes.
// Automatically trigger the save command:
if(Game.DlssPreset != value.Value)
{
IsDlssPresetSaved = false;
DlssPreset = value.Value;
SaveDlssPresetCommand.Execute(null);
}
}

public bool GameTitleHasChanged
{
get
Expand All @@ -44,11 +73,31 @@ public bool GameTitleHasChanged
}
}

public bool DlssPresetHasChanged
{
get
{

if (string.IsNullOrEmpty(DlssPreset))
{
return false;
}

return DlssPreset.Equals(Game.DlssPreset) == false;
}
}

public GameControlModel(GameControl gameControl, Game game)
{
gameControlWeakReference = new WeakReference<GameControl>(gameControl);
Game = game;
GameTitle = game.Title;
DlssPresetOptions = NVAPIHelper.Instance.DlssPresetOptions;
SelectedDlssPreset = DlssPresetOptions.FirstOrDefault(o => o.Value.Equals(game.DlssPreset, StringComparison.OrdinalIgnoreCase));
if (game.CurrentDLSS is null)
{
NVAPIHelper.Instance.DlssPresetOptions.Clear();
}
}


Expand Down Expand Up @@ -218,4 +267,17 @@ async Task SaveTitleAsync()
await Game.SaveToDatabaseAsync();
OnPropertyChanged(nameof(GameTitleHasChanged));
}

[RelayCommand]
async Task SaveDlssPresetAsync()
{
if(DlssPreset is not null)
{
Game.DlssPreset = DlssPreset;
NVAPIHelper.Instance.SetGameDLSSPreset(Game);
await Game.SaveToDatabaseAsync();
OnPropertyChanged(nameof(DlssPresetHasChanged));
IsDlssPresetSaved = true;
}
}
}