r.ScreenPercentage

r.ScreenPercentage

#Overview

name: r.ScreenPercentage

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

It is referenced in 26 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.ScreenPercentage is to control the rendering resolution relative to the display resolution, allowing for performance optimization or supersampling in Unreal Engine’s rendering system.

This setting variable is primarily used in the rendering system, particularly for managing screen resolution and performance. It is relied upon by several Unreal Engine subsystems and modules, including:

  1. The core Engine module
  2. The DisplayCluster plugin
  3. The ConsoleVariablesEditor plugin
  4. The UnrealEd module (for editor viewport rendering)
  5. The FunctionalTesting module

The value of r.ScreenPercentage is typically set through the console variable system. It can be set manually, through scalability settings, or dynamically adjusted by the engine based on performance requirements.

Several other variables interact with r.ScreenPercentage:

  1. CVarScreenPercentage: This is the associated console variable that directly represents r.ScreenPercentage.
  2. r.DynamicRes.TestScreenPercentage: Used for testing dynamic resolution.
  3. r.SecondaryScreenPercentage.GameViewport: Controls secondary screen percentage for the game viewport.

Developers should be aware of the following when using this variable:

  1. Values are in percentages, with 100 being the native resolution.
  2. Values below 100 render at lower resolution and upscale, improving performance.
  3. Values above 100 enable supersampling but may impact performance.
  4. Setting the value to 0 or below uses the default screen percentage determined by other CVars.
  5. It interacts with dynamic resolution systems and can be overridden by them.

Best practices for using r.ScreenPercentage include:

  1. Use it as part of a broader performance optimization strategy.
  2. Test thoroughly to find the right balance between performance and visual quality.
  3. Consider using dynamic resolution systems for more adaptive performance management.
  4. Be aware of its interaction with other rendering settings and resolution-related variables.

Regarding the associated variable CVarScreenPercentage:

The purpose of CVarScreenPercentage is to provide a console variable interface for r.ScreenPercentage. It allows for runtime modification and querying of the screen percentage value.

CVarScreenPercentage is used in the same subsystems as r.ScreenPercentage, primarily in the rendering and scalability systems.

Its value is set through the console variable system, either programmatically or via console commands.

CVarScreenPercentage directly interacts with r.ScreenPercentage, essentially serving as its console variable representation.

Developers should be aware that changes to CVarScreenPercentage will affect r.ScreenPercentage and vice versa. It’s subject to the same considerations and best practices as r.ScreenPercentage.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:33

Scope: file

Source code excerpt:


static TAutoConsoleVariable<float> CVarScreenPercentage(
	TEXT("r.ScreenPercentage"), 0.0f,
	TEXT("To render in lower resolution and upscale for better performance (combined up with the blenable post process setting).\n")
	TEXT("70 is a good value for low aliasing and performance, can be verified with 'show TestImage'\n")
	TEXT("in percent, >0 and <=100, larger numbers are possible (supersampling) but the downsampling quality is improvable.")
	TEXT("<=0 compute the screen percentage is determined by r.ScreenPercentage.Default cvars."),
	ECVF_Scalability | ECVF_Default);

#Loc: <Workspace>/Engine/Plugins/Editor/ConsoleVariablesEditor/Source/ConsoleVariablesEditor/Private/Views/MainPanel/ConsoleVariablesEditorMainPanel.cpp:116

Scope (from outer to inner):

file
function     FReply FConsoleVariablesEditorMainPanel::ValidateConsoleInputAndAddToCurrentPreset

