Diligent Engine implements automatic shader resource binding model. When D3D shader is compiled, the engine uses shader reflection system to query the list of resources used by the shader (see ID3D11ShaderReflection and ID3D12ShaderReflection on MSDN). For every resource, an instance of D3DShaderResourceAttribs struct is populated with the resource name, bind point, array size and other attributes.
String Name; // Move ctor will not work if it is const
const Uint16 BindPoint;
const Uint16 BindCount;
// 4 3 4 20 1
// bit | 0 1 2 3 | 4 5 6 | 7 8 9 10 | 11 12 ... 30 | 31 |
// | | | | | |
// | InputType | VariableType | SRV Dim | SamplerId | StaticSamplerFlag |
const Uint32 PackedAttribs;
The structure contains the following attributes:
Name is the name of the resource
- For arrays, the name does not contain brackets, thus for both of the following two declarations Texture2D g_Tex, and Texture2D g_Tex, the name will be deduced as "g_Tex".
- BindCount is the number of bind slots taken by the resource. For non-array resources, this is always 1. For array resources, this is the size of array.
PackedAttribs contains five attributes packed into 32 bits:
- InputType identifes resource type and takes values from D3D_SHADER_INPUT_TYPE enumeration.
- VariableType indetifies shader variable type ( SHADER_VARIABLE_TYPE enum).
- SRVDim is the shader resource view dimension (see D3D_SRV_DIMENSION).
- SamplerId for texture SRVs, this is the ID of the sampler that is assigned to this texture. Ignored for other types of resources.
- StaticSamplerFlag for samplers, indicates if this sampler is a static sampler. Ignored for other types of resources.
Shader resources are stored in an instance of the ShaderResources class. The class allocates continuous chunk of memory to store all resource in the following order:
- Constant Buffer Views
- Texture SRVs
- Texture UAVs
- Buffer SRVs
- Buffer UAVs
Consider the shader that uses the following resources:
cbuffer cbBuff0 : register(b5);
cbuffer cbBuff1 : register(b2);
Texture2D g_Tex0 : register(t16);
Texture2D g_Tex1 : register(t2);
Texture2D g_Tex2 : register(t4);
SamplerState g_Tex0_sampler : register(s3);
SamplerState g_Tex2_sampler : register(s5);
RWTexture2D<float4> g_rwTex0 : register(u3);
RWTexture2D<float4> g_rwTex1 : register(u0);
Buffer<float4> g_Buff : register(t32);
RWBuffer<uint4> g_rwBuff : register(u2);
For these resources, the ShaderResources class will contain the following data:
- Resource are enumerated in the order of their appearance in the shader, not by the binding points
- Resource bind points are explicitly set for illustration purposes only and selected arbitrary
- For sampler to be paired with the texture, it must have the form <TexureName>_sampler suffix (see this page for more details)
- For texture SRVs, SamplerID is the 0-based index of the sampler in the sampler part, or -1 if no sampler is assigned to the texture (not the sampler binding point)
Shader resource attributes are shared between D3D11 and D3D12 implementations. Both implementations use the same template function to query resources using D3D11 or D3D12 shader reflection system. D3D12 implementation uses ShaderResourcesD3D12 class that is derived from ShaderResources; D3D11 implementation uses ShaderResourcesD3D11 class also derived from ShaderResources. Both derived classes use LoadD3DShaderResources<> template function to query shader resource using either D3D11 or D3D12 reflection interface.
Both ShaderD3D11Impl and ShaderD3D12Impl classes maintain shared pointer to an instance of the ShaderResourcesD3D11 or ShaderResourcesD3D12 correspondingly. Shared pointer is required because shader resources are also referenced by other objects in the system.
Read next: Shader Resource Layout.