r.VSync
r.VSync
#Overview
name: r.VSync
The value of this variable can be defined or overridden in .ini config files. 3
.ini config files referencing this setting variable.
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
0: VSync is disabled.(default)\n1: VSync is enabled.
It is referenced in 19
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of r.VSync is to control vertical synchronization (VSync) in the rendering system of Unreal Engine 5. It is a console variable that can be set to enable or disable VSync, which synchronizes the frame rate of the game with the refresh rate of the display to prevent screen tearing.
This setting variable is primarily used by the rendering subsystem of Unreal Engine, but it also interacts with various other modules and plugins, including:
- Core Engine
- RenderGrid plugin
- AjaMedia plugin
- BlackmagicMedia plugin
- Dynamic Resolution system
- Game User Settings
- GPU Profiler
- Rendering Thread management
- Slate RHI Renderer
The value of this variable is typically set through the console or configuration files. It can also be modified programmatically using the console variable system.
Other variables that interact with r.VSync include:
- r.VSyncEditor (for editor-specific VSync settings)
- r.GTSyncType (for game thread synchronization)
- r.DynamicRes.FrameTimeBudget (for dynamic resolution calculations)
Developers should be aware of the following when using this variable:
- Enabling VSync (setting to 1) can impact performance and increase input lag.
- VSync may interfere with certain time-sensitive operations, such as genlock in media capture scenarios.
- It can affect GPU profiling results, potentially skewing timing data.
- It interacts with dynamic resolution and frame rate limiting features.
Best practices when using this variable include:
- Consider disabling VSync during performance profiling to get more accurate results.
- Be cautious when using VSync in conjunction with custom time steps or media capture features.
- Remember to account for VSync when implementing frame rate management or dynamic resolution systems.
- When developing multi-display or specialized rendering setups, carefully consider the implications of VSync on synchronization across displays.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEngine.ini:2214, section: [SystemSettingsEditor]
- INI Section:
SystemSettingsEditor
- Raw value:
0
- Is Array:
False
Location: <Workspace>/Engine/Config/Android/AndroidEngine.ini:74, section: [ConsoleVariables]
- INI Section:
ConsoleVariables
- Raw value:
1
- Is Array:
False
Location: <Workspace>/Projects/Lyra/Config/DefaultDeviceProfiles.ini:57, section: [Mobile DeviceProfile]
- INI Section:
Mobile DeviceProfile
- Raw value:
1
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/HAL/ConsoleManager.cpp:3834
Scope: file
Source code excerpt:
static TAutoConsoleVariable<int32> CVarSetVSyncEnabled(
TEXT("r.VSync"),
0,
TEXT("0: VSync is disabled.(default)\n"
"1: VSync is enabled."),
ECVF_Scalability | ECVF_RenderThreadSafe);
#if WITH_EDITOR
#Loc: <Workspace>/Engine/Plugins/Experimental/RenderGrid/Source/RenderGrid/Private/Utils/RenderGridUtils.cpp:428
Scope (from outer to inner):
file
function FRenderGridPreviousEngineFpsSettings UE::RenderGrid::Private::FRenderGridUtils::DisableFpsLimit
Source code excerpt:
if (GEngine)
{
static IConsoleVariable* VSync = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
static IConsoleVariable* VSyncEditor = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSyncEditor"));
UEditorPerformanceSettings* EditorPerformanceSettings = GetMutableDefault<UEditorPerformanceSettings>();
Settings.bHasBeenSet = true;
Settings.bUseFixedFrameRate = GEngine->bUseFixedFrameRate;
Settings.bForceDisableFrameRateSmoothing = GEngine->bForceDisableFrameRateSmoothing;
#Loc: <Workspace>/Engine/Plugins/Experimental/RenderGrid/Source/RenderGrid/Private/Utils/RenderGridUtils.cpp:455
Scope (from outer to inner):
file
function void UE::RenderGrid::Private::FRenderGridUtils::RestoreFpsLimit
Source code excerpt:
if (GEngine && Settings.bHasBeenSet)
{
static IConsoleVariable* VSync = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
static IConsoleVariable* VSyncEditor = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSyncEditor"));
UEditorPerformanceSettings* EditorPerformanceSettings = GetMutableDefault<UEditorPerformanceSettings>();
GEngine->bUseFixedFrameRate = Settings.bUseFixedFrameRate;
GEngine->bForceDisableFrameRateSmoothing = Settings.bForceDisableFrameRateSmoothing;
GEngine->SetMaxFPS(Settings.MaxFps);
#Loc: <Workspace>/Engine/Plugins/Experimental/RenderGrid/Source/RenderGrid/Public/Utils/RenderGridUtils.h:37
Scope (from outer to inner):
file
function struct RENDERGRID_API FRenderGridPreviousEngineFpsSettings { GENERATED_BODY
Source code excerpt:
float MaxFps = 0;
/** The previous value of console variable "r.VSync". */
UPROPERTY()
bool bVSync = false;
/** The previous value of console variable "r.VSyncEditor". */
UPROPERTY()
bool bVSyncEditor = false;
#Loc: <Workspace>/Engine/Plugins/Media/AjaMedia/Source/AjaMedia/Private/Assets/AjaCustomTimeStep.cpp:313
Scope (from outer to inner):
file
function bool UAjaCustomTimeStep::UpdateTimeStep
Source code excerpt:
// Warn about Vsync once
{
static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
if (!bWarnedAboutVSync)
{
bool bLockToVsync = CVar->GetValueOnGameThread() != 0;
if (bLockToVsync)
{
UE_LOG(LogAjaMedia, Warning, TEXT("The Engine is using VSync and may break the 'genlock'"));
#Loc: <Workspace>/Engine/Plugins/Media/AjaMedia/Source/AjaMediaOutput/Private/AjaMediaCapture.cpp:550
Scope (from outer to inner):
file
function bool UAjaMediaCapture::InitAJA
Source code excerpt:
if (bWaitForSyncEvent)
{
const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
bool bLockToVsync = CVar->GetValueOnGameThread() != 0;
if (bLockToVsync)
{
UE_LOG(LogAjaMediaOutput, Warning, TEXT("The Engine use VSync and something wants to wait for the sync event. This may break the \"gen-lock\"."));
}
#Loc: <Workspace>/Engine/Plugins/Media/BlackmagicMedia/Source/BlackmagicMedia/Private/Assets/BlackmagicCustomTimeStep.cpp:320
Scope (from outer to inner):
file
function bool UBlackmagicCustomTimeStep::UpdateTimeStep
Source code excerpt:
if (CurrentState == ECustomTimeStepSynchronizationState::Synchronized)
{
static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
if (!bWarnedAboutVSync)
{
bool bLockToVsync = CVar->GetValueOnGameThread() != 0;
if (bLockToVsync)
{
UE_LOG(LogBlackmagicMedia, Warning, TEXT("The Engine is using VSync and may break the 'genlock'"));
#Loc: <Workspace>/Engine/Plugins/Media/BlackmagicMedia/Source/BlackmagicMediaOutput/Private/BlackmagicMediaCapture.cpp:712
Scope (from outer to inner):
file
function bool UBlackmagicMediaCapture::InitBlackmagic
Source code excerpt:
if (bSuccess && bWaitForSyncEvent)
{
const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
bool bLockToVsync = CVar->GetValueOnGameThread() != 0;
if (bLockToVsync)
{
UE_LOG(LogBlackmagicMediaOutput, Warning, TEXT("The Engine use VSync and something to wait for the sync event. This may break the \"gen-lock\"."));
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DynamicResolution.cpp:77
Scope: file
Source code excerpt:
ECVF_RenderThreadSafe | ECVF_Default);
/** On desktop, the swap chain doesn't allow tear amount configuration, so an overbudget frame can be droped with r.VSync=1.
* So need to lower the heuristic's target budget to lower chances to go overbudget.
*
* Moreover the GPU is a shared ressource with other process which may or may not be included in our GPU timings,
* and need to leave some GPU capacity to these application to not get preempted by OS scheduler.
* Given we can measure other application's GPU cost, need to leave enough headroom for them all the time.
*/
static TAutoConsoleVariable<float> CVarOverBudgetGPUHeadRoomPercentage(
TEXT("r.DynamicRes.OverBudgetGPUHeadRoomPercentage"),
0.0f,
TEXT("Amount of GPU headroom needed from which the frame is considered over budget. This is for platform not supporting controllable tearing with VSync (in percent from r.DynamicRes.FrameTimeBudget)."),
ECVF_RenderThreadSafe | ECVF_Default);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/DynamicResolution.cpp:283
Scope (from outer to inner):
file
function void FDynamicResolutionHeuristicProxy::RefreshCurrentFrameResolutionFraction_RenderThread
Source code excerpt:
if (CVarDynamicFrameTimeEnable.GetValueOnRenderThread())
{
static const IConsoleVariable* VSyncCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
check(VSyncCVar);
const int32 FrameTimeTrack = CVarDynamicFrameTimeTrack.GetValueOnRenderThread();
// Find out the frame time that should be used.
TArray<float, TInlineAllocator<16>> SortedFrameTime;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameUserSettings.cpp:181
Scope (from outer to inner):
file
function bool UGameUserSettings::IsVSyncDirty
Source code excerpt:
if (GEngine && GEngine->GameViewport && GEngine->GameViewport->ViewportFrame)
{
static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
bIsDirty = (bUseVSync != (CVar->GetValueOnAnyThread() != 0));
}
return bIsDirty;
}
bool UGameUserSettings::IsDynamicResolutionDirty() const
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameUserSettings.cpp:376
Scope (from outer to inner):
file
function void UGameUserSettings::ValidateSettings
Source code excerpt:
// Force reset if there aren't any default .ini settings.
SetToDefaults();
static const auto CVarVSync = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
SetVSyncEnabled(CVarVSync->GetValueOnGameThread() != 0);
if (GEngine)
{
SetDynamicResolutionEnabled(GEngine->GetDynamicResolutionUserSetting());
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameUserSettings.cpp:445
Scope (from outer to inner):
file
function void UGameUserSettings::ApplyNonResolutionSettings
Source code excerpt:
else
{
static auto CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
CVar->Set(IsVSyncEnabled(), ECVF_SetByGameSetting);
}
}
GEngine->SetDynamicResolutionUserSetting(IsDynamicResolutionEnabled());
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameUserSettings.cpp:743
Scope (from outer to inner):
file
function void UGameUserSettings::ResetToCurrentSettings
Source code excerpt:
// Set the current VSync state
static const auto CVarVSync = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
SetVSyncEnabled(CVarVSync->GetValueOnGameThread() != 0);
// Set the current dynamic resolution state
SetDynamicResolutionEnabled(GEngine->GetDynamicResolutionUserSetting());
// Reset confirmed settings
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UnrealClient.cpp:1709
Scope (from outer to inner):
file
function void FViewport::Draw
Source code excerpt:
if( SizeX > 0 && SizeY > 0 )
{
static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VSync"));
bool bLockToVsync = CVar->GetValueOnGameThread() != 0;
ULocalPlayer* Player = (GEngine && World) ? GEngine->GetFirstGamePlayer(World) : NULL;
if ( Player )
{
bLockToVsync |= (Player && Player->PlayerController && Player->PlayerController->bCinematicMode);
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/UnrealEngine.cpp:680
Scope (from outer to inner):
file
function void CalculateFPSTimings
Source code excerpt:
static auto CVarGTSyncType = IConsoleManager::Get().FindConsoleVariable(TEXT("r.GTSyncType"));
static auto CVarVsync = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
if (CVarGTSyncType->GetInt() == 2 && CVarVsync->GetInt() != 0)
{
float RHIFrameTime = RHIGetFrameTime();
if (RHIFrameTime != 0)
{
FrameTimeMS = RHIFrameTime;
#Loc: <Workspace>/Engine/Source/Runtime/RHI/Private/GPUProfiler.cpp:479
Scope (from outer to inner):
file
function void FGPUProfilerEventNodeFrame::DumpEventTree
Source code excerpt:
// Display a warning if this is a GPU profile and the GPU was profiled with v-sync enabled
FText VsyncEnabledWarningText = FText::GetEmpty();
static IConsoleVariable* CVSyncVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
if (CVSyncVar->GetInt() != 0 && !PlatformDisablesVSync())
{
VsyncEnabledWarningText = LOCTEXT("GpuProfileVsyncEnabledWarning", "WARNING: This GPU profile was captured with v-sync enabled. V-sync wait time may show up in any bucket, and as a result the data in this profile may be skewed. Please profile with v-sync disabled to obtain the most accurate data.");
UE_LOG(LogRHI, Log, TEXT("%s"), *(VsyncEnabledWarningText.ToString()));
}
#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Private/RenderingThread.cpp:1215
Scope (from outer to inner):
file
function void FRenderCommandFence::BeginFence
Source code excerpt:
// Don't sync to the RHI and GPU if GtSyncType is disabled, or we're not vsyncing
//@TODO: do this logic in the caller?
static auto CVarVsync = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
check(CVarVsync != nullptr);
if (GTSyncType == 0 || CVarVsync->GetInt() == 0)
{
bSyncToRHIAndGPU = false;
}
#Loc: <Workspace>/Engine/Source/Runtime/SlateRHIRenderer/Private/SlateRHIRenderer.cpp:1748
Scope (from outer to inner):
file
function void FSlateRHIRenderer::DrawWindows_Private
Source code excerpt:
else
{
static IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync"));
bForceVsyncFromCVar = (CVar->GetInt() != 0);
}
bLockToVsync |= bForceVsyncFromCVar;
// Cache if the element batcher post buffer usage, will get reset on batch reset