Source code excerpt:

	}
	
	FString CommandKey; // The actual variable name, like r.ScreenPercentage
	FString ValueString; // The variable value, usually after the CommandKey and a single space
	FString AdditionalParams; // Some variables have multiple parameters between the CommandKey and ValueString

	if (CommandString.Contains(" "))
	{
		// We want to treat the last string after the last space as the value

#Loc: <Workspace>/Engine/Plugins/Editor/ConsoleVariablesEditor/Source/ConsoleVariablesEditor/Public/ConsoleVariablesEditorCommandInfo.h:19

Scope (from outer to inner):

file
function     struct CONSOLEVARIABLESEDITOR_API FConsoleVariablesEditorCommandInfo { enum class EConsoleObjectType { // A console command that has no associated console object but is parsed externally, e.g. 'st

Source code excerpt:

		// A console command with an associated console object, like 'r.SetNearClipPlane'
		Command,
		// A console variable such as 'r.ScreenPercentage'
		Variable
	};
	
	struct FStaticConsoleVariableFlagInfo
	{
		EConsoleVariableFlags Flag;

#Loc: <Workspace>/Engine/Plugins/Editor/DisplayClusterLaunch/Source/DisplayClusterLaunchEditor/Public/DisplayClusterLaunchEditorProjectSettings.h:114

Scope (from outer to inner):

file
function     class DISPLAYCLUSTERLAUNCHEDITOR_API UDisplayClusterLaunchEditorProjectSettings : public UObject { GENERATED_BODY

Source code excerpt:

	 * You can specify additional console variables here to be executed after those of the Console Variable Preset are executed.
	 * This is useful for overriding variables in your defined Console Variables Asset.
	 * Console Variables generally have a name and a value, like "r.ScreenPercentage 50"
	 */
	UPROPERTY(Config, EditAnywhere, Category="nDisplay Launch Settings|Console", meta = (Keywords = "DPCvars"))
	TSet<FString> AdditionalConsoleVariables;

	/**
	 * You can specify additional console commands here to be executed after those of the Console Variable Preset are executed.
	 * This is useful for overriding commands in your defined Console Variables Asset.
	 * Console Commands generally have a name and no value (i.e. 'stat unit') though some have a value too (i.e. "r.SetNearClipPlane 500")
	 */
	UPROPERTY(Config, EditAnywhere, Category="nDisplay Launch Settings|Console")
	TSet<FString> AdditionalConsoleCommands;

#Loc: <Workspace>/Engine/Plugins/Runtime/nDisplay/Source/DisplayCluster/Private/Game/EngineClasses/Basics/DisplayClusterViewportClient.cpp:800

Scope (from outer to inner):

file
function     void UDisplayClusterViewportClient::Draw

Source code excerpt:

					if (ViewFamily.EngineShowFlags.ScreenPercentage)
					{
						// Get global view fraction set by r.ScreenPercentage.
						GlobalResolutionFraction = CustomBufferRatio;

						// We need to split the screen percentage if below 0.5 because TAA upscaling only works well up to 2x.
						if (GlobalResolutionFraction < 0.5f)
						{
							SecondaryScreenPercentage = 2.0f * GlobalResolutionFraction;

#Loc: <Workspace>/Engine/Plugins/Runtime/nDisplay/Source/DisplayCluster/Private/Render/Viewport/DisplayClusterViewport.cpp:704

Scope (from outer to inner):

file
function     bool FDisplayClusterViewport::UpdateFrameContexts

Source code excerpt:

		Context.ContextSize = ContextSize;

		// r.ScreenPercentage
		switch (RenderSettings.CaptureMode)
		{
		case EDisplayClusterViewportCaptureMode::Chromakey:
		case EDisplayClusterViewportCaptureMode::Lightcard:
			// we should not change the size of the Chromakey\Lighcards due to the way copy\resolve works for RT's
			// if the viewfamily resolves to RenderTarget it will remove alpha channel

#Loc: <Workspace>/Engine/Plugins/Runtime/nDisplay/Source/DisplayClusterLightCardEditor/Private/Viewport/DisplayClusterLightCardEditorViewportClient.cpp:306

Scope (from outer to inner):

file
function     void FDisplayClusterLightCardEditorViewportClient::Draw

Source code excerpt:

			}

			// In editor viewport, we ignore r.ScreenPercentage and FPostProcessSettings::ScreenPercentage by design.
			ViewFamily.SetScreenPercentageInterface(new FLegacyScreenPercentageDriver(ViewFamily, GlobalResolutionFraction));
		}

		check(ViewFamily.GetScreenPercentageInterface() != nullptr);
	}

#Loc: <Workspace>/Engine/Plugins/VirtualProduction/ICVFXTesting/Source/ICVFXTesting/Public/ICVFXTestControllerBase.h:74

Scope (from outer to inner):

file
class        class UICVFXTestControllerBase : public UGauntletTestController

Source code excerpt:

		TEXT("ICVFXTest"),
		TEXT("r.nanite"),
		TEXT("r.ScreenPercentage"),
		TEXT("r.RayTracing"),
		TEXT("r.DynamicGlobalIlluminationMethod"),
		TEXT("r.ReflectionMethod"),
		TEXT("r.Lumen"),
		TEXT("FX.AllowGPUParticles"),
		TEXT("r.Shadow.Virtual.Enable")};

#Loc: <Workspace>/Engine/Source/Developer/FunctionalTesting/Private/AutomationBlueprintFunctionLibrary.cpp:248

Scope (from outer to inner):

file
function     FAutomationTestScreenshotEnvSetup::FAutomationTestScreenshotEnvSetup

Source code excerpt:

	, TonemapperGamma(TEXT("r.TonemapperGamma"))
	, TonemapperSharpen(TEXT("r.Tonemapper.Sharpen"))
	, ScreenPercentage(TEXT("r.ScreenPercentage"))
	, DynamicResTestScreenPercentage(TEXT("r.DynamicRes.TestScreenPercentage"))
	, DynamicResOperationMode(TEXT("r.DynamicRes.OperationMode"))
	, SecondaryScreenPercentage(TEXT("r.SecondaryScreenPercentage.GameViewport"))
{
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Editor/EditorPerformanceSettings.h:17

Scope: file

Source code excerpt:

	ProjectDefault,

	// Directly controls the screen percentage with the r.ScreenPercentage cvar
	Manual UMETA(DisplayName = "Manual"),

	// Automatic control the screen percentage based on the display resolution, r.ScreenPercentage.Auto.*
	BasedOnDisplayResolution UMETA(DisplayName = "Based on display resolution"),

	// Based on DPI scale.

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorViewportClient.cpp:4274

Scope (from outer to inner):

file
function     void FEditorViewportClient::Draw

Source code excerpt:

			}

			// In editor viewport, we ignore r.ScreenPercentage and FPostProcessSettings::ScreenPercentage by design.
			ViewFamily.SetScreenPercentageInterface(new FLegacyScreenPercentageDriver(
				ViewFamily, GlobalResolutionFraction));
		}

		check(ViewFamily.GetScreenPercentageInterface() != nullptr);
	}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SScalabilitySettings.cpp:123

Scope (from outer to inner):

file
function     bool SScalabilitySettings::IsResolutionScaleEditable

Source code excerpt:

	}

	static IConsoleVariable* CVarScreenPercentage = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ScreenPercentage"));
	if ((uint32(CVarScreenPercentage->GetFlags()) & uint32(ECVF_SetByMask)) > uint32(ECVF_SetByScalability))
	{
		return false;
	}
	
	return true;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SScalabilitySettings.cpp:272

