r.DynamicRes.ChangePercentageThreshold

r.DynamicRes.ChangePercentageThreshold

#Overview

name: r.DynamicRes.ChangePercentageThreshold

This variable is created as a Console Variable (cvar).

It is referenced in 4 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.DynamicRes.ChangePercentageThreshold is to control the minimal increase percentage threshold allowed when changing resolution in Unreal Engine’s dynamic resolution system. This setting is part of the rendering system, specifically the dynamic resolution feature.

The dynamic resolution system in Unreal Engine 5 relies on this setting variable, which is primarily used in the Engine module, particularly within the DynamicResolution.cpp file.

The value of this variable is set using a console variable (CVar) named CVarChangeThreshold. It is initialized with a default value derived from DynamicRenderScaling::FHeuristicSettings::kDefaultChangeThreshold, converted to a percentage.

This variable interacts with several other variables in the dynamic resolution system, such as CVarUpperBoundQuantization, CVarFrameTimeBudget, and CVarOverBudgetGPUHeadRoomPercentage. It is used in conjunction with these variables to determine when and how to adjust the rendering resolution.

Developers must be aware that this variable affects the sensitivity of the dynamic resolution system. A lower threshold will allow for more frequent, but smaller changes in resolution, while a higher threshold will result in less frequent, but more significant changes.

Best practices when using this variable include:

  1. Carefully tuning it based on the specific needs of your game or application.
  2. Considering the balance between visual stability and performance optimization.
  3. Testing thoroughly with various hardware configurations to ensure optimal results across different systems.

Regarding the associated variable CVarChangeThreshold:

The purpose of CVarChangeThreshold is to store and provide access to the r.DynamicRes.ChangePercentageThreshold value within the engine’s code. It is used to retrieve the threshold value in various parts of the dynamic resolution system.

This variable is part of the Engine module and is specifically used in the dynamic resolution subsystem.

The value of CVarChangeThreshold is set when the r.DynamicRes.ChangePercentageThreshold console variable is initialized or modified.

CVarChangeThreshold interacts directly with the r.DynamicRes.ChangePercentageThreshold console variable and is used in the GetPrimaryDynamicResolutionSettings function to configure the dynamic resolution settings.

Developers should be aware that modifying CVarChangeThreshold directly is not recommended. Instead, they should use the r.DynamicRes.ChangePercentageThreshold console variable to adjust the threshold.

Best practices for using CVarChangeThreshold include:

  1. Accessing its value using the GetValueOnAnyThread() method when needed in code.
  2. Avoiding direct modification of the variable and instead using the console variable system for changes.
  3. Considering the impact on performance and visual quality when adjusting the associated console variable.

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DynamicResolution.cpp:116

Scope: file

Source code excerpt:


static TAutoConsoleVariable<float> CVarChangeThreshold(
	TEXT("r.DynamicRes.ChangePercentageThreshold"),
	DynamicRenderScaling::FractionToPercentage(DynamicRenderScaling::FHeuristicSettings::kDefaultChangeThreshold),
	TEXT("Minimal increase percentage threshold to alow when changing resolution."),
	ECVF_RenderThreadSafe | ECVF_Default);

static TAutoConsoleVariable<int32> CVarMaxConsecutiveOverBudgetGPUFrameCount(
	TEXT("r.DynamicRes.MaxConsecutiveOverBudgetGPUFrameCount"),

#Associated Variable and Callsites

This variable is associated with another variable named CVarChangeThreshold. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DynamicResolution.cpp:115

Scope: file

Source code excerpt:

	ECVF_RenderThreadSafe | ECVF_Default);

static TAutoConsoleVariable<float> CVarChangeThreshold(
	TEXT("r.DynamicRes.ChangePercentageThreshold"),
	DynamicRenderScaling::FractionToPercentage(DynamicRenderScaling::FHeuristicSettings::kDefaultChangeThreshold),
	TEXT("Minimal increase percentage threshold to alow when changing resolution."),
	ECVF_RenderThreadSafe | ECVF_Default);

static TAutoConsoleVariable<int32> CVarMaxConsecutiveOverBudgetGPUFrameCount(

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DynamicResolution.cpp:153

Scope (from outer to inner):

file
function     DynamicRenderScaling::FHeuristicSettings GetPrimaryDynamicResolutionSettings

Source code excerpt:

	BudgetSetting.UpperBoundQuantization     = CVarUpperBoundQuantization.GetValueOnAnyThread();
	BudgetSetting.BudgetMs                   = CVarFrameTimeBudget.GetValueOnAnyThread() * (1.0f - DynamicRenderScaling::GetPercentageCVarToFraction(CVarOverBudgetGPUHeadRoomPercentage));
	BudgetSetting.ChangeThreshold            = DynamicRenderScaling::GetPercentageCVarToFraction(CVarChangeThreshold);
	BudgetSetting.TargetedHeadRoom           = DynamicRenderScaling::GetPercentageCVarToFraction(CVarTargetedGPUHeadRoomPercentage);
	BudgetSetting.IncreaseAmortizationFactor = CVarIncreaseAmortizationFactor.GetValueOnAnyThread();
	return BudgetSetting;
}

DynamicRenderScaling::FBudget GDynamicPrimaryResolutionFraction(TEXT("DynamicPrimaryResolution"), &GetPrimaryDynamicResolutionSettings);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DynamicResolution.cpp:563

Scope (from outer to inner):

file
function     void FDynamicResolutionHeuristicProxy::RefreshCurrentFrameResolutionFraction_RenderThread

Source code excerpt:

			const DynamicRenderScaling::FBudget& Budget = **BudgetIt;

			// CVarChangeThreshold avoids very small changes.
			bWouldBeWorthChangingRes = bWouldBeWorthChangingRes || CurrentFrameResolutionFractions[Budget] != NewFrameResolutionFractions[Budget];
		}
		
		// We do not change resolution too often to avoid interferences with temporal sub pixel in TAA upsample.
		if ((bWouldBeWorthChangingRes && bCanChangeResolution) || bGlobalGPUOverBudgetPanic)
		{