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

Diligent Engine API Reference

ShaderResources.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
29
30 // ShaderResources class uses continuous chunk of memory to store all resources, as follows:
31 //
32 //
33 // m_MemoryBuffer m_TexSRVOffset m_TexUAVOffset m_BufSRVOffset m_BufUAVOffset m_SamplersOffset m_MemorySize
34 // | | | | | | |
35 // | CB[0] ... CB[Ncb-1] | TexSRV[0] ... TexSRV[Ntsrv-1] | TexUAV[0] ... TexUAV[Ntuav-1] | BufSRV[0] ... BufSRV[Nbsrv-1] | BufUAV[0] ... BufUAV[Nbuav-1] | Sam[0] ... Sam[Nsam-1] |
36 //
37 // Ncb - number of constant buffers
38 // Ntsrv - number of texture SRVs
39 // Ntuav - number of texture UAVs
40 // Nbsrv - number of buffer SRVs
41 // Nbuav - number of buffer UAVs
42 // Nsam - number of samplers
43 //
44 //
45 // If texture SRV is assigned a sampler, it is referenced through SamplerId:
46 //
47 // _________________________SamplerId_______________________
48 // | |
49 // | V
50 // | CBs | ... TexSRV[n] ... | TexUAVs | BufSRVs | BufUAVs | Sam[0] ... Sam[SamplerId] ... |
51 //
52 //
53
54 #include <memory>
55
56 #define NOMINMAX
57 #include <d3dcommon.h>
58
59 #include "Shader.h"
60 #include "STDAllocator.h"
61
62 namespace Diligent
63 {
64
65 static const Char* D3DSamplerSuffix = "_sampler";
66
67 inline bool IsAllowedType(SHADER_VARIABLE_TYPE VarType, Uint32 AllowedTypeBits)noexcept
68 {
69 return ((1 << VarType) & AllowedTypeBits) != 0;
70 }
71
72 inline Uint32 GetAllowedTypeBits(const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes)noexcept
73 {
74 if(AllowedVarTypes == nullptr)
75 return 0xFFFFFFFF;
76
77 Uint32 AllowedTypeBits = 0;
78 for(Uint32 i=0; i < NumAllowedTypes; ++i)
79 AllowedTypeBits |= 1 << AllowedVarTypes[i];
80 return AllowedTypeBits;
81 }
82
83
84 struct D3DShaderResourceAttribs
85 {
86 D3DShaderResourceAttribs(String &&_Name,
87 UINT _BindPoint,
88 UINT _BindCount,
89 D3D_SHADER_INPUT_TYPE _InputType,
90 SHADER_VARIABLE_TYPE _VariableType,
91 D3D_SRV_DIMENSION SRVDimension,
92 Uint32 SamplerId,
93 bool _IsStaticSampler) :
94 Name(std::move(_Name)),
95 BindPoint(static_cast<Uint16>(_BindPoint)),
96 BindCount(static_cast<Uint16>(_BindCount)),
97 PackedAttribs( PackAttribs(_InputType, _VariableType, SRVDimension, SamplerId, _IsStaticSampler) )
98 {
99 VERIFY( static_cast<Uint32>(_InputType) <= ShaderInputTypeMask, "Shader input type is out of expected range");
100 VERIFY( static_cast<Uint32>(_VariableType) <= VariableTypeMask, "Variable type is out of expected range");
101 VERIFY( static_cast<Uint32>(SRVDimension) <= SRVDimMask, "SRV dimensions is out of expected range");
102 VERIFY(SamplerId <= SamplerIdMask, "Sampler Id is out of allowed range" );
103 VERIFY_EXPR(GetInputType() == _InputType);
104 VERIFY_EXPR(GetVariableType() == _VariableType);
105 VERIFY(_BindPoint <= MaxBindPoint || _BindPoint == InvalidBindPoint, "Bind Point is out of allowed range" );
106 VERIFY(_BindCount <= MaxBindCount, "Bind Count is out of allowed range" );
107 #ifdef _DEBUG
108 if(_InputType==D3D_SIT_SAMPLER)
109 {
110 VERIFY_EXPR(IsStaticSampler() == _IsStaticSampler);
111 }
112 else
113 {
114 VERIFY(!_IsStaticSampler, "Only samplers can be marked as static");
115 }
116
117 if (_InputType == D3D_SIT_TEXTURE)
118 {
119 VERIFY_EXPR(GetSamplerId() == SamplerId);
120 }
121 else
122 {
123 VERIFY(SamplerId == InvalidSamplerId, "Only textures can be assigned valid texture sampler");
124 }
125
126 if(_IsStaticSampler)
127 {
128 VERIFY( _InputType == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" );
129 }
130 #endif
131 }
132
133 D3DShaderResourceAttribs(const D3DShaderResourceAttribs& rhs) = default;
134
135 D3DShaderResourceAttribs(const D3DShaderResourceAttribs& rhs, Uint32 SamplerId)noexcept :
136 Name(rhs.Name),
137 BindPoint(rhs.BindPoint),
138 BindCount(rhs.BindCount),
139 PackedAttribs( PackAttribs(rhs.GetInputType(), rhs.GetVariableType(), rhs.GetSRVDimension(), SamplerId, false) )
140 {
141 VERIFY(GetInputType() == D3D_SIT_TEXTURE, "Only textures can be assigned a texture sampler");
142
143 VERIFY_EXPR(GetInputType() == rhs.GetInputType());
144 VERIFY_EXPR(GetVariableType() == rhs.GetVariableType());
145 VERIFY_EXPR(GetSamplerId() == SamplerId);
146 }
147
148 D3DShaderResourceAttribs(D3DShaderResourceAttribs&& rhs, Uint32 SamplerId)noexcept :
149 Name(std::move(rhs.Name)),
150 BindPoint(rhs.BindPoint),
151 BindCount(rhs.BindCount),
152 PackedAttribs( PackAttribs(rhs.GetInputType(), rhs.GetVariableType(), rhs.GetSRVDimension(), SamplerId, false) )
153 {
154 VERIFY(GetInputType() == D3D_SIT_TEXTURE, "Only textures can be assigned a texture sampler");
155
156 VERIFY_EXPR(GetInputType() == rhs.GetInputType());
157 VERIFY_EXPR(GetVariableType() == rhs.GetVariableType());
158 VERIFY_EXPR(GetSamplerId() == SamplerId);
159 }
160
161 D3DShaderResourceAttribs(D3DShaderResourceAttribs&& rhs)noexcept :
162 Name(std::move(rhs.Name)),
163 BindPoint(rhs.BindPoint),
164 BindCount(rhs.BindCount),
165 PackedAttribs( rhs.PackedAttribs )
166 {
167 }
168
169 D3D_SHADER_INPUT_TYPE GetInputType()const
170 {
171 return static_cast<D3D_SHADER_INPUT_TYPE>( (PackedAttribs >> ShaderInputTypeBitOffset) & ShaderInputTypeMask );
172 }
173
174 SHADER_VARIABLE_TYPE GetVariableType()const
175 {
176 return static_cast<SHADER_VARIABLE_TYPE>( (PackedAttribs >> VariableTypeBitOffset) & VariableTypeMask );
177 }
178
179 D3D_SRV_DIMENSION GetSRVDimension()const
180 {
181 return static_cast<D3D_SRV_DIMENSION>( (PackedAttribs >> SRVDimBitOffset) & SRVDimMask );
182 }
183
184 Uint32 GetSamplerId()const
185 {
186 VERIFY( GetInputType() == D3D_SIT_TEXTURE, "Invalid input type: D3D_SIT_TEXTURE is expected" );
187 return (PackedAttribs >> SamplerIdBitOffset) & SamplerIdMask;
188 }
189
190 bool IsStaticSampler()const
191 {
192 VERIFY( GetInputType() == D3D_SIT_SAMPLER, "Invalid input type: D3D_SIT_SAMPLER is expected" );
193 return (PackedAttribs & (1 << IsStaticSamplerFlagBitOffset)) != 0;
194 }
195
196 bool IsValidSampler()const
197 {
198 VERIFY( GetInputType() == D3D_SIT_TEXTURE, "Invalid input type: D3D_SIT_TEXTURE is expected" );
199 return GetSamplerId() != InvalidSamplerId;
200 }
201
202 bool IsValidBindPoint()const
203 {
204 return BindPoint != InvalidBindPoint;
205 }
206
207 static constexpr Uint16 InvalidBindPoint = std::numeric_limits<Uint16>::max();
208
209 String Name; // Move ctor will not work if it is const
210 const Uint16 BindPoint;
211 const Uint16 BindCount;
212
213 String GetPrintName(Uint32 ArrayInd)const
214 {
215 VERIFY_EXPR(ArrayInd < BindCount);
216 if(BindCount > 1)
217 return String(Name) + '[' + std::to_string(ArrayInd) + ']';
218 else
219 return Name;
220 }
221 private:
222 static constexpr Uint16 MaxBindPoint = InvalidBindPoint-1;
223 static constexpr Uint16 MaxBindCount = std::numeric_limits<Uint16>::max();
224
225 static constexpr Uint32 ShaderInputTypeBits = 4; // Max value: D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER==11
226 static constexpr Uint32 ShaderInputTypeMask = (1 << ShaderInputTypeBits)-1;
227 static constexpr Uint32 ShaderInputTypeBitOffset = 0;
228 static_assert( D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER <= ShaderInputTypeMask, "Not enough bits to represent D3D_SHADER_INPUT_TYPE" );
229
230 static constexpr Uint32 VariableTypeBits = 3; // Max value: SHADER_VARIABLE_TYPE_DYNAMIC == 2
231 static constexpr Uint32 VariableTypeMask = (1<<VariableTypeBits)-1;
232 static constexpr Uint32 VariableTypeBitOffset = ShaderInputTypeBitOffset + ShaderInputTypeBits;
233 static_assert( SHADER_VARIABLE_TYPE_NUM_TYPES-1 <= VariableTypeMask, "Not enough bits to represent SHADER_VARIABLE_TYPE" );
234
235 static constexpr Uint32 SRVDimBits = 4; // Max value: D3D_SRV_DIMENSION_BUFFEREX == 11
236 static constexpr Uint32 SRVDimMask = (1<<SRVDimBits)-1;
237 static constexpr Uint32 SRVDimBitOffset = VariableTypeBitOffset + VariableTypeBits;
238 static_assert( D3D_SRV_DIMENSION_BUFFEREX <= SRVDimMask, "Not enough bits to represent D3D_SRV_DIMENSION" );
239
240 static constexpr Uint32 SamplerIdBits = 32 - 1 - ShaderInputTypeBits - VariableTypeBits - SRVDimBits;
241 static constexpr Uint32 SamplerIdMask = (1 << SamplerIdBits) - 1;
242 static constexpr Uint32 SamplerIdBitOffset = SRVDimBitOffset + SRVDimBits;
243 public:
244 static constexpr Uint32 InvalidSamplerId = SamplerIdMask;
245 private:
246
247 static constexpr Uint32 IsStaticSamplerFlagBits = 1;
248 static constexpr Uint32 IsStaticSamplerFlagMask = (1 << IsStaticSamplerFlagBits) - 1;
249 static constexpr Uint32 IsStaticSamplerFlagBitOffset = SamplerIdBitOffset + SamplerIdBits;
250 static_assert(IsStaticSamplerFlagBitOffset == 31, "Unexpected static sampler flag offset");
251
252 static Uint32 PackAttribs(D3D_SHADER_INPUT_TYPE _InputType, SHADER_VARIABLE_TYPE _VariableType, D3D_SRV_DIMENSION SRVDimension, Uint32 SamplerId, bool _IsStaticSampler)
253 {
254 return ((static_cast<Uint32>(_InputType) & ShaderInputTypeMask) << ShaderInputTypeBitOffset) |
255 ((static_cast<Uint32>(_VariableType) & VariableTypeMask) << VariableTypeBitOffset ) |
256 ((static_cast<Uint32>(SRVDimension) & SRVDimMask) << SRVDimBitOffset) |
257 ((SamplerId & SamplerIdMask) << SamplerIdBitOffset) |
258 ((_IsStaticSampler ? 1 : 0) << IsStaticSamplerFlagBitOffset);
259 }
260
261 // 4 3 4 20 1
262 // bit | 0 1 2 3 | 4 5 6 | 7 8 9 10 | 11 12 ... 30 | 31 |
263 // | | | | | |
264 // | InputType | VariableType | SRV Dim | SamplerId | StaticSamplerFlag |
265 const Uint32 PackedAttribs;
266 };
267
268
270 class ShaderResources
271 {
272 public:
273 ShaderResources(IMemoryAllocator &Allocator, SHADER_TYPE ShaderType);
274
275 // Copies specified types of resources from another ShaderResources objects
276 // Only resources listed in AllowedVarTypes are copied
277 ShaderResources(IMemoryAllocator &Allocator,
278 const ShaderResources& SrcResources,
279 const SHADER_VARIABLE_TYPE *AllowedVarTypes,
280 Uint32 NumAllowedTypes);
281
282 ShaderResources (const ShaderResources&) = delete;
283 ShaderResources (ShaderResources&&) = delete;
284 ShaderResources& operator = (const ShaderResources&) = delete;
285 ShaderResources& operator = (ShaderResources&&) = delete;
286
287 ~ShaderResources();
288
289 Uint32 GetNumCBs() const noexcept{ return (m_TexSRVOffset - 0); }
290 Uint32 GetNumTexSRV() const noexcept{ return (m_TexUAVOffset - m_TexSRVOffset); }
291 Uint32 GetNumTexUAV() const noexcept{ return (m_BufSRVOffset - m_TexUAVOffset); }
292 Uint32 GetNumBufSRV() const noexcept{ return (m_BufUAVOffset - m_BufSRVOffset); }
293 Uint32 GetNumBufUAV() const noexcept{ return (m_SamplersOffset - m_BufUAVOffset); }
294 Uint32 GetNumSamplers()const noexcept{ return (m_BufferEndOffset- m_SamplersOffset); }
295
296 const D3DShaderResourceAttribs& GetCB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumCBs(), 0); }
297 const D3DShaderResourceAttribs& GetTexSRV (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); }
298 const D3DShaderResourceAttribs& GetTexUAV (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); }
299 const D3DShaderResourceAttribs& GetBufSRV (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); }
300 const D3DShaderResourceAttribs& GetBufUAV (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); }
301 const D3DShaderResourceAttribs& GetSampler(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); }
302
303
304 void CountResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes,
305 Uint32& NumCBs, Uint32& NumTexSRVs, Uint32& NumTexUAVs,
306 Uint32& NumBufSRVs, Uint32& NumBufUAVs, Uint32& NumSamplers)const noexcept;
307
308 SHADER_TYPE GetShaderType()const noexcept{return m_ShaderType;}
309
310 // Process only resources listed in AllowedVarTypes
311 template<typename THandleCB,
312 typename THandleTexSRV,
313 typename THandleTexUAV,
314 typename THandleBufSRV,
315 typename THandleBufUAV>
316 void ProcessResources(const SHADER_VARIABLE_TYPE *AllowedVarTypes,
317 Uint32 NumAllowedTypes,
318 THandleCB HandleCB,
319 THandleTexSRV HandleTexSRV,
320 THandleTexUAV HandleTexUAV,
321 THandleBufSRV HandleBufSRV,
322 THandleBufUAV HandleBufUAV)const
323 {
324 Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
325
326 for(Uint32 n=0; n < GetNumCBs(); ++n)
327 {
328 const auto& CB = GetCB(n);
329 if( IsAllowedType(CB.GetVariableType(), AllowedTypeBits) )
330 HandleCB(CB);
331 }
332
333 for(Uint32 n=0; n < GetNumTexSRV(); ++n)
334 {
335 const auto &TexSRV = GetTexSRV(n);
336 if( IsAllowedType(TexSRV.GetVariableType(), AllowedTypeBits) )
337 HandleTexSRV(TexSRV);
338 }
339
340 for(Uint32 n=0; n < GetNumTexUAV(); ++n)
341 {
342 const auto &TexUAV = GetTexUAV(n);
343 if( IsAllowedType(TexUAV.GetVariableType(), AllowedTypeBits) )
344 HandleTexUAV(TexUAV);
345 }
346
347 for(Uint32 n=0; n < GetNumBufSRV(); ++n)
348 {
349 const auto &BufSRV = GetBufSRV(n);
350 if( IsAllowedType(BufSRV.GetVariableType(), AllowedTypeBits) )
351 HandleBufSRV(BufSRV);
352 }
353
354 for(Uint32 n=0; n < GetNumBufUAV(); ++n)
355 {
356 const auto& BufUAV = GetBufUAV(n);
357 if( IsAllowedType(BufUAV.GetVariableType(), AllowedTypeBits) )
358 HandleBufUAV(BufUAV);
359 }
360 }
361
362 protected:
363 void Initialize(IMemoryAllocator &Allocator, Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers);
364
365 __forceinline D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset)noexcept
366 {
367 VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Max allowed index: ", NumResources-1);
368 VERIFY_EXPR(Offset + n < m_BufferEndOffset);
369 return reinterpret_cast<D3DShaderResourceAttribs*>(m_MemoryBuffer.get())[Offset + n];
370 }
371
372 __forceinline const D3DShaderResourceAttribs& GetResAttribs(Uint32 n, Uint32 NumResources, Uint32 Offset)const noexcept
373 {
374 VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Max allowed index: ", NumResources-1);
375 VERIFY_EXPR(Offset + n < m_BufferEndOffset);
376 return reinterpret_cast<D3DShaderResourceAttribs*>(m_MemoryBuffer.get())[Offset + n];
377 }
378
379 D3DShaderResourceAttribs& GetCB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumCBs(), 0); }
380 D3DShaderResourceAttribs& GetTexSRV (Uint32 n)noexcept{ return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); }
381 D3DShaderResourceAttribs& GetTexUAV (Uint32 n)noexcept{ return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); }
382 D3DShaderResourceAttribs& GetBufSRV (Uint32 n)noexcept{ return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); }
383 D3DShaderResourceAttribs& GetBufUAV (Uint32 n)noexcept{ return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); }
384 D3DShaderResourceAttribs& GetSampler(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); }
385
386 Uint32 FindAssignedSamplerId(const D3DShaderResourceAttribs& TexSRV)const;
387
388 private:
389 // Memory buffer that holds all resources as continuous chunk of memory:
390 // | CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers |
391 std::unique_ptr< void, STDDeleterRawMem<void> > m_MemoryBuffer;
392
393 // Offsets in elements of D3DShaderResourceAttribs
394 typedef Uint16 OffsetType;
395 OffsetType m_TexSRVOffset = 0;
396 OffsetType m_TexUAVOffset = 0;
397 OffsetType m_BufSRVOffset = 0;
398 OffsetType m_BufUAVOffset = 0;
399 OffsetType m_SamplersOffset = 0;
400 OffsetType m_BufferEndOffset = 0;
401
402 SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN;
403 };
404
405 }
Diligent::SHADER_TYPE
SHADER_TYPE
Describes the shader type.
Definition: Shader.h:46
Diligent
Graphics engine namespace.
Definition: AdaptiveFixedBlockAllocator.h:30
std
Definition: AdvancedMath.h:316
Diligent::ShaderResources
Diligent::ShaderResources class.
Definition: ShaderResources.h:270
Diligent::IMemoryAllocator
Base interface for a raw memory allocator.
Definition: MemoryAllocator.h:35
Diligent::SHADER_VARIABLE_TYPE
SHADER_VARIABLE_TYPE
Describes shader variable type that is used by ShaderVariableDesc.
Definition: Shader.h:100
Diligent::String
std::basic_string< Char > String
String variable.
Definition: BasicTypes.h:51
Diligent::SHADER_TYPE_UNKNOWN
Unknown shader type.
Definition: Shader.h:48
Diligent::Uint16
uint16_t Uint16
16-bit unsigned integer
Definition: BasicTypes.h:40
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:39
Diligent::SHADER_VARIABLE_TYPE_NUM_TYPES
Total number of shader variable types.
Definition: Shader.h:117