Scope (from outer to inner):

file
function     FFormatNamedArguments SScalabilitySettings::GetScreenPercentageFormatArguments

Source code excerpt:

	FormatArguments.Add(TEXT("ViewportMode"), UEnum::GetDisplayValueAsText(ViewportRenderingMode));

	static IConsoleVariable* CVarScreenPercentage = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ScreenPercentage"));
	const TCHAR* CVarScreenPercentageSetBy = GetConsoleVariableSetByName(CVarScreenPercentage->GetFlags());
	float CVarScreenPercentageValue = CVarScreenPercentage->GetFloat();
	if (EConsoleVariableFlags(uint32(CVarScreenPercentage->GetFlags()) & uint32(ECVF_SetByMask)) > ECVF_SetByScalability)
	{
		if (CVarScreenPercentageValue > 0.0f)
		{
			FormatArguments.Add(TEXT("SettingSource"), FText::Format(
				LOCTEXT("ScreenPercentageCVarSetBy", "r.ScreenPercentage={0} set by {1}"),
				FText::AsNumber(CVarScreenPercentageValue),
				FText::FromString(CVarScreenPercentageSetBy)));
		}
		else
		{
			FormatArguments.Add(TEXT("SettingSource"), FText::Format(
				LOCTEXT("ScreenPercentageCVarSetByUsesProjectDefaults", "Project Settings' default due to r.ScreenPercentage={0} set by {1}"),
				FText::AsNumber(CVarScreenPercentageValue),
				FText::FromString(CVarScreenPercentageSetBy)));
		}
	}
	else
	{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:71

Scope (from outer to inner):

file
function     void OnScreenPercentageChange

Source code excerpt:

	}

	// Check whether dynamic resolution is overriding r.ScreenPercentage.
	{
		FDynamicResolutionStateInfos DynResInfo;
		GEngine->GetDynamicResolutionCurrentStateInfos(/* out */ DynResInfo);

		if (DynResInfo.Status == EDynamicResolutionStatus::Enabled)
		{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:175

Scope (from outer to inner):

file
function     float FLegacyScreenPercentageDriver::GetCVarResolutionFraction

Source code excerpt:

{
	check(IsInGameThread());
	static const auto ScreenPercentageCVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.ScreenPercentage"));

	float GlobalFraction = GetResolutionFraction(CVarScreenPercentage.GetValueOnGameThread());
	if (GlobalFraction <= GetResolutionFraction(Scalability::MinResolutionScale))
	{
		GlobalFraction = 1.0f;
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Scalability.cpp:456

Scope (from outer to inner):

file
namespace    Scalability
function     float GetResolutionScreenPercentage

Source code excerpt:

float GetResolutionScreenPercentage()
{
	static IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ScreenPercentage"));
	return FMath::Clamp(CVar->GetFloat(), MinResolutionScale, MaxResolutionScale);
}

FText GetScalabilityNameFromQualityLevel(int32 QualityLevel)
{
#define LOCTEXT_NAMESPACE "EngineScalabiltySettings"

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Scalability.cpp:502

Scope (from outer to inner):

file
namespace    Scalability
function     static void SetResolutionQualityLevel

Source code excerpt:

//	UE_LOG(LogConsoleResponse, Display, TEXT("  ResolutionQuality %.2f"), "", InResolutionQualityLevel);

	static IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ScreenPercentage"));

	// if it wasn't created yet we either need to change the order or store like we do for ini loading
	check(CVar);

	CVar->Set(InResolutionQualityLevel, ECVF_SetByScalability);
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/LegacyScreenPercentageDriver.h:21

Scope (from outer to inner):

file
class        class FLegacyScreenPercentageDriver : public ISceneViewFamilyScreenPercentage

Source code excerpt:

		float InGlobalResolutionFractionUpperBound);

	/** Gets the view rect fraction from the r.ScreenPercentage cvar. */
	static ENGINE_API float GetCVarResolutionFraction();

private:
	// View family to take care of.
	const FSceneViewFamily& ViewFamily;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/LegacyScreenPercentageDriver.h:90

Scope: file

Source code excerpt:

		EScreenPercentageMode Mode = EScreenPercentageMode::Manual;

		// r.ScreenPercentage when Mode = EMode::Manual.
		float GlobalResolutionFraction = 1.0f;

		// r.ScreenPercentage.{Min,Max}Resolution
		float MinRenderingResolution = 0.0f;
		float MaxRenderingResolution = 0.0f;

		// r.ScreenPercentage.Auto.* Mode = EMode::BasedOnDisplayResolution.
		float AutoPixelCountMultiplier = 1.0f;

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SScalabilitySettings.cpp:123

Scope (from outer to inner):

file
function     bool SScalabilitySettings::IsResolutionScaleEditable

Source code excerpt:

	}

	static IConsoleVariable* CVarScreenPercentage = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ScreenPercentage"));
	if ((uint32(CVarScreenPercentage->GetFlags()) & uint32(ECVF_SetByMask)) > uint32(ECVF_SetByScalability))
	{
		return false;
	}
	
	return true;
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SScalabilitySettings.cpp:272

Scope (from outer to inner):

file
function     FFormatNamedArguments SScalabilitySettings::GetScreenPercentageFormatArguments

Source code excerpt:

	FormatArguments.Add(TEXT("ViewportMode"), UEnum::GetDisplayValueAsText(ViewportRenderingMode));

	static IConsoleVariable* CVarScreenPercentage = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ScreenPercentage"));
	const TCHAR* CVarScreenPercentageSetBy = GetConsoleVariableSetByName(CVarScreenPercentage->GetFlags());
	float CVarScreenPercentageValue = CVarScreenPercentage->GetFloat();
	if (EConsoleVariableFlags(uint32(CVarScreenPercentage->GetFlags()) & uint32(ECVF_SetByMask)) > ECVF_SetByScalability)
	{
		if (CVarScreenPercentageValue > 0.0f)
		{
			FormatArguments.Add(TEXT("SettingSource"), FText::Format(
				LOCTEXT("ScreenPercentageCVarSetBy", "r.ScreenPercentage={0} set by {1}"),
				FText::AsNumber(CVarScreenPercentageValue),

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:32

Scope: file

Source code excerpt:

	ECVF_Scalability | ECVF_Default);

static TAutoConsoleVariable<float> CVarScreenPercentage(
	TEXT("r.ScreenPercentage"), 0.0f,
	TEXT("To render in lower resolution and upscale for better performance (combined up with the blenable post process setting).\n")
	TEXT("70 is a good value for low aliasing and performance, can be verified with 'show TestImage'\n")
	TEXT("in percent, >0 and <=100, larger numbers are possible (supersampling) but the downsampling quality is improvable.")
	TEXT("<=0 compute the screen percentage is determined by r.ScreenPercentage.Default cvars."),
	ECVF_Scalability | ECVF_Default);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:94

Scope (from outer to inner):

file
function     void InitScreenPercentage

Source code excerpt:

{
#if !UE_BUILD_SHIPPING
	CVarScreenPercentage.AsVariable()->SetOnChangedCallback(FConsoleVariableDelegate::CreateStatic(&OnScreenPercentageChange));
#endif
}

static float GetRenderingPixelCount(float Rendering169Height)
{
	return Rendering169Height * FMath::Abs(Rendering169Height) * (1920.0f / 1080.0f);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:177

Scope (from outer to inner):

file
function     float FLegacyScreenPercentageDriver::GetCVarResolutionFraction

Source code excerpt:

	static const auto ScreenPercentageCVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.ScreenPercentage"));

	float GlobalFraction = GetResolutionFraction(CVarScreenPercentage.GetValueOnGameThread());
	if (GlobalFraction <= GetResolutionFraction(Scalability::MinResolutionScale))
	{
		GlobalFraction = 1.0f;
	}

	return GlobalFraction;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:212

Scope (from outer to inner):

file
function     void FStaticResolutionFractionHeuristic::FUserSettings::PullRunTimeRenderingSettings

Source code excerpt:

void FStaticResolutionFractionHeuristic::FUserSettings::PullRunTimeRenderingSettings(EViewStatusForScreenPercentage ViewStatus)
{
	float GlobalResolutionFractionOverride = GetResolutionFraction(CVarScreenPercentage.GetValueOnGameThread());
	MinRenderingResolution = CVarScreenPercentageMinResolution.GetValueOnGameThread();
	MaxRenderingResolution = CVarScreenPercentageMaxResolution.GetValueOnGameThread();

	if (GlobalResolutionFractionOverride > 0.0)
	{
		Mode = EScreenPercentageMode::Manual;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:258

Scope (from outer to inner):

file
function     void FStaticResolutionFractionHeuristic::FUserSettings::PullRunTimeRenderingSettings

Source code excerpt:

{
	Mode = EScreenPercentageMode::Manual;
	GlobalResolutionFraction = GetResolutionFraction(CVarScreenPercentage.GetValueOnGameThread());
	MinRenderingResolution = CVarScreenPercentageMinResolution.GetValueOnGameThread();
	MaxRenderingResolution = CVarScreenPercentageMaxResolution.GetValueOnGameThread();
	AutoPixelCountMultiplier = CVarAutoPixelCountMultiplier.GetValueOnGameThread();

	if (GlobalResolutionFraction <= 0.0)
	{