r.ShaderDevelopmentMode

r.ShaderDevelopmentMode

#Overview

name: r.ShaderDevelopmentMode

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

It is referenced in 15 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.ShaderDevelopmentMode is to enable various shader development utilities, such as the ability to retry on failed shader compile and extra logging as shaders are compiled. This setting is primarily used for shader development and debugging purposes.

The Unreal Engine subsystems that rely on this setting variable include:

  1. Shader Compilation System
  2. Rendering Core
  3. D3D11, D3D12, and Vulkan RHI (Rendering Hardware Interface)
  4. Material System

The value of this variable is set through the console variable system, typically initialized to 0 (default mode) and can be changed to 1 to enable shader development utilities.

This variable interacts with several other variables and systems:

  1. It affects the verbosity of LogShaders category.
  2. It influences the engine and app registration process for AMD GPUs.
  3. It impacts shader compilation job settings, such as setting bErrorsAreLikelyToBeCode to true.
  4. It affects the compilation environment for mesh material shaders.

Developers should be aware that:

  1. Enabling this mode may increase shader compilation time and logging overhead.
  2. It can affect performance and should generally be disabled for production builds.
  3. It may expose additional debugging information that could be sensitive in released products.

Best practices when using this variable include:

  1. Use it only during shader development and debugging phases.
  2. Disable it before creating production builds.
  3. Be cautious about using it in conjunction with other performance-sensitive settings.

Regarding the associated variable CVarShaderDevelopmentMode:

This is the actual console variable object that controls the r.ShaderDevelopmentMode setting. It’s used internally by the engine to query and set the shader development mode. The behavior and usage are the same as described for r.ShaderDevelopmentMode, as they represent the same concept within the engine.

Developers should interact with this setting primarily through the r.ShaderDevelopmentMode console command rather than directly manipulating CVarShaderDevelopmentMode in code, unless they’re implementing new engine-level functionality that needs to query this setting.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Private/ShaderCore.cpp:50

Scope: file

Source code excerpt:


static TAutoConsoleVariable<int32> CVarShaderDevelopmentMode(
	TEXT("r.ShaderDevelopmentMode"),
	0,
	TEXT("0: Default, 1: Enable various shader development utilities, such as the ability to retry on failed shader compile, and extra logging as shaders are compiled."),
	ECVF_Default);

