BindlessSamplers
BindlessSamplers
#Overview
name: BindlessSamplers
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 13
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of BindlessSamplers is to enable the use of bindless samplers in shaders within Unreal Engine 5. Bindless samplers allow for a more flexible and efficient way of accessing sampler resources in shaders, particularly when dealing with a large number of samplers.
This setting variable is primarily used in the rendering system, specifically in the D3D12 RHI (Render Hardware Interface) and shader compilation process. The following Unreal Engine subsystems and modules rely on this setting:
- ShaderCompilerCommon
- D3D12RHI
- RenderCore
The value of this variable is typically set through compiler flags or configuration settings. For example, in the D3D12 RHI, it’s determined by the BindlessSamplersConfig variable.
BindlessSamplers often interacts with other variables and flags, such as:
- BindlessResources
- EShaderResourceUsageFlags
- EShaderCodeFeatures
- ED3D12RootSignatureFlags
Developers should be aware of the following when using this variable:
- Mixing bindless samplers with non-bindless samplers in the same shader is not allowed and will result in compilation errors.
- Bindless samplers require hardware support, so it may not be available on all platforms or GPU configurations.
- The use of bindless samplers affects the root signature creation and shader resource binding process.
Best practices when using this variable include:
- Ensure that the target hardware supports bindless samplers before enabling this feature.
- Use bindless samplers consistently across your shaders to avoid mixing with non-bindless samplers.
- Be aware of the performance implications and potential benefits of using bindless samplers in your specific use case.
- Consider the impact on shader compilation and runtime performance when enabling this feature.
- Properly configure the root signature and resource binding code to accommodate bindless samplers when enabled.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:15, section: [PCD3D_SM5]
- INI Section:
PCD3D_SM5
- Raw value:
Disabled
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:19, section: [PCD3D_SM6]
- INI Section:
PCD3D_SM6
- Raw value:
Disabled
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:23, section: [SF_VULKAN_SM5]
- INI Section:
SF_VULKAN_SM5
- Raw value:
Disabled
- Is Array:
False
Location: <Workspace>/Engine/Config/Windows/BaseWindowsEngine.ini:27, 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:419
Scope (from outer to inner):
file
function bool UE::ShaderCompilerCommon::ValidatePackedResourceCounts
Source code excerpt:
}
if (EnumHasAnyFlags(PackedResourceCounts.UsageFlags, EShaderResourceUsageFlags::BindlessSamplers) && PackedResourceCounts.NumSamplers > 0)
{
const FString Names = GetAllResourcesOfType(EShaderParameterType::Sampler);
Output.Errors.Add(FString::Printf(TEXT("Shader is mixing bindless samplers with non-bindless samplers. %d sampler slots were detected: %s"), PackedResourceCounts.NumSamplers, *Names));
Output.bSucceeded = false;
}
}
#Loc: <Workspace>/Engine/Source/Developer/Windows/ShaderFormatD3D/Private/D3DShaderCompilerDXC.cpp:1155
Scope (from outer to inner):
file
function bool CompileAndProcessD3DShaderDXC
Source code excerpt:
if (Input.Environment.CompilerFlags.Contains(CFLAG_BindlessSamplers))
{
PackedResourceCounts.UsageFlags |= EShaderResourceUsageFlags::BindlessSamplers;
}
if (bHasNoDerivativeOps)
{
PackedResourceCounts.UsageFlags |= EShaderResourceUsageFlags::NoDerivativeOps;
}
#Loc: <Workspace>/Engine/Source/Developer/Windows/ShaderFormatD3D/Private/D3DShaderCompilerDXC.cpp:1236
Scope (from outer to inner):
file
function bool CompileAndProcessD3DShaderDXC
lambda-function
Source code excerpt:
if ((ShaderRequiresFlags & D3D_SHADER_REQUIRES_SAMPLER_DESCRIPTOR_HEAP_INDEXING) != 0)
{
EnumAddFlags(CodeFeatures.CodeFeatures, EShaderCodeFeatures::BindlessSamplers);
}
if ((ShaderRequiresFlags & D3D_SHADER_REQUIRES_STENCIL_REF) != 0)
{
EnumAddFlags(CodeFeatures.CodeFeatures, EShaderCodeFeatures::StencilRef);
}
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Adapter.cpp:1336
Scope (from outer to inner):
file
function void FD3D12Adapter::InitializeDevices
Source code excerpt:
if (BindlessSamplersConfig == ERHIBindlessConfiguration::AllShaders)
{
EnumAddFlags(GraphicsFlags, ED3D12RootSignatureFlags::BindlessSamplers);
}
StaticGraphicsRootSignature.InitStaticGraphicsRootSignature(GraphicsFlags);
StaticGraphicsWithConstantsRootSignature.InitStaticGraphicsRootSignature(GraphicsFlags | ED3D12RootSignatureFlags::RootConstants);
StaticComputeRootSignature.InitStaticComputeRootSignatureDesc(GraphicsFlags);
StaticComputeWithConstantsRootSignature.InitStaticComputeRootSignatureDesc(GraphicsFlags | ED3D12RootSignatureFlags::RootConstants);
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Adapter.cpp:1352
Scope (from outer to inner):
file
function void FD3D12Adapter::InitializeDevices
Source code excerpt:
if (BindlessSamplersConfig != ERHIBindlessConfiguration::Disabled)
{
EnumAddFlags(RayTracingFlags, ED3D12RootSignatureFlags::BindlessSamplers);
}
StaticRayTracingGlobalRootSignature.InitStaticRayTracingGlobalRootSignatureDesc(RayTracingFlags);
StaticRayTracingLocalRootSignature.InitStaticRayTracingLocalRootSignatureDesc(RayTracingFlags);
#endif
#endif // USE_STATIC_ROOT_SIGNATURE
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Commands.cpp:933
Scope (from outer to inner):
file
function FD3D12ResourceBinder
Source code excerpt:
#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
void SetBindlessHandle(const FRHIDescriptorHandle& Handle, uint32 Offset)
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Shader.h:115
Scope (from outer to inner):
file
function bool UsesBindlessSamplers
Source code excerpt:
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);
};
/** This represents a vertex shader that hasn't been combined with a specific declaration to create a bound shader. */
#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:20
Scope: file
Source code excerpt:
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:208
Scope (from outer to inner):
file
namespace D3D12ShaderUtils
function void SetFlags
Source code excerpt:
}
if (EnumHasAnyFlags(InFlags, ED3D12RootSignatureFlags::BindlessSamplers))
{
AddRootFlag(D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED);
}
}
bool HasFlags(ED3D12RootSignatureFlags InFlags) const
#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Public/D3D12RootSignatureDefinitions.h:238
Scope (from outer to inner):
file
namespace D3D12ShaderUtils
function inline bool ShouldSkipType
Source code excerpt:
if (Type == ERootSignatureRangeType::Sampler)
{
return EnumHasAnyFlags(Flags, ED3D12RootSignatureFlags::BindlessSamplers);
}
return false;
}
};
#Loc: <Workspace>/Engine/Source/Runtime/RenderCore/Public/ShaderCore.h:728
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:766
Scope: file
Source code excerpt:
DiagnosticBuffer = 1 << 4,
BindlessResources = 1 << 5,
BindlessSamplers = 1 << 6,
StencilRef = 1 << 7,
BarycentricsSemantic = 1 << 8,
};
ENUM_CLASS_FLAGS(EShaderCodeFeatures);
struct FShaderCodeFeatures