FrameRateLock

FrameRateLock

#Overview

name: FrameRateLock

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 5 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of FrameRateLock is to control the maximum frame rate of the game on iOS devices, primarily to manage power consumption and performance.

This setting variable is primarily relied upon by the iOS-specific subsystems of Unreal Engine, particularly the Metal RHI (Rendering Hardware Interface) and the iOS platform frame pacer. It’s also referenced in the Mac platform frame pacer, suggesting some shared functionality between iOS and macOS implementations.

The value of this variable is set in the IOSRuntimeSettings class, which is part of the IOSRuntimeSettings module. It’s defined as an UPROPERTY with the GlobalConfig and EditAnywhere attributes, meaning it can be modified in the project settings within the Unreal Engine editor.

FrameRateLock interacts with other variables such as bEnableDynamicMaxFPS and the device’s maximum refresh rate. It’s used to calculate the frame interval for the frame pacer and can affect the Metal present frame pacing.

Developers must be aware that:

  1. The FrameRateLock value is an enum (EPowerUsageFrameRateLock) and not a direct numeric value.
  2. It can be overridden via command line parameters.
  3. If set to 0, it defaults to the device’s maximum refresh rate.
  4. It’s used in conjunction with the maximum refresh rate of the device to calculate the actual frame interval.

Best practices when using this variable include:

  1. Consider the power consumption implications when setting this value. Lower frame rates can save battery life.
  2. Ensure the chosen frame rate lock is appropriate for the game’s performance requirements and target devices.
  3. Be aware that it can be overridden by command line parameters, which might be useful for debugging or testing.
  4. Consider using the bEnableDynamicMaxFPS option for more flexible frame rate management.
  5. Remember that changes to this setting may require restarting the application to take effect.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:3003, section: [/Script/IOSRuntimeSettings.IOSRuntimeSettings]

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Apple/MetalRHI/Private/MetalContext.cpp:373

Scope (from outer to inner):

file
function     FMetalDeviceContext::FMetalDeviceContext

Source code excerpt:

		{
			FString FrameRateLockAsEnum;
			GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("FrameRateLock"), FrameRateLockAsEnum, GEngineIni);
	
			uint32 FrameRateLock = 0;
			FParse::Value(*FrameRateLockAsEnum, TEXT("PUFRL_"), FrameRateLock);
			if (FrameRateLock > 0)
			{
				GMetalPresentFramePacing = (float)FrameRateLock;
			}
		}
	}
	
    const bool bIsVisionOS = PLATFORM_VISIONOS;
	if (bIsVisionOS || FParse::Param(FCommandLine::Get(), TEXT("MetalIntermediateBackBuffer")) || FParse::Param(FCommandLine::Get(), TEXT("MetalOffscreenOnly")))

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/IOS/IOSPlatformFramePacer.cpp:141

Scope (from outer to inner):

file
function     bool FIOSPlatformRHIFramePacer::IsEnabled

Source code excerpt:

	{
		FString FrameRateLockAsEnum;
		GConfig->GetString(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("FrameRateLock"), FrameRateLockAsEnum, GEngineIni);

		uint32 MaxRefreshRate = GetMaxRefreshRate();
		uint32 FrameRateLock = MaxRefreshRate;
		FParse::Value(*FrameRateLockAsEnum, TEXT("PUFRL_"), FrameRateLock);

        const bool bOverridesFrameRate = FParse::Value( FCommandLine::Get(), TEXT( "FrameRateLock=" ), FrameRateLockAsEnum );
        if (bOverridesFrameRate)
        {
            FParse::Value(*FrameRateLockAsEnum, TEXT("PUFRL_"), FrameRateLock);
        }
        
        if (FrameRateLock == 0)
        {
            FrameRateLock = MaxRefreshRate;
        }

        if (!bIsRHIFramePacerEnabled)
		{
			check((MaxRefreshRate % FrameRateLock) == 0);
			FrameInterval = MaxRefreshRate / FrameRateLock;
			MinFrameInterval = FrameInterval;

			bIsRHIFramePacerEnabled = (FrameInterval > 0);
			
			// remember the Pace if we are enabled
			Pace = bIsRHIFramePacerEnabled ? FrameRateLock : 0;
		}
		bInitialized = true;
	}
	
	return bIsRHIFramePacerEnabled;
#endif

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Mac/MacPlatformFramePacer.cpp:159

Scope (from outer to inner):

file
function     void FMacFramePacer::Signal

Source code excerpt:

	if (!bInitialized)
	{
		GConfig->GetBool(TEXT("/Script/MacTargetPlatform.MacTargetSettings"), TEXT("FrameRateLock"), bIsRHIFramePacerEnabled, GEngineIni);
		bInitialized = true;
	}
	
	return bIsRHIFramePacerEnabled;
}

#Loc: <Workspace>/Engine/Source/Runtime/IOS/IOSRuntimeSettings/Classes/IOSRuntimeSettings.h:276

Scope (from outer to inner):

file
class        class UIOSRuntimeSettings : public UObject

Source code excerpt:

    /** Set the maximum frame rate to save on power consumption */
    UPROPERTY(GlobalConfig, EditAnywhere, Category = PowerUsage, meta = (ConfigHierarchyEditable))
    EPowerUsageFrameRateLock FrameRateLock;

    //Whether or not to allow taking the MaxRefreshRate from the device instead of a constant (60fps) in IOSPlatformFramePacer
    UPROPERTY(GlobalConfig, EditAnywhere, Category = PowerUsage, meta = (ConfigHierarchyEditable))
    bool bEnableDynamicMaxFPS;

    // Enable the use of RSync for remote builds on a mac

#Loc: <Workspace>/Engine/Source/Runtime/IOS/IOSRuntimeSettings/Private/IOSRuntimeSettings.cpp:35

Scope (from outer to inner):

file
function     UIOSRuntimeSettings::UIOSRuntimeSettings

Source code excerpt:

	BundleIdentifier = TEXT("com.YourCompany.GameNameNoSpaces");
	VersionInfo = TEXT("1.0.0");
    FrameRateLock = EPowerUsageFrameRateLock::PUFRL_30;
	bEnableDynamicMaxFPS = false;
	bSupportsIPad = true;
	bSupportsIPhone = true;
	bEnableSplitView = false;
	bEnableSimulatorSupport = false;
	MinimumiOSVersion = EIOSVersion::IOS_Minimum;