r.Vulkan.DescriptorSetLayoutMode

r.Vulkan.DescriptorSetLayoutMode

#Overview

name: r.Vulkan.DescriptorSetLayoutMode

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

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

It is referenced in 4 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.Vulkan.DescriptorSetLayoutMode is to control the layout of descriptor sets in the Vulkan rendering backend of Unreal Engine 5. This setting variable is used to optimize the organization of shader resources, particularly uniform buffers, across different shader stages.

This setting variable is primarily used in the Vulkan RHI (Rendering Hardware Interface) subsystem of Unreal Engine 5. It’s specifically referenced in the VulkanShaders.cpp file, which is part of the VulkanRHI module.

The value of this variable is set through a console variable, which means it can be adjusted at runtime or set in configuration files. It’s defined with three possible values: 0: Default mode, where descriptor sets are not changed (e.g., Set 0 for Vertex shader, Set 1 for Pixel shader, etc.) 1: Use a new set for common Uniform Buffers 2: Collapse all sets into Set 0

This variable interacts closely with another variable named GDescriptorSetLayoutMode, which is the actual TAutoConsoleVariable that stores and provides access to the value.

Developers must be aware that changing this variable can significantly impact the organization of shader resources and potentially affect performance. It’s marked as read-only and render thread safe, indicating that it should not be changed frequently during runtime.

Best practices when using this variable include:

  1. Carefully testing performance impacts when changing from the default value.
  2. Considering the implications on shader complexity and resource management when collapsing all sets into Set 0.
  3. Using it in conjunction with profiling tools to optimize descriptor set layouts for specific use cases.

Regarding the associated variable GDescriptorSetLayoutMode:

The purpose of GDescriptorSetLayoutMode is to provide a programmatic interface to access and manipulate the r.Vulkan.DescriptorSetLayoutMode setting. It’s an instance of TAutoConsoleVariable, which is Unreal Engine’s mechanism for creating console variables.

This variable is used directly in the Vulkan shader compilation and resource binding process. It’s referenced in functions like ProcessBindingsForStage and FinalizeBindings, which are responsible for organizing shader resources into descriptor sets.

The value of GDescriptorSetLayoutMode is set at the same time as r.Vulkan.DescriptorSetLayoutMode, through the console variable system.

Developers should be aware that accessing GDescriptorSetLayoutMode.GetValueOnAnyThread() is thread-safe and can be done from any thread, which is useful for querying the current mode during shader compilation and resource setup.

Best practices for using GDescriptorSetLayoutMode include:

  1. Using GetValueOnAnyThread() when accessing the value, to ensure thread safety.
  2. Considering caching the value if it’s accessed frequently in performance-critical code paths.
  3. Being aware that changes to this value may require recompilation of shaders or reorganization of descriptor sets, which could impact performance or cause hitches if done at runtime.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseDeviceProfiles.ini:799, section: [Android DeviceProfile]

#References in C++ code

#Callsites

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

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

Scope: file

Source code excerpt:


static TAutoConsoleVariable<int32> GDescriptorSetLayoutMode(
	TEXT("r.Vulkan.DescriptorSetLayoutMode"),
	0,
	TEXT("0 to not change layouts (eg Set 0 = Vertex, 1 = Pixel, etc\n")\
	TEXT("1 to use a new set for common Uniform Buffers\n")\
	TEXT("2 to collapse all sets into Set 0"),
	ECVF_ReadOnly | ECVF_RenderThreadSafe
);

#Associated Variable and Callsites

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

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

Scope: file

Source code excerpt:



static TAutoConsoleVariable<int32> GDescriptorSetLayoutMode(
	TEXT("r.Vulkan.DescriptorSetLayoutMode"),
	0,
	TEXT("0 to not change layouts (eg Set 0 = Vertex, 1 = Pixel, etc\n")\
	TEXT("1 to use a new set for common Uniform Buffers\n")\
	TEXT("2 to collapse all sets into Set 0"),
	ECVF_ReadOnly | ECVF_RenderThreadSafe

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

Scope (from outer to inner):

file
function     void FVulkanDescriptorSetsLayoutInfo::ProcessBindingsForStage

Source code excerpt:

void FVulkanDescriptorSetsLayoutInfo::ProcessBindingsForStage(VkShaderStageFlagBits StageFlags, ShaderStage::EStage DescSetStage, const FVulkanShaderHeader& CodeHeader, FUniformBufferGatherInfo& OutUBGatherInfo) const
{
	const bool bMoveCommonUBsToExtraSet = GDescriptorSetLayoutMode.GetValueOnAnyThread() == 1 || GDescriptorSetLayoutMode.GetValueOnAnyThread() == 2;

	// Find all common UBs from different stages
	for (const FVulkanShaderHeader::FUniformBufferInfo& UBInfo : CodeHeader.UniformBuffers)
	{
		if (bMoveCommonUBsToExtraSet)
		{

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

Scope (from outer to inner):

file
function     void FVulkanDescriptorSetsLayoutInfo::FinalizeBindings

Source code excerpt:

	const bool bConvertAllUBsToDynamic = !Device.SupportsBindless() && (GDynamicGlobalUBs.GetValueOnAnyThread() > 1);
	const bool bConvertPackedUBsToDynamic = !Device.SupportsBindless() && (bConvertAllUBsToDynamic || (GDynamicGlobalUBs.GetValueOnAnyThread() == 1));
	const bool bConsolidateAllIntoOneSet = GDescriptorSetLayoutMode.GetValueOnAnyThread() == 2;
	const uint32 MaxDescriptorSetUniformBuffersDynamic = Device.GetLimits().maxDescriptorSetUniformBuffersDynamic;

	uint8	DescriptorStageToSetMapping[ShaderStage::NumStages];
	FMemory::Memset(DescriptorStageToSetMapping, UINT8_MAX);

	const bool bMoveCommonUBsToExtraSet = (UBGatherInfo.CommonUBLayoutsToStageMap.Num() > 0) || bConsolidateAllIntoOneSet;