Diligent Engine API Reference
ShaderResourceCacheD3D11.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 #include "TextureBaseD3D11.h"
30 #include "BufferD3D11Impl.h"
31 #include "SamplerD3D11Impl.h"
32 
33 namespace Diligent
34 {
35 
37 // All resources are stored in the continuous memory using the following layout:
38 //
39 // | CachedCB | ID3D11Buffer* || CachedResource | ID3D11ShaderResourceView* || CachedSampler | ID3D11SamplerState* || CachedResource | ID3D11UnorderedAccessView*||
40 // |---------------------------------------------------||--------------------------|---------------------------||------------------------------|-----------------------------||-------------------------|---------------------------||
41 // | 0 | 1 | ... | CBCount-1 | 0 | 1 | ...| CBCount-1 || 0 | 1 | ... | SRVCount-1 | 0 | 1 | ... | SRVCount-1 || 0 | 1 | ... | SamplerCount-1 | 0 | 1 | ...| SamplerCount-1 ||0 | 1 | ... | UAVCount-1 | 0 | 1 | ... | UAVCount-1 ||
42 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
43 //
44 //
45 // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache/
47 {
48 public:
50  {}
51 
53 
54 
56  ShaderResourceCacheD3D11& operator = (const ShaderResourceCacheD3D11&) = delete;
58  ShaderResourceCacheD3D11& operator = (ShaderResourceCacheD3D11&&) = delete;
59 
61  struct CachedCB
62  {
65  __forceinline void Set(RefCntAutoPtr<BufferD3D11Impl> &&_pBuff)
66  {
67  pBuff = std::move(_pBuff);
68  }
69  };
70 
73  {
76  __forceinline void Set(SamplerD3D11Impl *pSam)
77  {
78  pSampler = pSam;
79  }
80  };
81 
84  {
91  TextureBaseD3D11* pTexture;
92  BufferD3D11Impl* pBuffer;
93  // There is no need to keep strong reference to D3D11 resource as
94  // it is already kept by either pTexture or pBuffer
95  ID3D11Resource *pd3d11Resource;
96  CachedResource() : pTexture(nullptr), pBuffer(nullptr), pd3d11Resource(nullptr)
97  {}
98 
99  __forceinline void Set(RefCntAutoPtr<TextureViewD3D11Impl>&& pTexView)
100  {
101  pBuffer = nullptr;
102  // Avoid unnecessary virtual function calls
103  pTexture = pTexView ? ValidatedCast<TextureBaseD3D11>(pTexView->TextureViewD3D11Impl::GetTexture()) : nullptr;
104  pView.Attach(pTexView.Detach());
105  pd3d11Resource = pTexture ? pTexture->TextureBaseD3D11::GetD3D11Texture() : nullptr;
106  }
107 
108  __forceinline void Set(RefCntAutoPtr<BufferViewD3D11Impl>&& pBufView)
109  {
110  pTexture = nullptr;
111  // Avoid unnecessary virtual function calls
112  pBuffer = pBufView ? ValidatedCast<BufferD3D11Impl>(pBufView->BufferViewD3D11Impl::GetBuffer()) : nullptr;
113  pView.Attach(pBufView.Detach());
114  pd3d11Resource = pBuffer ? pBuffer->BufferD3D11Impl::GetD3D11Buffer() : nullptr;
115  }
116  };
117 
118  void Initialize(Int32 CBCount, Int32 SRVCount, Int32 SamplerCount, Int32 UAVCount, class IMemoryAllocator &MemAllocator);
119  void Destroy(class IMemoryAllocator &MemAllocator);
120 
121 
122  __forceinline void SetCB(Uint32 Slot, RefCntAutoPtr<BufferD3D11Impl> &&pBuffD3D11Impl)
123  {
124  auto *pd3d11Buff = pBuffD3D11Impl ? pBuffD3D11Impl->BufferD3D11Impl::GetD3D11Buffer() : nullptr;
125  SetD3D11ResourceInternal<CachedCB>(Slot, GetCBCount(), &ShaderResourceCacheD3D11::GetCBArrays, std::move(pBuffD3D11Impl), pd3d11Buff);
126  }
127 
128  __forceinline void SetTexSRV(Uint32 Slot, RefCntAutoPtr<TextureViewD3D11Impl>&& pTexView)
129  {
130  auto pd3d11SRV = pTexView ? static_cast<ID3D11ShaderResourceView*>(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr;
131  SetD3D11ResourceInternal<CachedResource>(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pTexView), pd3d11SRV);
132  }
133 
134  __forceinline void SetBufSRV(Uint32 Slot, RefCntAutoPtr<BufferViewD3D11Impl> &&pBuffView)
135  {
136  auto pd3d11SRV = pBuffView ? static_cast<ID3D11ShaderResourceView*>(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr;
137  SetD3D11ResourceInternal<CachedResource>(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pBuffView), pd3d11SRV);
138  }
139 
140  __forceinline void SetTexUAV(Uint32 Slot, RefCntAutoPtr<TextureViewD3D11Impl>&& pTexView)
141  {
142  auto pd3d11UAV = pTexView ? static_cast<ID3D11UnorderedAccessView*>(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr;
143  SetD3D11ResourceInternal<CachedResource>(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pTexView), pd3d11UAV);
144  }
145 
146  __forceinline void SetBufUAV(Uint32 Slot, RefCntAutoPtr<BufferViewD3D11Impl> &&pBuffView)
147  {
148  auto pd3d11UAV = pBuffView ? static_cast<ID3D11UnorderedAccessView*>(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr;
149  SetD3D11ResourceInternal<CachedResource>(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pBuffView), pd3d11UAV);
150  }
151 
152  __forceinline void SetSampler(Uint32 Slot, SamplerD3D11Impl *pSampler)
153  {
154  auto *pd3d11Sampler = pSampler ? pSampler->SamplerD3D11Impl::GetD3D11SamplerState() : nullptr;
155  SetD3D11ResourceInternal<CachedSampler>(Slot, GetSamplerCount(), &ShaderResourceCacheD3D11::GetSamplerArrays, pSampler, pd3d11Sampler);
156  }
157 
158 
159 
160  __forceinline CachedCB& GetCB(Uint32 Slot)
161  {
162  VERIFY(Slot < GetCBCount(), "CB slot is out of range" );
163  ShaderResourceCacheD3D11::CachedCB *CBs;
164  ID3D11Buffer **pd3d11CBs;
165  GetCBArrays(CBs, pd3d11CBs);
166  return CBs[Slot];
167  }
168 
169  __forceinline CachedResource& GetSRV(Uint32 Slot)
170  {
171  VERIFY(Slot < GetSRVCount(), "SRV slot is out of range" );
172  ShaderResourceCacheD3D11::CachedResource *SRVResources;
173  ID3D11ShaderResourceView **pd3d11SRVs;
174  GetSRVArrays(SRVResources, pd3d11SRVs);
175  return SRVResources[Slot];
176  }
177 
178  __forceinline CachedResource& GetUAV(Uint32 Slot)
179  {
180  VERIFY(Slot < GetUAVCount(), "UAV slot is out of range" );
181  ShaderResourceCacheD3D11::CachedResource *UAVResources;
182  ID3D11UnorderedAccessView **pd3d11UAVs;
183  GetUAVArrays(UAVResources, pd3d11UAVs);
184  return UAVResources[Slot];
185  }
186 
187  __forceinline CachedSampler& GetSampler(Uint32 Slot)
188  {
189  VERIFY(Slot < GetSamplerCount(), "Sampler slot is out of range" );
190  ShaderResourceCacheD3D11::CachedSampler *Samplers;
191  ID3D11SamplerState **pd3d11Samplers;
192  GetSamplerArrays(Samplers, pd3d11Samplers);
193  return Samplers[Slot];
194  }
195 
196 
197  __forceinline bool IsCBBound(Uint32 Slot)const
198  {
199  CachedCB* CBs = nullptr;
200  ID3D11Buffer** d3d11CBs = nullptr;
201  const_cast<ShaderResourceCacheD3D11*>(this)->GetCBArrays(CBs, d3d11CBs);
202  if( Slot < GetCBCount() && d3d11CBs[Slot] != nullptr )
203  {
204  VERIFY(CBs[Slot].pBuff != nullptr, "No relevant buffer resource");
205  return true;
206  }
207  return false;
208  }
209 
210  __forceinline bool IsSRVBound(Uint32 Slot, bool dbgIsTextureView)const
211  {
212  CachedResource* SRVResources = nullptr;
213  ID3D11ShaderResourceView** d3d11SRVs = nullptr;
214  const_cast<ShaderResourceCacheD3D11*>(this)->GetSRVArrays(SRVResources, d3d11SRVs);
215  if( Slot < GetSRVCount() && d3d11SRVs[Slot] != nullptr )
216  {
217  VERIFY( ( dbgIsTextureView && SRVResources[Slot].pTexture != nullptr) ||
218  (!dbgIsTextureView && SRVResources[Slot].pBuffer != nullptr), "No relevant resource");
219  return true;
220  }
221  return false;
222  }
223 
224  __forceinline bool IsUAVBound(Uint32 Slot, bool dbgIsTextureView)const
225  {
226  CachedResource* UAVResources = nullptr;
227  ID3D11UnorderedAccessView** d3d11UAVs = nullptr;
228  const_cast<ShaderResourceCacheD3D11*>(this)->GetUAVArrays(UAVResources, d3d11UAVs);
229  if( Slot < GetUAVCount() && d3d11UAVs[Slot] != nullptr )
230  {
231  VERIFY( ( dbgIsTextureView && UAVResources[Slot].pTexture != nullptr) ||
232  (!dbgIsTextureView && UAVResources[Slot].pBuffer != nullptr), "No relevant resource");
233  return true;
234  }
235  return false;
236  }
237 
238  __forceinline bool IsSamplerBound(Uint32 Slot)const
239  {
240  CachedSampler* Samplers = nullptr;
241  ID3D11SamplerState** d3d11Samplers = nullptr;
242  const_cast<ShaderResourceCacheD3D11*>(this)->GetSamplerArrays(Samplers, d3d11Samplers);
243  if( Slot < GetSamplerCount() && d3d11Samplers[Slot] != nullptr )
244  {
245  VERIFY(Samplers[Slot].pSampler != nullptr, "No relevant sampler");
246  return true;
247  }
248  return false;
249  }
250 
251  void dbgVerifyCacheConsistency();
252 
253 
254  static __forceinline Uint32 PackResourceCounts(Uint32 CBCount, Uint32 SRVCount, Uint32 SamplerCount, Uint32 UAVCount)
255  {
256  VERIFY_EXPR(CBCount <= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT );
257  VERIFY_EXPR(SRVCount <= D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
258  VERIFY_EXPR(SamplerCount <= D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT);
259  VERIFY_EXPR(UAVCount <= D3D11_PS_CS_UAV_REGISTER_COUNT);
260  return (CBCount & 0xFF) | ((SRVCount & 0xFF) << 8) | ((SamplerCount & 0xFF) << 16) | ((UAVCount & 0xFF) << 24);
261  }
262 
263  static __forceinline Uint32 UnpackCBCount (Uint32 PackedCounts) {return (PackedCounts >> 0) & 0xFF; }
264  static __forceinline Uint32 UnpackSRVCount (Uint32 PackedCounts) {return (PackedCounts >> 8) & 0xFF; }
265  static __forceinline Uint32 UnpackSamplerCount (Uint32 PackedCounts) {return (PackedCounts >> 16) & 0xFF; }
266  static __forceinline Uint32 UnpackUAVCount (Uint32 PackedCounts) {return (PackedCounts >> 24) & 0xFF; }
267 
268  __forceinline Uint32 GetCBCount() const{ return UnpackCBCount (m_ResourceCounts);}
269  __forceinline Uint32 GetSRVCount() const{ return UnpackSRVCount (m_ResourceCounts);}
270  __forceinline Uint32 GetSamplerCount()const{ return UnpackSamplerCount(m_ResourceCounts);}
271  __forceinline Uint32 GetUAVCount() const{ return UnpackUAVCount (m_ResourceCounts);}
272  __forceinline Uint32 GetPackedCounts()const{ return m_ResourceCounts;}
273 
274  __forceinline void GetResourceArrays(CachedCB* &CBs, ID3D11Buffer** &pd3d11CBs,
275  CachedResource* &SRVResources, ID3D11ShaderResourceView** &d3d11SRVs,
276  CachedSampler* &Samplers, ID3D11SamplerState** &pd3d11Samplers,
277  CachedResource* &UAVResources, ID3D11UnorderedAccessView** &pd3d11UAVs)
278  {
279  VERIFY_EXPR(IsInitialized());
280  CBs = reinterpret_cast<CachedCB*>( m_pResourceData );
281  pd3d11CBs = reinterpret_cast<ID3D11Buffer**>( CBs + GetCBCount() );
282  SRVResources = reinterpret_cast<CachedResource*>( pd3d11CBs + GetCBCount() );
283  d3d11SRVs = reinterpret_cast<ID3D11ShaderResourceView**>( SRVResources + GetSRVCount() );
284  Samplers = reinterpret_cast<CachedSampler*>( d3d11SRVs + GetSRVCount() );
285  pd3d11Samplers = reinterpret_cast<ID3D11SamplerState**>( Samplers + GetSamplerCount() );
286  UAVResources = reinterpret_cast<CachedResource*>( pd3d11Samplers + GetSamplerCount() );
287  pd3d11UAVs = reinterpret_cast<ID3D11UnorderedAccessView**>( UAVResources + GetUAVCount() );
288  }
289 
290  __forceinline void GetCBArrays(CachedCB* &CBs, ID3D11Buffer** &pd3d11CBs)
291  {
292  CBs = reinterpret_cast<CachedCB*>( m_pResourceData );
293  pd3d11CBs = reinterpret_cast<ID3D11Buffer**>( CBs + GetCBCount() );
294  }
295 
296  __forceinline void GetSRVArrays(CachedResource* &SRVResources, ID3D11ShaderResourceView** &d3d11SRVs)
297  {
298  SRVResources = reinterpret_cast<CachedResource*>( m_pResourceData + (sizeof(CachedCB) + sizeof(ID3D11Buffer*)) * GetCBCount() );
299  d3d11SRVs = reinterpret_cast<ID3D11ShaderResourceView**>( SRVResources + GetSRVCount() );
300  }
301 
302  __forceinline void GetSamplerArrays(CachedSampler* &Samplers, ID3D11SamplerState** &pd3d11Samplers)
303  {
304  Samplers = reinterpret_cast<CachedSampler*>( m_pResourceData +
305  (sizeof(CachedCB) + sizeof(ID3D11Buffer*)) * GetCBCount() +
306  (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)) * GetSRVCount() );
307  pd3d11Samplers = reinterpret_cast<ID3D11SamplerState**>( Samplers + GetSamplerCount() );
308  }
309 
310  __forceinline void GetUAVArrays(CachedResource* &UAVResources, ID3D11UnorderedAccessView** &pd3d11UAVs)
311  {
312  UAVResources = reinterpret_cast<CachedResource*>( m_pResourceData +
313  (sizeof(CachedCB) + sizeof(ID3D11Buffer*)) * GetCBCount() +
314  (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)) * GetSRVCount() +
315  (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*)) * GetSamplerCount() );
316  pd3d11UAVs = reinterpret_cast<ID3D11UnorderedAccessView**>( UAVResources + GetUAVCount() );
317  }
318 
319  __forceinline bool IsInitialized()const{return m_ResourceCounts != InvalidResourceCounts;}
320 
321 private:
322 
323  template<typename TCachedResourceType, typename TGetResourceArraysFunc, typename TSrcResourceType, typename TD3D11ResourceType>
324  __forceinline void SetD3D11ResourceInternal(Uint32 Slot, Uint32 Size,
325  TGetResourceArraysFunc GetArrays,
326  TSrcResourceType &&pResource,
327  TD3D11ResourceType *pd3d11Resource)
328  {
329  VERIFY(Slot < Size, "Resource cache is not big enough" );
330  VERIFY(pResource != nullptr && pd3d11Resource != nullptr || pResource == nullptr && pd3d11Resource == nullptr,
331  "Resource and D3D11 resource must be set/unset atomically");
332  TCachedResourceType* Resources;
333  TD3D11ResourceType** d3d11ResArr;
334  (this->*GetArrays)(Resources, d3d11ResArr);
335  Resources[Slot].Set(std::forward<TSrcResourceType>(pResource));
336  d3d11ResArr[Slot] = pd3d11Resource;
337  }
338 
339  static constexpr Uint32 InvalidResourceCounts = 0xFFFFFFFF;
340  // Resource limits in D3D11:
341  // Max CB count: 14
342  // Max SRV count: 128
343  // Max Sampler count: 16
344  // Max UAV count: 8
345  Uint32 m_ResourceCounts = InvalidResourceCounts; // CBCount == (m_ResourceCounts >> 0) & 0xFF
346  // SRVCount == (m_ResourceCounts >> 8) & 0xFF
347  // SamplerCount == (m_ResourceCounts >> 16) & 0xFF
348  // UAVCount == (m_ResourceCounts >> 24) & 0xFF
349  Uint8 *m_pResourceData = nullptr;
350 
351 #ifdef _DEBUG
352  IMemoryAllocator *m_pdbgMemoryAllocator = nullptr;
353 #endif
354 };
355 
356 }
Base implementation of the Diligent::ITextureD3D11 interface.
Definition: TextureBaseD3D11.h:50
The class implements a cache that holds resources bound to a specific shader stage.
Definition: ShaderResourceCacheD3D11.h:46
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
RefCntAutoPtr< class SamplerD3D11Impl > pSampler
Strong reference to the sampler.
Definition: ShaderResourceCacheD3D11.h:75
Describes resources associated with the cached SRV or UAV.
Definition: ShaderResourceCacheD3D11.h:83
Describes resources associated with the cached constant buffer.
Definition: ShaderResourceCacheD3D11.h:61
Implementation of the Diligent::ISamplerD3D11 interface.
Definition: SamplerD3D11Impl.h:38
RefCntAutoPtr< IDeviceObject > pView
Wee keep strong reference to the view instead of the reference to the texture or buffer because this ...
Definition: ShaderResourceCacheD3D11.h:90
Template class that implements reference counting.
Definition: RefCntAutoPtr.h:71
RefCntAutoPtr< BufferD3D11Impl > pBuff
Strong reference to the buffer.
Definition: ShaderResourceCacheD3D11.h:64
Describes resources associated with the cached sampler.
Definition: ShaderResourceCacheD3D11.h:72
Implementation of the Diligent::IBufferD3D11 interface.
Definition: BufferD3D11Impl.h:51