r.Vulkan.EnableValidation

r.Vulkan.EnableValidation

#Overview

name: r.Vulkan.EnableValidation

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

It is referenced in 11 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.Vulkan.EnableValidation is to control the level of Vulkan validation layers enabled during runtime. It is primarily used for debugging and performance optimization in the Vulkan rendering system.

This setting variable is primarily used by the Vulkan RHI (Runtime Hardware Interface) subsystem of Unreal Engine. It’s particularly important for the debugging and validation components of the Vulkan implementation.

The value of this variable is set through a console variable (CVar) named GValidationCvar. It can be set programmatically, through the console, or via command-line arguments.

The variable interacts closely with several other debugging and validation-related variables, particularly GGPUValidationCvar for GPU validation.

Developers should be aware that:

  1. Higher validation levels can significantly impact performance and should generally be used only during development.
  2. The variable uses different integer values to enable different levels of validation, from 0 (disabled) to 5 (all messages).
  3. It affects the creation and behavior of the Vulkan debug messenger.

Best practices for using this variable include:

  1. Use it in development builds, but disable or minimize its use in release builds.
  2. Start with lower levels (1 or 2) and increase as needed for more detailed debugging.
  3. Be prepared to handle the performance impact when enabling higher levels of validation.

Regarding the associated variable GValidationCvar: The purpose of GValidationCvar is to provide a programmatic interface to control the r.Vulkan.EnableValidation setting. It’s used throughout the Vulkan RHI implementation to check the current validation level and adjust behavior accordingly.

GValidationCvar is used in various parts of the Vulkan RHI, including debug layer setup, instance creation, and error handling. It’s particularly important in the setup of the debug messenger and in determining which validation features to enable.

The value of GValidationCvar is typically set based on the r.Vulkan.EnableValidation CVar, but it can also be influenced by command-line arguments.

Developers should be aware that changes to GValidationCvar can have wide-ranging effects on the Vulkan RHI’s behavior, particularly in terms of error reporting and performance.

Best practices for GValidationCvar include using it consistently throughout the codebase when checking validation levels, and ensuring it’s properly synchronized across different threads when necessary.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanLayers.cpp:20

Scope: file

Source code excerpt:

