Diligent Engine API Reference: D:/GitHub/DiligentEngine/DiligentCore/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.h Source File

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/
46 class ShaderResourceCacheD3D11
47 {
48 public:
49 ShaderResourceCacheD3D11()
50 {}
51
52 ~ShaderResourceCacheD3D11();
53
54
55 ShaderResourceCacheD3D11(const ShaderResourceCacheD3D11&) = delete;
56 ShaderResourceCacheD3D11& operator = (const ShaderResourceCacheD3D11&) = delete;
57 ShaderResourceCacheD3D11(ShaderResourceCacheD3D11&&) = delete;
58 ShaderResourceCacheD3D11& operator = (ShaderResourceCacheD3D11&&) = delete;
59
61 struct CachedCB
62 {
64 RefCntAutoPtr<BufferD3D11Impl> pBuff;
65 __forceinline void Set(RefCntAutoPtr<BufferD3D11Impl> &&_pBuff)
66 {
67 pBuff = std::move(_pBuff);
68 }
69 };
70
72 struct CachedSampler
73 {
75 RefCntAutoPtr<class SamplerD3D11Impl> pSampler;
76 __forceinline void Set(SamplerD3D11Impl *pSam)
77 {
78 pSampler = pSam;
79 }
80 };
81
83 struct CachedResource
84 {
90 RefCntAutoPtr<IDeviceObject> pView;
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 }
Diligent::TextureBaseD3D11
Base implementation of the Diligent::ITextureD3D11 interface.
Definition: TextureBaseD3D11.h:50
Diligent::ShaderResourceCacheD3D11
The class implements a cache that holds resources bound to a specific shader stage.
Definition: ShaderResourceCacheD3D11.h:46
Diligent
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
Diligent::ShaderResourceCacheD3D11::CachedSampler::pSampler
RefCntAutoPtr< class SamplerD3D11Impl > pSampler
Strong reference to the sampler.
Definition: ShaderResourceCacheD3D11.h:75
Diligent::ShaderResourceCacheD3D11::CachedResource
Describes resources associated with the cached SRV or UAV.
Definition: ShaderResourceCacheD3D11.h:83
Diligent::ShaderResourceCacheD3D11::CachedCB
Describes resources associated with the cached constant buffer.
Definition: ShaderResourceCacheD3D11.h:61
Diligent::SamplerD3D11Impl
Implementation of the Diligent::ISamplerD3D11 interface.
Definition: SamplerD3D11Impl.h:38
Diligent::ShaderResourceCacheD3D11::CachedResource::pView
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
Diligent::RefCntAutoPtr
Template class that implements reference counting.
Definition: RefCntAutoPtr.h:71
Diligent::ShaderResourceCacheD3D11::CachedCB::pBuff
RefCntAutoPtr< BufferD3D11Impl > pBuff
Strong reference to the buffer.
Definition: ShaderResourceCacheD3D11.h:64
Diligent::ShaderResourceCacheD3D11::CachedSampler
Describes resources associated with the cached sampler.
Definition: ShaderResourceCacheD3D11.h:72
Diligent::BufferD3D11Impl
Implementation of the Diligent::IBufferD3D11 interface.
Definition: BufferD3D11Impl.h:51