Skip to content

Commit cf2ca8c

Browse files
committed
Added Non-Linear Color sRGB and PQ options which might improve IQ with FSR4. Thanks to "new knowledgeable Discord members"
1 parent 53f9271 commit cf2ca8c

8 files changed

+109
-15
lines changed

OptiScaler.ini

+10
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,16 @@ DlssReactiveMaskBias=auto
281281
; true or false - Default (auto) is true
282282
Fsr4Update=auto
283283

284+
; Indicates input color resource contains perceptual sRGB colors
285+
; Might improve IQ of FSR4
286+
; true or false - Default (auto) is true
287+
FsrNonLinearSRGB=auto
288+
289+
; Indicates input color resource contains perceptual PQ colors
290+
; Might improve IQ of FSR4
291+
; true or false - Default (auto) is true
292+
FsrNonLinearPQ=auto
293+
284294

285295

286296
; -------------------------------------------------------

OptiScaler/Config.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ bool Config::Reload(std::filesystem::path iniPath)
117117
FsrUseMaskForTransparency.set_from_config(readBool("FSR", "UseReactiveMaskForTransparency"));
118118
DlssReactiveMaskBias.set_from_config(readFloat("FSR", "DlssReactiveMaskBias"));
119119
Fsr4Update.set_from_config(readBool("FSR", "Fsr4Update"));
120+
FsrNonLinearPQ.set_from_config(readBool("FSR", "FsrNonLinearPQ"));
121+
FsrNonLinearSRGB.set_from_config(readBool("FSR", "FsrNonLinearSRGB"));
122+
123+
// Only sRGB or PQ should be enabled
124+
if (FsrNonLinearPQ.has_value() && FsrNonLinearPQ.value())
125+
FsrNonLinearSRGB = false;
126+
else if (FsrNonLinearSRGB.has_value() && FsrNonLinearSRGB.value())
127+
FsrNonLinearPQ = false;
120128
}
121129

122130
// XeSS
@@ -604,6 +612,8 @@ bool Config::SaveIni()
604612
ini.SetValue("FSR", "UseReactiveMaskForTransparency", GetBoolValue(Instance()->FsrUseMaskForTransparency.value_for_config()).c_str());
605613
ini.SetValue("FSR", "DlssReactiveMaskBias", GetFloatValue(Instance()->DlssReactiveMaskBias.value_for_config()).c_str());
606614
ini.SetValue("FSR", "Fsr4Update", GetBoolValue(Instance()->Fsr4Update.value_for_config()).c_str());
615+
ini.SetValue("FSR", "FsrNonLinearPQ", GetBoolValue(Instance()->FsrNonLinearPQ.value_for_config()).c_str());
616+
ini.SetValue("FSR", "FsrNonLinearSRGB", GetBoolValue(Instance()->FsrNonLinearSRGB.value_for_config()).c_str());
607617
}
608618

609619
// XeSS

OptiScaler/Config.h

+2
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ class Config
256256
CustomOptional<bool> FsrUseMaskForTransparency{ true };
257257
CustomOptional<float> FsrVelocity{ 1.0f };
258258
CustomOptional<bool> Fsr4Update{ false };
259+
CustomOptional<bool> FsrNonLinearSRGB{ false };
260+
CustomOptional<bool> FsrNonLinearPQ{ false };
259261

260262
// FSR Common
261263
CustomOptional<float> FsrVerticalFov{ 60.0f };

OptiScaler/menu/menu_common.cpp

+43-15
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,34 @@ bool MenuCommon::RenderMenu()
19091909

