BindlessResources
BindlessResources
#Overview
name: BindlessResources
The value of this variable can be defined or overridden in .ini config files. 4
.ini config files referencing this setting variable.
It is referenced in 15
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of BindlessResources is to enable bindless resource access in shaders, which allows for more flexible and efficient use of GPU resources. This feature is part of Unreal Engine’s rendering system and is particularly important for modern GPU architectures that support bindless rendering.
Unreal Engine subsystems that rely on this setting variable include:
- Shader Compiler
- D3D12 Renderer
- Ray Tracing System
The value of this variable is typically set through compiler flags and configuration settings. In the D3D12 renderer, it’s controlled by the BindlessResourcesConfig variable.
Other variables that interact with BindlessResources include:
- BindlessSamplers
- ResourceCounts.UsageFlags
- EShaderCodeFeatures
- ED3D12RootSignatureFlags
Developers must be aware of the following when using this variable:
- Mixing bindless and non-bindless resources in the same shader is not allowed and will result in compilation errors.
- It affects root signature creation and resource binding in D3D12.
- It’s only supported on platforms that support bindless rendering (PLATFORM_SUPPORTS_BINDLESS_RENDERING).
- It may have different behavior for different shader frequencies (e.g., graphics vs. ray tracing shaders).
Best practices when using this variable include:
- Ensure that the target platform supports bindless rendering before enabling it.
- Use it consistently across related shaders and resources to avoid mixing bindless and non-bindless access.
- Be aware of the performance implications and potential increased shader complexity when using bindless resources.
- Consider the impact on root signature design and descriptor heap management when enabling bindless resources.
- Test thoroughly on all target platforms to ensure compatibility and performance.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:14, section: [PCD3D_SM5]
- INI Section:
PCD3D_SM5
- Raw value:
Disabled
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:18, section: [PCD3D_SM6]
- INI Section:
PCD3D_SM6
- Raw value:
Disabled
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:22, section: [SF_VULKAN_SM5]
- INI Section:
SF_VULKAN_SM5
- Raw value:
Disabled
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:26, section: [SF_VULKAN_SM6]
- INI Section:
SF_VULKAN_SM6
- Raw value:
Disabled
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Developer/ShaderCompilerCommon/Private/ShaderCompilerCommon.cpp:405
Scope (from outer to inner):
file
function bool UE::ShaderCompilerCommon::ValidatePackedResourceCounts
Source code excerpt:
};
if (EnumHasAnyFlags(PackedResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessResources) && PackedResourceCounts.NumSRVs > 0)
{
const FString Names = GetAllResourcesOfType(EShaderParameterType::SRV);
Output.Errors.Add(FString::Printf(TEXT("Shader is mixing bindless resources with non-bindless resources. %d SRV slots were detected: %s"), PackedResourceCounts.NumSRVs, *Names));
Output.bSucceeded = false;
}
if (EnumHasAnyFlags(PackedResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessResources) && PackedResourceCounts.NumUAVs > 0)
{
const FString Names = GetAllResourcesOfType(EShaderParameterType::UAV);
Output.Errors.Add(FString::Printf(TEXT("Shader is mixing bindless resources with non-bindless resources. %d UAV slots were detected: %s"), PackedResourceCounts.NumUAVs, *Names));
Output.bSucceeded = false;
}
#Loc: <Workspace>/Engine/Source/Developer/Windows/ShaderFormatD3D/Private/D3DShaderCompilerDXC.cpp:1150
Scope (from outer to inner):
file
function bool CompileAndProcessD3DShaderDXC
Source code excerpt:
if (Input.Environment.CompilerFlags.Contains(CFLAG_BindlessResources))
{
PackedResourceCounts.UsageFlags |= EShaderResourceUsageFlags::BindlessResources;
}
if (Input.Environment.CompilerFlags.Contains(CFLAG_BindlessSamplers))
{
PackedResourceCounts.UsageFlags |= EShaderResourceUsageFlags::BindlessSamplers;
}
#Loc: <Workspace>/Engine/Source/Developer/Windows/ShaderFormatD3D/Private/D3DShaderCompilerDXC.cpp:1231
Scope (from outer to inner):
file
function bool CompileAndProcessD3DShaderDXC
lambda-function
Source code excerpt:
if ((ShaderRequiresFlags & D3D_SHADER_REQUIRES_RESOURCE_DESCRIPTOR_HEAP_INDEXING) != 0)
{
EnumAddFlags(CodeFeatures.CodeFeatures, EShaderCodeFeatures::BindlessResources);
}
if ((ShaderRequiresFlags & D3D_SHADER_REQUIRES_SAMPLER_DESCRIPTOR_HEAP_INDEXING) != 0)
{
EnumAddFlags(CodeFeatures.CodeFeatures, EShaderCodeFeatures::BindlessSamplers);
}
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Adapter.cpp:1332
Scope (from outer to inner):
file
function void FD3D12Adapter::InitializeDevices
Source code excerpt:
if (BindlessResourcesConfig == ERHIBindlessConfiguration::AllShaders)
{
EnumAddFlags(GraphicsFlags, ED3D12RootSignatureFlags::BindlessResources);
}
if (BindlessSamplersConfig == ERHIBindlessConfiguration::AllShaders)
{
EnumAddFlags(GraphicsFlags, ED3D12RootSignatureFlags::BindlessSamplers);
}
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Adapter.cpp:1348
Scope (from outer to inner):
file
function void FD3D12Adapter::InitializeDevices
Source code excerpt:
if (BindlessResourcesConfig != ERHIBindlessConfiguration::Disabled)
{
EnumAddFlags(RayTracingFlags, ED3D12RootSignatureFlags::BindlessResources);
}
if (BindlessSamplersConfig != ERHIBindlessConfiguration::Disabled)
{
EnumAddFlags(RayTracingFlags, ED3D12RootSignatureFlags::BindlessSamplers);
}
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Commands.cpp:932
Scope (from outer to inner):
file
function FD3D12ResourceBinder
Source code excerpt:
, Frequency(InFrequency)
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
, bBindlessResources(EnumHasAnyFlags(ShaderData->ResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessResources))
, bBindlessSamplers(EnumHasAnyFlags(ShaderData->ResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessSamplers))
#endif
{
}
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12RayTracing.cpp:4462
Scope (from outer to inner):
file
function static bool SetRayTracingShaderResources
Source code excerpt:
{
#if D3D12RHI_USE_CONSTANT_BUFFER_VIEWS
if (!EnumHasAllFlags(Shader->ResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessResources))
{
const uint32 DescriptorTableBaseIndex = DescriptorCache.AllocateDeduplicated(Bindings.CBVVersions, Bindings.LocalCBVs, NumCBVs, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, WorkerIndex);
const uint32 BindSlot = RootSignature->CBVRDTBindSlot(SF_Compute);
check(BindSlot != 0xFF);
const D3D12_GPU_DESCRIPTOR_HANDLE ResourceDescriptorTableBaseGPU = DescriptorCache.ViewHeap.GetDescriptorGPU(DescriptorTableBaseIndex);
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Shader.h:114
Scope (from outer to inner):
file
function bool UsesBindlessResources
Source code excerpt:
FORCEINLINE bool UsesDiagnosticBuffer() const { return EnumHasAnyFlags(GetFeatures(), EShaderCodeFeatures::DiagnosticBuffer); }
FORCEINLINE bool UsesGlobalUniformBuffer() const { return EnumHasAnyFlags(ResourceCounts.UsageFlags, EShaderResourceUsageFlags::GlobalUniformBuffer); }
FORCEINLINE bool UsesBindlessResources() const { return EnumHasAnyFlags(ResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessResources); }
FORCEINLINE bool UsesBindlessSamplers() const { return EnumHasAnyFlags(ResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessSamplers); }
FORCEINLINE bool UsesRootConstants() const { return EnumHasAnyFlags(ResourceCounts.UsageFlags, EShaderResourceUsageFlags::RootConstants); }
bool InitCommon(TArrayView<const uint8> InCode);
};
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Shaders.cpp:73
Scope (from outer to inner):
file
function static bool ValidateShaderIsUsable
Source code excerpt:
}
if (EnumHasAnyFlags(InShader->Features, EShaderCodeFeatures::BindlessResources | EShaderCodeFeatures::BindlessSamplers))
{
if (GRHIBindlessSupport == ERHIBindlessSupport::Unsupported ||
(GRHIBindlessSupport == ERHIBindlessSupport::RayTracingOnly && !IsRayTracingShaderFrequency(InFrequency)))
{
return false;
}
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Public/D3D12RootSignatureDefinitions.h:19
Scope: file
Source code excerpt:
AllowMeshShaders = 1 << 0,
InputAssembler = 1 << 1,
BindlessResources = 1 << 2,
BindlessSamplers = 1 << 3,
RootConstants = 1 << 4,
};
ENUM_CLASS_FLAGS(ED3D12RootSignatureFlags)
namespace D3D12ShaderUtils
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Public/D3D12RootSignatureDefinitions.h:203
Scope (from outer to inner):
file
namespace D3D12ShaderUtils
function void SetFlags
Source code excerpt:
}
if (EnumHasAnyFlags(InFlags, ED3D12RootSignatureFlags::BindlessResources))
{
AddRootFlag(D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED);
}
if (EnumHasAnyFlags(InFlags, ED3D12RootSignatureFlags::BindlessSamplers))
{
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Public/D3D12RootSignatureDefinitions.h:233
Scope (from outer to inner):
file
namespace D3D12ShaderUtils
function inline bool ShouldSkipType
Source code excerpt:
if (Type == ERootSignatureRangeType::SRV || Type == ERootSignatureRangeType::UAV)
{
return EnumHasAnyFlags(Flags, ED3D12RootSignatureFlags::BindlessResources);
}
if (Type == ERootSignatureRangeType::Sampler)
{
return EnumHasAnyFlags(Flags, ED3D12RootSignatureFlags::BindlessSamplers);
}
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Public/D3D12RootSignatureDefinitions.h:454
Scope (from outer to inner):
file
namespace D3D12ShaderUtils
function inline void CreateRayTracingSignature
Source code excerpt:
}
if (Creator.HasFlags(ED3D12RootSignatureFlags::BindlessResources))
{
for (uint32 Index = 0; Index < MAX_CBS; Index++)
{
Creator.AddConstantBufferViewParameter(Index, Creator.GetRegisterSpace());
}
}
#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Public/ShaderCore.h:727
Scope: file
Source code excerpt:
{
GlobalUniformBuffer = 1 << 0,
BindlessResources = 1 << 1,
BindlessSamplers = 1 << 2,
RootConstants = 1 << 3,
NoDerivativeOps = 1 << 4,
ShaderBundle = 1 << 5,
};
ENUM_CLASS_FLAGS(EShaderResourceUsageFlags)
#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Public/ShaderCore.h:765
Scope: file
Source code excerpt:
Atomic64 = 1 << 3,
DiagnosticBuffer = 1 << 4,
BindlessResources = 1 << 5,
BindlessSamplers = 1 << 6,
StencilRef = 1 << 7,
BarycentricsSemantic = 1 << 8,
};
ENUM_CLASS_FLAGS(EShaderCodeFeatures);