Shader Resource Cache

Shader resource cache ( ShaderResourceCacheD3D11 class) provides storage for references to objects bound to shader resource variables. In D3D11 implementation, shader resource cache is always one-to-one coupled with the shader resource layout. The class uses three internal structures to hold resource references.  CachedCB is used to hold a resource bound as a constant buffer, CachedSampler structure keeps a sampler, and CachedResource is used to cache references to resources bound as either SRV or UAV. The fist two structures only contain one member which is the object reference:

CachedResource structure contains more members as it can represent both a texture or a buffer:

pView member is a strong reference to the resource view, which in turn keeps strong reference to the object itself. This makes sure that the object is alive while it is bound to the cache. Only one of the pTexture or pBuffer members is initialized depending on the type of the resource.  pd3d11Resource member provides shortcut to the D3D11 resource that will be bound to the D3D11 pipeline.

Similar to shader resource layout, shader resource cache allocates continuous chunk of memory to store resources bound as constant buffers, SRVs, samplers, and UAVs, in that order. This grouping is determined by the four register types in HLSL, so that resources in every group map directly to shader registers ( c#, t#, s#, and u#). There are also four arrays containing raw pointers to D3D11 objects ( ID3D11Buffer*, ID3D11ShaderResourceView*, ID3D11SamplerState*, and ID3D11UnorderedAccessView*) that can be directly used in calls to ID3D11DeviceContext::@SSetConstantBuffers(), ID3D11DeviceContext::@SSetShaderResources(), ID3D11DeviceContext::@SSetSamplers(), and ID3D11DeviceContext::@SSetUnorderedAccessViews(), where @ can be any of V, P, G, H, D, C.  The data is organized in memory in the following order:

  • Constant buffers (array of CachedCB)
  • Array of raw pointers ID3D11Buffer* that can be fed directly to ID3D11DeviceContext::@SSetConstantBuffers() method
  • Shader resource views (array of  CachedResource)
  • Array of raw pointers  ID3D11ShaderResourceView* that can be directly passed to  ID3D11DeviceContext::@SSetShaderResources() method
  • Samplers (array of  CachedSampler)
  • Array of raw pointers  ID3D11SamplerState* that can be directly passed to  ID3D11DeviceContext::@SSetSamplers() method
  • Unordered access views (array of  CachedResource)
  • Array of raw pointers ID3D11UnorderedAccessView* that can be directly passed to ID3D11DeviceContext::@SSetUnorderedAccessViews() method

The following figure illustrates structure of the shader resource cache and its connection to the shader resource layout for the example given in the previous section:

D3D11ShaderResCacheB

ShaderResourceCacheD3D11 class similar to  ShaderResourceLayoutD3D11 allocates raw memory and initializes structures using inplace new. Resources are accessed by computing offset from the beginning of the raw memory buffer. For instance, to get sampler data, we need to skip all constant buffers and shader resource views. The function shown in the listing below returns pointers to arrays containing cached samplers:

Shader Resource Cache Initialization

There are two ways shader resource cache is initialized that correspond to the two usage scenarios:

  • When shader resource cache is initialized as part of the shader object to keep references to static resources, it is initialized by the ShaderResourceLayoutD3D11::Initialize() method. The method reserves space to hold static resources only
  • When shader resource cache is initialized as part of the shader resource binding object, it is initialized by the constructor of ShaderResourceBindingD3D11Impl class, which requestes enough space to hold resources of all types (static, mutable, and dynamic). Shader resource layout that is paired with this cache is initialized to keep only mutable and dynamic resources. Static resources are copied into the cache the first time the resources are committed to the GPU.

Binding Objects to Shader Resource Variables

Textures, Buffers and Samplers are bound to shader resource cache slots through the shader resource layout. Every D3D11 shader resource layout internal structure ( ConstBuffBindInfo, TexAndSamplerBindInfo, TexUAVBindInfo, BuffUAVBindInfo, and BuffSRVBindInfo) defines specific resource binding method. Since every structure keeps reference to D3DShaderAttribs instance, which in turn contains shader register, the required shader resource cache slot can be unambiguously identified. For instance, the following method binds a buffer as a constant buffer:

ShaderResourceCacheD3D11::SetCB() method binds buffer to to the specified CB slot in the resource cache and is defined as shown in the listing below:

Note that the function uses move semantics to avoid unnecessary copies (which in case with smart pointers can be quite costly). SetD3D11ResourceInternal is an internal template helper function defined as follows:

Here, GetArrays() is the pointer to the function that returns the required data arrays, such as the  GetSamplerArrays() method described above.

D3D11 Shader Resource Layout and Shader Resource Cache Summary

There are two ways shader resource layouts and caches are used in D3D11 implementation:

  • Every shader object instance incorporates shader resource layout and shader resource cache to manage static resources
    • Both shader resource layout and cache only contain static resources
  • Every shader resource binding object instance contains shader resource layout and shader resource cache for every active shader stage that keep references to resources bound to shader resource variables
    • Shader resource layout is initialized to keep mutable and dynamic variables, but the cache is initialized to have enough space to hold resources of all types (static, mutable and dynamic). The first time the resources are committed to the GPU pipeline, static resources are copied from the static resource cache of the corresponding shader object

The figure bellow illustrates different components of the shader resource binding system system:

D3D11ResLayoutAndCacheUseCasesB

 

Read next: committing resources to the GPU pipeline.