release: prepare 0.1.5 with RDNA2 kernels and in-game DLSS/FSR switching

- Add native preset K kernels for gfx1030–gfx1036 using software matrix
  products, with fast and accuracy builds and RDNA2 motion kernels.
- Follow OptiScaler's DLSS and RR preset overrides, sanitize unsupported
  values and select the preset matching the feature's quality mode.
- Enable FSR 4 under NVIDIA GPU spoofing by exposing real AMD PCI IDs
  to OptiScaler and FidelityFX modules; bundle AMD's loader and upscaler.
- Keep K on native kernels in engine auto mode unless HIP is selected,
  and fall back to CUDA for M/L when shader_float8 is unavailable.
- Add native-engine K GPU timings, preset recreation harness controls
  and regression coverage; fix the input-wait test's glibc name clash.
- Update configuration, installer guidance and release documentation,
  simplify the README and move gameplay videos to docs/videos.md.

RDNA2 kernels remain untested on RDNA2 hardware; software matrix
arithmetic was validated against WMMA on RDNA3.
This commit is contained in:
ayo committed 2026-10-17 16:05:09 -04:00
1 parent 34e6b0fe71
commit 0e851b7f90
24 files changed
+703 -174

No files matched your search

+16
View File
@@ -2445,6 +2445,22 @@ int main(int argc, char** argv)
d4r_ngx_set_uint(parameters, "Height", height);
d4r_ngx_set_uint(parameters, "DLSS.Render.Subrect.Dimensions.Width", width);
d4r_ngx_set_uint(parameters, "DLSS.Render.Subrect.Dimensions.Height", height);
// D4R_HARNESS_RECREATE_PRESETS=11,5,13: every Super Sampling preset slot of cycle N takes entry N-1 (cycling),
// as OptiScaler's Render Presets Override + Apply Changes recreates the feature with the picked model
if (const char* list = std::getenv("D4R_HARNESS_RECREATE_PRESETS"); list != nullptr && *list != '\0')
{
std::vector<unsigned int> presets;
for (const char* cursor = list; *cursor != '\0';)
{
char* end = nullptr;
presets.push_back(static_cast<unsigned int>(std::strtoul(cursor, &end, 0)));
cursor = *end != '\0' ? end + 1 : end;
}
const unsigned int preset = presets[(cycle - 1) % presets.size()];
for (const char* mode : {"DLAA", "Quality", "Balanced", "Performance", "UltraPerformance", "UltraQuality"})
d4r_ngx_set_uint(parameters, (std::string("DLSS.Hint.Render.Preset.") + mode).c_str(), preset);
std::printf("RECREATE cycle %d: presets %u\n", cycle, preset);
}
result = createFeature(g_list, featureId, parameters, &feature);
if (result != NGX_SUCCESS)
{
+173
View File
@@ -0,0 +1,173 @@
// FSR 4 from OptiScaler's upscaler menu while the game sees an NVIDIA GPU.
//
// d4r's games run with WINE_HIDE_AMD_GPU (PROTON_FORCE_NVAPI), so every DXGI adapter reports vendor 0x10de. Three
// parties then refuse FSR 4 on the AMD GPU that runs it: OptiScaler's own GPU check (RDNA3/RDNA4 -> FSR 4 update,
// INT8 or FP8 model), AMD's amd_fidelityfx_upscaler_dx12.dll and the FSR 4 provider amdxcffx64.dll, each of which
// reads the adapter's vendor before using the driver extension (2026-10-17: with the identity hidden, FSR 4.1.1
// produced FSR 3.1's output byte for byte; amdxcffx64.dll never loaded unless Fsr4Update was forced, and then the
// upscaler still chose FSR 3.1).
//
// The adapter's GetDesc family is wrapped so that these callers alone - OptiScaler (found by its PE export name,
// whatever its loader file is called) and AMD's FidelityFX modules - read the GPU's real PCI vendor and device ids,
// from sysfs. The game, vkd3d-proton, NVIDIA's NGX libraries and everything else keep the NVIDIA identity, and only
// the adapter behind the game's D3D12 device is changed.
#pragma once
#include <windows.h>
#include <dxgi1_6.h>
#include <cstdint>
#include <cstring>
#include <string>
#include "d4r_fsr_rr_identity.h"
namespace d4r_fsr4_identity
{
inline D4rPciIdentity g_real;
inline LUID g_luid = {};
using GetDescFn = HRESULT(STDMETHODCALLTYPE*)(IDXGIAdapter*, DXGI_ADAPTER_DESC*);
using GetDesc1Fn = HRESULT(STDMETHODCALLTYPE*)(IDXGIAdapter1*, DXGI_ADAPTER_DESC1*);
using GetDesc2Fn = HRESULT(STDMETHODCALLTYPE*)(IDXGIAdapter2*, DXGI_ADAPTER_DESC2*);
using GetDesc3Fn = HRESULT(STDMETHODCALLTYPE*)(IDXGIAdapter4*, DXGI_ADAPTER_DESC3*);
inline GetDescFn g_getDesc = nullptr;
inline GetDesc1Fn g_getDesc1 = nullptr;
inline GetDesc2Fn g_getDesc2 = nullptr;
inline GetDesc3Fn g_getDesc3 = nullptr;
// The DLL name in a module's PE export directory ("OptiScaler.dll" for OptiScaler under any file name).
inline bool export_name_is(HMODULE module, const char* expected)
{
auto* base = reinterpret_cast<const unsigned char*>(module);
auto* dos = reinterpret_cast<const IMAGE_DOS_HEADER*>(base);
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
return false;
auto* nt = reinterpret_cast<const IMAGE_NT_HEADERS*>(base + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE)
return false;
const IMAGE_DATA_DIRECTORY& directory = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (directory.VirtualAddress == 0 || directory.Size == 0)
return false;
auto* exports = reinterpret_cast<const IMAGE_EXPORT_DIRECTORY*>(base + directory.VirtualAddress);
return exports->Name != 0 && _stricmp(reinterpret_cast<const char*>(base + exports->Name), expected) == 0;
}
// Whether the code at `address` belongs to OptiScaler or to one of AMD's FidelityFX/FSR 4 modules.
inline bool caller_sees_real(void* address)
{
HMODULE module = nullptr;
if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
static_cast<const char*>(address), &module) || module == nullptr)
return false;
char path[MAX_PATH] = {};
const DWORD length = GetModuleFileNameA(module, path, MAX_PATH);
if (length == 0 || length >= MAX_PATH)
return false;
const char* slash = std::strrchr(path, '\\');
const char* name = slash != nullptr ? slash + 1 : path;
if (_strnicmp(name, "amd_fidelityfx_", 15) == 0 || _stricmp(name, "amdxcffx64.dll") == 0 ||
_stricmp(name, "amdxc64.dll") == 0)
return true;
return export_name_is(module, "OptiScaler.dll");
}
template <typename Desc> inline void correct(void* caller, Desc* out)
{
if (out->AdapterLuid.LowPart == g_luid.LowPart && out->AdapterLuid.HighPart == g_luid.HighPart &&
caller_sees_real(caller))
{
out->VendorId = g_real.vendor;
out->DeviceId = g_real.device;
}
}
inline HRESULT STDMETHODCALLTYPE get_desc(IDXGIAdapter* self, DXGI_ADAPTER_DESC* desc)
{
const HRESULT result = g_getDesc(self, desc);
if (SUCCEEDED(result) && desc != nullptr)
correct(__builtin_return_address(0), desc);
return result;
}
inline HRESULT STDMETHODCALLTYPE get_desc1(IDXGIAdapter1* self, DXGI_ADAPTER_DESC1* desc)
{
const HRESULT result = g_getDesc1(self, desc);
if (SUCCEEDED(result) && desc != nullptr)
correct(__builtin_return_address(0), desc);
return result;
}
inline HRESULT STDMETHODCALLTYPE get_desc2(IDXGIAdapter2* self, DXGI_ADAPTER_DESC2* desc)
{
const HRESULT result = g_getDesc2(self, desc);
if (SUCCEEDED(result) && desc != nullptr)
correct(__builtin_return_address(0), desc);
return result;
}
inline HRESULT STDMETHODCALLTYPE get_desc3(IDXGIAdapter4* self, DXGI_ADAPTER_DESC3* desc)
{
const HRESULT result = g_getDesc3(self, desc);
if (SUCCEEDED(result) && desc != nullptr)
correct(__builtin_return_address(0), desc);
return result;
}
template <typename Fn> inline void patch_slot(void** vtable, int slot, Fn hook, Fn& original)
{
if (vtable[slot] == reinterpret_cast<void*>(hook))
return;
DWORD protect = 0;
if (!VirtualProtect(&vtable[slot], sizeof(void*), PAGE_READWRITE, &protect))
return;
original = reinterpret_cast<Fn>(vtable[slot]);
vtable[slot] = reinterpret_cast<void*>(hook);
VirtualProtect(&vtable[slot], sizeof(void*), protect, &protect);
}
// Installs the wrapper for the adapter of `device` when the GPU is really AMD's and DXGI reports someone else.
// Once per process; `detail` says what was found and done.
inline bool install(ID3D12Device* device, std::string& detail)
{
const D4rPciIdentity reported = d4r_dxgi_identity(device);
std::string pci;
const D4rPciIdentity real = d4r_true_identity(device, pci);
char text[640];
std::snprintf(text, sizeof(text), "DXGI reports %04x:%04x; %s", reported.vendor, reported.device,
real.known ? pci.c_str() : ("real PCI identity unknown (" + pci + ")").c_str());
detail = text;
if (!real.known || real.vendor != 0x1002)
{
detail += "; not an AMD GPU: nothing to do";
return false;
}
if (reported.known && reported.vendor == real.vendor)
{
detail += "; DXGI already reports the real vendor: nothing to do";
return false;
}
g_real = real;
device->GetAdapterLuid(&g_luid);
IDXGIFactory4* factory = nullptr;
if (FAILED(CreateDXGIFactory2(0, __uuidof(IDXGIFactory4), reinterpret_cast<void**>(&factory))))
{
detail += "; no DXGI factory";
return false;
}
IDXGIAdapter4* adapter = nullptr;
const HRESULT found = factory->EnumAdapterByLuid(g_luid, __uuidof(IDXGIAdapter4), reinterpret_cast<void**>(&adapter));
factory->Release();
if (FAILED(found) || adapter == nullptr)
{
detail += "; the device's adapter has no IDXGIAdapter4";
return false;
}
// IDXGIAdapter4's vtable: GetDesc 8, GetDesc1 10, GetDesc2 11, GetDesc3 18. All adapters of the
// implementation share it; the LUID check above keeps other adapters unchanged.
void** vtable = *reinterpret_cast<void***>(adapter);
patch_slot(vtable, 8, &get_desc, g_getDesc);
patch_slot(vtable, 10, &get_desc1, g_getDesc1);
patch_slot(vtable, 11, &get_desc2, g_getDesc2);
patch_slot(vtable, 18, &get_desc3, g_getDesc3);
adapter->Release();
detail += "; OptiScaler and AMD's FidelityFX modules read the real ids (FSR 4)";
return g_getDesc != nullptr && g_getDesc1 != nullptr && g_getDesc2 != nullptr && g_getDesc3 != nullptr;
}
} // namespace d4r_fsr4_identity
+112 -7
View File
@@ -100,6 +100,7 @@
#include <bcrypt.h>
#include "d4r_fsr_rr.h"
#include "d4r_fsr_rr_identity.h"
#include "d4r_fsr4_identity.h"
#include "d4r_fsr_rr_passes.h"
#include "../engine/game.h"
#include "../engine/game_m.h"
@@ -625,6 +626,12 @@ static void load_portable_config()
model.clear();
if (!model.empty())
portable_set("D4R_DLSS_PRESET", model);
// [OptiScaler] FollowPresets: its Render Presets Override picks the model in game (d4r_render_presets.h);
// Fsr4: OptiScaler and AMD's FidelityFX modules see the real GPU, for its FSR 4 option (d4r_fsr4_identity.h).
if (ini_flag(ini, "optiscaler", "FollowPresets", 1) == 0)
portable_set("D4R_FOLLOW_OPTISCALER", "0");
if (ini_flag(ini, "optiscaler", "Fsr4", 1) == 0)
portable_set("D4R_FSR4_IDENTITY", "0");
// Ray Reconstruction is configured on its own section and drives its own feature, so
// nothing here reaches [DLSS] Model and nothing there reaches this.
@@ -755,6 +762,10 @@ static void load_portable_config()
else
on = ini_flag(ini, "engine", "Enabled", 0) != 0;
portable_set("D4R_ENGINE", on ? "1" : "0");
// auto leaves K on the native kernels: K's Vulkan network is slower (2026-10-17, 7700 XT, 1706x960 -> 1440p:
// 3.59 ms vs 2.35 ms dlss_gpu). Enabled = true, or Network = hip with a model that has the HIP layers, keeps it.
if (enabled.empty() || enabled == "auto")
portable_set("D4R_ENGINE_K", "0");
}
if (const std::string engineModel = ini_value(ini, "engine", "ModelDir"); !engineModel.empty())
portable_set(L"D4R_ENGINE_MODEL_DIR", portable_path(engineModel));
@@ -1982,6 +1993,13 @@ static NgxResult initialize(unsigned long long applicationId, const wchar_t* dat
LUID luid;
device->GetAdapterLuid(&luid);
set_cuda_adapter_luid(luid);
// OptiScaler's FSR 4 option needs the real AMD identity for OptiScaler and AMD's modules (d4r_fsr4_identity.h)
if (env_string("D4R_FSR4_IDENTITY") != "0")
{
std::string detail;
d4r_fsr4_identity::install(device, detail);
logf("FSR 4 identity: %s", detail.c_str());
}
}
g.paths.clear();
@@ -3364,6 +3382,9 @@ struct VulkanInterop
VkDevice device = VK_NULL_HANDLE;
VkPhysicalDeviceMemoryProperties memory = {};
VkPhysicalDevice physical = VK_NULL_HANDLE;
// VK_EXT_shader_float8 (vkd3d-proton enables it when the GPU has it): M's and L's engine layers are FP8
// cooperative-matrix shaders, which RADV's compiler crashes on without it (RDNA3)
bool float8 = false;
PFN_vkGetPhysicalDeviceFormatProperties formatProperties = nullptr;
PFN_vkCreateBuffer createBuffer = nullptr;
PFN_vkDestroyBuffer destroyBuffer = nullptr;
@@ -9027,6 +9048,36 @@ static NgxResult create_cuda_feature(Feature& feature)
return result;
}
// Whether the presets of this creation were picked in OptiScaler (d4r_render_presets.h): its override is on in
// OptiScaler.ini, or the presets changed since the game's first creation. (OptiScaler forwards the game's
// AllocateParameters to this DLL, so the table itself does not say who filled it.) D4R_FOLLOW_OPTISCALER=0 always
// keeps d4r's model. g.mutex is held.
static bool optiscaler_chose_presets(bool rayReconstruction, const unsigned int (&presets)[6])
{
static D4rPresetFollower followers[2];
static bool iniOverride[2] = {};
static std::once_flag iniOnce;
if (env_string("D4R_FOLLOW_OPTISCALER") == "0")
return false;
std::call_once(iniOnce, [] {
// OptiScaler reads OptiScaler.ini beside its own DLL, which d4r's install puts beside the game's EXE
wchar_t exe[MAX_PATH] = {};
const DWORD length = GetModuleFileNameW(nullptr, exe, MAX_PATH);
if (length == 0 || length >= MAX_PATH)
return;
std::wstring path(exe, length);
path.resize(path.find_last_of(L"\\/") + 1);
std::string text;
if (!read_whole_file(path + L"OptiScaler.ini", text))
return;
const std::vector<IniEntry> ini = parse_ini(text);
iniOverride[0] = ini_flag(ini, "dlss", "RenderPresetOverride", 0) == 1;
iniOverride[1] = ini_flag(ini, "dlssd", "RenderPresetOverride", 0) == 1;
logf("OptiScaler.ini: RenderPresetOverride DLSS=%d DLSSD=%d", iniOverride[0], iniOverride[1]);
});
return followers[rayReconstruction].follow(presets, iniOverride[rayReconstruction]);
}
static NgxResult fsr_rr_create(Feature& feature, void* parameters);
static NgxResult create_feature_locked(unsigned int featureId, void* parameters, NgxHandle** handle,
bool nativeVulkan);
@@ -9111,27 +9162,40 @@ static NgxResult create_feature_locked(unsigned int featureId, void* parameters,
presets[index] = get_uint_or(parameters, presetNames[index], 0);
const std::string forced = env_string(d4r_render_preset_variable(rayReconstruction));
const auto presetOverride = d4r_parse_render_preset_override(forced.c_str());
// Flagged, retired or unknown values count as Default, both for spotting OptiScaler's change and in what is followed
if (presetOverride.enabled)
d4r_sanitize_presets(presets, rayReconstruction);
const bool followed = presetOverride.enabled && optiscaler_chose_presets(rayReconstruction, presets);
if (followed)
{
logf("DLSS model: OptiScaler's preset override [DLAA=%u Quality=%u Balanced=%u Performance=%u "
"UltraPerformance=%u UltraQuality=%u] wins over %s=%s (which still fills Default slots)",
presets[0], presets[1], presets[2], presets[3], presets[4], presets[5],
d4r_render_preset_variable(rayReconstruction), forced.c_str());
d4r_apply_followed_presets(presets, presetOverride);
}
else if (presetOverride.enabled)
{
const unsigned int value = presetOverride.value;
const char* model = value == 5 ? "E" : value == 11 ? "K" : value == 12 ? "L" : value == 13 ? "M" : "custom";
logf("DLSS model override: D4R_DLSS_PRESET=%s (model %s) overrides game/OptiScaler presets "
logf("DLSS model override: D4R_DLSS_PRESET=%s (model %s) overrides game presets "
"[DLAA=%u Quality=%u Balanced=%u Performance=%u UltraPerformance=%u UltraQuality=%u]; "
"using preset=%u for all quality modes",
forced.c_str(), model, presets[0], presets[1], presets[2], presets[3], presets[4], presets[5], value);
presetOverride.apply(presets);
}
presetOverride.apply(presets);
feature->preset = presets[1];
// NGX runs the preset of the feature's quality mode.
feature->preset = presets[d4r_preset_slot(quality)];
// Direct output needs the native output kernel of the preset in use (verified: K = 11 through
// hiluma_engine_output, M = 13 through rrlite_downsample_kernel, its last kernel). Only a forced
// Super Sampling preset qualifies; a Ray Reconstruction preset never does here.
// hiluma_engine_output, M = 13 through rrlite_downsample_kernel, its last kernel). Only a forced or
// OptiScaler-chosen Super Sampling preset qualifies; a Ray Reconstruction preset never does here.
if (!forced.empty() && !rayReconstruction)
{
char allowed[128] = "11,13";
if (const std::string list = env_string("D4R_SHIM_OUTPUT_DIRECT_PRESETS"); !list.empty())
snprintf(allowed, sizeof(allowed), "%s", list.c_str());
for (char* token = strtok(allowed, ","); token != nullptr; token = strtok(nullptr, ","))
feature->outputDirectAllowed |= strtoul(token, nullptr, 0) == presets[1];
feature->outputDirectAllowed |= strtoul(token, nullptr, 0) == feature->preset;
}
feature->rayReconstruction = rayReconstruction;
if (rayReconstruction)
@@ -9139,7 +9203,7 @@ static NgxResult create_feature_locked(unsigned int featureId, void* parameters,
feature->auxScalarBaseline[index] = get_int_or(parameters, kAuxScalars[index].name, 0);
logf("NVSDK_NGX_D3D12_CreateFeature(feature=%u%s): %ux%u -> %ux%u quality=%d flags=0x%x subrects=%d preset=%u",
featureId, rayReconstruction ? ", Ray Reconstruction" : "", feature->width, feature->height,
feature->outWidth, feature->outHeight, quality, flags, subrects, presets[1]);
feature->outWidth, feature->outHeight, quality, flags, subrects, feature->preset);
feature->subrects = subrects;
std::copy(std::begin(presets), std::end(presets), feature->creationPresets.begin());
@@ -9244,6 +9308,18 @@ static void init_engine_vulkan()
logf("engine backend: Vulkan entry points are unavailable");
return;
}
auto enumerate = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
instanceProc(instance, "vkEnumerateDeviceExtensionProperties"));
uint32_t count = 0;
if (enumerate != nullptr && enumerate(g_vk.physical, nullptr, &count, nullptr) == VK_SUCCESS)
{
std::vector<VkExtensionProperties> extensions(count);
if (enumerate(g_vk.physical, nullptr, &count, extensions.data()) == VK_SUCCESS)
for (uint32_t index = 0; index < count; ++index)
g_vk.float8 |= std::strcmp(extensions[index].extensionName, "VK_EXT_shader_float8") == 0;
}
logf("engine backend: VK_EXT_shader_float8 %s", g_vk.float8 ? "available (M and L engine layers)" : "unavailable: "
"M and L run on the CUDA backend");
}
static void init_engine_backend()
@@ -9982,6 +10058,10 @@ static bool engine_evaluate_m(Feature& feature, ID3D12GraphicsCommandList* list,
};
// NVSDK_NGX_DLSS_Feature_Flags: IsHDR 1, MVLowRes 2, MVJittered 4, DepthInverted 8, AutoExposure 0x40.
const bool ldr = (feature.flags & 0x1) == 0; // NGX's LDR stages: a model directory of its own, no exposure
// The model's pipelines include the FP8 layers even when the HIP network runs them; creating those without
// VK_EXT_shader_float8 crashes the driver (RADV on RDNA3, vkCreateComputePipelines), so never load the model.
if (!g_vk.float8)
return refuse("the GPU has no VK_EXT_shader_float8 for the FP8 layers");
std::call_once(g_engineM.once[presetL][ldr], [presetL, ldr] { init_engine_backend_m_variant(presetL, ldr); });
d4r::MModel* const model = g_engineM.models[presetL][ldr].get();
if (model == nullptr)
@@ -10561,6 +10641,8 @@ static bool engine_evaluate(Feature& feature, ID3D12GraphicsCommandList* list, I
return engine_evaluate_rr(feature, list, color, depth, motion, output, parameters, p, frame);
if (feature.preset == 13 || feature.preset == 12)
return engine_evaluate_m(feature, list, color, depth, motion, output, p, frame);
if (feature.preset == 11 && env_string("D4R_ENGINE_K") == "0" && env_string("D4R_ENGINE_NETWORK") != "hip")
return refuse("[Engine] Enabled = auto keeps K on the native kernels (faster than the Vulkan network)");
// Without the HDR flag NGX runs its LDR input and output kernels: a model directory of its own.
const bool ldr = (feature.flags & 0x1) == 0;
if (ldr)
@@ -10745,6 +10827,24 @@ static bool engine_evaluate(Feature& feature, ID3D12GraphicsCommandList* list, I
}
if (FAILED(g_vk.lifetime->RetainExternalResources(list, feature.resources)))
return refuse("the command list cannot retain the engine's resources");
// D4R_PROFILE: the Vulkan network's GPU time on the game's queue (timestamps around the whole recording)
const bool profile = profile_enabled() && env_uint("D4R_PROFILE_GPU_TIMESTAMPS", 1) != 0 &&
profile_timestamps_ready(feature);
if (profile)
{
FrameTiming measured;
read_profile_timestamps(feature, frame, measured);
const auto now = ProfileClock::now();
const double interval = feature.engineRProfileAt.time_since_epoch().count() ?
profile_ms(feature.engineRProfileAt, now) : 0.0;
feature.engineRProfileAt = now;
if (profile_log_frame(frame) && measured.vkTotal >= 0)
logf("D4R_ENGINE_K_PROFILE frame=%u gpu_frame=%u render=%ux%u output=%ux%u gpu_eval=%.3f "
"game_interval=%.3f age=0", frame, frame - kOutputSlots, p.renderWidth, p.renderHeight,
feature.outWidth, feature.outHeight, measured.vkTotal, interval);
profile_timestamp(feature, list, frame, 0);
profile_timestamp(feature, list, frame, 1);
}
for (const Source& source : sources)
transition(list, source.resource, source.state, source.copyState);
VkCommandBuffer command = VK_NULL_HANDLE;
@@ -10772,6 +10872,11 @@ static bool engine_evaluate(Feature& feature, ID3D12GraphicsCommandList* list, I
transition(list, source.resource, source.copyState, source.state);
if (!recorded)
return refuse(failure);
if (profile)
{
profile_timestamp(feature, list, frame, 2);
profile_timestamp(feature, list, frame, 3);
}
feature.engineJitter[0] = p.jitterX;
feature.engineJitter[1] = p.jitterY;
if (frame <= 3 || frame % 600 == 0)
+76
View File
@@ -30,3 +30,79 @@ inline D4rRenderPresetOverride d4r_parse_render_preset_override(const char* over
return {false, 0};
return {true, static_cast<unsigned int>(std::strtoul(overrideValue, nullptr, 0))};
}
// OptiScaler's own preset override (its menu's "Render Presets Override" and "Apply Changes", or
// RenderPresetOverride=true in OptiScaler.ini) recreates the feature with the presets the player picked. The
// first creation carries the game's presets; a later one that carries different presets was changed in
// OptiScaler, and those win over [DLSS] Model / [RayReconstruction] Model until they change back to the game's.
// Super Sampling and Ray Reconstruction keep a follower each.
inline constexpr unsigned int kD4rPresetLatest = 0x00FFFFFF; // OptiScaler's "Latest": the DLL's choice
struct D4rPresetFollower
{
bool haveBaseline = false;
unsigned int baseline[6] = {};
// true when `presets` were chosen in OptiScaler. `iniOverride`: OptiScaler.ini enables the override, so
// even the first creation carries the player's choice.
bool follow(const unsigned int (&presets)[6], bool iniOverride)
{
if (!haveBaseline)
{
for (int index = 0; index < 6; ++index)
baseline[index] = presets[index];
haveBaseline = true;
return iniOverride;
}
if (iniOverride)
return true;
for (int index = 0; index < 6; ++index)
if (presets[index] != baseline[index])
return true;
return false;
}
};
// A slot the follower may honour: Super Sampling E, F (CNN), J, K (DLSS 4), L, M (DLSS 4.5); Ray Reconstruction
// D, E (DLSS 4), F (DLSS 4.5); or Default/Latest. Everything else reads as Default (0): flagged values such as
// Alan Wake 2's 0x80000005/0x80000006 (Streamline's "default", E and F with the high bit set), and presets DLSS 310
// no longer ships (A-D, G-I) or that do not exist.
inline unsigned int d4r_followable_preset(unsigned int preset, bool rayReconstruction)
{
if (preset == kD4rPresetLatest)
return preset;
if (rayReconstruction)
return preset >= 4 && preset <= 6 ? preset : 0;
switch (preset)
{
case 5: case 6: case 10: case 11: case 12: case 13:
return preset;
default:
return 0;
}
}
inline void d4r_sanitize_presets(unsigned int (&presets)[6], bool rayReconstruction)
{
for (unsigned int& preset : presets)
preset = d4r_followable_preset(preset, rayReconstruction);
}
// Followed presets keep every quality mode that names a model; Default (0) and "Latest" take d4r's override.
inline void d4r_apply_followed_presets(unsigned int (&presets)[6], const D4rRenderPresetOverride& overrideValue)
{
if (!overrideValue.enabled)
return;
for (unsigned int& preset : presets)
if (preset == 0 || preset == kD4rPresetLatest)
preset = overrideValue.value;
}
// The preset slot ([DLAA, Quality, Balanced, Performance, UltraPerformance, UltraQuality]) NGX uses for
// NVSDK_NGX_PerfQuality_Value `quality` (MaxPerf 0, Balanced 1, MaxQuality 2, UltraPerformance 3,
// UltraQuality 4, DLAA 5).
inline int d4r_preset_slot(int quality)
{
static const int slots[6] = {3, 2, 1, 4, 5, 0};
return quality >= 0 && quality < 6 ? slots[quality] : 1;
}