rhi.SyncInterval

rhi.SyncInterval

#Overview

name: rhi.SyncInterval

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

It is referenced in 14 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of rhi.SyncInterval is to control the vertical synchronization (VSync) behavior in Unreal Engine’s rendering system. It determines how frequently the engine synchronizes frame rendering with the display’s refresh rate.

This setting variable is primarily used by the RHI (Rendering Hardware Interface) subsystem of Unreal Engine. It’s also utilized by the ApplicationCore module for frame pacing and by the Core module for profiling purposes.

The value of rhi.SyncInterval is typically set through the console variable system. It can be modified at runtime using console commands or through code using the IConsoleManager interface.

The rhi.SyncInterval variable interacts closely with the associated variable CVarRHISyncInterval. They share the same value, with CVarRHISyncInterval being the actual console variable implementation.

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

  1. A value of 0 means vsync is disabled, allowing for uncapped framerates.
  2. A value of 1 means the engine will sync with every vblank interval (typically 60fps on a 60Hz display).
  3. Higher values will result in lower frame rates (e.g., 2 would cap at 30fps on a 60Hz display).

Best practices for using this variable include:

  1. Consider the target platform’s capabilities and limitations when setting this value.
  2. Be aware that changing this value can affect input lag and overall game feel.
  3. Use in conjunction with other frame pacing mechanisms for optimal results.
  4. Test thoroughly on target hardware to ensure desired performance.

Regarding the associated variable CVarRHISyncInterval:

The purpose of CVarRHISyncInterval is to provide a console variable interface for rhi.SyncInterval. It allows for easy modification of the sync interval through console commands or code.

This variable is defined in the RHI module and is used to retrieve the actual sync interval value in various parts of the engine.

The value of CVarRHISyncInterval is set when the console variable is created, but can be modified at runtime.

Developers should be aware that modifying CVarRHISyncInterval directly will affect the behavior controlled by rhi.SyncInterval.

Best practices for using CVarRHISyncInterval include:

  1. Use the IConsoleManager interface to modify this variable programmatically if needed.
  2. Remember that changes to this variable will immediately affect the engine’s vsync behavior.
  3. Consider exposing this setting in user-facing graphics options for players to adjust based on their preferences and hardware capabilities.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/RHIUtilities.cpp:74

Scope: file

Source code excerpt:


TAutoConsoleVariable<int32> CVarRHISyncInterval(
	TEXT("rhi.SyncInterval"),
	1,
	TEXT("Determines the frequency of VSyncs in supported RHIs.\n")
	TEXT("This is in multiples of 16.66 on a 60hz display, but some platforms support higher refresh rates.\n")
	TEXT("Assuming 60fps, the values correspond to:\n")
	TEXT("  0 - Unlocked (present immediately)\n")
	TEXT("  1 - Present every vblank interval\n")

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Android/AndroidPlatformFramePacer.cpp:102

Scope (from outer to inner):

file
function     int32 FAndroidPlatformRHIFramePacer::SetFramePace

Source code excerpt:

	int32 NewFramePace = SupportsFramePace(InFramePace) ? InFramePace : 0;

	// Call generic framepacer to update rhi.SyncInterval where possible
	FGenericPlatformRHIFramePacer::SetFramePaceToSyncInterval(InFramePace);

	/* Update cvar if necessary */
	if (InternalFramePace != NewFramePace)
	{
		InternalFramePace = NewFramePace;

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/GenericPlatform/GenericPlatformFramePacer.cpp:7

Scope (from outer to inner):

file
function     int32 FGenericPlatformRHIFramePacer::GetFramePaceFromSyncInterval

Source code excerpt:

{
	int32 SyncInterval = 0;
	static IConsoleVariable* SyncIntervalCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("rhi.SyncInterval"));
	if (ensure(SyncIntervalCVar != nullptr))
	{
		SyncInterval = SyncIntervalCVar->GetInt();
	}

	if (SyncInterval <= 0)

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/GenericPlatform/GenericPlatformFramePacer.cpp:36

Scope (from outer to inner):

file
function     int32 FGenericPlatformRHIFramePacer::SetFramePaceToSyncInterval

Source code excerpt:

int32 FGenericPlatformRHIFramePacer::SetFramePaceToSyncInterval(int32 InFramePace)
{
	static IConsoleVariable* SyncIntervalCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("rhi.SyncInterval"));
	if (SupportsFramePace(InFramePace) && ensure(SyncIntervalCVar != nullptr))
	{
		int32 NewSyncInterval = InFramePace > 0
			? FMath::Clamp(FPlatformMisc::GetMaxRefreshRate() / InFramePace, 1, FPlatformMisc::GetMaxSyncInterval())
			: 0;

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

Scope (from outer to inner):

file
function     int32 FIOSPlatformRHIFramePacer::SetFramePace

Source code excerpt:

	int32 NewPace = 0;

	static IConsoleVariable* SyncIntervalCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("rhi.SyncInterval"));
	if (ensure(SyncIntervalCVar != nullptr))
	{
		int32 MaxRefreshRate = GetMaxRefreshRate();
		int32 NewSyncInterval = InFramePace > 0 ? MaxRefreshRate / InFramePace : 0;
		SyncIntervalCVar->Set(NewSyncInterval, ECVF_SetByCode);

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

Scope (from outer to inner):

file
function     int32 FIOSPlatformRHIFramePacer::GetFramePace

Source code excerpt:

{
	int32 CurrentPace = 0;
	static IConsoleVariable* SyncIntervalCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("rhi.SyncInterval"));
	if (ensure(SyncIntervalCVar != nullptr))
	{
		int SyncInterval = SyncIntervalCVar->GetInt();
		if (SyncInterval > 0)
		{
			CurrentPace = GetMaxRefreshRate() / SyncInterval;

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Public/GenericPlatform/GenericPlatformFramePacer.h:18

Scope: file

Source code excerpt:

	/**
	 * The pace we are running at (30 = 30fps, 0 = unpaced)
	 * The generic implementation returns a result based on rhi.SyncInterval and FPlatformMisc::GetMaxRefreshRate().
	 */
	static inline int32 GetFramePace() 
	{
		return GetFramePaceFromSyncInterval();
	}

	/**
	 * Sets the pace we would like to running at (30 = 30fps, 0 = unpaced).
	 * The generic implementation sets the value for rhi.SyncInterval according to FPlatformMisc::GetMaxRefreshRate().
	 *
	 * @return the pace we will run at.
	 */
	static inline int32 SetFramePace(int32 FramePace)
	{
		return SetFramePaceToSyncInterval(FramePace);
	}

	/**
	 * Returns whether the hardware is able to frame pace at the specified frame rate
	 */

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Public/GenericPlatform/GenericPlatformFramePacer.h:43

Scope: file

Source code excerpt:

protected:
	/**
	 * The generic implementation returns a result based on rhi.SyncInterval and FPlatformMisc::GetMaxRefreshRate().
	 */
	static APPLICATIONCORE_API int32 GetFramePaceFromSyncInterval();

	/**
	 * The generic implementation sets rhi.SyncInterval based on FPlatformMisc::GetMaxRefreshRate().
	 *
	 * @return the pace we will run at.
	 */
	static APPLICATIONCORE_API int32 SetFramePaceToSyncInterval(int32 FramePace);
};

#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/ProfilingDebugging/CsvProfiler.cpp:3037

Scope (from outer to inner):

file
function     void FCsvProfiler::BeginFrame

Source code excerpt:

					static IConsoleVariable* CsvTargetFrameRateCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("csv.TargetFrameRateOverride"));
					static IConsoleVariable* MaxFPSCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("t.MaxFPS"));
					static IConsoleVariable* SyncIntervalCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("rhi.SyncInterval"));
					int32 CmdLineTargetFPS = TargetFPS;
					if (CsvTargetFrameRateCVar && CsvTargetFrameRateCVar->GetInt() > 0)
					{
						TargetFPS = CsvTargetFrameRateCVar->GetInt();
					}
					else if (FParse::Value(FCommandLine::Get(), TEXT("csv.TargetFrameRateOverride"), CmdLineTargetFPS)) // Too early to set CsvTargetFrameRateCVar with execcmds

#Loc: <Workspace>/Engine/Source/Runtime/Core/Public/GenericPlatform/GenericPlatformMisc.h:1877

Scope: file

Source code excerpt:


	/**
	 * Returns the platform's maximum allowed value for rhi.SyncInterval
	 */
	static inline int32 GetMaxSyncInterval()
	{
		// Generic platform has no limit.
		return MAX_int32;
	}
	
	/**

#Loc: <Workspace>/Engine/Source/Runtime/RHI/Public/RHIUtilities.h:615

Scope: file

Source code excerpt:

extern RHI_API void SetDepthBoundsTest(FRHICommandList& RHICmdList, float WorldSpaceDepthNear, float WorldSpaceDepthFar, const FMatrix& ProjectionMatrix);

/** Returns the value of the rhi.SyncInterval CVar. */
extern RHI_API uint32 RHIGetSyncInterval();

/** Returns the value of the rhi.SyncSlackMS CVar or length of a full frame interval if the frame offset system is disabled. */
extern RHI_API float RHIGetSyncSlackMS();

/** Returns the top and bottom vsync present thresholds (the values of rhi.PresentThreshold.Top and rhi.PresentThreshold.Bottom) */

#Loc: <Workspace>/Projects/Lyra/Source/LyraGame/Settings/LyraSettingsLocal.cpp:371

Scope (from outer to inner):

file
function     void ULyraSettingsLocal::LoadSettings

Source code excerpt:

	Super::LoadSettings(bForceReload);

	// Console platforms use rhi.SyncInterval to limit framerate
	const ULyraPlatformSpecificRenderingSettings* PlatformSettings = ULyraPlatformSpecificRenderingSettings::Get();
	if (PlatformSettings->FramePacingMode == ELyraFramePacingMode::ConsoleStyle)
	{
		FrameRateLimit = 0.0f;
	}

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/RHIUtilities.cpp:73

Scope: file

Source code excerpt:

}

TAutoConsoleVariable<int32> CVarRHISyncInterval(
	TEXT("rhi.SyncInterval"),
	1,
	TEXT("Determines the frequency of VSyncs in supported RHIs.\n")
	TEXT("This is in multiples of 16.66 on a 60hz display, but some platforms support higher refresh rates.\n")
	TEXT("Assuming 60fps, the values correspond to:\n")
	TEXT("  0 - Unlocked (present immediately)\n")

#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/RHIUtilities.cpp:516

Scope (from outer to inner):

file
function     uint32 RHIGetSyncInterval

Source code excerpt:

uint32 RHIGetSyncInterval()
{
	return FMath::Max(CVarRHISyncInterval.GetValueOnAnyThread(), 0);
}

float RHIGetSyncSlackMS()
{
#if USE_FRAME_OFFSET_THREAD
	const float SyncSlackMS = CVarRHISyncSlackMS.GetValueOnAnyThread();