19101910
if (currentBackend == "fsr31" || currentBackend == "fsr31_12")
19111911
{
1912+
if (bool nlSRGB = Config::Instance()->FsrNonLinearSRGB.value_or_default(); ImGui::Checkbox("FSR Non-Linear sRGB Input", &nlSRGB))
1913+
{
1914+
Config::Instance()->FsrNonLinearSRGB = nlSRGB;
1915+
1916+
if (nlSRGB)
1917+
Config::Instance()->FsrNonLinearPQ = false;
1918+
1919+
State::Instance().newBackend = currentBackend;
1920+
for (auto& singleChangeBackend : State::Instance().changeBackend)
1921+
singleChangeBackend.second = true;
1922+
}
1923+
ShowHelpMarker("Indicates input color resource contains perceptual sRGB colors\n"
1924+
"Might improve upscaling quality of FSR4");
1925+
1926+
if (bool nlPQ = Config::Instance()->FsrNonLinearPQ.value_or_default(); ImGui::Checkbox("FSR Non-Linear PQ Input", &nlPQ))
1927+
{
1928+
Config::Instance()->FsrNonLinearPQ = nlPQ;
1929+
1930+
if (nlPQ)
1931+
Config::Instance()->FsrNonLinearSRGB = false;
1932+
1933+
State::Instance().newBackend = currentBackend;
1934+
for (auto& singleChangeBackend : State::Instance().changeBackend)
1935+
singleChangeBackend.second = true;
1936+
}
1937+
ShowHelpMarker("Indicates input color resource contains perceptual PQ colors\n"
1938+
"Might improve upscaling quality of FSR4");
1939+
19121940
if (bool dView = Config::Instance()->FsrDebugView.value_or_default(); ImGui::Checkbox("FSR 3.X Debug View", &dView))
19131941
Config::Instance()->FsrDebugView = dView;
19141942
ShowHelpMarker("Top left: Dilated Motion Vectors\n"
@@ -2310,7 +2338,7 @@ bool MenuCommon::RenderMenu()
23102338
if (State::Instance().api == DX12 || State::Instance().api == DX11)
23112339
{
23122340
// if motion vectors are not display size
2313-
ImGui::BeginDisabled(!Config::Instance()->DisplayResolution.value_or(false) && !State::Instance().DisplaySizeMV.value_or(false) &&
2341+
ImGui::BeginDisabled(!Config::Instance()->DisplayResolution.value_or(false) && !State::Instance().DisplaySizeMV.value_or(false) &&
23142342
!(State::Instance().currentFeature->GetFeatureFlags() & NVSDK_NGX_DLSS_Feature_Flags_MVLowRes));
23152343

23162344
ImGui::SeparatorText("Output Scaling");
@@ -2389,7 +2417,7 @@ bool MenuCommon::RenderMenu()
23892417
if (currentFeature != nullptr)
23902418
{
23912419
ImGui::Text("Output Scaling is %s, target res: %dx%d", Config::Instance()->OutputScalingEnabled.value_or_default() ? "ENABLED" : "DISABLED",
2392-
(uint32_t)(currentFeature->DisplayWidth() * _ssRatio), (uint32_t)(currentFeature->DisplayHeight() * _ssRatio));
2420+
(uint32_t)(currentFeature->DisplayWidth() * _ssRatio), (uint32_t)(currentFeature->DisplayHeight() * _ssRatio));
23932421
}
23942422

23952423
ImGui::EndDisabled();
@@ -2416,7 +2444,7 @@ bool MenuCommon::RenderMenu()
24162444
}
24172445
}
24182446
ShowHelpMarker("Ignores the value sent by the game\n"
2419-
"and uses the value set below");
2447+
"and uses the value set below");
24202448

24212449
ImGui::BeginDisabled(!Config::Instance()->OverrideSharpness.value_or_default());
24222450

@@ -2435,9 +2463,9 @@ bool MenuCommon::RenderMenu()
24352463
if (bool upOverride = Config::Instance()->UpscaleRatioOverrideEnabled.value_or_default(); ImGui::Checkbox("Ratio Override", &upOverride))
24362464
Config::Instance()->UpscaleRatioOverrideEnabled = upOverride;
24372465
ShowHelpMarker("Let's you override every upscaler preset\n"
2438-
"with a value set below\n\n"
2439-
"1.5x on a 1080p screen means internal resolution of 720p\n"
2440-
"1080 / 1.5 = 720");
2466+
"with a value set below\n\n"
2467+
"1.5x on a 1080p screen means internal resolution of 720p\n"
2468+
"1080 / 1.5 = 720");
24412469

24422470
ImGui::BeginDisabled(!Config::Instance()->UpscaleRatioOverrideEnabled.value_or_default());
24432471

@@ -2453,9 +2481,9 @@ bool MenuCommon::RenderMenu()
24532481
if (bool qOverride = Config::Instance()->QualityRatioOverrideEnabled.value_or_default(); ImGui::Checkbox("Quality Override", &qOverride))
24542482
Config::Instance()->QualityRatioOverrideEnabled = qOverride;
24552483
ShowHelpMarker("Let's you override each preset's ratio individually\n"
2456-
"Note that not every game supports every quality preset\n\n"
2457-
"1.5x on a 1080p screen means internal resolution of 720p\n"
2458-
"1080 / 1.5 = 720");
2484+
"Note that not every game supports every quality preset\n\n"
2485+
"1.5x on a 1080p screen means internal resolution of 720p\n"
2486+
"1080 / 1.5 = 720");
24592487

