Skip to content
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Settings for all games. Every option has a short explanation, and the help butto
| [RenoDX DLSS add-on](https://github.com/clshortfuse/renodx) | ShortFuse's ReShade add-on for neural rendering. | You import the file yourself. |
| Lecram DLSS5 add-on | A ReShade add-on for neural rendering by Lecram. | You import it yourself. The builds are available to supporters on the author's Buy Me a Coffee. |
| Deep Fried Chicken | A neural rendering add-on. Its licence allows personal use only. | You import the extracted release folder (or a .zip) yourself. Every import is kept, and each game can use its own version. |
| DLSS5-Feeder | An MIT ReShade add-on that makes the DLSS calls for games without DLSS, so Deep Fried Chicken can run in them. DLAA only. | Downloaded from its GitHub releases and checked against the SHA-256 GitHub publishes. Single-player games only. |

The app only replaces files in a game with files from the sources above or files you imported. Which of these you use is up to you. Most people only need the OptiScaler mode or **DLSS only**.

Expand Down
65 changes: 65 additions & 0 deletions docs/addons/dlss5-feeder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# DLSS5-Feeder

ReShade add-on by Jean-Laurent Rouzies (`jlrouzies-fr/DLSS5-Feeder`). It makes the DLSS calls a game without DLSS never
makes: it takes the backbuffer, ReShade's depth (Generic Depth add-on) and estimated motion vectors from a ReShade shader,
and hands them to NVIDIA's DLSS as a DLAA frame, so a neural consumer (Deep Fried Chicken here) has something to run on.
DLAA only: no upscaling, no performance gain, a few ms per frame at 4K. Facts below are from its README and release notes
(docs/research/methods-2026-10.md section 1); nothing was reverse engineered.

## Component model (docs/design.md section 2)

| Part | Feeder |
|---|---|
| Source | `Download` and `Import`. Releases of exactly `jlrouzies-fr/DLSS5-Feeder` (copycat repositories exist, the owner and name are pinned in `FeederLibrary.Repo`). Asset `DLSS5-Feeder-<version>.zip`. |
| Licence | MIT for `src/`, `shaders/`, `host/` (GitHub reports NOASSERTION because of an extra notice line). Third-party parts keep their own licences and none is bundled in the zip. Downloading and copying into the user's game is what the licence allows. |
| Verification | The SHA-256 GitHub publishes in the asset's `digest` field (all 4 releases checked 2026-10-21 had one). A release without a digest is not offered: no digest = no install. **Import** (Settings → ReShade add-ons → DLSS5-Feeder builds: Import… for the release .zip or `dlss5-feed.addon64`, Folder… for the extracted release): the four package files are copied byte for byte as a build whose id is the SHA-256 of the 64-bit add-on, labelled with the version from `READ-ME-FIRST.txt` ("imported" in the list); no digest check, the user chose the files. Imports are never removed by the automatic cleanup. The catalog repo needs no `feeder` section for that reason; add one (SHA-256 plus a mirror) the day GitHub stops publishing digests. |
| Library | `LibraryKind.Feeder`: `components\dlss5-feeder\<tag>\pkg\` plus the `.complete` record. Only the four files below are kept. Newest first by `BuildOrder`. |
| Default / per-game | `Components["dlss5-feeder"].Build` in settings and `GameOverride.BuildPick("dlss5-feeder")`; the picker shows **"Auto (<build>)"** first (the newest build, or the pinned default) and then every build; a pick wins, and "Reset to auto" (Settings and the game page) goes back. A removed build's pins go back to Auto, never to another build. The author tags betas (`v1.18.0-beta.2`) without GitHub's prerelease flag, so a beta is told by its tag and follows Settings' "include pre-releases" like the other downloads. |
| Cleanup | In `BuildCleanup` like every library; the default, per-game picks and builds installed in a game are protected. |
| Install record | Generic `InstalledComponent` (`dlss5-feeder`, build id = tag, version label, files with SHA-256, backups). `Extras`: `bits` (`64`/`32`) and, for 32-bit, `manual`. |
| Config | None, so there is nothing to override per game. `dlss5-feed.cfg` is created by the add-on itself with working defaults and re-read while the game runs; the README documents `host_window`, `preset`, `stall_log_ms` and others, but the app writes no key. |
| Update check | Through `GitHubClient.GetReleasesAsync` (ETag cache); offline it uses the cached release list, then the library. |

## What the app places

| Game | Files (relative to the install folder) |
|---|---|
| 64-bit | `dlss5-feed.addon64`, `reshade-shaders\Shaders\DLSS5_Feed.fx` |
| 32-bit | `dlss5-feed.addon32`, `reshade-shaders\Shaders\DLSS5_Feed.fx`, `host64\dlss5-feed-host64.exe` |

Taken from the zip by exact name; a zip missing one of them is refused whole. Not taken: `dlss5-feed-helper.addon64` (64-bit
helper mode, only for games whose own process cannot run NGX), the Vulkan layers (`layer-x64`, `layer-x86`: machine-wide
registration needs administrator rights), `READ-ME-FIRST.txt` and `Verify-DLSS5Feeder.ps1`.

## What it needs and the app does not do

- **One neural consumer, Deep Fried Chicken** (imported, 4.x or newer for games without DLSS). The planner
(`NrAddons.FeederRefusal`, checked in `Installer`) refuses Feeder without it and next to stock OptiScaler, the DX11 bridge,
ShortFuse's RenoDX add-on, Lecram or GITC Uplift. Feeder's README also names `renodx-dlss5` and an OptiScaler DLSS-NR fork as
consumers; the app only pairs it with DFC, the one it can install in a game without DLSS.
- **ReShade 6.8+ with add-on support**, the user's imported `nvngx_dlssnr.dll` (never downloaded by the app) and an
`nvngx_dlss.dll` (the app places NVIDIA's, as for DFC without DLSS).
- **A motion-vector shader** in `reshade-shaders\Shaders`, picked with `DLSS5_MV_PROVIDER` in the overlay. LumeniteFX Kernel is
recommended; its AGNYA licence ("all rights reserved unless explicitly stated") stops the app from shipping it. The advisor
treats `lumenite_*.fx` in the shader folder as "present".
- **The right depth buffer** in Generic Depth, MSAA/SSAA off, single-player only.
- Routes with manual steps: Direct3D 9 (dgVoodoo2, freeware that cannot be redistributed; the README has the settings),
Vulkan (ReShade's Vulkan layer, one administrator prompt, plus `ReShadeApps.ini`), 32-bit (the `host64\` folder needs a 64-bit
ReShade and DFC's 64-bit set placed by hand). The advisor lists each as a "Needs" line.

## Checked builds

| Release | Published | Zip (bytes) | Checked | Notes |
|---|---|---|---|---|
| v1.19.0 | 2026-10-11 | 503554 | 2026-10-21 | Layout: `dlss5-feed.addon64`, `dlss5-feed.addon32`, `dlss5-feed-helper.addon64`, `host64\dlss5-feed-host64.exe`, `reshade-shaders\Shaders\DLSS5_Feed.fx`, `layer-x64\`, `layer-x86\`, `READ-ME-FIRST.txt`, `Verify-DLSS5Feeder.ps1`. README: "NOT RUN IN A GAME: the two 1.19.0 fixes". Line 1 of `dlss5-feed.log` must say `dlss5-feed 1.19.0 commit 3c09eab`. |
| v1.18.0-beta.2 | 2026-10-06 | 503310 | 2026-10-21 (listing only) | Same asset name pattern; beta. |
| v1.18.0-beta.1 | 2026-09-29 | 492288 | 2026-10-21 (listing only) | Beta. |
| v1.17.0 | 2026-09-27 | 390753 | 2026-10-21 (listing only) | No helper add-on yet. |

Volatility: four releases in four weeks; the driver/consumer matrix in its README changes with them (driver 616.64+ breaks
`renodx-dlss5` 4.6/4.7, DFC is fine). Re-check this table, the zip layout and `FeederLibrary.PackageFiles` for every new release.

## Tests

`tests/DLSSUpdater.Tests/FeederTests.cs` (release choice, digest check, library, 64-bit and 32-bit install and uninstall, update),
`DfcTests.cs` (install in the same run as DFC, removal by a run without it, refusals), `NrConsumerTests.cs` (the rule).
44 changes: 44 additions & 0 deletions docs/advisor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Method advisor

The game page's **Works in this game** panel answers "which ways of improving this game does the app know, and which fit
here". `MethodAdvisor.Advise(AdvisorInput)` (`Core/MethodAdvisor.cs`) is pure: the caller reads the game, the GPU, the catalog
and the library and passes them in. It implements the decision table of `docs/research/methods-2026-10.md` section 8 (20
rows); `MethodAdvice.Rows` reports which rows applied, and `tests/DLSSUpdater.Tests/MethodAdvisorTests.cs` has a test per row.

## Input

| Input | From |
|---|---|
| Graphics APIs, bitness, engine, upscaler DLL and plugin signals, anti-cheat | `GameInfo` / `GameTech` (the detection scan) |
| Native DLSS | `Installer.HasNativeDlss`: DLLs our own install placed don't count |
| GPU vendor and RTX generation | `GpuDetector` (display adapter class in the registry, read once at startup); tests inject a `GpuInfo`. An unreadable GPU never hides a method. |
| OptiScaler compatibility list, HUDfix-incompatible list | the catalog's `optiscalerCompat` section (`docs/catalog.md`), matched by title with `GameMatcher.MatchName` |
| RenoDX game list | the catalog's `renodx` section, `GameMatcher` |
| Imported builds, DFC version | the component library |
| Routes already in the game | `NrAddons.PresentIn` (record and files) |
| Store install | `MethodAdvisor.IsProtectedStoreInstall` (under `WindowsApps`, or `MicrosoftGame.config` with an unreadable exe) |

## Output

An ordered list of `MethodOption`: title, `Availability` (available / needs setup / not possible / coming), a one-line reason,
the component ids it would install (and the install mode), what it needs, and an `Unverified` flag (also said in the reason)
where the research marks something unverified: Smooth Motion's RTX 40/50 requirement, the DX11 bridge requirement, the DX10
route, an Unreal DLSS plugin standing in for the DLL, an assumed graphics API. What cannot be done comes last with its reason.
Anti-cheat and protected Store installs return no methods and a `Blocked` line (row 20); a non-NVIDIA or GTX GPU leaves only
OptiScaler (row 19).

Methods the app does not install yet (Luma, third-party upscaler mods, the DX11 bridge, the all-in-one add-on, the RenoDX HDR
mod) are listed as **coming**, so the answer is complete without promising an install.

## The button

"Select" turns on the components of a method on the game page (and the install mode it needs). It never installs; the user
presses Install. Smooth Motion has no components: it is a driver setting on the game's NVIDIA tab.

## One neural consumer

`NrAddons` holds the rule (`Refusal`, `FeederRefusal`, `PresentIn`): DFC, GITC Uplift, ShortFuse, Lecram, the DX11 bridge and
OptiScaler's NR all detour the game's NGX calls, so a game gets one (ShortFuse + Lecram only with the Settings override, as
before). `Installer` checks it before anything is fetched (`EnsureOneNeuralConsumer`): a DX11 bridge in the folder blocks any
route, and DLSS5-Feeder needs ReShade + add-ons mode and Deep Fried Chicken alone. Routes the app places itself replace each
other as before.
1 change: 1 addition & 0 deletions docs/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ allows it. Its README documents the format (and `schema/catalog.schema.json` is
| `CatalogState.cs` | The catalog the app holds: the last good copy at startup, refreshed with every update check; a failed refresh keeps what it has. Holds the `HdrPicker`. |
| `CatalogClient.cs` | `LoadAsync` fetches catalog.json through `GitHubClient.GetRepoFileAsync` (ETag cache, 304s are free) and keeps the last good copy in `AppPaths.CatalogFile`. Offline, rate-limited, damaged or newer-than-us (`schema` > 1) answers fall back to that copy; it never throws except on cancellation. `LoadCached` reads the copy with no request. |
| `CatalogDownloader.cs` | `DownloadAsync(file, dest, ...)` downloads from `MirrorUrl`, else `Url` (and from `Url` when the mirror copy fails), into a staging file, checks size and SHA-256, and only then moves it to `dest`. A mismatch returns a one-line `Refusal` and leaves nothing behind. |
| `OptiCompatIndex.cs` | The `optiscalerCompat` section (OptiScaler's wiki compatibility list and its HUDfix-incompatible list) looked up by game title with `GameMatcher.MatchName`. Feeds the method advisor (`docs/advisor.md`); an older catalog without the section just leaves it empty. |
| `GameMatcher.cs` | `new GameMatcher(catalog.Sections.Renodx).Match(game)`: overrides first, then Steam AppID, then the normalised name (exact; game name contains entry name, longest wins; entry starts with game name). Anything that is "name + only a sequel number" (digits, roman numerals up to 39) is not a match. Only `main` and `engine` entries take part; a matched entry can be `Blocked`, so check `Mod.Blocked` and show `BlockReason`. |

`GameInfo.SteamAppId` comes from the Steam appmanifest (`Launchers.SteamLibrary`); other launchers and manual folders have none.
Expand Down
21 changes: 21 additions & 0 deletions src/DLSSUpdater/Core/AdvisorCatalog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace DLSSUpdater.Core;

/// <summary>What the method advisor reads from the catalog, built once per catalog document (the document is replaced as a whole on refresh).</summary>
public sealed class AdvisorCatalog
{
public static readonly AdvisorCatalog Empty = new(null);

private static readonly System.Runtime.CompilerServices.ConditionalWeakTable<CatalogDocument, AdvisorCatalog> Cache = [];

public OptiCompatIndex OptiCompat { get; }
/// <summary>Matches games to RenoDX's list; null when the catalog has no RenoDX section.</summary>
public GameMatcher? RenoDx { get; }

private AdvisorCatalog(CatalogDocument? doc)
{
OptiCompat = new OptiCompatIndex(doc?.Sections.OptiscalerCompat);
RenoDx = doc?.Sections.Renodx is { } renodx ? new GameMatcher(renodx) : null;
}

public static AdvisorCatalog For(CatalogDocument? doc) => doc is null ? Empty : Cache.GetValue(doc, d => new AdvisorCatalog(d));
}
3 changes: 2 additions & 1 deletion src/DLSSUpdater/Core/BuildLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace DLSSUpdater.Core;
/// Every library of kept builds: the downloaded OptiScaler and GITC Uplift releases, the imported add-ons and the NR runtime.
/// Each keeps several builds side by side; settings choose a default and each game may choose its own.
/// </summary>
public enum LibraryKind { OptiScaler, Uplift, Lecram, RenoDx, Dfc, DlssNr, RenoDxHdr, ReShade }
public enum LibraryKind { OptiScaler, Uplift, Lecram, RenoDx, Dfc, DlssNr, RenoDxHdr, ReShade, Feeder }

/// <summary>
/// One kept build as the lists and the cleanup see it. <see cref="Id"/> is what settings, game picks and install records name
Expand Down Expand Up @@ -175,6 +175,7 @@ public sealed partial class ComponentStore
LibraryKind.Uplift => ReleaseBuilds(Component.Uplift),
LibraryKind.RenoDxHdr => HdrLibraryBuilds(),
LibraryKind.ReShade => ReShadeBuilds.Select(b => new LibraryBuild(kind, b.Id, b.Label, b.Version, b.Added, ReShadeBuildDir(b), Downloaded: b.Downloaded)).ToList(),
LibraryKind.Feeder => FeederLibrary.Builds(),
_ when AddonOf(kind) is { } addon => AddonBuilds(addon)
.Select(b => new LibraryBuild(kind, b.Id, b.Label, b.DetectedLabel, b.Imported, Path.Combine(AddonRoot(addon), b.Id), Downloaded: b.Downloaded))
.ToList(),
Expand Down
25 changes: 25 additions & 0 deletions src/DLSSUpdater/Core/CatalogModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public sealed class CatalogDocument
public sealed class CatalogSections
{
public CatalogRenodx? Renodx { get; set; }
public CatalogOptiCompat? OptiscalerCompat { get; set; }
/// <summary>ShortFuse's renodx-dlss add-on: hash-pinned builds, never mirrored (licence unknown).</summary>
public CatalogRenodxDlss? RenodxDlss { get; set; }
}
Expand All @@ -33,6 +34,30 @@ public sealed class CatalogDlssBuild
public CatalogBinary File { get; set; } = new();
}

/// <summary>OptiScaler's own compatibility list (its wiki), as the catalog copied it: facts and a pointer back to the wiki page.</summary>
public sealed class CatalogOptiCompat
{
public string? Updated { get; set; }
public List<CatalogOptiGame> Games { get; set; } = [];
/// <summary>Games OptiScaler's wiki lists as unable to use OptiFG's HUDfix.</summary>
public List<string> HudfixIncompatible { get; set; } = [];
}

public sealed class CatalogOptiGame
{
public string Name { get; set; } = "";
/// <summary>The wiki page of the game: https://github.com/optiscaler/OptiScaler/wiki/&lt;Page&gt;; null when the list has none.</summary>
public string? Page { get; set; }
/// <summary>"main", "upscalerMods" (games that got an upscaler through a third-party mod) or "lumaUe".</summary>
public string List { get; set; } = "main";
/// <summary>"working", "single-os" or "not-working".</summary>
public string Compat { get; set; } = "working";
/// <summary>Upscaler inputs the game offers OptiScaler, as the wiki writes them: DLSS, FSR2, FSR3, FSR3.1/4, XeSS.</summary>
public List<string> Inputs { get; set; } = [];
public bool OptiPatcher { get; set; }
public string? Notes { get; set; }
}

public sealed class CatalogRenodx
{
public string? Updated { get; set; }
Expand Down
3 changes: 3 additions & 0 deletions src/DLSSUpdater/Core/ComponentRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public static class ComponentRegistry
public const string Uplift = "gitc-uplift";
/// <summary>RenoDX HDR mods per game (named, Unreal Extended, generic Unreal and Unity). Not the ShortFuse DLSS add-on, <see cref="RenoDx"/>.</summary>
public const string RenoDxHdr = "renodx-hdr";
/// <summary>DLSS5-Feeder (MIT, downloaded): makes the DLSS calls for games without DLSS; recorded the generic way (<see cref="FeederLibrary"/>).</summary>
public const string Feeder = "dlss5-feeder";
/// <summary>Not a component with files: the per-game record of what the app wrote into the NVIDIA driver profile (<see cref="NvidiaRecord"/>).</summary>
public const string NvidiaDriver = "nvidia-driver";

Expand All @@ -73,6 +75,7 @@ static ComponentRegistry()
Register(new(Dlss, "DLSS") { Legacy = true, OwnedFiles = ComponentStore.DlssFiles });
// Recorded the generic way. The wildcard also matches renodx-dlss.addon64, which is ShortFuse's other component.
Register(new(RenoDxHdr, "RenoDX HDR") { Library = LibraryKind.RenoDxHdr, Label = "RenoDX HDR", OwnedFiles = ["renodx-*.addon64", "renodx-*.addon32"] });
Register(new(Feeder, "DLSS5-Feeder") { Library = LibraryKind.Feeder, Label = "Feeder", OwnedFiles = FeederLibrary.OwnedFiles });
}

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/DLSSUpdater/Core/ComponentStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public sealed class CachedComponent
public bool Prerelease { get; set; }
public DateTime? Published { get; set; }
public DateTime Fetched { get; set; }
/// <summary>The user brought this build in (DLSS5-Feeder only so far): kept byte for byte and never removed by the automatic cleanup.</summary>
public bool Imported { get; set; }
/// <summary>The version of an imported build, as read from its files.</summary>
public string? Label { get; set; }
}

/// <summary>Resolves the latest releases, downloads them once per tag and holds the user-supplied files.</summary>
Expand Down
Loading