Skip to content

Commit 082100e

Browse files
DLSSNR: add automatic exposure and trim anchors
1 parent 7b7220b commit 082100e

16 files changed

Lines changed: 3688 additions & 3514 deletions

‎OptiScaler/Config.cpp‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ bool Config::Reload(std::filesystem::path iniPath)
342342
DlssNrUseProxy.set_from_config(readBool("DlssNr", "UseProxy"));
343343
DlssNrScanExposure.set_from_config(readBool("DlssNr", "ScanExposure"));
344344
DlssNrWhitePointSource.set_from_config(readUInt("DlssNr", "WhitePointSource"));
345+
DlssNrAutoExposureTrim.set_from_config(readFloat("DlssNr", "AutoExposureTrim"));
346+
DlssNrAutoExposureShadowProtection.set_from_config(
347+
readFloat("DlssNr", "AutoExposureShadowProtection"));
348+
DlssNrGameExposureTrimAnchors.set_from_config(readString("DlssNr", "GameExposureTrimAnchors"));
349+
DlssNrAutoExposureTrimAnchors.set_from_config(readString("DlssNr", "AutoExposureTrimAnchors"));
345350

346351
// Migrate the retired flag only when the new key was genuinely absent, which is why this
347352
// has to run AFTER the read above -- set_from_config assigns only into an empty optional,
@@ -1240,6 +1245,14 @@ bool Config::SaveIni()
12401245
// restart -- the white-point source, both trims, the anchor, the pass count and the rest all
12411246
// reset to default on the next run.
12421247
ini.SetValue("DlssNr", "WhitePointSource", GetIntValue(Instance()->DlssNrWhitePointSource.value_for_config()).c_str());
1248+
ini.SetValue("DlssNr", "AutoExposureTrim",
1249+
GetFloatValue(Instance()->DlssNrAutoExposureTrim.value_for_config()).c_str());
1250+
ini.SetValue("DlssNr", "AutoExposureShadowProtection",
1251+
GetFloatValue(Instance()->DlssNrAutoExposureShadowProtection.value_for_config()).c_str());
1252+
ini.SetValue("DlssNr", "GameExposureTrimAnchors",
1253+
Instance()->DlssNrGameExposureTrimAnchors.value_for_config_or("").c_str());
1254+
ini.SetValue("DlssNr", "AutoExposureTrimAnchors",
1255+
Instance()->DlssNrAutoExposureTrimAnchors.value_for_config_or("").c_str());
12431256
ini.SetValue("DlssNr", "WhitePointTrim", GetFloatValue(Instance()->DlssNrWhitePointTrim.value_for_config()).c_str());
12441257
ini.SetValue("DlssNr", "ScanTrim", GetFloatValue(Instance()->DlssNrScanTrim.value_for_config()).c_str());
12451258
ini.SetValue("DlssNr", "ScanAnchorValue", GetFloatValue(Instance()->DlssNrScanAnchorValue.value_for_config()).c_str());

‎OptiScaler/Config.h‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#pragma once
1+
#pragma once
22

33
#include "SysUtils.h"
44
#include "State.h"
@@ -427,8 +427,9 @@ class Config
427427
// Where the white point comes from. One control, because there is one answer.
428428
//
429429
// 0 the paper white slider, and nothing else
430-
// 1 the exposure the game hands the upscaler
431-
// 2 a buffer the scan found, anchored to a white point the user chose once
430+
// 1 the exposure the game hands the upscaler (game only; no automatic fallback)
431+
// 2 OptiScaler automatic exposure, calculated from the original linear-HDR frame
432+
// 3 a buffer the scan found, anchored to a white point the user chose once
432433
//
433434
// This replaces two independent checkboxes that could both be on. They were made exclusive by
434435
// greying, which deadlocked -- each disabled the other, so once both were set the only way out
@@ -437,6 +438,20 @@ class Config
437438
// choice cannot reach it: there is nothing to keep consistent, because there is only one value.
438439
CustomOptional<uint32_t> DlssNrWhitePointSource { 1 };
439440

441+
// Separate trim for OptiScaler's own GPU-calculated exposure (WhitePointSource == 2).
442+
CustomOptional<float> DlssNrAutoExposureTrim { 5.0f };
443+
CustomOptional<float> DlssNrAutoExposureShadowProtection { 100.0f };
444+
445+
// Base-white-point-dependent Trim calibration tables, serialized as baseWhitePoint:trim pairs.
446+
// The two sources are intentionally separate because their white-point scales need not match.
447+
CustomOptional<std::string> DlssNrGameExposureTrimAnchors { std::string() };
448+
CustomOptional<std::string> DlssNrAutoExposureTrimAnchors { std::string() };
449+
450+
// Calibration aid only. These are deliberately not persisted: after a restart anchors are
451+
// active again, rather than a forgotten preview checkbox silently bypassing them.
452+
CustomOptional<bool> DlssNrGameExposureTrimPreview { false };
453+
CustomOptional<bool> DlssNrAutoExposureTrimPreview { false };
454+
440455
CustomOptional<bool> DlssNrScanMeter { false };
441456

442457
CustomOptional<float> DlssNrScanAnchorValue { 0.0f }; // legacy single anchor, migrated then unused

‎OptiScaler/dlssnr/DlssNrFeature_Dx12.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ struct ExposureStatus
163163
};
164164

165165
ExposureStatus GameExposureStatus();
166+
ExposureStatus AutoExposureStatus();
166167

167168
// The white point the exposure meter has settled on, or 0 if it has not taken a reading yet. For the
168169
// overlay, so the number in use is visible rather than inferred.

0 commit comments

Comments
 (0)