#if VULKAN_HAS_DEBUGGING_ENABLED
TAutoConsoleVariable<int32> GValidationCvar(
	TEXT("r.Vulkan.EnableValidation"),
	VULKAN_VALIDATION_DEFAULT_VALUE,
	TEXT("0 to disable validation layers\n")
	TEXT("1 to enable errors\n")
	TEXT("2 to enable errors & warnings\n")
	TEXT("3 to enable errors, warnings & performance warnings\n")
	TEXT("4 to enable errors, warnings, performance & information messages\n")

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Public/VulkanConfiguration.h:27

Scope: file

Source code excerpt:

#endif

// default value of r.Vulkan.EnableValidation
// 0 - disable validation layers
// 1 - enable errors
// 2 - enable errors & warnings
// 3 - enable errors, warnings & performance warnings
// 4 - enable errors, warnings, performance & information messages
// 5 - enable all messages

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanDebug.cpp:31

Scope: file

Source code excerpt:

#endif // PLATFORM_ANDROID

extern TAutoConsoleVariable<int32> GValidationCvar;

static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT MsgSeverity, 
	VkDebugUtilsMessageTypeFlagsEXT MsgType, const VkDebugUtilsMessengerCallbackDataEXT* CallbackData, void* UserData)
{
	const bool bError = (MsgSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0;
	const bool bWarning = (MsgSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0;

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanDebug.cpp:186

Scope (from outer to inner):

file
function     void FVulkanDynamicRHI::SetupDebugLayerCallback

Source code excerpt:

			ZeroVulkanStruct(CreateInfo, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);

			const int32 CVar = GValidationCvar.GetValueOnRenderThread();
			CreateInfo.messageSeverity = (CVar >= 1 ? VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT : 0) |
				(CVar >= 2 ? VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT : 0) | (CVar >= 3 ? VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT : 0);
			CreateInfo.messageType = (CVar >= 1 ? (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) : 0) |
				(CVar >= 3 ? VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT : 0);
			CreateInfo.pfnUserCallback = DebugUtilsCallback;
			VkResult Result = (*CreateDebugUtilsMessengerEXT)(Instance, &CreateInfo, nullptr, &Messenger);

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanExtensions.cpp:1472

Scope (from outer to inner):

file
class        class FVulkanEXTValidationFeaturesExtension : public FVulkanInstanceExtension
function     virtual void PreCreateInstance

Source code excerpt:

	{
#if VULKAN_HAS_DEBUGGING_ENABLED
		check(GValidationCvar.GetValueOnAnyThread() > 0);

		auto GetValidationFeaturesEnabled = []()
		{
			TArray<VkValidationFeatureEnableEXT> Features;
			const int32 GPUValidationValue = GGPUValidationCvar.GetValueOnAnyThread();
			if (GPUValidationValue > 0)

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanLayers.cpp:19

Scope: file

Source code excerpt:


#if VULKAN_HAS_DEBUGGING_ENABLED
TAutoConsoleVariable<int32> GValidationCvar(
	TEXT("r.Vulkan.EnableValidation"),
	VULKAN_VALIDATION_DEFAULT_VALUE,
	TEXT("0 to disable validation layers\n")
	TEXT("1 to enable errors\n")
	TEXT("2 to enable errors & warnings\n")
	TEXT("3 to enable errors, warnings & performance warnings\n")

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanLayers.cpp:309

Scope (from outer to inner):

file
function     void FVulkanDynamicRHI::SetupValidationRequests

Source code excerpt:

{
#if VULKAN_HAS_DEBUGGING_ENABLED
	int32 VulkanValidationOption = GValidationCvar.GetValueOnAnyThread();

	// Command line overrides Cvar
	if (FParse::Param(FCommandLine::Get(), TEXT("vulkandebug")))
	{
		// Match D3D and GL
		GValidationCvar->Set(2, ECVF_SetByCommandline);
	}
	else if (FParse::Value(FCommandLine::Get(), TEXT("vulkanvalidation="), VulkanValidationOption))
	{
		GValidationCvar->Set(VulkanValidationOption, ECVF_SetByCommandline);
	}

	if (FParse::Param(FCommandLine::Get(), TEXT("gpuvalidation")))
	{
		if (GValidationCvar->GetInt() < 2)
		{
			GValidationCvar->Set(2, ECVF_SetByCommandline);
		}
		GGPUValidationCvar->Set(2, ECVF_SetByCommandline);
	}
	GRHIGlobals.IsDebugLayerEnabled = (GValidationCvar.GetValueOnAnyThread() > 0);
#endif
}


// Get a list of debugging layers to activate
void FVulkanIntanceSetupHelper::AddDebugLayers(const TArray<FLayerWithExtensions>& LayerProperties, FVulkanInstanceExtensionArray& UEExtensions, TArray<const ANSICHAR*>& OutLayers)

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanRHI.cpp:1067

Scope (from outer to inner):

file
function     void FVulkanDynamicRHI::InitInstance

Source code excerpt:

#if VULKAN_SUPPORTS_VALIDATION_CACHE
#if VULKAN_HAS_DEBUGGING_ENABLED
		if (GValidationCvar.GetValueOnAnyThread() > 0)
		{
			SaveValidationCacheCmd = IConsoleManager::Get().RegisterConsoleCommand(
				TEXT("r.Vulkan.SaveValidationCache"),
				TEXT("Save validation cache."),
				FConsoleCommandDelegate::CreateStatic(SaveValidationCache),
				ECVF_Default

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanRHIPrivate.h:600

Scope: file

Source code excerpt:


#if VULKAN_HAS_DEBUGGING_ENABLED
extern TAutoConsoleVariable<int32> GValidationCvar;
#endif

static inline VkAttachmentLoadOp RenderTargetLoadActionToVulkan(ERenderTargetLoadAction InLoadAction)
{
	VkAttachmentLoadOp OutLoadAction = VK_ATTACHMENT_LOAD_OP_MAX_ENUM;

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanSwapChain.cpp:713

Scope (from outer to inner):

file
function     int32 FVulkanSwapChain::AcquireImageIndex

Source code excerpt:

	if (Result == VK_ERROR_VALIDATION_FAILED_EXT)
	{
		extern TAutoConsoleVariable<int32> GValidationCvar;
		if (GValidationCvar.GetValueOnRenderThread() == 0)
		{
			UE_LOG(LogVulkanRHI, Fatal, TEXT("vkAcquireNextImageKHR failed with Validation error. Try running with r.Vulkan.EnableValidation=1 to get information from the driver"));
		}
	}
	else
#endif

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanUtil.cpp:1078

Scope (from outer to inner):

file
namespace    VulkanRHI
function     void VerifyVulkanResult

Source code excerpt:

		if (Result == VK_ERROR_VALIDATION_FAILED_EXT)
		{
			if (GValidationCvar.GetValueOnRenderThread() == 0)
			{
				UE_LOG(LogVulkanRHI, Fatal, TEXT("Failed with Validation error. Try running with r.Vulkan.EnableValidation=1 or -vulkandebug to get information from the validation layers."));
			}
		}
#endif