24602488
ImGui::BeginDisabled(!Config::Instance()->QualityRatioOverrideEnabled.value_or_default());
24612489

@@ -2520,7 +2548,7 @@ bool MenuCommon::RenderMenu()
25202548
singleChangeBackend.second = true;
25212549
}
25222550
ShowHelpMarker("Some Unreal Engine games need this\n"
2523-
"Might fix colors, especially in dark areas");
2551+
"Might fix colors, especially in dark areas");
25242552

25252553
ImGui::TableNextColumn();
25262554
if (bool hdr = Config::Instance()->HDR.value_or(false); ImGui::Checkbox("HDR", &hdr))
@@ -2596,7 +2624,7 @@ bool MenuCommon::RenderMenu()
25962624
singleChangeBackend.second = true;
25972625
}
25982626
ShowHelpMarker("Mostly a fix for Unreal Engine games\n"
2599-
"Top left part of the screen will be blurry");
2627+
"Top left part of the screen will be blurry");
26002628

26012629
ImGui::TableNextColumn();
26022630
auto accessToReactiveMask = State::Instance().currentFeature->AccessToReactiveMask();
@@ -2619,8 +2647,8 @@ bool MenuCommon::RenderMenu()
26192647

26202648
if (accessToReactiveMask)
26212649
ShowHelpMarker("Allows the use of a reactive mask\n"
2622-
"Keep in mind that a reactive mask sent to DLSS\n"
2623-
"will not produce a good image in combination with FSR/XeSS");
2650+
"Keep in mind that a reactive mask sent to DLSS\n"
2651+
"will not produce a good image in combination with FSR/XeSS");
26242652
else
26252653
ShowHelpMarker("Option disabled because tha game doesn't provide a reactive mask");
26262654

@@ -2707,8 +2735,8 @@ bool MenuCommon::RenderMenu()
27072735
Config::Instance()->ExtendedLimits = extendedLimits;
27082736

27092737
ShowHelpMarker("Extended sliders limit for quality presets\n\n"
2710-
"Using this option changes resolution detection logic\n"
2711-
"and might cause issues and crashes!");
2738+
"Using this option changes resolution detection logic\n"
2739+
"and might cause issues and crashes!");
27122740
}
27132741

27142742
bool pcShaders = Config::Instance()->UsePrecompiledShaders.value_or_default();

OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ bool FSR31FeatureDx11::Evaluate(ID3D11DeviceContext* DeviceContext, NVSDK_NGX_Pa
176176
if (Config::Instance()->FsrDebugView.value_or_default())
177177
params.flags = Fsr31::FFX_FSR3_UPSCALER_FLAG_DRAW_DEBUG_VIEW;
178178

179+
if (Config::Instance()->FsrNonLinearPQ.value_or_default())
180+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_PQ;
181+
else if (Config::Instance()->FsrNonLinearSRGB.value_or_default())
182+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_SRGB;
183+
179184
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_X, &params.jitterOffset.x);
180185
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_Y, &params.jitterOffset.y);
181186

@@ -678,6 +683,12 @@ bool FSR31FeatureDx11::InitFSR3(const NVSDK_NGX_Parameter* InParameters)
678683
LOG_INFO("contextDesc.initFlags (LowResMV) {0:b}", _upscalerContextDesc.flags);
679684
}
680685

686+
if (Config::Instance()->FsrNonLinearPQ.value_or_default() || Config::Instance()->FsrNonLinearSRGB.value_or_default())
687+
{
688+
_contextDesc.flags |= FFX_UPSCALE_ENABLE_NON_LINEAR_COLORSPACE;
689+
LOG_INFO("contextDesc.initFlags (NonLinearColorSpace) {0:b}", _contextDesc.flags);
690+
}
691+
681692
if (Config::Instance()->OutputScalingEnabled.value_or_default() && !Config::Instance()->DisplayResolution.value_or(false) && !State::Instance().DisplaySizeMV.value_or(false))
682693
{
683694
float ssMulti = Config::Instance()->OutputScalingMultiplier.value_or_default();

OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_
166166
if (Config::Instance()->FsrDebugView.value_or_default())
167167
params.flags = FFX_UPSCALE_FLAG_DRAW_DEBUG_VIEW;
168168

169+
if (Config::Instance()->FsrNonLinearPQ.value_or_default())
170+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_PQ;
171+
else if (Config::Instance()->FsrNonLinearSRGB.value_or_default())
172+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_SRGB;
173+
169174
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_X, &params.jitterOffset.x);
170175
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_Y, &params.jitterOffset.y);
171176

