Diligent Engine API Reference
ShaderResourceLayoutD3D12.h
1 /* Copyright 2015-2018 Egor Yusov
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12  *
13  * In no event and under no legal theory, whether in tort (including negligence),
14  * contract, or otherwise, unless required by applicable law (such as deliberate
15  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16  * liable for any damages, including any direct, indirect, special, incidental,
17  * or consequential damages of any character arising as a result of this License or
18  * out of the use or inability to use the software (including but not limited to damages
19  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20  * all other commercial damages or losses), even if such Contributor has been advised
21  * of the possibility of such damages.
22  */
23 
24 #pragma once
25 
28 
29 // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout/
30 
31 // All resources are stored in a single continuous chunk of memory using the following layout:
32 //
33 // m_ResourceBuffer m_Samplers
34 // | |
35 // | SRV_CBV_UAV[0] ... SRV_CBV_UAV[s-1] | SRV_CBV_UAV[s] ... SRV_CBV_UAV[s+m-1] | SRV_CBV_UAV[s+m] ... SRV_CBV_UAV[s+m+d-1] || Sampler[0] ... Sampler[s'-1] | Sampler[s'] ... Sampler[s'+m'-1] | Sampler[s'+m'] ... Sampler[s'+m'+d'-1] ||
36 // | | | || | | ||
37 // | SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC ||
38 // | | | ||
39 //
40 // s == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC]
41 // m == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE]
42 // d == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC]
43 //
44 // s' == m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC]
45 // m' == m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE]
46 // d' == m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC]
47 //
48 //
49 // Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block
50 // memory allocator is used. This ensures that all resources from different shader resource bindings reside in
51 // continuous memory. If allocation granularity == 1, raw allocator is used.
52 //
53 //
54 // Every SRV_CBV_UAV and Sampler structure holds a reference to D3DShaderResourceAttribs structure from ShaderResources.
55 // ShaderResourceLayoutD3D12 holds shared pointer to ShaderResourcesD3D12 instance. Note that ShaderResources::SamplerId
56 // references a sampler in ShaderResources, while SRV_CBV_UAV::SamplerId references a sampler in ShaderResourceLayoutD3D12,
57 // and the two are not the same
58 //
59 //
60 // ________________SamplerId____________________
61 // | |
62 // _________________ ______________|_____________________________________________V________
63 // | | unique_ptr | | | | | | |
64 // | ShaderResources |--------------->| CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers |
65 // |_________________| |________|___________|___________|___________|___________|____________|
66 // A A A A
67 // | \ / \
68 // |shared_ptr Ref Ref Ref
69 // ________|__________________ ________\________________________/_________________________\_________________________________________
70 // | | unique_ptr | | | | | | |
71 // | ShaderResourceLayoutD3D12 |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... |
72 // |___________________________| |___________________|_________________|_______________|__________________|_________________|__________|
73 // | | | A | /
74 // | Raw ptr | |___________________SamplerId________________________| | /
75 // | | / /
76 // | \ / /
77 // ________V_________________ ________V_______________________________________________________V____V__
78 // | | | |
79 // | ShaderResourceCacheD3D12 |---------------->| Resources |
80 // |__________________________| |________________________________________________________________________|
81 //
82 // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Figure2
83 // Resources in the resource cache are identified by the root index and offset in the descriptor table
84 //
85 //
86 // ShaderResourceLayoutD3D12 is used as follows:
87 // * Every pipeline state object (PipelineStateD3D12Impl) maintains shader resource layout for every active shader stage
88 // ** These resource layouts are not bound to a resource cache and are used as reference layouts for shader resource binding objects
89 // ** All variable types are preserved
90 // ** Root indices and descriptor table offsets are assigned during the initialization
91 // ** Resource cache is not assigned
92 // * Every shader object (ShaderD3D12Impl) contains shader resource layout that facilitates management of static shader resources
93 // ** The resource layout defines artificial layout and is bound to a resource cache that actually holds references to resources
94 // ** Resource cache is assigned and initialized
95 // * Every shader resource binding object (ShaderResourceBindingD3D12Impl) encompasses shader resource layout for every active shader
96 // stage in the parent pipeline state
97 // ** Resource layouts are initialized by clonning reference layouts from the pipeline state object and are bound to the resource
98 // cache that holds references to resources set by the application
99 // ** All shader variable types are clonned
100 // ** Resource cache is assigned, but not initialized; Initialization is performed by the root signature
101 //
102 
103 // Set this define to 1 to use unordered_map to store shader variables.
104 // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64).
105 #define USE_VARIABLE_HASH_MAP 0
106 
107 #include "unordered_map"
108 
109 #include "ShaderD3DBase.h"
110 #include "ShaderBase.h"
111 #include "HashUtils.h"
112 #include "ShaderResourcesD3D12.h"
113 #include "ShaderResourceCacheD3D12.h"
114 #include "ShaderVariableD3DBase.h"
115 
116 #ifdef _DEBUG
117 # define VERIFY_SHADER_BINDINGS
118 #endif
119 
120 namespace Diligent
121 {
122 
124 // sizeof(ShaderResourceLayoutD3D12)==80 (MS compiler, x64)
126 {
127 public:
128  ShaderResourceLayoutD3D12(IObject &Owner, IMemoryAllocator &ResourceLayoutDataAllocator);
129 
130  // This constructor is used by ShaderResourceBindingD3D12Impl to clone layout from the reference layout in PipelineStateD3D12Impl.
131  // Root indices and descriptor table offsets must be correct. Resource cache is assigned, but not initialized.
132  ShaderResourceLayoutD3D12(IObject &Owner,
133  const ShaderResourceLayoutD3D12& SrcLayout,
134  IMemoryAllocator &ResourceLayoutDataAllocator,
135  const SHADER_VARIABLE_TYPE *AllowedVarTypes,
136  Uint32 NumAllowedTypes,
137  ShaderResourceCacheD3D12 &ResourceCache);
138 
141  ShaderResourceLayoutD3D12& operator =(const ShaderResourceLayoutD3D12&) = delete;
143 
145 
146  // The method is called by
147  // - ShaderD3D12Impl class instance to initialize static resource layout and initialize shader resource cache
148  // to hold static resources
149  // - PipelineStateD3D12Impl class instance to reference all types of resources (static, mutable, dynamic).
150  // Root indices and descriptor table offsets are assigned during the initialization;
151  // no shader resource cache is provided
152  void Initialize(ID3D12Device *pd3d12Device,
153  const std::shared_ptr<const ShaderResourcesD3D12>& pSrcResources,
154  IMemoryAllocator &LayoutDataAllocator,
155  const SHADER_VARIABLE_TYPE *VarTypes,
156  Uint32 NumAllowedTypes,
157  ShaderResourceCacheD3D12 *pResourceCache,
158  class RootSignature *pRootSig);
159 
160  // sizeof(SRV_CBV_UAV) == 32 (x64)
161  struct SRV_CBV_UAV : ShaderVariableD3DBase<ShaderResourceLayoutD3D12>
162  {
163  SRV_CBV_UAV(const SRV_CBV_UAV&) = delete;
164  SRV_CBV_UAV(SRV_CBV_UAV&&) = delete;
165  SRV_CBV_UAV& operator = (const SRV_CBV_UAV&) = delete;
166  SRV_CBV_UAV& operator = (SRV_CBV_UAV&&) = delete;
167 
168  static constexpr Uint32 ResTypeBits = 3;
169  static constexpr Uint32 RootIndBits = 16-ResTypeBits;
170  static constexpr Uint32 RootIndMask = (1 << RootIndBits)-1;
171  static constexpr Uint32 ResTypeMask = (1 << ResTypeBits)-1;
172 
173  static constexpr Uint16 InvalidRootIndex = RootIndMask;
174  static constexpr Uint16 MaxRootIndex = RootIndMask-1;
175 
176  static constexpr Uint32 InvalidSamplerId = 0xFFFF;
177  static constexpr Uint32 MaxSamplerId = InvalidSamplerId-1;
178  static constexpr Uint32 InvalidOffset = static_cast<Uint32>(-1);
179 
180  static_assert( static_cast<int>(CachedResourceType::NumTypes) <= ResTypeMask, "3 bits is not enough to store CachedResourceType");
181 
182  const Uint32 OffsetFromTableStart;
183 
184  // Special copy constructor. Note that sampler ID refers to the ID of the sampler
185  // within THIS layout, and may not be the same as in original layout
186  SRV_CBV_UAV(ShaderResourceLayoutD3D12 &ParentLayout, const SRV_CBV_UAV &rhs, Uint32 SamId ) :
187  ResType_RootIndex(rhs.ResType_RootIndex),
188  SamplerId(static_cast<Uint16>(SamId)),
189  OffsetFromTableStart(rhs.OffsetFromTableStart),
190  ShaderVariableD3DBase<ShaderResourceLayoutD3D12>(ParentLayout, rhs.Attribs)
191  {
192  VERIFY(SamId == InvalidSamplerId || SamId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" );
193  VERIFY(rhs.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references");
194  VERIFY(IsValidOffset(), "Offset must be valid" );
195  VERIFY(IsValidRootIndex(), "Root index must be valid" );
196  }
197 
198  SRV_CBV_UAV(ShaderResourceLayoutD3D12 &ParentLayout,
199  const D3DShaderResourceAttribs &_Attribs,
200  CachedResourceType ResType,
201  Uint32 RootIndex,
202  Uint32 _OffsetFromTableStart,
203  Uint32 _SamplerId) :
204  ResType_RootIndex( (static_cast<Uint16>(ResType) << RootIndBits) | (RootIndex & RootIndMask)),
205  SamplerId( static_cast<Uint16>(_SamplerId) ),
206  OffsetFromTableStart(_OffsetFromTableStart),
207  ShaderVariableD3DBase<ShaderResourceLayoutD3D12>(ParentLayout, _Attribs)
208  {
209  VERIFY(RootIndex == InvalidRootIndex || RootIndex <= MaxRootIndex, "Root index exceeds max allowed value (", MaxRootIndex, ")" );
210  VERIFY(IsValidOffset(), "Offset must be valid" );
211  VERIFY(SamplerId == InvalidSamplerId || SamplerId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" );
212  }
213 
214  bool IsBound(Uint32 ArrayIndex);
215 
216  // Non-virtual function
217  void BindResource(IDeviceObject *pObject, Uint32 ArrayIndex, const ShaderResourceLayoutD3D12 *dbgResLayout);
218  virtual void Set(IDeviceObject *pObject)override final{ BindResource(pObject, 0, nullptr); }
219 
220  virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final
221  {
222  for(Uint32 Elem = 0; Elem < NumElements; ++Elem)
223  BindResource(ppObjects[Elem], FirstElement+Elem, nullptr);
224  }
225 
226  bool IsValidSampler() const{return GetSamplerId() != InvalidSamplerId;}
227  bool IsValidRootIndex()const{return GetRootIndex() != InvalidRootIndex;}
228  bool IsValidOffset() const{return OffsetFromTableStart != InvalidOffset; }
229 
230  CachedResourceType GetResType()const
231  {
232  return static_cast<CachedResourceType>( (ResType_RootIndex >> RootIndBits) & ResTypeMask );
233  }
234  Uint32 GetRootIndex()const
235  {
236  return ResType_RootIndex & RootIndMask;
237  }
238 
239  Uint32 GetSamplerId()const
240  {
241  return SamplerId;
242  }
243 
244  private:
245  const Uint16 ResType_RootIndex; // bit
246  // | 0 1 .... 12 | 13 14 15 |
247  // | | |
248  // | Root index | ResType |
249  const Uint16 SamplerId;
250 
251  void CacheCB(IDeviceObject *pBuffer,
252  ShaderResourceCacheD3D12::Resource& DstRes,
253  Uint32 ArrayInd,
254  D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle);
255 
256  template<typename TResourceViewType,
257  typename TViewTypeEnum,
258  typename TBindSamplerProcType>
259  void CacheResourceView(IDeviceObject *pView,
260  ShaderResourceCacheD3D12::Resource& DstRes,
261  Uint32 ArrayIndex,
262  D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle,
263  TViewTypeEnum dbgExpectedViewType,
264  TBindSamplerProcType BindSamplerProc);
265  };
266 
267  // sizeof(Sampler) == 24 (x64)
268  struct Sampler
269  {
270  Sampler(const Sampler&) = delete;
271  Sampler(Sampler&&) = delete;
272  Sampler& operator = (const Sampler&) = delete;
273  Sampler& operator = (Sampler&&) = delete;
274 
275  const D3DShaderResourceAttribs &Attribs;
276  ShaderResourceLayoutD3D12 &m_ParentResLayout;
277 
278  static constexpr Uint32 InvalidRootIndex = static_cast<Uint32>(-1);
279  static constexpr Uint32 InvalidOffset = static_cast<Uint32>(-1);
280 
281  const Uint32 RootIndex;
282  const Uint32 OffsetFromTableStart;
283 
284  Sampler(ShaderResourceLayoutD3D12 &ParentLayout, const Sampler& Sam):
285  Attribs(Sam.Attribs),
286  m_ParentResLayout(ParentLayout),
287  RootIndex(Sam.RootIndex),
288  OffsetFromTableStart(Sam.OffsetFromTableStart)
289  {
290  VERIFY(Sam.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references");
291  VERIFY(IsValidRootIndex(), "Root index must be valid" );
292  VERIFY(IsValidOffset(), "Offset must be valid" );
293  }
294 
295  Sampler(ShaderResourceLayoutD3D12 &ParentResLayout, const D3DShaderResourceAttribs &_Attribs, Uint32 _RootIndex, Uint32 _OffsetFromTableStart) :
296  RootIndex(_RootIndex),
297  OffsetFromTableStart(_OffsetFromTableStart),
298  Attribs(_Attribs),
299  m_ParentResLayout(ParentResLayout)
300  {
301  VERIFY(IsValidRootIndex(), "Root index must be valid" );
302  VERIFY(IsValidOffset(), "Offset must be valid" );
303  }
304 
305  bool IsValidRootIndex()const{return RootIndex != InvalidRootIndex;}
306  bool IsValidOffset() const{return OffsetFromTableStart != InvalidOffset; }
307 
308  void CacheSampler(class ITextureViewD3D12 *pTexViewD3D12, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle);
309  };
310 
311 
312  void CopyStaticResourceDesriptorHandles(const ShaderResourceLayoutD3D12 &SrcLayout);
313 
314  // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive
315  // while Layout is alive
316  void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D12 *dbgResourceCache );
317 
318  IShaderVariable* GetShaderVariable( const Char* Name );
319 
320 #ifdef VERIFY_SHADER_BINDINGS
321  void dbgVerifyBindings()const;
322 #endif
323 
324  IObject& GetOwner(){return m_Owner;}
325 
326 private:
327  void InitVariablesHashMap();
328 
329  Sampler &GetAssignedSampler(const SRV_CBV_UAV &TexSrv);
330 
331  const Char* GetShaderName()const;
332 
333  // There is no need to use shared ptr as referenced resource cache is either part of the
334  // parent ShaderD3D12Impl object or ShaderResourceBindingD3D12Impl object
335  ShaderResourceCacheD3D12 *m_pResourceCache;
336 
337  std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
338  Sampler* m_Samplers = nullptr;
339  Uint16 m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
340  Uint16 m_NumSamplers [SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0};
341 
342  Uint32 GetSrvCbvUavOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
343  {
344  VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] );
345  static_assert(SHADER_VARIABLE_TYPE_STATIC == 0, "SHADER_VARIABLE_TYPE_STATIC == 0 expected");
346  r += (VarType > SHADER_VARIABLE_TYPE_STATIC) ? m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] : 0;
347  static_assert(SHADER_VARIABLE_TYPE_MUTABLE == 1, "SHADER_VARIABLE_TYPE_MUTABLE == 1 expected");
348  r += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] : 0;
349  return r;
350  }
351  SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)
352  {
353  VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] );
354  auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
355  return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)];
356  }
357  const SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
358  {
359  VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] );
360  auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
361  return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)];
362  }
363  SRV_CBV_UAV& GetSrvCbvUav(Uint32 r)
364  {
365  VERIFY_EXPR( r < GetTotalSrvCbvUavCount() );
366  auto* CbvSrvUav = reinterpret_cast<SRV_CBV_UAV*>(m_ResourceBuffer.get());
367  return CbvSrvUav[r];
368  }
369 
370  Uint32 GetSamplerOffset(SHADER_VARIABLE_TYPE VarType, Uint32 s)const
371  {
372  VERIFY_EXPR( s < m_NumSamplers[VarType] );
373  static_assert(SHADER_VARIABLE_TYPE_STATIC == 0, "SHADER_VARIABLE_TYPE_STATIC == 0 expected");
374  s += (VarType > SHADER_VARIABLE_TYPE_STATIC) ? m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] : 0;
375  static_assert(SHADER_VARIABLE_TYPE_MUTABLE == 1, "SHADER_VARIABLE_TYPE_MUTABLE == 1 expected");
376  s += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] : 0;
377  return s;
378  }
379  Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)
380  {
381  VERIFY_EXPR( s < m_NumSamplers[VarType] );
382  return m_Samplers[GetSamplerOffset(VarType,s)];
383  }
384  const Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)const
385  {
386  VERIFY_EXPR( s < m_NumSamplers[VarType] );
387  return m_Samplers[GetSamplerOffset(VarType,s)];
388  }
389  Uint32 GetTotalSrvCbvUavCount()const
390  {
391  static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?");
392  return m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] + m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC];
393  }
394  Uint32 GetTotalSamplerCount()const
395  {
396  static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?");
397  return m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] + m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC];
398  }
399 
400  void AllocateMemory(IMemoryAllocator &Allocator);
401 
402 #if USE_VARIABLE_HASH_MAP
403  // Hash map to look up shader variables by name.
404  // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64).
405  typedef std::pair<HashMapStringKey, IShaderVariable*> VariableHashElemType;
406  std::unordered_map<HashMapStringKey, IShaderVariable*, std::hash<HashMapStringKey>, std::equal_to<HashMapStringKey>, STDAllocatorRawMem<VariableHashElemType> > m_VariableHash;
407 #endif
408 
409  CComPtr<ID3D12Device> m_pd3d12Device;
410  IObject &m_Owner;
411  // We must use shared_ptr to reference ShaderResources instance, because
412  // there may be multiple objects referencing the same set of resources
413  std::shared_ptr<const ShaderResourcesD3D12> m_pResources;
414 };
415 
416 }
Base interface for all objects created by the render device Diligent::IRenderDevice.
Definition: DeviceObject.h:40
Shader resource variable.
Definition: Shader.h:265
Implementation of the Diligent::RootSignature class.
Definition: RootSignature.h:161
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
Interface to the texture view object implemented in D3D11.
Definition: TextureViewD3D12.h:39
Resouce mapping.
Definition: ResourceMapping.h:80
SHADER_VARIABLE_TYPE
Describes shader variable type that is used by ShaderVariableDesc.
Definition: Shader.h:100
Shader variable is constant across all shader instances. It must be set once directly through IShader...
Definition: Shader.h:105
Shader variable is dynamic. It can be set multiple times for every instance of shader resource bindin...
Definition: Shader.h:114
Diligent::ShaderResourceLayoutD3D12 class.
Definition: ShaderResourceLayoutD3D12.h:125
Shader variable is constant across shader resource bindings instance (see IShaderResourceBinding). It must be set once through IShaderResourceBinding::BindResources() or through the shader variable. It cannot be set through IShader interface.
Definition: Shader.h:110
Total number of shader variable types.
Definition: Shader.h:117