static TAutoConsoleVariable<bool> CVarDumpDebugInfoForCacheHits(
	TEXT("r.ShaderCompiler.DumpDebugInfoForCacheHits"),

#Loc: <Workspace>/Engine/Source/Developer/Windows/ShaderFormatD3D/Private/D3DShaderCompiler.cpp:856

Scope (from outer to inner):

file
function     static bool CompileAndProcessD3DShaderFXCExt

Source code excerpt:

				FSCWErrorCode::Reset();

				// Let the user know this shader had to be cross-compiled due to a crash in FXC. Only shows up if CVar 'r.ShaderDevelopmentMode' is enabled.
				Output.Errors.Add(FShaderCompilerError(TEXT("Cross-compiled shader to intermediate HLSL after first attempt crashed FXC")));
			}
		}
	}
	else
	{

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Adapter.cpp:554

Scope (from outer to inner):

file
function     void FD3D12Adapter::CreateRootDevice

Source code excerpt:

	if (IsRHIDeviceAMD() && FD3D12DynamicRHI::GetD3DRHI()->GetAmdAgsContext())
	{
		auto* CVarShaderDevelopmentMode = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ShaderDevelopmentMode"));
		auto* CVarDisableEngineAndAppRegistration = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DisableEngineAndAppRegistration"));

		const bool bDisableEngineRegistration = (CVarShaderDevelopmentMode && CVarShaderDevelopmentMode->GetValueOnAnyThread() != 0) ||
			(CVarDisableEngineAndAppRegistration && CVarDisableEngineAndAppRegistration->GetValueOnAnyThread() != 0);
		const bool bDisableAppRegistration = bDisableEngineRegistration || !FApp::HasProjectName();

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MaterialShader.cpp:1881

Scope (from outer to inner):

file
function     int32 FMaterialShaderMap::SubmitCompileJobs

Source code excerpt:

	// DebugExtension and Description make the jobs unnecessarily different. Use them if the job cache is disabled or shader dev mode is on
	static IConsoleVariable* CVarCacheEnabled = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ShaderCompiler.JobCache"));
	static IConsoleVariable* CVarShaderDevMode = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ShaderDevelopmentMode"));
	if ((CVarCacheEnabled && CVarCacheEnabled->GetInt() == 0) || (CVarShaderDevMode && CVarShaderDevMode->GetInt() != 0))
	{
		DebugExtensionStr = FString::Printf(TEXT("_%08x%08x"), ShaderMapId.BaseMaterialId.A, ShaderMapId.BaseMaterialId.B);
		DebugDescriptionStr = GetDebugDescription();
	}
	const TCHAR* DebugExtension = *DebugExtensionStr;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MeshMaterialShader.cpp:30

Scope (from outer to inner):

file
function     static void PrepareMeshMaterialShaderCompileJob

Source code excerpt:

	NewJob->bIsGlobalShader = false;

	static IConsoleVariable* CVarShaderDevMode = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ShaderDevelopmentMode"));
	if (CVarShaderDevMode && CVarShaderDevMode->GetInt() != 0)
	{
		NewJob->bErrorsAreLikelyToBeCode = true;
	}

	const FMaterialShaderParameters MaterialParameters(Material);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ShaderCompiler/ShaderCompiler.cpp:1984

Scope (from outer to inner):

file
function     int32 FShaderJobCache::GetPendingJobs

Source code excerpt:


		GShaderCompilerStats->RegisterAssignedJob(Job);
		// Temporary commented out until r.ShaderDevelopmentMode=1 shader error retry crash gets fixed
		//check(Job.CurrentWorker == EShaderCompilerWorkerType::None);
		//check(Job.PendingPriority == InPriority);
		ensure(!ShaderCompiler::IsJobCacheEnabled() || Job.bInputHashSet);

		It.Next();

#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Private/ShaderCore.cpp:63

Scope (from outer to inner):

file
function     void UpdateShaderDevelopmentMode

Source code excerpt:

void UpdateShaderDevelopmentMode()
{
	// Keep LogShaders verbosity in sync with r.ShaderDevelopmentMode
	// r.ShaderDevelopmentMode==1 results in all LogShaders log messages being displayed.
	// if r.ShaderDevelopmentMode isn't set, we leave the category alone (it defaults to Error, but we can be overriding it to something higher)
	bool bLogShadersUnsuppressed = UE_LOG_ACTIVE(LogShaders, Log);
	bool bDesiredLogShadersUnsuppressed = CVarShaderDevelopmentMode.GetValueOnGameThread() == 1;

	if (bLogShadersUnsuppressed != bDesiredLogShadersUnsuppressed)
	{
		if (bDesiredLogShadersUnsuppressed)

#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Public/ShaderCore.h:59

Scope: file

Source code excerpt:

/**
 * Controls whether shader related logs are visible.
 * Note: The runtime verbosity is driven by the console variable 'r.ShaderDevelopmentMode'
 */
#if UE_BUILD_DEBUG && (PLATFORM_UNIX)
RENDERCORE_API DECLARE_LOG_CATEGORY_EXTERN(LogShaders, Log, All);
#else
RENDERCORE_API DECLARE_LOG_CATEGORY_EXTERN(LogShaders, Error, All);
#endif

DECLARE_DWORD_ACCUMULATOR_STAT_EXTERN(TEXT("Num Total Niagara Shaders"), STAT_ShaderCompiling_NumTotalNiagaraShaders, STATGROUP_ShaderCompiling, RENDERCORE_API);
DECLARE_FLOAT_ACCUMULATOR_STAT_EXTERN(TEXT("Total Niagara Shader Compiling Time"), STAT_ShaderCompiling_NiagaraShaders, STATGROUP_ShaderCompiling, RENDERCORE_API);

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

Scope (from outer to inner):

file
function     void FVulkanDynamicRHI::CreateInstance

Source code excerpt:

{
	// Engine registration can be disabled via console var. Also disable automatically if ShaderDevelopmentMode is on.
	auto* CVarShaderDevelopmentMode = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ShaderDevelopmentMode"));
	auto* CVarDisableEngineAndAppRegistration = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DisableEngineAndAppRegistration"));
	bool bDisableEngineRegistration = (CVarDisableEngineAndAppRegistration && CVarDisableEngineAndAppRegistration->GetValueOnAnyThread() != 0) ||
		(CVarShaderDevelopmentMode && CVarShaderDevelopmentMode->GetValueOnAnyThread() != 0);

	// Use the API version stored in the profile
	ApiVersion = GetVulkanApiVersionForFeatureLevel(GMaxRHIFeatureLevel, false);

#Loc: <Workspace>/Engine/Source/Runtime/Windows/D3D11RHI/Private/Windows/WindowsD3D11Device.cpp:1822

Scope (from outer to inner):

file
function     void FD3D11DynamicRHI::InitD3DDevice

Source code excerpt:


			// Engine registration can be disabled via console var. Also disable automatically if ShaderDevelopmentMode is on.
			auto* CVarShaderDevelopmentMode = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ShaderDevelopmentMode"));
			auto* CVarDisableEngineAndAppRegistration = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DisableEngineAndAppRegistration"));
			const bool bDisableEngineRegistration = (CVarShaderDevelopmentMode && CVarShaderDevelopmentMode->GetValueOnAnyThread() != 0) || 
				(CVarDisableEngineAndAppRegistration && CVarDisableEngineAndAppRegistration->GetValueOnAnyThread() != 0);
			const bool bDisableAppRegistration = bDisableEngineRegistration || !FApp::HasProjectName();

			AGSDX11ExtensionParams AmdExtensionParams;

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Adapter.cpp:554

Scope (from outer to inner):

file
function     void FD3D12Adapter::CreateRootDevice

Source code excerpt:

	if (IsRHIDeviceAMD() && FD3D12DynamicRHI::GetD3DRHI()->GetAmdAgsContext())
	{
		auto* CVarShaderDevelopmentMode = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ShaderDevelopmentMode"));
		auto* CVarDisableEngineAndAppRegistration = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DisableEngineAndAppRegistration"));

		const bool bDisableEngineRegistration = (CVarShaderDevelopmentMode && CVarShaderDevelopmentMode->GetValueOnAnyThread() != 0) ||
			(CVarDisableEngineAndAppRegistration && CVarDisableEngineAndAppRegistration->GetValueOnAnyThread() != 0);
		const bool bDisableAppRegistration = bDisableEngineRegistration || !FApp::HasProjectName();

		// Creating the Direct3D device with AGS registration and extensions.
		AGSDX12DeviceCreationParams AmdDeviceCreationParams = {
			GetAdapter(),											// IDXGIAdapter*               pAdapter;

#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Private/ShaderCore.cpp:49

Scope: file

Source code excerpt:

#endif

static TAutoConsoleVariable<int32> CVarShaderDevelopmentMode(
	TEXT("r.ShaderDevelopmentMode"),
	0,
	TEXT("0: Default, 1: Enable various shader development utilities, such as the ability to retry on failed shader compile, and extra logging as shaders are compiled."),
	ECVF_Default);

static TAutoConsoleVariable<bool> CVarDumpDebugInfoForCacheHits(

#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Private/ShaderCore.cpp:67

Scope (from outer to inner):

file
function     void UpdateShaderDevelopmentMode

Source code excerpt:

	// if r.ShaderDevelopmentMode isn't set, we leave the category alone (it defaults to Error, but we can be overriding it to something higher)
	bool bLogShadersUnsuppressed = UE_LOG_ACTIVE(LogShaders, Log);
	bool bDesiredLogShadersUnsuppressed = CVarShaderDevelopmentMode.GetValueOnGameThread() == 1;

	if (bLogShadersUnsuppressed != bDesiredLogShadersUnsuppressed)
	{
		if (bDesiredLogShadersUnsuppressed)
		{
			UE_SET_LOG_VERBOSITY(LogShaders, Log);

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

Scope (from outer to inner):

file
function     void FVulkanDynamicRHI::CreateInstance

Source code excerpt:

{
	// Engine registration can be disabled via console var. Also disable automatically if ShaderDevelopmentMode is on.
	auto* CVarShaderDevelopmentMode = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ShaderDevelopmentMode"));
	auto* CVarDisableEngineAndAppRegistration = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DisableEngineAndAppRegistration"));
	bool bDisableEngineRegistration = (CVarDisableEngineAndAppRegistration && CVarDisableEngineAndAppRegistration->GetValueOnAnyThread() != 0) ||
		(CVarShaderDevelopmentMode && CVarShaderDevelopmentMode->GetValueOnAnyThread() != 0);

	// Use the API version stored in the profile
	ApiVersion = GetVulkanApiVersionForFeatureLevel(GMaxRHIFeatureLevel, false);

#if VULKAN_RHI_RAYTRACING
	// Run a profile check to see if this device can support our raytacing requirements since it might change the required API version of the instance

#Loc: <Workspace>/Engine/Source/Runtime/Windows/D3D11RHI/Private/Windows/WindowsD3D11Device.cpp:1822

Scope (from outer to inner):

file
function     void FD3D11DynamicRHI::InitD3DDevice

Source code excerpt:


			// Engine registration can be disabled via console var. Also disable automatically if ShaderDevelopmentMode is on.
			auto* CVarShaderDevelopmentMode = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ShaderDevelopmentMode"));
			auto* CVarDisableEngineAndAppRegistration = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DisableEngineAndAppRegistration"));
			const bool bDisableEngineRegistration = (CVarShaderDevelopmentMode && CVarShaderDevelopmentMode->GetValueOnAnyThread() != 0) || 
				(CVarDisableEngineAndAppRegistration && CVarDisableEngineAndAppRegistration->GetValueOnAnyThread() != 0);
			const bool bDisableAppRegistration = bDisableEngineRegistration || !FApp::HasProjectName();

			AGSDX11ExtensionParams AmdExtensionParams;
			FMemory::Memzero(&AmdExtensionParams, sizeof(AmdExtensionParams));
			// Set the reserved UAV slot - matching the other vendor extensions.