[UE4]Scalability Notes
keywords: UE4, UE5, Unreal Engine, Scalability Settings, Graphics Quality, Scalability Group
Scalability Command
Run follows in console command or execute UKismetSystemLibrary::ExecuteConsoleCommand()
to modify graphics quality at run-time:
r.PostProcessAAQuality 4
sg.PostProcessQuality 3
sg.ShadowQuality 3
sg.TextureQuality 3
sg.EffectsQuality 3
foliage.DensityScale 1.0
grass.DensityScale 1.0
Blueprint function Execute Console Command
(C++ interface is UKismetSystemLibrary::ExecuteConsoleCommand()
) also works in shipping package.
Reference:
Scalability Reference
https://docs.unrealengine.com/en-us/Engine/Performance/Scalability/ScalabilityReference
Unreal Engine 4 Save and Load Graphics Settings using Blueprints Tutorial
https://www.youtube.com/watch?v=5AXA2CrPwTo
Change Graphics Settings In-Game - Unreal Engine 4 Tutorial
https://www.youtube.com/watch?v=T90vqA9x5so
Q: Is there any way to set all quality groups to the same level?
A: Scalability::SetFromSingleQualityLevel(3);
(in Engine\Source\Runtime\Engine\Public\Scalability.h)
// Sets all other settings based on an overall value
// @param Value 0:low, 1:medium, 2:high, 3:epic, 4:cinematic (gets clamped if needed)
ENGINE_API void SetFromSingleQualityLevel(int32 Value);
// Sets all other settings based on an overall value, but relative to the maximum.
// @param Value 0: maximum level, 1: maximumlevel -1, etc
ENGINE_API void SetFromSingleQualityLevelRelativeToMax(int32 Value);
Scalability on mobile
Take Android device as example, graphics quality configuration on mobile:
Example in \Engine\Config\Android\AndroidScalability.ini
; ------------------------------------------------------------------------------
; Foliage settings
; ------------------------------------------------------------------------------
[FoliageQuality@0]
foliage.DensityScale=0.5
grass.DensityScale=0.5
[FoliageQuality@1]
grass.densityScale=0.8
grass.CullDistanceScale=0.8
foliage.DensityScale=0.8
Take high-end Android device an example, the default configuration for different device type:
Example in \Engine\Config\BaseDeviceProfiles.ini
[Android_High DeviceProfile]
DeviceType=Android
BaseProfileName=Android
+CVars=sg.ViewDistanceQuality=2
+CVars=sg.AntiAliasingQuality=2
+CVars=sg.ShadowQuality=2
+CVars=sg.PostProcessQuality=2
+CVars=sg.TextureQuality=2
+CVars=sg.EffectsQuality=2
+CVars=sg.FoliageQuality=2
+CVars=r.MobileContentScaleFactor=1.0
Customizing Device Profiles and Scalability for Android - Official Docs
Scalability on PC & Console
Directory in PIE:
[UnrealEngine]/Engine/Config/BaseScalability.ini
Directory in shipped package:
- Shipping Client:
%localappdata%/[ProjectName]/Saved/Config/WindowsNoEditor/Engine.ini
- Others:
[ProjectName]/Saved/Config/WindowsNoEditor/Engine.ini
Example content in Engine\Config\BaseScalability.ini
:
[ShadowQuality@0]
r.LightFunctionQuality=0
r.ShadowQuality=0
r.Shadow.CSM.MaxCascades=1
r.Shadow.MaxResolution=512
r.Shadow.MaxCSMResolution=512
r.Shadow.RadiusThreshold=0.06
r.Shadow.DistanceScale=0.6
r.Shadow.CSM.TransitionScale=0
r.Shadow.PreShadowResolutionFactor=0.5
r.DistanceFieldShadowing=0
r.DistanceFieldAO=0
r.VolumetricFog=0
r.LightMaxDrawDistanceScale=0
r.CapsuleShadows=0
Content in AndroidScalability.ini
will be merged into Engine.ini
automatically and override settings of Engine\Config\BaseScalability.ini
while building package.
If want to change Scalability group, tweak it in [MyProj]\Saved\Config\Windows\GameUserSettings.ini
, example in UE5:
[ScalabilityGroups]
sg.ResolutionQuality=0
sg.ViewDistanceQuality=3
sg.AntiAliasingQuality=3
sg.ShadowQuality=3
sg.GlobalIlluminationQuality=3
sg.ReflectionQuality=3
sg.PostProcessQuality=3
sg.TextureQuality=3
sg.EffectsQuality=3
sg.FoliageQuality=3
sg.ShadingQuality=3
[/Script/Engine.GameUserSettings]
bUseVSync=False
bUseDynamicResolution=False
ResolutionSizeX=1920
ResolutionSizeY=1200
LastUserConfirmedResolutionSizeX=1920
LastUserConfirmedResolutionSizeY=1200
WindowPosX=-1
WindowPosY=-1
FullscreenMode=1
LastConfirmedFullscreenMode=1
PreferredFullscreenMode=1
Version=5
AudioQualityLevel=0
LastConfirmedAudioQualityLevel=0
FrameRateLimit=0.000000
DesiredScreenWidth=1280
bUseDesiredScreenHeight=False
DesiredScreenHeight=720
LastUserConfirmedDesiredScreenWidth=1280
LastUserConfirmedDesiredScreenHeight=720
LastRecommendedScreenWidth=-1.000000
LastRecommendedScreenHeight=-1.000000
LastCPUBenchmarkResult=-1.000000
LastGPUBenchmarkResult=-1.000000
LastGPUBenchmarkMultiplier=1.000000
bUseHDRDisplayOutput=False
HDRDisplayOutputNits=1000
sg.ResolutionQuality
wasn’t using the usual 0/1/2/3 quality levels, the value directly maps to r.ScreenPercentage
.
sg.ResolutionQuality=0
(by default) means to apply screen percentage as default value: UE5 is 66.662
= (1440.0f / 2160.0f - 0.1f / 2160.0f) , while UE4 is 100.0
.
For more details, see BaseScalability.ini.
Screen Resolution on Mobile
iOS:
r.MobileContentScaleFactor 0.0
:Native resolution.r.MobileContentScaleFactor 1.0
:Use non-Retina resolution on Retina devices.r.MobileContentScaleFactor 2.0
:Native resolution of iPhone 4 ~ iPhone 6.r.MobileContentScaleFactor 3.0
:Native resolution of iPhone 6+.
Android:
r.MobileContentScaleFactor 0.0
:Native resolution.r.MobileContentScaleFactor 1.0
:720p (1280 x 720).r.MobileContentScaleFactor 2.0
:Scale of1.0
(720p).
Origin:
https://www.jianshu.com/p/7ee6b5020767
Checking Scalability
The entry of setting scalability automatically on application startup:
in Engine\Source\Runtime\Engine\Private\DeviceProfiles\DeviceProfileManager.cpp
/**
* Startup and select the active device profile
* Then Init the CVars from this profile and it's Device profile parent tree.
*/
static void InitializeCVarsForActiveDeviceProfile(bool bPushSettings=false, bool bForceDeviceProfilePriority = false);
Gather device scalability detail and set graphics quality automatically:
Console command:
scalability auto
This command will also output details in log file.
C++ API:
if(UGameUserSettings* GameUserSettings = UGameUserSettings::GetGameUserSettings())
{
GameUserSettings->RunHardwareBenchmark();
GameUserSettings->ApplyHardwareBenchmarkResults();
}
Gather CPU and GPU benchmark data:
uint32 WorkScale = 10.f;
float CPUMultiplier = 1.f;
float GPUMultiplier = 1.f;
const Scalability::FQualityLevels State = Scalability::BenchmarkQualityLevels(uint32 WorkScale, float CPUMultiplier, float GPUMultiplier);
const float CPUIndex = State.CPUBenchmarkResults;
const float GPUIndex = State.GPUBenchmarkResults;
The return value corresponds to the configuration in Engine\Config\BaseScalability.ini
:
[ScalabilitySettings]
; PerfIndexThresholds define the thresholds that determine what the autodetected quality should be for each group.
; When you auto detect performance, both a CPUIndex and GPUIndex are calculated on the machine.
; Use the console command "scalability auto" to print these values for a machine.
; The type of perfindex used to determine the quality for a group is either the GPU, CPU or Min.
; GPU means the quality is based on the speed of the graphics card. CPU means the quality is based on the processor, and Min means the group quality is based on the slower of either the CPU or GPU.
; Each group has a type followed by three numbers.
; The first number is the perfindex threshold that changes quality from 0 to 1. The second is the threshold from 1 to 2, the third is the threshold from 2 to 3.
PerfIndexThresholds_ResolutionQuality="GPU 18 42 115"
PerfIndexThresholds_ViewDistanceQuality="Min 18 42 105"
PerfIndexThresholds_AntiAliasingQuality="GPU 18 42 115"
PerfIndexThresholds_ShadowQuality="Min 18 42 105"
PerfIndexThresholds_PostProcessQuality="GPU 18 42 115"
PerfIndexThresholds_TextureQuality="GPU 18 42 115"
PerfIndexThresholds_EffectsQuality="Min 18 42 105"
PerfIndexThresholds_FoliageQuality="GPU 18 42 115"
PerfIndexThresholds_ShadingQuality="GPU 18 42 115"
; This is the screen percentage for the resolution quality, corresponding to 25% pixels, 50% pixels, 75% pixels, and 100% pixels
PerfIndexValues_ResolutionQuality="50 71 87 100 100"
Output log:
Cmd: scalability auto
LogSynthBenchmark: Display: FSynthBenchmark (V0.95): requested WorkScale=10.00
LogSynthBenchmark: Display: ===============
LogSynthBenchmark: Display: Main Processor:
LogSynthBenchmark: Display: ... 0.049066 s/Run 'RayIntersect'
LogSynthBenchmark: Display: ... 0.030856 s/Run 'Fractal'
LogSynthBenchmark: Display:
LogSynthBenchmark: Display: CompiledTarget_x_Bits: 64
LogSynthBenchmark: Display: UE_BUILD_SHIPPING: 0
LogSynthBenchmark: Display: UE_BUILD_TEST: 0
LogSynthBenchmark: Display: UE_BUILD_DEBUG: 0
LogSynthBenchmark: Display: TotalPhysicalGBRam: 32
LogSynthBenchmark: Display: NumberOfCores (physical): 8
LogSynthBenchmark: Display: NumberOfCores (logical): 8
LogSynthBenchmark: Display: CPU Perf Index 0: 52.2 (weight 1.00)
LogSynthBenchmark: Display: CPU Perf Index 1: 92.7 (weight 1.50)
LogSynthBenchmark: Display:
LogSynthBenchmark: Display: Graphics:
LogSynthBenchmark: Display: Adapter Name: 'Radeon RX 470 Series'
LogSynthBenchmark: Display: (On Optimus the name might be wrong, memory should be ok)
LogSynthBenchmark: Display: Vendor Id: 0x1002
LogSynthBenchmark: Display: Device Id: 0x67DF
LogSynthBenchmark: Display: Device Revision: 0xFF
LogSynthBenchmark: Display: GPU Memory: 4076/0/16351 MB
LogSynthBenchmark: Display: GPU first test: 0.05s
LogSynthBenchmark: Display: ... 7.508 s/GigaPix, Confidence=89% 'ALUHeavyNoise' (likely to be very inaccurate)
LogSynthBenchmark: Display: ... 5.685 s/GigaPix, Confidence=89% 'TexHeavy' (likely to be very inaccurate)
LogSynthBenchmark: Display: ... 5.209 s/GigaPix, Confidence=89% 'DepTexHeavy' (likely to be very inaccurate)
LogSynthBenchmark: Display: ... 15.020 s/GigaPix, Confidence=40% 'FillOnly' (likely to be very inaccurate)
LogSynthBenchmark: Display: ... 0.629 s/GigaPix, Confidence=100% 'Bandwidth' (likely to be very inaccurate)
LogSynthBenchmark: Display: ... 2.354 s/GigaVert, Confidence=51% 'VertThroughPut1' (likely to be very inaccurate)
LogSynthBenchmark: Display: ... 4.441 s/GigaVert, Confidence=100% 'VertThroughPut2' (likely to be very inaccurate)
LogSynthBenchmark: Display: GPU second test: 0.29s
LogSynthBenchmark: Display: ... 11.496 s/GigaPix, Confidence=70% 'ALUHeavyNoise' (likely to be inaccurate)
LogSynthBenchmark: Display: ... 8.107 s/GigaPix, Confidence=89% 'TexHeavy' (likely to be inaccurate)
LogSynthBenchmark: Display: ... 7.910 s/GigaPix, Confidence=100% 'DepTexHeavy' (likely to be inaccurate)
LogSynthBenchmark: Display: ... 32.663 s/GigaPix, Confidence=100% 'FillOnly' (likely to be inaccurate)
LogSynthBenchmark: Display: ... 0.672 s/GigaPix, Confidence=100% 'Bandwidth' (likely to be inaccurate)
LogSynthBenchmark: Display: ... 2.340 s/GigaVert, Confidence=100% 'VertThroughPut1' (likely to be inaccurate)
LogSynthBenchmark: Display: ... 4.447 s/GigaVert, Confidence=100% 'VertThroughPut2' (likely to be inaccurate)
LogSynthBenchmark: Display: GPU Final Results:
LogSynthBenchmark: Display: ... 11.496 s/GigaPix, Confidence=70% 'ALUHeavyNoise'
LogSynthBenchmark: Display: ... 8.107 s/GigaPix, Confidence=89% 'TexHeavy'
LogSynthBenchmark: Display: ... 7.910 s/GigaPix, Confidence=100% 'DepTexHeavy'
LogSynthBenchmark: Display: ... 32.663 s/GigaPix, Confidence=100% 'FillOnly'
LogSynthBenchmark: Display: ... 0.672 s/GigaPix, Confidence=100% 'Bandwidth'
LogSynthBenchmark: Display: ... 2.340 s/GigaVert, Confidence=100% 'VertThroughPut1'
LogSynthBenchmark: Display: ... 4.447 s/GigaVert, Confidence=100% 'VertThroughPut2'
LogSynthBenchmark: Display:
LogSynthBenchmark: Display: GPU Perf Index 0: 249.9 (weight 1.00)
LogSynthBenchmark: Display: GPU Perf Index 1: 108.9 (weight 0.10)
LogSynthBenchmark: Display: GPU Perf Index 2: 205.6 (weight 0.10)
LogSynthBenchmark: Display: GPU Perf Index 3: 128.3 (weight 3.00)
LogSynthBenchmark: Display: GPU Perf Index 4: 62.7 (weight 1.00)
LogSynthBenchmark: Display: GPU Perf Index 5: 152.2 (weight 0.00)
LogSynthBenchmark: Display: GPU Perf Index 6: 251.7 (weight 0.00)
LogSynthBenchmark: Display: GPUIndex: 140.2
LogSynthBenchmark: Display: CPUIndex: 76.5
LogSynthBenchmark: Display:
LogSynthBenchmark: Display: ... Total Time: 2.228119 sec
Auto-detect Optimal Graphics Settings for Unreal
https://www.tomlooman.com/auto-detect-graphics-settings-ue4/
GameUserSettings->RunHardwareBenchmark();
and Scalability::BenchmarkQualityLevels();
only work on PC and console. The mobile device fluctuates inaccurately, and may be greatly affected by temperature.
By default GTX 970 will be identified as Epic
group (yes, even UE5), but for your game, probably the Epic
group should be at least RTX 3070, to address this, you can tweak GPUMultiplier
, e.g. 0.39
.
How to read config file (.ini)
config file path: [Project]/Config/DefaultMyGameSettings.ini
[/Script/MyGame.MyGameSettings]
+AssetList=/Game/Assets/Textures/T_Diffuse
+AssetList=/Game/Assets/Textures/T_Normal
Reading example:
TArray<FString> AssetList;
FString Path = FPaths::SourceConfigDir() + TEXT("DefaultMyGameSettings.ini");
GConfig->GetArray(TEXT("/Script/MyGame.MyGameSettings"), TEXT("+AssetList"), AssetList, Path);
Example from Engine\Source\Runtime\Engine\Private\Scalability.cpp
:
const FString ArrayKey = FString(TEXT("PerfIndexThresholds_")) + GroupName;
TArray<FString> PerfIndexThresholds;
GConfig->GetSingleLineArray(TEXT("ScalabilitySettings"), *ArrayKey, PerfIndexThresholds, GScalabilityIni);
How to get device profile name
FString DefaultDeviceProfileName = FPlatformMisc::GetDefaultDeviceProfileName();
UE_LOG(LogTemp, Display, TEXT("DeviceProfile+++++ %s"), *DefaultDeviceProfileName);
UDeviceProfile* DeviceProfile = UDeviceProfileManager::Get().GetActiveProfile();
FString ProfileName = "";
if (DeviceProfile != nullptr)
{
if (DeviceProfile->BaseProfileName.IsEmpty())
{
ProfileName = DeviceProfile->GetName();
}
else
{
ProfileName = DeviceProfile->BaseProfileName;
}
}
How to get scalability value using C++
int32 PostProcessQuality = UKismetSystemLibrary::GetConsoleVariableIntValue(TEXT("sg.PostProcessQuality"))
Or
int Value = 0;
IConsoleVariable* Variable = IConsoleManager::Get().FindConsoleVariable(TEXT("sg.PostProcessQuality"));
if (Variable)
{
Value = Variable->GetInt();
}
How to change RHI (DirectX 11, DirectX 12)
Engine.ini
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_DX11
How to run game in fixed frame rate
Append follows in Engine.ini
.
Fixed frame rate:
[/Script/Engine.Engine]
bUseFixedFrameRate=True
FixedFrameRate=60.000000
Unlimited frame rate:
[/Script/Engine.Engine]
bUseFixedFrameRate=False
You need to disable VSync if want to play with fixed frame rate: Engine.ini
[SystemSettings]
r.VSync=0
Or alter GameUserSettings.ini
[/Script/Engine.GameUserSettings]
bUseVSync=False
How to start game in fullscreen mode
Add follows in MyProject/Config/DefaultGameUserSettings.ini
[/Script/Engine.GameUserSettings]
//ResolutionSizeX=1920
//ResolutionSizeY=1080
//LastUserConfirmedResolutionSizeX=1920
//LastUserConfirmedResolutionSizeY=1080
WindowPosX=-1
WindowPosY=-1
bUseDesktopResolutionForFullscreen=True
FullscreenMode=0
LastConfirmedFullscreenMode=0
The mode type explanation in GameUserSettings.h:
/**
* Game window fullscreen mode
* 0 = Fullscreen
* 1 = Windowed fullscreen
* 2 = Windowed
*/
UPROPERTY(config)
int32 FullscreenMode;
Origin:
https://answers.unrealengine.com/questions/206504/how-to-default-fullscreen-in-shipping-package.html
How to get CPU model and GPU model (brand information)
FString FWindowsPlatformMisc::GetPrimaryGPUBrand()
FString FWindowsPlatformMisc::GetCPUBrand()
Callstack: from UKismetSystemLibrary::ExecuteConsoleCommand to FConsoleVariableBase::CanChange
Callstack in UE5 (but still works for UE4):
FConsoleVariableBase::CanChange(EConsoleVariableFlags SetBy) Line 144
at D:\UE5\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp(144)
FConsoleVariable<int>::Set(const wchar_t * InValue, EConsoleVariableFlags SetBy) Line 568
at D:\UE5\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp(568)
OnSetCVarFromIniEntry(const wchar_t * IniFile, const wchar_t * Key, const wchar_t * Value, unsigned int SetBy, bool bAllowCheating) Line 5094
at D:\UE5\Engine\Source\Runtime\Core\Private\Misc\ConfigCacheIni.cpp(5094)
ApplyCVarSettingsFromIni(const wchar_t * InSectionName, const wchar_t * InIniFilename, unsigned int SetBy, bool bAllowCheating) Line 5138
at D:\UE5\Engine\Source\Runtime\Core\Private\Misc\ConfigCacheIni.cpp(5138)
Scalability::SetGroupQualityLevel(const wchar_t * InGroupName, int InQualityLevel, int InNumLevels) Line 402
at D:\UE5\Engine\Source\Runtime\Engine\Private\Scalability.cpp(402)
Invoke(void(*)(IConsoleVariable *) &) Line 47
at D:\UE5\Engine\Source\Runtime\Core\Public\Templates\Invoke.h(47)
UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(*)(IConsoleVariable *) &) Line 324
at D:\UE5\Engine\Source\Runtime\Core\Public\Templates\Tuple.h(324)
TBaseStaticDelegateInstance<void __cdecl(IConsoleVariable *),FDefaultDelegateUserPolicy>::ExecuteIfSafe(IConsoleVariable * <Params_0>) Line 731
at D:\UE5\Engine\Source\Runtime\Core\Public\Delegates\DelegateInstancesImpl.h(731)
TMulticastDelegate<void __cdecl(IConsoleVariable *),FDefaultDelegateUserPolicy>::Broadcast(IConsoleVariable *) Line 967
at D:\UE5\Engine\Source\Runtime\Core\Public\Delegates\DelegateSignatureImpl.inl(967)
FConsoleVariableBase::OnChanged(EConsoleVariableFlags SetBy) Line 196
at D:\UE5\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp(196)
FConsoleVariable<int>::OnChanged(EConsoleVariableFlags) Line 605
at D:\UE5\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp(605)
FConsoleVariable<int>::Set(const wchar_t * InValue, EConsoleVariableFlags SetBy) Line 571
at D:\UE5\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp(571)
FConsoleManager::ProcessUserConsoleInput(const wchar_t * InInput, FOutputDevice & Ar, UWorld * InWorld) Line 1798
at D:\UE5\Engine\Source\Runtime\Core\Private\HAL\ConsoleManager.cpp(1798)
UEngine::Exec(UWorld * InWorld, const wchar_t * Cmd, FOutputDevice & Ar) Line 4871
at D:\UE5\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp(4871)
UEditorEngine::Exec(UWorld * InWorld, const wchar_t * Stream, FOutputDevice & Ar) Line 5914
at D:\UE5\Engine\Source\Editor\UnrealEd\Private\EditorServer.cpp(5914)
UUnrealEdEngine::Exec(UWorld * InWorld, const wchar_t * Stream, FOutputDevice & Ar) Line 659
at D:\UE5\Engine\Source\Editor\UnrealEd\Private\UnrealEdSrv.cpp(659)
UGameViewportClient::Exec(UWorld * InWorld, const wchar_t * Cmd, FOutputDevice & Ar) Line 3014
at D:\UE5\Engine\Source\Runtime\Engine\Private\GameViewportClient.cpp(3014)
ULocalPlayer::Exec(UWorld * InWorld, const wchar_t * Cmd, FOutputDevice & Ar) Line 1499
at D:\UE5\Engine\Source\Runtime\Engine\Private\LocalPlayer.cpp(1499)
UPlayer::ConsoleCommand(const FString & Cmd, bool bWriteToLog) Line 51
at D:\UE5\Engine\Source\Runtime\Engine\Private\Player.cpp(51)
APlayerController::ConsoleCommand(const FString & Cmd, bool bWriteToLog) Line 411
at D:\UE5\Engine\Source\Runtime\Engine\Private\PlayerController.cpp(411)
UKismetSystemLibrary::ExecuteConsoleCommand(const UObject * WorldContextObject, const FString & Command, APlayerController * Player) Line 396
at D:\UE5\Engine\Source\Runtime\Engine\Private\KismetSystemLibrary.cpp(396)
Issue: Console Priority
Error when execute console command:
LogConsoleManager: Warning: |ConsoleManager.cpp:161|Setting the console variable 'r.ViewDistanceScale' with 'SetByScalability' was ignored as it is lower priority than the previous 'SetByConsole'. Value remains '1'
Solution:
IConsoleVariable* Var = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ViewDistanceScale"));
Var->Set(TEXT("0.8"), ECVF_SetByConsole);
Origin: UE4控制台命令
https://www.cnblogs.com/kekec/p/11102365.html
References
Lyra Scalability and Device Profiles - UE5 Official Docs
A man who cannot tolerate small misfortunes can never accomplish great things. -Chinese Proverbs