@@ -632,6 +637,12 @@ bool FSR31FeatureDx11on12::InitFSR3(const NVSDK_NGX_Parameter* InParameters)
632637
LOG_INFO("contextDesc.initFlags (LowResMV) {0:b}", _contextDesc.flags);
633638
}
634639

640+
if (Config::Instance()->FsrNonLinearPQ.value_or_default() || Config::Instance()->FsrNonLinearSRGB.value_or_default())
641+
{
642+
_contextDesc.flags |= FFX_UPSCALE_ENABLE_NON_LINEAR_COLORSPACE;
643+
LOG_INFO("contextDesc.initFlags (NonLinearColorSpace) {0:b}", _contextDesc.flags);
644+
}
645+
635646
if (Config::Instance()->OutputScalingEnabled.value_or_default() && !Config::Instance()->DisplayResolution.value_or(false) && !State::Instance().DisplaySizeMV.value_or(false))
636647
{
637648
float ssMulti = Config::Instance()->OutputScalingMultiplier.value_or_default();

OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_
5959
if (Config::Instance()->FsrDebugView.value_or_default())
6060
params.flags = FFX_UPSCALE_FLAG_DRAW_DEBUG_VIEW;
6161

62+
if (Config::Instance()->FsrNonLinearPQ.value_or_default())
63+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_PQ;
64+
else if (Config::Instance()->FsrNonLinearSRGB.value_or_default())
65+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_SRGB;
66+
6267
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_X, &params.jitterOffset.x);
6368
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_Y, &params.jitterOffset.y);
6469

@@ -609,6 +614,12 @@ bool FSR31FeatureDx12::InitFSR3(const NVSDK_NGX_Parameter* InParameters)
609614
LOG_INFO("contextDesc.initFlags (LowResMV) {0:b}", _contextDesc.flags);
610615
}
611616

617+
if (Config::Instance()->FsrNonLinearPQ.value_or_default() || Config::Instance()->FsrNonLinearSRGB.value_or_default())
618+
{
619+
_contextDesc.flags |= FFX_UPSCALE_ENABLE_NON_LINEAR_COLORSPACE;
620+
LOG_INFO("contextDesc.initFlags (NonLinearColorSpace) {0:b}", _contextDesc.flags);
621+
}
622+
612623
if (Config::Instance()->OutputScalingEnabled.value_or_default() && !Config::Instance()->DisplayResolution.value_or(false) && !State::Instance().DisplaySizeMV.value_or(false))
613624
{
614625
float ssMulti = Config::Instance()->OutputScalingMultiplier.value_or_default();

OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ bool FSR31FeatureVk::InitFSR3(const NVSDK_NGX_Parameter* InParameters)
227227
LOG_INFO("contextDesc.initFlags (LowResMV) {0:b}", _contextDesc.flags);
228228
}
229229

230+
if (Config::Instance()->FsrNonLinearPQ.value_or_default() || Config::Instance()->FsrNonLinearSRGB.value_or_default())
231+
{
232+
_contextDesc.flags |= FFX_UPSCALE_ENABLE_NON_LINEAR_COLORSPACE;
233+
LOG_INFO("contextDesc.initFlags (NonLinearColorSpace) {0:b}", _contextDesc.flags);
234+
}
235+
230236
if (Config::Instance()->ExtendedLimits.value_or_default())
231237
{
232238
_contextDesc.maxRenderSize.width = RenderWidth() < DisplayWidth() ? DisplayWidth() : RenderWidth();
@@ -311,6 +317,11 @@ bool FSR31FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter*
311317
if (Config::Instance()->FsrDebugView.value_or_default())
312318
params.flags = FFX_UPSCALE_FLAG_DRAW_DEBUG_VIEW;
313319

320+
if (Config::Instance()->FsrNonLinearPQ.value_or_default())
321+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_PQ;
322+
else if (Config::Instance()->FsrNonLinearSRGB.value_or_default())
323+
params.flags = FFX_UPSCALE_FLAG_NON_LINEAR_COLOR_SRGB;
324+
314325
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_X, &params.jitterOffset.x);
315326
InParameters->Get(NVSDK_NGX_Parameter_Jitter_Offset_Y, &params.jitterOffset.y);
316327

0 commit comments

Comments
 (0)