git.s-ol.nu ~forks/DiligentCore / 78fa6c9
merged with resource_signature azhirnov authored 7 months ago assiduous committed 6 months ago
50 changed file(s) with 4844 addition(s) and 4575 deletion(s). Raw diff Collapse all Expand all
194194 // All the access functions do not require locking reference counters pointer because if it is valid,
195195 // the smart pointer holds strong reference to the object and it thus cannot be released by
196196 // ohter thread
197 bool operator!() const noexcept { return m_pObject == nullptr; }
198 operator bool() const noexcept { return m_pObject != nullptr; }
199 bool operator==(const RefCntAutoPtr& Ptr) const noexcept { return m_pObject == Ptr.m_pObject; }
200 bool operator!=(const RefCntAutoPtr& Ptr) const noexcept { return m_pObject != Ptr.m_pObject; }
201 bool operator<(const RefCntAutoPtr& Ptr) const noexcept { return static_cast<const T*>(*this) < static_cast<const T*>(Ptr); }
197 bool operator!() const noexcept { return m_pObject == nullptr; }
198 explicit operator bool() const noexcept { return m_pObject != nullptr; }
199 bool operator==(const RefCntAutoPtr& Ptr) const noexcept { return m_pObject == Ptr.m_pObject; }
200 bool operator!=(const RefCntAutoPtr& Ptr) const noexcept { return m_pObject != Ptr.m_pObject; }
201 bool operator<(const RefCntAutoPtr& Ptr) const noexcept { return static_cast<const T*>(*this) < static_cast<const T*>(Ptr); }
202202
203203 T& operator*() noexcept { return *m_pObject; }
204204 const T& operator*() const noexcept { return *m_pObject; }
11871187
11881188 auto Flag = ExtractLSB(Flags);
11891189
1190 static_assert(PIPELINE_RESOURCE_FLAG_LAST == 0x04, "Please update the switch below to handle the new pipeline resource flag.");
1190 static_assert(PIPELINE_RESOURCE_FLAG_LAST == 0x08, "Please update the switch below to handle the new pipeline resource flag.");
11911191 switch (Flag)
11921192 {
11931193 case PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS:
12001200
12011201 case PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER:
12021202 Str.append(GetFullName ? "PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER" : "FORMATTED_BUFFER");
1203 break;
1204
1205 case PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY:
1206 Str.append(GetFullName ? "PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY" : "RUNTIME_ARRAY");
12031207 break;
12041208
12051209 default:
100100 return std::pair<Uint32, Uint32>{m_ResourceOffsets[VarType], m_ResourceOffsets[VarType + 1]};
101101 }
102102
103 SHADER_TYPE GetActiveShaderStages() const { return m_ShaderStages; }
104
105103 // Returns the number of shader stages that have resources.
106104 Uint32 GetNumActiveShaderStages() const { return m_NumShaderStages; }
107105
16421642
16431643 /// Indicates if device supports reading 8-bit types from uniform buffers.
16441644 DEVICE_FEATURE_STATE UniformBuffer8BitAccess DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
1645
1646 /// Indicates if device supports runtime-sized arrays in shader.
1647 /// DirectX 12 backend already supports this feature,
1648 /// Vulkan backend has optional support,
1649 /// other backends are does not support this feature.
1650 DEVICE_FEATURE_STATE ShaderResourceRuntimeArray DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
16451651
16461652
16471653 #if DILIGENT_CPP_INTERFACE
16791685 ShaderInputOutput16 {State},
16801686 ShaderInt8 {State},
16811687 ResourceBuffer8BitAccess {State},
1682 UniformBuffer8BitAccess {State}
1688 UniformBuffer8BitAccess {State},
1689 ShaderResourceRuntimeArray {State}
16831690 {
16841691 # if defined(_MSC_VER) && defined(_WIN64)
1685 static_assert(sizeof(*this) == 32, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
1692 static_assert(sizeof(*this) == 33, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
16861693 # endif
16871694 }
16881695 #endif
107107 /// PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER flag.
108108 PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER = 0x04,
109109
110 PIPELINE_RESOURCE_FLAG_LAST = PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER
110 /// DirectX 12 only - runtime sized array must be in separate space.
111 PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY = 0x08,
112
113 PIPELINE_RESOURCE_FLAG_LAST = PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY
111114 };
112115 DEFINE_FLAG_ENUM_OPERATORS(PIPELINE_RESOURCE_FLAGS);
113116
461461
462462 /// Direct3D12 only: the name of the constant buffer that will be used by the local root signature.
463463 /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero.
464 /// In Vulkan backend in HLSL add [[vk::shader_record_nv]] attribute to the constant buffer, in GLSL add shaderRecord layout to buffer.
464 /// In Vulkan backend in HLSL add [[vk::shader_record_ext]] attribute to the constant buffer, in GLSL add shaderRecord layout to buffer.
465465 const char* pShaderRecordName DEFAULT_INITIALIZER(nullptr);
466466
467467 /// Direct3D12 only: the maximum hit shader attribute size in bytes.
578578
579579
580580 /// Checks if this pipeline state object is compatible with another PSO
581 // Deprecated: use IsCompatibleWith() for pipeline resource signature.
582581
583582 /// If two pipeline state objects are compatible, they can use shader resource binding
584583 /// objects interchangebly, i.e. SRBs created by one PSO can be committed
592591 /// to commit resources for the second pipeline, a runtime error will occur.\n
593592 /// The function only checks compatibility of shader resource layouts. It does not take
594593 /// into account vertex shader input layout, number of outputs, etc.
594 ///
595 /// \remarks On Vulkan backend PSO may be partially compatible, on other backends this behavior is emulated.
596 /// For Vulkan changing PSO between totally or partially compatible may increase performance,
597 /// for DirectX 12 only changing PSO between compatible may increase performance.
595598 VIRTUAL bool METHOD(IsCompatibleWith)(THIS_
596599 const struct IPipelineState* pPSO) CONST PURE;
597600
3030 include/ShaderD3D12Impl.hpp
3131 include/ShaderResourceBindingD3D12Impl.hpp
3232 include/ShaderResourceCacheD3D12.hpp
33 include/ShaderResourceLayoutD3D12.hpp
3433 include/ShaderResourcesD3D12.hpp
3534 include/ShaderVariableD3D12.hpp
3635 include/SwapChainD3D12Impl.hpp
3938 include/BottomLevelASD3D12Impl.hpp
4039 include/TopLevelASD3D12Impl.hpp
4140 include/ShaderBindingTableD3D12Impl.hpp
41 include/PipelineResourceSignatureD3D12Impl.hpp
4242 )
4343
4444 set(INTERFACE
8888 src/ShaderD3D12Impl.cpp
8989 src/ShaderResourceBindingD3D12Impl.cpp
9090 src/ShaderResourceCacheD3D12.cpp
91 src/ShaderResourceLayoutD3D12.cpp
9291 src/ShaderResourcesD3D12.cpp
9392 src/ShaderVariableD3D12.cpp
9493 src/SwapChainD3D12Impl.cpp
9796 src/BottomLevelASD3D12Impl.cpp
9897 src/TopLevelASD3D12Impl.cpp
9998 src/ShaderBindingTableD3D12Impl.cpp
99 src/PipelineResourceSignatureD3D12Impl.cpp
100100 )
101101
102102 if(PLATFORM_WIN32)
155155 {
156156 return pSrvCbvUavHeap == rhs.pSrvCbvUavHeap && pSamplerHeap == rhs.pSamplerHeap;
157157 }
158 operator bool() const
158 explicit operator bool() const
159159 {
160160 return pSrvCbvUavHeap != nullptr || pSamplerHeap != nullptr;
161161 }
247247 class ComputeContext : public CommandContext
248248 {
249249 public:
250 // For compute and ray tracing.
250251 void SetComputeRootSignature(ID3D12RootSignature* pRootSig)
251252 {
252253 if (pRootSig != m_pCurComputeRootSignature)
385385 ID3D12Resource*& pd3d12ArgsBuff,
386386 Uint64& BuffDataStartByteOffset);
387387
388 struct RootTableInfo
389 {
390 using Bitfield = Uint8;
391 static_assert(sizeof(Bitfield) * 8 >= MAX_RESOURCE_SIGNATURES, "not enought space to store MAX_RESOURCE_SIGNATURES bits");
392
393 //Bitfield ActiveSRBMask ; // Indicates which SRBs are active in current PSO
394 bool bRootViewsCommitted; // Indicates if root views have been committed since the time SRB has been committed.
395 bool bRootTablesCommited;
396 bool IsCompute : 1;
397 ID3D12RootSignature* pRootSig;
398
399 std::array<class ShaderResourceBindingD3D12Impl*, MAX_RESOURCE_SIGNATURES> SRBs;
400
401 RootTableInfo(bool _IsCompute)
402 {
403 memset(this, 0, sizeof(*this));
404 IsCompute = _IsCompute;
405 }
406
407 __forceinline bool RequireUpdate(bool DynamicBuffersIntact = false) const
408 {
409 return true; //(StaleSRBMask & ActiveSRBMask) != 0 || ((DynamicBuffersMask & ActiveSRBMask) != 0 && !DynamicBuffersIntact);
410 }
411 };
412 __forceinline RootTableInfo& GetRootTableInfo(PIPELINE_TYPE PipelineType);
413
414 __forceinline void CommitRootTables(RootTableInfo& RootInfo);
415 #ifdef DILIGENT_DEVELOPMENT
416 void DvpValidateCommittedShaderResources();
417 #endif
418
388419 struct TextureUploadSpace
389420 {
390421 D3D12DynamicAllocation Allocation;
423454 // Indicates if currently committed D3D11 index buffer is up to date
424455 bool bCommittedD3D12IBUpToDate = false;
425456
426 // Indicates if root views have been committed since the time SRB
427 // has been committed.
428 bool bRootViewsCommitted = false;
429
430 class ShaderResourceCacheD3D12* pCommittedResourceCache = nullptr;
457 // AZ TODO
458 bool CommittedResourcesValidated = false;
431459 } m_State;
460
461 RootTableInfo m_GraphicsResources;
462 RootTableInfo m_ComputeResources;
432463
433464 CComPtr<ID3D12CommandSignature> m_pDrawIndirectSignature;
434465 CComPtr<ID3D12CommandSignature> m_pDrawIndexedIndirectSignature;
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Declaration of Diligent::PipelineResourceSignatureD3D12Impl class
31
32 #include <array>
33
34 #include "PipelineResourceSignatureBase.hpp"
35 #include "SRBMemoryAllocator.hpp"
36
37 namespace Diligent
38 {
39
40 class CommandContext;
41 class RenderDeviceD3D12Impl;
42 class DeviceContextD3D12Impl;
43 class ShaderResourceCacheD3D12;
44 class ShaderVariableManagerD3D12;
45
46 /// Implementation of the Diligent::PipelineResourceSignatureD3D12Impl class
47 class PipelineResourceSignatureD3D12Impl final : public PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceD3D12Impl>
48 {
49 friend class RootSignatureD3D12;
50
51 public:
52 using TPipelineResourceSignatureBase = PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceD3D12Impl>;
53
54 PipelineResourceSignatureD3D12Impl(IReferenceCounters* pRefCounters,
55 RenderDeviceD3D12Impl* pDevice,
56 const PipelineResourceSignatureDesc& Desc,
57 bool bIsDeviceInternal = false);
58 ~PipelineResourceSignatureD3D12Impl();
59
60 enum class CacheContentType
61 {
62 Signature = 0, // only static resources
63 SRB = 1 // in SRB
64 };
65
66 // sizeof(ResourceAttribs) == 16, x64
67 struct ResourceAttribs
68 {
69 private:
70 static constexpr Uint32 _BindPointBits = 16;
71 static constexpr Uint32 _SpaceBits = 8;
72 static constexpr Uint32 _SRBRootIndexBits = 16;
73 static constexpr Uint32 _SigRootIndexBits = 3;
74 static constexpr Uint32 _SamplerIndBits = 16;
75 static constexpr Uint32 _SamplerAssignedBits = 1;
76 static constexpr Uint32 _SigOffsetBits = 16;
77 static constexpr Uint32 _RootViewBits = 1;
78
79 static_assert((1u << _BindPointBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store bind point");
80 static_assert((1u << _SamplerIndBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store sampler resource index");
81
82 public:
83 static constexpr Uint32 InvalidSamplerInd = (1u << _SamplerIndBits) - 1;
84 static constexpr Uint32 InvalidSRBRootIndex = (1u << _SRBRootIndexBits) - 1;
85 static constexpr Uint32 InvalidSigRootIndex = (1u << _SigRootIndexBits) - 1;
86 static constexpr Uint32 InvalidBindPoint = (1u << _BindPointBits) - 1;
87 static constexpr Uint32 InvalidOffset = ~0u;
88
89 // clang-format off
90 const Uint32 BindPoint : _BindPointBits; // shader register
91 const Uint32 SRBRootIndex : _SRBRootIndexBits; // Root view/table index for SRB
92 const Uint32 SamplerInd : _SamplerIndBits; // Index in m_Desc.Resources and m_pResourceAttribs
93 const Uint32 SigRootIndex : _SigRootIndexBits; // Root table index for signature (static only)
94 const Uint32 Space : _SpaceBits; // shader register space
95 const Uint32 ImtblSamplerAssigned : _SamplerAssignedBits; // Immutable sampler flag
96 const Uint32 RootView : _RootViewBits; // Is root view (for debugging)
97 const Uint32 SigOffsetFromTableStart; // Offset in the root table for signature (static only)
98 const Uint32 SRBOffsetFromTableStart; // Offset in the root table for SRB
99 // clang-format on
100
101 ResourceAttribs(Uint32 _BindPoint,
102 Uint32 _Space,
103 Uint32 _SamplerInd,
104 Uint32 _SRBRootIndex,
105 Uint32 _SRBOffsetFromTableStart,
106 Uint32 _SigRootIndex,
107 Uint32 _SigOffsetFromTableStart,
108 bool _ImtblSamplerAssigned,
109 bool _IsRootView) noexcept :
110 // clang-format off
111 BindPoint {_BindPoint },
112 SRBRootIndex {_SRBRootIndex },
113 SamplerInd {_SamplerInd },
114 SigRootIndex {_SigRootIndex },
115 Space {_Space },
116 ImtblSamplerAssigned {_ImtblSamplerAssigned ? 1u : 0u},
117 RootView {_IsRootView ? 1u : 0u },
118 SigOffsetFromTableStart{_SigOffsetFromTableStart },
119 SRBOffsetFromTableStart{_SRBOffsetFromTableStart }
120 // clang-format on
121 {
122 VERIFY(BindPoint == _BindPoint, "Bind point (", _BindPoint, ") exceeds maximum representable value");
123 VERIFY(SRBRootIndex == _SRBRootIndex, "SRB Root index (", _SRBRootIndex, ") exceeds maximum representable value");
124 VERIFY(SigRootIndex == _SigRootIndex, "Signature Root index (", SigRootIndex, ") exceeds maximum representable value");
125 VERIFY(SamplerInd == _SamplerInd, "Sampler index (", _SamplerInd, ") exceeds maximum representable value");
126 VERIFY(Space == _Space, "Space (", Space, ") exceeds maximum representable value");
127 }
128
129 bool IsImmutableSamplerAssigned() const { return ImtblSamplerAssigned != 0; }
130 bool IsCombinedWithSampler() const { return SamplerInd != InvalidSamplerInd; }
131 bool IsRootView() const { return RootView != 0; }
132
133 Uint32 RootIndex(CacheContentType Type) const { return Type == CacheContentType::SRB ? SRBRootIndex : SigRootIndex; }
134 Uint32 OffsetFromTableStart(CacheContentType Type) const { return Type == CacheContentType::SRB ? SRBOffsetFromTableStart : SigOffsetFromTableStart; }
135 };
136
137 const ResourceAttribs& GetResourceAttribs(Uint32 ResIndex) const
138 {
139 VERIFY_EXPR(ResIndex < m_Desc.NumResources);
140 return m_pResourceAttribs[ResIndex];
141 }
142
143 const PipelineResourceDesc& GetResourceDesc(Uint32 ResIndex) const
144 {
145 VERIFY_EXPR(ResIndex < m_Desc.NumResources);
146 return m_Desc.Resources[ResIndex];
147 }
148
149 struct ImmutableSamplerAttribs
150 {
151 private:
152 static constexpr Uint32 _ShaderRegisterBits = 16;
153 static constexpr Uint32 _RegisterSpaceBits = 16;
154 static constexpr Uint32 _InvalidShaderRegister = (1u << _ShaderRegisterBits) - 1;
155 static constexpr Uint32 _InvalidRegisterSpace = (1u << _RegisterSpaceBits) - 1;
156
157 public:
158 Uint32 ArraySize = 1;
159 Uint32 ShaderRegister : _ShaderRegisterBits;
160 Uint32 RegisterSpace : _RegisterSpaceBits;
161
162 ImmutableSamplerAttribs() :
163 ShaderRegister{_InvalidShaderRegister},
164 RegisterSpace{_InvalidRegisterSpace}
165 {}
166
167 ImmutableSamplerAttribs(Uint32 _ArraySize,
168 Uint32 _ShaderRegister,
169 Uint32 _RegisterSpace) noexcept :
170 // clang-format off
171 ArraySize {_ArraySize },
172 ShaderRegister{_ShaderRegister},
173 RegisterSpace {_RegisterSpace }
174 // clang-format on
175 {
176 VERIFY(ShaderRegister == _ShaderRegister, "Shader register (", _ShaderRegister, ") exceeds maximum representable value");
177 VERIFY(RegisterSpace == _RegisterSpace, "Shader register space (", _RegisterSpace, ") exceeds maximum representable value");
178 }
179
180 bool IsAssigned() const { return ShaderRegister != _InvalidShaderRegister; }
181 };
182
183 const ImmutableSamplerAttribs& GetImmutableSamplerAttribs(Uint32 SampIndex) const
184 {
185 VERIFY_EXPR(SampIndex < m_Desc.NumImmutableSamplers);
186 return m_ImmutableSamplers[SampIndex];
187 }
188
189 const ImmutableSamplerDesc& GetImmutableSamplerDesc(Uint32 SampIndex) const
190 {
191 VERIFY_EXPR(SampIndex < m_Desc.NumImmutableSamplers);
192 return m_Desc.ImmutableSamplers[SampIndex];
193 }
194
195 Uint32 GetTotalRootCount() const
196 {
197 return m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews();
198 }
199
200 Uint32 GetBaseRegisterSpace() const
201 {
202 return m_Desc.BindingIndex * MAX_SPACES_PER_SIGNATURE;
203 }
204
205 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding,
206 bool InitStaticResources) override final;
207
208 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final;
209
210 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
211
212 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final;
213
214 virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags,
215 IResourceMapping* pResourceMapping,
216 Uint32 Flags) override final;
217
218 virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineResourceSignature* pPRS) const override final
219 {
220 VERIFY_EXPR(pPRS != nullptr);
221 return IsCompatibleWith(*ValidatedCast<const PipelineResourceSignatureD3D12Impl>(pPRS));
222 }
223
224 bool IsCompatibleWith(const PipelineResourceSignatureD3D12Impl& Other) const;
225
226 bool IsIncompatibleWith(const PipelineResourceSignatureD3D12Impl& Other) const
227 {
228 return GetHash() != Other.GetHash();
229 }
230
231 SRBMemoryAllocator& GetSRBMemoryAllocator()
232 {
233 return m_SRBMemAllocator;
234 }
235
236 void InitSRBResourceCache(ShaderResourceCacheD3D12& ResourceCache,
237 IMemoryAllocator& CacheMemAllocator,
238 const char* DbgPipelineName) const;
239
240 void InitializeStaticSRBResources(ShaderResourceCacheD3D12& ResourceCache) const;
241
242 // Binds object pObj to resource with index ResIndex in m_Desc.Resources and
243 // array index ArrayIndex.
244 void BindResource(IDeviceObject* pObj,
245 Uint32 ArrayIndex,
246 Uint32 ResIndex,
247 ShaderResourceCacheD3D12& ResourceCache) const;
248
249 bool IsBound(Uint32 ArrayIndex,
250 Uint32 ResIndex,
251 ShaderResourceCacheD3D12& ResourceCache) const;
252
253 void TransitionResources(ShaderResourceCacheD3D12& ResourceCache, CommandContext& Ctx, bool PerformResourceTransitions, bool ValidateStates) const;
254
255 void CommitRootTables(ShaderResourceCacheD3D12& ResourceCache,
256 CommandContext& Ctx,
257 DeviceContextD3D12Impl* pDeviceCtx,
258 Uint32 DeviceCtxId,
259 bool IsCompute,
260 Uint32 FirstRootIndex);
261
262 void CommitRootViews(ShaderResourceCacheD3D12& ResourceCache,
263 CommandContext& Ctx,
264 DeviceContextD3D12Impl* pDeviceCtx,
265 Uint32 DeviceCtxId,
266 bool IsCompute,
267 Uint32 FirstRootIndex);
268
269 private:
270 enum ROOT_TYPE : Uint8
271 {
272 ROOT_TYPE_STATIC = 0,
273 ROOT_TYPE_DYNAMIC = 1,
274 ROOT_TYPE_COUNT
275 };
276 static ROOT_TYPE GetRootType(SHADER_RESOURCE_VARIABLE_TYPE VarType);
277
278
279 class RootParameter
280 {
281 public:
282 RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
283 Uint32 RootIndex,
284 UINT Register,
285 UINT RegisterSpace,
286 D3D12_SHADER_VISIBILITY Visibility,
287 ROOT_TYPE RootType) noexcept;
288
289 RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
290 Uint32 RootIndex,
291 UINT Register,
292 UINT RegisterSpace,
293 UINT NumDwords,
294 D3D12_SHADER_VISIBILITY Visibility,
295 ROOT_TYPE RootType) noexcept;
296
297 RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
298 Uint32 RootIndex,
299 UINT NumRanges,
300 D3D12_DESCRIPTOR_RANGE* pRanges,
301 D3D12_SHADER_VISIBILITY Visibility,
302 ROOT_TYPE RootType) noexcept;
303
304 RootParameter(const RootParameter& RP) noexcept;
305
306 RootParameter(const RootParameter& RP,
307 UINT NumRanges,
308 D3D12_DESCRIPTOR_RANGE* pRanges) noexcept;
309
310 RootParameter& operator=(const RootParameter&) = delete;
311 RootParameter& operator=(RootParameter&&) = delete;
312
313 void SetDescriptorRange(UINT RangeIndex,
314 D3D12_DESCRIPTOR_RANGE_TYPE Type,
315 UINT Register,
316 UINT RegisterSpace,
317 UINT Count,
318 UINT OffsetFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND);
319
320 ROOT_TYPE GetRootType() const { return m_RootType; }
321
322 Uint32 GetDescriptorTableSize() const;
323
324 D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return m_RootParam.ShaderVisibility; }
325 D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return m_RootParam.ParameterType; }
326
327 Uint32 GetLocalRootIndex() const { return m_RootIndex; }
328
329 operator const D3D12_ROOT_PARAMETER&() const { return m_RootParam; }
330
331 bool operator==(const RootParameter& rhs) const;
332 bool operator!=(const RootParameter& rhs) const { return !(*this == rhs); }
333
334 size_t GetHash() const;
335
336 private:
337 ROOT_TYPE m_RootType = static_cast<ROOT_TYPE>(-1);
338 D3D12_ROOT_PARAMETER m_RootParam = {};
339 Uint32 m_DescriptorTableSize = 0;
340 Uint32 m_RootIndex = static_cast<Uint32>(-1);
341 };
342
343
344 class RootParamsManager
345 {
346 public:
347 RootParamsManager(IMemoryAllocator& MemAllocator);
348
349 // clang-format off
350 RootParamsManager (const RootParamsManager&) = delete;
351 RootParamsManager& operator=(const RootParamsManager&) = delete;
352 RootParamsManager (RootParamsManager&&) = delete;
353 RootParamsManager& operator=(RootParamsManager&&) = delete;
354 // clang-format on
355
356 Uint32 GetNumRootTables() const { return m_NumRootTables; }
357 Uint32 GetNumRootViews() const { return m_NumRootViews; }
358
359 const RootParameter& GetRootTable(Uint32 TableInd) const
360 {
361 VERIFY_EXPR(TableInd < m_NumRootTables);
362 return m_pRootTables[TableInd];
363 }
364
365 RootParameter& GetRootTable(Uint32 TableInd)
366 {
367 VERIFY_EXPR(TableInd < m_NumRootTables);
368 return m_pRootTables[TableInd];
369 }
370
371 const RootParameter& GetRootView(Uint32 ViewInd) const
372 {
373 VERIFY_EXPR(ViewInd < m_NumRootViews);
374 return m_pRootViews[ViewInd];
375 }
376
377 RootParameter& GetRootView(Uint32 ViewInd)
378 {
379 VERIFY_EXPR(ViewInd < m_NumRootViews);
380 return m_pRootViews[ViewInd];
381 }
382
383 void AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType,
384 Uint32 RootIndex,
385 UINT Register,
386 UINT RegisterSpace,
387 D3D12_SHADER_VISIBILITY Visibility,
388 ROOT_TYPE RootType);
389
390 void AddRootTable(Uint32 RootIndex,
391 D3D12_SHADER_VISIBILITY Visibility,
392 ROOT_TYPE RootType,
393 Uint32 NumRangesInNewTable = 1);
394
395 void AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges = 1);
396
397 template <class TOperation>
398 void ProcessRootTables(TOperation) const;
399
400 bool operator==(const RootParamsManager& RootParams) const;
401
402 private:
403 size_t GetRequiredMemorySize(Uint32 NumExtraRootTables,
404 Uint32 NumExtraRootViews,
405 Uint32 NumExtraDescriptorRanges) const;
406
407 D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables,
408 Uint32 NumExtraRootViews,
409 Uint32 NumExtraDescriptorRanges,
410 Uint32 RootTableToAddRanges = static_cast<Uint32>(-1));
411
412 IMemoryAllocator& m_MemAllocator;
413 std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;
414 Uint32 m_NumRootTables = 0;
415 Uint32 m_NumRootViews = 0;
416 Uint32 m_TotalDescriptorRanges = 0;
417 RootParameter* m_pRootTables = nullptr;
418 RootParameter* m_pRootViews = nullptr;
419 };
420
421 using CacheOffsetsType = std::array<Uint32, 2>;
422
423 void CreateLayout();
424
425 // Allocates root signature slot for the given resource.
426 // For graphics and compute pipelines, BindPoint is the same as the original bind point.
427 // For ray-tracing pipeline, BindPoint will be overriden. Bind points are then
428 // remapped by PSO constructor.
429 void AllocateResourceSlot(SHADER_TYPE ShaderStages,
430 SHADER_RESOURCE_VARIABLE_TYPE VariableType,
431 D3D12_DESCRIPTOR_RANGE_TYPE RangeType,
432 Uint32 ArraySize,
433 bool IsRootView,
434 Uint32 BindPoint,
435 Uint32 Space,
436 Uint32& RootIndex,
437 Uint32& OffsetFromTableStart);
438
439 size_t CalculateHash() const;
440
441 void Destruct();
442
443 std::vector<Uint32, STDAllocatorRawMem<Uint32>> GetCacheTableSizes() const;
444
445 Uint32 FindAssignedSampler(const PipelineResourceDesc& SepImg) const;
446
447 private:
448 static constexpr Uint8 InvalidRootTableIndex = static_cast<Uint8>(-1);
449 static constexpr Uint32 MAX_SPACES_PER_SIGNATURE = 128;
450
451 ResourceAttribs* m_pResourceAttribs = nullptr; // [m_Desc.NumResources]
452
453 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_StaticVarIndex = {-1, -1, -1, -1, -1, -1};
454 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
455
456 // The array below contains array index of a CBV/SRV/UAV root table
457 // in m_RootParams (NOT the Root Index!), for every variable type
458 // (static, mutable, dynamic) and every shader type,
459 // or -1, if the table is not yet assigned to the combination
460 std::array<Uint8, ROOT_TYPE_COUNT* MAX_SHADERS_IN_PIPELINE> m_SrvCbvUavRootTablesMap = {};
461 // This array contains the same data for Sampler root table
462 std::array<Uint8, ROOT_TYPE_COUNT* MAX_SHADERS_IN_PIPELINE> m_SamplerRootTablesMap = {};
463
464 std::array<Uint32, ROOT_TYPE_COUNT> m_TotalSrvCbvUavSlots = {};
465 std::array<Uint32, ROOT_TYPE_COUNT> m_TotalSamplerSlots = {};
466 std::array<Uint32, ROOT_TYPE_COUNT> m_TotalRootViews = {};
467
468 Uint32 m_NumSpaces = 0;
469
470 ShaderResourceCacheD3D12* m_pStaticResCache = nullptr;
471 ShaderVariableManagerD3D12* m_StaticVarsMgrs = nullptr; // [m_NumShaderStages]
472
473 ImmutableSamplerAttribs* m_ImmutableSamplers = nullptr; // [m_Desc.NumImmutableSamplers]
474
475 RootParamsManager m_RootParams;
476
477 SRBMemoryAllocator m_SRBMemAllocator;
478 };
479
480
481 } // namespace Diligent
3333 #include "PipelineStateD3D12.h"
3434 #include "PipelineStateBase.hpp"
3535 #include "RootSignature.hpp"
36 #include "ShaderResourceLayoutD3D12.hpp"
37 #include "SRBMemoryAllocator.hpp"
3836 #include "RenderDeviceD3D12Impl.hpp"
39 #include "ShaderVariableD3D12.hpp"
4037 #include "ShaderD3D12Impl.hpp"
4138
4239 namespace Diligent
5754
5855 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineStateD3D12, TPipelineStateBase)
5956
60 /// Implementation of IPipelineState::BindStaticResources() in Direct3D12 backend.
61 virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final;
62
63 /// Implementation of IPipelineState::GetStaticVariableCount() in Direct3D12 backend.
64 virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final;
65
66 /// Implementation of IPipelineState::GetStaticVariableByName() in Direct3D12 backend.
67 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) override final;
68
69 /// Implementation of IPipelineState::GetStaticVariableByIndex() in Direct3D12 backend.
70 virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final;
71
72 /// Implementation of IPipelineState::CreateShaderResourceBinding() in Direct3D12 backend.
73 virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final;
74
7557 /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D12 backend.
7658 virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
59
60 /// Implementation of IPipelineState::GetResourceSignatureCount() in Direct3D12 backend.
61 virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return GetSignatureCount(); }
62
63 /// Implementation of IPipelineState::GetResourceSignature() in Direct3D12 backend.
64 virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final { return GetSignature(Index); }
7765
7866 /// Implementation of IPipelineStateD3D12::GetD3D12PipelineState().
7967 virtual ID3D12PipelineState* DILIGENT_CALL_TYPE GetD3D12PipelineState() const override final { return static_cast<ID3D12PipelineState*>(m_pd3d12PSO.p); }
8270 virtual ID3D12StateObject* DILIGENT_CALL_TYPE GetD3D12StateObject() const override final { return static_cast<ID3D12StateObject*>(m_pd3d12PSO.p); }
8371
8472 /// Implementation of IPipelineStateD3D12::GetD3D12RootSignature().
85 virtual ID3D12RootSignature* DILIGENT_CALL_TYPE GetD3D12RootSignature() const override final { return m_RootSig.GetD3D12RootSignature(); }
73 virtual ID3D12RootSignature* DILIGENT_CALL_TYPE GetD3D12RootSignature() const override final { return m_RootSig->GetD3D12RootSignature(); }
8674
87 struct CommitAndTransitionResourcesAttribs
75 const RootSignatureD3D12* GetRootSignature() const { return m_RootSig; }
76
77 Uint32 GetSignatureCount() const { return m_SignatureCount; }
78
79 PipelineResourceSignatureD3D12Impl* GetSignature(Uint32 index) const
8880 {
89 Uint32 CtxId = 0;
90 IShaderResourceBinding* pShaderResourceBinding = nullptr;
91 bool CommitResources = false;
92 bool TransitionResources = false;
93 bool ValidateStates = false;
94 };
95 ShaderResourceCacheD3D12* CommitAndTransitionShaderResources(class DeviceContextD3D12Impl* pDeviceCtx,
96 class CommandContext& CmdCtx,
97 CommitAndTransitionResourcesAttribs& Attrib) const;
98
99 const RootSignature& GetRootSignature() const { return m_RootSig; }
100
101 const ShaderResourceLayoutD3D12& GetShaderResLayout(Uint32 ShaderInd) const
102 {
103 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
104 return m_pShaderResourceLayouts[ShaderInd];
105 }
106
107 const ShaderResourceLayoutD3D12& GetStaticShaderResLayout(Uint32 ShaderInd) const
108 {
109 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
110 return m_pShaderResourceLayouts[GetNumShaderStages() + ShaderInd];
111 }
112
113 ShaderResourceCacheD3D12& GetStaticShaderResCache(Uint32 ShaderInd) const
114 {
115 VERIFY_EXPR(ShaderInd < GetNumShaderStages());
116 return m_pStaticResourceCaches[ShaderInd];
117 }
118
119 bool ContainsShaderResources() const;
120
121 SRBMemoryAllocator& GetSRBMemoryAllocator()
122 {
123 return m_SRBMemAllocator;
81 VERIFY_EXPR(index < m_SignatureCount);
82 return m_Signatures[index].RawPtr<PipelineResourceSignatureD3D12Impl>();
12483 }
12584
12685 private:
13291 void Append(ShaderD3D12Impl* pShader);
13392 size_t Count() const;
13493
135 SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
136 std::vector<ShaderD3D12Impl*> Shaders;
94 SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
95 std::vector<ShaderD3D12Impl*> Shaders;
96 std::vector<CComPtr<ID3DBlob>> ByteCodes;
13797 };
13898 using TShaderStages = std::vector<ShaderStageInfo>;
13999
140100 template <typename PSOCreateInfoType>
141101 void InitInternalObjects(const PSOCreateInfoType& CreateInfo,
142 RootSignatureBuilder& RootSigBuilder,
143102 TShaderStages& ShaderStages,
144 LocalRootSignature* pLocalRoot = nullptr);
103 LocalRootSignatureD3D12* pLocalRootSig = nullptr);
145104
146 void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
147 RootSignatureBuilder& RootSigBuilder,
148 TShaderStages& ShaderStages,
149 LocalRootSignature* pLocalRoot);
105 void InitRootSignature(const PipelineStateCreateInfo& CreateInfo,
106 TShaderStages& ShaderStages,
107 LocalRootSignatureD3D12* pLocalRootSig);
108
109 void CreateDefaultResourceSignature(const PipelineStateCreateInfo& CreateInfo,
110 TShaderStages& ShaderStages,
111 LocalRootSignatureD3D12* pLocalRootSig,
112 IPipelineResourceSignature** ppImplicitSignature);
150113
151114 void Destruct();
152115
153 CComPtr<ID3D12DeviceChild> m_pd3d12PSO;
154 RootSignature m_RootSig;
116 private:
117 CComPtr<ID3D12DeviceChild> m_pd3d12PSO;
118 RefCntAutoPtr<RootSignatureD3D12> m_RootSig;
155119
156 SRBMemoryAllocator m_SRBMemAllocator;
120 using SignatureArrayType = RootSignatureD3D12::SignatureArrayType;
157121
158 ShaderResourceLayoutD3D12* m_pShaderResourceLayouts = nullptr; // [m_NumShaderStages * 2]
159 ShaderResourceCacheD3D12* m_pStaticResourceCaches = nullptr; // [m_NumShaderStages]
160 ShaderVariableManagerD3D12* m_pStaticVarManagers = nullptr; // [m_NumShaderStages]
122 Uint8 m_SignatureCount = 0;
123 SignatureArrayType m_Signatures = {};
161124
162 // Resource layout index in m_pShaderResourceLayouts array for every shader stage,
163 // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
164 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1};
165 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
125 void* m_pRawMem = nullptr; // AZ TODO: move to base class
126
127 #ifdef DILIGENT_DEVELOPMENT
128 // Shader resources for all shaders in all shader stages
129 std::vector<std::shared_ptr<const ShaderResourcesD3D12>> m_ShaderResources;
130 // Resource info for every resource in m_ShaderResources, in the same order
131 //std::vector<PipelineLayoutVk::ResourceInfo> m_ResInfo;
132 #endif
166133 };
167134
168135 } // namespace Diligent
4040 #include "GenerateMips.hpp"
4141 #include "QueryManagerD3D12.hpp"
4242 #include "DXCompiler.hpp"
43 #include "RootSignature.hpp"
4344
4445 // The macros below are only defined in Win SDK 19041+ and are missing in 17763
4546 #ifndef D3D12_RAYTRACING_MAX_RAY_GENERATION_SHADER_THREADS
136137 virtual void DILIGENT_CALL_TYPE CreateSBT(const ShaderBindingTableDesc& Desc,
137138 IShaderBindingTable** ppSBT) override final;
138139
140 /// Implementation of IRenderDevice::CreatePipelineResourceSignature() in Direct3D12 backend.
141 virtual void DILIGENT_CALL_TYPE CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc,
142 IPipelineResourceSignature** ppSignature) override final;
143
144 void CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc,
145 IPipelineResourceSignature** ppSignature,
146 bool IsDeviceInternal);
147
139148 /// Implementation of IRenderDeviceD3D12::GetD3D12Device().
140149 virtual ID3D12Device* DILIGENT_CALL_TYPE GetD3D12Device() override final { return m_pd3d12Device; }
141150
161170 const TopLevelASDesc& Desc,
162171 RESOURCE_STATE InitialState,
163172 ITopLevelAS** ppTLAS) override final;
173
174 void CreateRootSignature(const RefCntAutoPtr<class PipelineResourceSignatureD3D12Impl>* ppSignatures, Uint32 SignatureCount, RootSignatureD3D12** ppRootSig);
175
176 RootSignatureCacheD3D12& GetRootSignatureCache() { return m_RootSignatureCache; }
164177
165178 DescriptorHeapAllocation AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1);
166179 DescriptorHeapAllocation AllocateGPUDescriptors(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1);
261274 Properties m_Properties;
262275
263276 std::unique_ptr<IDXCompiler> m_pDxCompiler;
277
278 FixedBlockMemoryAllocator m_RootSignatureAllocator;
279 RootSignatureCacheD3D12 m_RootSignatureCache;
264280 };
265281
266282 } // namespace Diligent
2727 #pragma once
2828
2929 /// \file
30 /// Declaration of Diligent::RootSignature class
30 /// Declaration of Diligent::RootSignatureD3D12 class
3131 #include <array>
32 #include "ShaderResourceLayoutD3D12.hpp"
33 #include "BufferD3D12Impl.hpp"
32 #include <mutex>
33 #include <unordered_set>
34
3435 #include "D3D12TypeConversions.hpp"
36 #include "ShaderResourceCacheD3D12.hpp"
37 #include "PipelineResourceSignatureD3D12Impl.hpp"
38 #include "PrivateConstants.h"
39 #include "ShaderResources.hpp"
3540
3641 namespace Diligent
3742 {
3843
39 class RootParameter
44 class RenderDeviceD3D12Impl;
45 class PipelineResourceSignatureD3D12Impl;
46
47 /// Implementation of the Diligent::RootSignature class
48 class RootSignatureD3D12 final : public ObjectBase<IObject>
4049 {
4150 public:
42 RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
43 Uint32 RootIndex,
44 UINT Register,
45 UINT RegisterSpace,
46 D3D12_SHADER_VISIBILITY Visibility,
47 SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept :
48 // clang-format off
49 m_RootIndex {RootIndex},
50 m_ShaderVarType{VarType }
51 // clang-format on
51 RootSignatureD3D12(IReferenceCounters* pRefCounters,
52 RenderDeviceD3D12Impl* pDeviceD3D12Impl,
53 const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>* ppSignatures,
54 Uint32 SignatureCount);
55 ~RootSignatureD3D12();
56
57 void Finalize();
58
59 size_t GetHash() const { return m_Hash; }
60
61 Uint32 GetSignatureCount() const { return m_SignatureCount; }
62
63 PipelineResourceSignatureD3D12Impl* GetSignature(Uint32 index) const
5264 {
53 VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, "Unexpected parameter type - verify argument list");
54 m_RootParam.ParameterType = ParameterType;
55 m_RootParam.ShaderVisibility = Visibility;
56 m_RootParam.Descriptor.ShaderRegister = Register;
57 m_RootParam.Descriptor.RegisterSpace = RegisterSpace;
65 VERIFY_EXPR(index < m_SignatureCount);
66 return m_Signatures[index].RawPtr<PipelineResourceSignatureD3D12Impl>();
5867 }
5968
60 RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
61 Uint32 RootIndex,
62 UINT Register,
63 UINT RegisterSpace,
64 UINT NumDwords,
65 D3D12_SHADER_VISIBILITY Visibility,
66 SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept :
67 // clang-format off
68 m_RootIndex {RootIndex},
69 m_ShaderVarType{VarType }
70 // clang-format on
69 ID3D12RootSignature* GetD3D12RootSignature() const
7170 {
72 VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, "Unexpected parameter type - verify argument list");
73 m_RootParam.ParameterType = ParameterType;
74 m_RootParam.ShaderVisibility = Visibility;
75 m_RootParam.Constants.Num32BitValues = NumDwords;
76 m_RootParam.Constants.ShaderRegister = Register;
77 m_RootParam.Constants.RegisterSpace = RegisterSpace;
71 VERIFY_EXPR(m_pd3d12RootSignature);
72 return m_pd3d12RootSignature;
7873 }
7974
80 RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
81 Uint32 RootIndex,
82 UINT NumRanges,
83 D3D12_DESCRIPTOR_RANGE* pRanges,
84 D3D12_SHADER_VISIBILITY Visibility,
85 SHADER_RESOURCE_VARIABLE_TYPE VarType) noexcept :
86 // clang-format off
87 m_RootIndex {RootIndex},
88 m_ShaderVarType{VarType }
89 // clang-format on
75 Uint32 GetFirstRootIndex(Uint32 BindingIndex) const
9076 {
91 VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type - verify argument list");
92 VERIFY_EXPR(pRanges != nullptr);
93 m_RootParam.ParameterType = ParameterType;
94 m_RootParam.ShaderVisibility = Visibility;
95 m_RootParam.DescriptorTable.NumDescriptorRanges = NumRanges;
96 m_RootParam.DescriptorTable.pDescriptorRanges = pRanges;
97 #ifdef DILIGENT_DEBUG
98 for (Uint32 r = 0; r < NumRanges; ++r)
99 pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1);
100 #endif
77 VERIFY_EXPR(BindingIndex < m_SignatureCount);
78 return m_FirstRootIndex[BindingIndex];
10179 }
10280
103 RootParameter(const RootParameter& RP) noexcept :
104 // clang-format off
105 m_RootParam {RP.m_RootParam },
106 m_DescriptorTableSize{RP.m_DescriptorTableSize},
107 m_ShaderVarType {RP.m_ShaderVarType },
108 m_RootIndex {RP.m_RootIndex }
109 // clang-format on
110 {
111 VERIFY(m_RootParam.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Use another constructor to copy descriptor table");
112 }
113
114 RootParameter(const RootParameter& RP,
115 UINT NumRanges,
116 D3D12_DESCRIPTOR_RANGE* pRanges) noexcept :
117 // clang-format off
118 m_RootParam {RP.m_RootParam },
119 m_DescriptorTableSize{RP.m_DescriptorTableSize},
120 m_ShaderVarType {RP.m_ShaderVarType },
121 m_RootIndex {RP.m_RootIndex }
122 // clang-format on
123 {
124 VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table");
125 VERIFY(NumRanges >= m_RootParam.DescriptorTable.NumDescriptorRanges, "New table must be larger than source one");
126 auto& DstTbl = m_RootParam.DescriptorTable;
127 DstTbl.NumDescriptorRanges = NumRanges;
128 DstTbl.pDescriptorRanges = pRanges;
129 const auto& SrcTbl = RP.m_RootParam.DescriptorTable;
130 memcpy(pRanges, SrcTbl.pDescriptorRanges, SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE));
131 #ifdef DILIGENT_DEBUG
132 {
133 Uint32 dbgTableSize = 0;
134 for (Uint32 r = 0; r < SrcTbl.NumDescriptorRanges; ++r)
135 {
136 const auto& Range = SrcTbl.pDescriptorRanges[r];
137 dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors);
138 }
139 VERIFY(dbgTableSize == m_DescriptorTableSize, "Incorrect descriptor table size");
140
141 for (Uint32 r = SrcTbl.NumDescriptorRanges; r < DstTbl.NumDescriptorRanges; ++r)
142 pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1);
143 }
144 #endif
145 }
146
147 RootParameter& operator=(const RootParameter&) = delete;
148 RootParameter& operator=(RootParameter&&) = delete;
149
150 void SetDescriptorRange(UINT RangeIndex,
151 D3D12_DESCRIPTOR_RANGE_TYPE Type,
152 UINT Register,
153 UINT Count,
154 UINT Space = 0,
155 UINT OffsetFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
156 {
157 VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected");
158 auto& Tbl = m_RootParam.DescriptorTable;
159 VERIFY(RangeIndex < Tbl.NumDescriptorRanges, "Invalid descriptor range index");
160 D3D12_DESCRIPTOR_RANGE& range = const_cast<D3D12_DESCRIPTOR_RANGE&>(Tbl.pDescriptorRanges[RangeIndex]);
161 VERIFY(range.RangeType == static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1), "Descriptor range has already been initialized. m_DescriptorTableSize may be updated incorrectly");
162 range.RangeType = Type;
163 range.NumDescriptors = Count;
164 range.BaseShaderRegister = Register;
165 range.RegisterSpace = Space;
166 range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart;
167 m_DescriptorTableSize = std::max(m_DescriptorTableSize, OffsetFromTableStart + Count);
168 }
169
170 SHADER_RESOURCE_VARIABLE_TYPE GetShaderVariableType() const { return m_ShaderVarType; }
171
172 Uint32 GetDescriptorTableSize() const
173 {
174 VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected");
175 return m_DescriptorTableSize;
176 }
177
178 D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return m_RootParam.ShaderVisibility; }
179 D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return m_RootParam.ParameterType; }
180
181 Uint32 GetRootIndex() const { return m_RootIndex; }
182
183 operator const D3D12_ROOT_PARAMETER&() const { return m_RootParam; }
184
185 bool operator==(const RootParameter& rhs) const
186 {
187 if (m_ShaderVarType != rhs.m_ShaderVarType ||
188 m_DescriptorTableSize != rhs.m_DescriptorTableSize ||
189 m_RootIndex != rhs.m_RootIndex)
190 return false;
191
192 if (m_RootParam.ParameterType != rhs.m_RootParam.ParameterType ||
193 m_RootParam.ShaderVisibility != rhs.m_RootParam.ShaderVisibility)
194 return false;
195
196 switch (m_RootParam.ParameterType)
197 {
198 case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
199 {
200 const auto& tbl0 = m_RootParam.DescriptorTable;
201 const auto& tbl1 = rhs.m_RootParam.DescriptorTable;
202 if (tbl0.NumDescriptorRanges != tbl1.NumDescriptorRanges)
203 return false;
204 for (UINT r = 0; r < tbl0.NumDescriptorRanges; ++r)
205 {
206 const auto& rng0 = tbl0.pDescriptorRanges[r];
207 const auto& rng1 = tbl1.pDescriptorRanges[r];
208 if (memcmp(&rng0, &rng1, sizeof(rng0)) != 0)
209 return false;
210 }
211 }
212 break;
213
214 case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
215 {
216 const auto& cnst0 = m_RootParam.Constants;
217 const auto& cnst1 = rhs.m_RootParam.Constants;
218 if (memcmp(&cnst0, &cnst1, sizeof(cnst0)) != 0)
219 return false;
220 }
221 break;
222
223 case D3D12_ROOT_PARAMETER_TYPE_CBV:
224 case D3D12_ROOT_PARAMETER_TYPE_SRV:
225 case D3D12_ROOT_PARAMETER_TYPE_UAV:
226 {
227 const auto& dscr0 = m_RootParam.Descriptor;
228 const auto& dscr1 = rhs.m_RootParam.Descriptor;
229 if (memcmp(&dscr0, &dscr1, sizeof(dscr0)) != 0)
230 return false;
231 }
232 break;
233
234 default: UNEXPECTED("Unexpected root parameter type");
235 }
236
237 return true;
238 }
239
240 bool operator!=(const RootParameter& rhs) const
241 {
242 return !(*this == rhs);
243 }
244
245 size_t GetHash() const
246 {
247 size_t hash = ComputeHash(m_ShaderVarType, m_DescriptorTableSize, m_RootIndex);
248 HashCombine(hash, m_RootParam.ParameterType, m_RootParam.ShaderVisibility);
249
250 switch (m_RootParam.ParameterType)
251 {
252 case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
253 {
254 const auto& tbl = m_RootParam.DescriptorTable;
255 HashCombine(hash, tbl.NumDescriptorRanges);
256 for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r)
257 {
258 const auto& rng = tbl.pDescriptorRanges[r];
259 HashCombine(hash, rng.BaseShaderRegister, rng.NumDescriptors, rng.OffsetInDescriptorsFromTableStart, rng.RangeType, rng.RegisterSpace);
260 }
261 }
262 break;
263
264 case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
265 {
266 const auto& cnst = m_RootParam.Constants;
267 HashCombine(hash, cnst.Num32BitValues, cnst.RegisterSpace, cnst.ShaderRegister);
268 }
269 break;
270
271 case D3D12_ROOT_PARAMETER_TYPE_CBV:
272 case D3D12_ROOT_PARAMETER_TYPE_SRV:
273 case D3D12_ROOT_PARAMETER_TYPE_UAV:
274 {
275 const auto& dscr = m_RootParam.Descriptor;
276 HashCombine(hash, dscr.RegisterSpace, dscr.ShaderRegister);
277 }
278 break;
279
280 default: UNEXPECTED("Unexpected root parameter type");
281 }
282
283 return hash;
284 }
81 using SignatureArrayType = std::array<RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>, MAX_RESOURCE_SIGNATURES>;
28582
28683 private:
287 SHADER_RESOURCE_VARIABLE_TYPE m_ShaderVarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(-1);
288 D3D12_ROOT_PARAMETER m_RootParam = {};
289 Uint32 m_DescriptorTableSize = 0;
290 Uint32 m_RootIndex = static_cast<Uint32>(-1);
84 using FirstRootIndexArrayType = std::array<Uint32, MAX_RESOURCE_SIGNATURES>; // AZ TODO: use 8 or 16 bit int
85 FirstRootIndexArrayType m_FirstRootIndex = {};
86
87 size_t m_Hash = 0;
88 CComPtr<ID3D12RootSignature> m_pd3d12RootSignature;
89
90 // The number of resource signatures used by this root signature
91 // (Maximum is MAX_RESOURCE_SIGNATURES)
92 Uint8 m_SignatureCount = 0;
93 SignatureArrayType m_Signatures = {};
94
95 RenderDeviceD3D12Impl* m_pDeviceD3D12Impl;
29196 };
29297
29398
29499
295 /// Implementation of the Diligent::RootSignature class
296 class RootSignature
297 {
298 friend class RootSignatureBuilder;
299
300 public:
301 RootSignature();
302
303 ID3D12RootSignature* GetD3D12RootSignature() const { return m_pd3d12RootSignature; }
304
305 void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator) const;
306
307 // This method should be thread-safe as it does not modify any object state
308 void (RootSignature::*CommitDescriptorHandles)(class RenderDeviceD3D12Impl* pRenderDeviceD3D12,
309 ShaderResourceCacheD3D12& ResourceCache,
310 class CommandContext& Ctx,
311 bool IsCompute,
312 bool ValidateStates) const = nullptr;
313
314 void (RootSignature::*TransitionAndCommitDescriptorHandles)(class RenderDeviceD3D12Impl* pRenderDeviceD3D12,
315 ShaderResourceCacheD3D12& ResourceCache,
316 class CommandContext& Ctx,
317 bool IsCompute,
318 bool ValidateStates) const = nullptr;
319
320 void TransitionResources(ShaderResourceCacheD3D12& ResourceCache,
321 class CommandContext& Ctx) const;
322
323 __forceinline void CommitRootViews(ShaderResourceCacheD3D12& ResourceCache,
324 class CommandContext& CmdCtx,
325 bool IsCompute,
326 Uint32 DeviceCtxId,
327 class DeviceContextD3D12Impl* pDeviceCtx,
328 bool CommitViews,
329 bool ProcessDynamicBuffers,
330 bool ProcessNonDynamicBuffers,
331 bool TransitionStates,
332 bool ValidateStates) const;
333
334 Uint32 GetTotalSrvCbvUavSlots(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
335 {
336 return m_TotalSrvCbvUavSlots[VarType];
337 }
338 Uint32 GetTotalSamplerSlots(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
339 {
340 return m_TotalSamplerSlots[VarType];
341 }
342 Uint32 GetTotalRootViews(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
343 {
344 return m_TotalRootViews[VarType];
345 }
346
347 bool IsSameAs(const RootSignature& RS) const
348 {
349 return m_RootParams == RS.m_RootParams;
350 }
351 size_t GetHash() const
352 {
353 return m_RootParams.GetHash();
354 }
355
356 private:
357 #ifdef DILIGENT_DEVELOPMENT
358 static void DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resource& Res,
359 D3D12_DESCRIPTOR_RANGE_TYPE RangeType);
360 #endif
361
362 std::vector<Uint32, STDAllocatorRawMem<Uint32>> GetCacheTableSizes() const;
363
364 std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> m_TotalSrvCbvUavSlots = {};
365 std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> m_TotalSamplerSlots = {};
366 std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> m_TotalRootViews = {};
367
368 CComPtr<ID3D12RootSignature> m_pd3d12RootSignature;
369
370 class RootParamsManager
371 {
372 public:
373 RootParamsManager(IMemoryAllocator& MemAllocator);
374
375 // clang-format off
376 RootParamsManager (const RootParamsManager&) = delete;
377 RootParamsManager& operator=(const RootParamsManager&) = delete;
378 RootParamsManager (RootParamsManager&&) = delete;
379 RootParamsManager& operator=(RootParamsManager&&) = delete;
380 // clang-format on
381
382 Uint32 GetNumRootTables() const { return m_NumRootTables; }
383 Uint32 GetNumRootViews() const { return m_NumRootViews; }
384
385 const RootParameter& GetRootTable(Uint32 TableInd) const
386 {
387 VERIFY_EXPR(TableInd < m_NumRootTables);
388 return m_pRootTables[TableInd];
389 }
390
391 RootParameter& GetRootTable(Uint32 TableInd)
392 {
393 VERIFY_EXPR(TableInd < m_NumRootTables);
394 return m_pRootTables[TableInd];
395 }
396
397 const RootParameter& GetRootView(Uint32 ViewInd) const
398 {
399 VERIFY_EXPR(ViewInd < m_NumRootViews);
400 return m_pRootViews[ViewInd];
401 }
402
403 RootParameter& GetRootView(Uint32 ViewInd)
404 {
405 VERIFY_EXPR(ViewInd < m_NumRootViews);
406 return m_pRootViews[ViewInd];
407 }
408
409 void AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType,
410 Uint32 RootIndex,
411 UINT Register,
412 D3D12_SHADER_VISIBILITY Visibility,
413 SHADER_RESOURCE_VARIABLE_TYPE VarType);
414
415 void AddRootTable(Uint32 RootIndex,
416 D3D12_SHADER_VISIBILITY Visibility,
417 SHADER_RESOURCE_VARIABLE_TYPE VarType,
418 Uint32 NumRangesInNewTable = 1);
419
420 void AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges = 1);
421
422 template <class TOperation>
423 void ProcessRootTables(TOperation) const;
424
425 bool operator==(const RootParamsManager& RootParams) const;
426 size_t GetHash() const;
427
428 private:
429 size_t GetRequiredMemorySize(Uint32 NumExtraRootTables,
430 Uint32 NumExtraRootViews,
431 Uint32 NumExtraDescriptorRanges) const;
432
433 D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables,
434 Uint32 NumExtraRootViews,
435 Uint32 NumExtraDescriptorRanges,
436 Uint32 RootTableToAddRanges = static_cast<Uint32>(-1));
437
438 IMemoryAllocator& m_MemAllocator;
439 std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;
440 Uint32 m_NumRootTables = 0;
441 Uint32 m_NumRootViews = 0;
442 Uint32 m_TotalDescriptorRanges = 0;
443 RootParameter* m_pRootTables = nullptr;
444 RootParameter* m_pRootViews = nullptr;
445 };
446
447 static constexpr Uint8 InvalidRootTableIndex = static_cast<Uint8>(-1);
448
449 // The array below contains array index of a CBV/SRV/UAV root table
450 // in m_RootParams (NOT the Root Index!), for every variable type
451 // (static, mutable, dynamic) and every shader type,
452 // or -1, if the table is not yet assigned to the combination
453 std::array<Uint8, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES* MAX_SHADERS_IN_PIPELINE> m_SrvCbvUavRootTablesMap = {};
454 // This array contains the same data for Sampler root table
455 std::array<Uint8, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES* MAX_SHADERS_IN_PIPELINE> m_SamplerRootTablesMap = {};
456
457 RootParamsManager m_RootParams;
458
459 IMemoryAllocator& m_MemAllocator;
460
461 // Commits descriptor handles for static and mutable variables
462 template <bool PerformResourceTransitions>
463 void CommitDescriptorHandlesInternal_SM(class RenderDeviceD3D12Impl* pRenderDeviceD3D12,
464 ShaderResourceCacheD3D12& ResourceCache,
465 class CommandContext& Ctx,
466 bool IsCompute,
467 bool ValidateStates) const;
468 template <bool PerformResourceTransitions>
469 // Commits descriptor handles for static, mutable, and dynamic variables
470 void CommitDescriptorHandlesInternal_SMD(class RenderDeviceD3D12Impl* pRenderDeviceD3D12,
471 ShaderResourceCacheD3D12& ResourceCache,
472 class CommandContext& Ctx,
473 bool IsCompute,
474 bool ValidateStates) const;
475 };
476
477
478 class RootSignatureBuilder
100 class LocalRootSignatureD3D12
479101 {
480102 public:
481 RootSignatureBuilder(RootSignature& RootSig, const PipelineResourceLayoutDesc& PipelineResLayout);
103 LocalRootSignatureD3D12(const char* pCBName, Uint32 ShaderRecordSize);
482104
483 void InitImmutableSampler(SHADER_TYPE ShaderType,
484 const char* SamplerName,
485 const char* SamplerSuffix,
486 const D3DShaderResourceAttribs& ShaderResAttribs);
487
488 // Allocates root signature slot for the given resource.
489 // For graphics and compute pipelines, BindPoint is the same as the original bind point.
490 // For ray-tracing pipeline, BindPoint will be overriden. Bind points are then
491 // remapped by PSO constructor.
492 void AllocateResourceSlot(SHADER_TYPE ShaderType,
493 PIPELINE_TYPE PipelineType,
494 const D3DShaderResourceAttribs& ShaderResAttribs,
495 SHADER_RESOURCE_VARIABLE_TYPE VariableType,
496 D3D12_DESCRIPTOR_RANGE_TYPE RangeType,
497 Uint32& BindPoint,
498 Uint32& RootIndex,
499 Uint32& OffsetFromTableStart);
500
501 void Finalize(ID3D12Device* pd3d12Device);
502
503 size_t GetResourceCacheRequiredMemSize() const;
504
505 size_t GetHash() const
506 {
507 return m_RootSig.GetHash();
508 }
509
510 struct ImmutableSamplerAttribs
511 {
512 const SamplerDesc& Desc;
513 const String SamplerName;
514 const UINT ShaderRegister;
515 const UINT ArraySize;
516 const UINT RegisterSpace;
517 const SHADER_TYPE ShaderType;
518
519 ImmutableSamplerAttribs(
520 const SamplerDesc& _Desc,
521 const char* _SamplerName,
522 const UINT _ShaderRegister,
523 const UINT _ArraySize,
524 const UINT _RegisterSpace,
525 const SHADER_TYPE _ShaderType) noexcept :
526 // clang-format off
527 Desc {_Desc},
528 SamplerName {_SamplerName},
529 ShaderRegister{_ShaderRegister},
530 ArraySize {_ArraySize},
531 RegisterSpace {_RegisterSpace},
532 ShaderType {_ShaderType}
533 // clang-format on
534 {}
535 };
536 const ImmutableSamplerAttribs* GetImmutableSamplers() const { return m_ImmutableSamplers.data(); }
537 size_t GetImmutableSamplerCount() const { return m_ImmutableSamplers.size(); }
538
539 private:
540 #ifdef DILIGENT_DEBUG
541 void dbgVerifyRootParameters() const;
542 #endif
543
544 RootSignature& m_RootSig;
545
546 const PipelineResourceLayoutDesc& m_PipelineResLayout;
547
548 // Resource counters for every descriptor range type used to assign bind points
549 // for ray-tracing shaders.
550 std::array<Uint32, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER + 1> m_NumResources = {};
551
552 std::vector<ImmutableSamplerAttribs, STDAllocatorRawMem<ImmutableSamplerAttribs>> m_ImmutableSamplers;
553 };
554
555
556 void RootSignature::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache,
557 CommandContext& CmdCtx,
558 bool IsCompute,
559 Uint32 DeviceCtxId,
560 DeviceContextD3D12Impl* pDeviceCtx,
561 bool CommitViews,
562 bool ProcessDynamicBuffers,
563 bool ProcessNonDynamicBuffers,
564 bool TransitionStates,
565 bool ValidateStates) const
566 {
567 for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
568 {
569 auto& RootView = m_RootParams.GetRootView(rv);
570 auto RootInd = RootView.GetRootIndex();
571
572 SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
573 #ifdef DILIGENT_DEBUG
574 {
575 auto& Param = static_cast<const D3D12_ROOT_PARAMETER&>(RootView);
576 VERIFY_EXPR(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV);
577 dbgShaderType = D3D12ShaderVisibilityToShaderType(Param.ShaderVisibility);
578 }
579 #endif
580
581 auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType);
582 if (auto* pBuffToTransition = Res.pObject.RawPtr<BufferD3D12Impl>())
583 {
584 bool IsDynamic = pBuffToTransition->GetDesc().Usage == USAGE_DYNAMIC;
585 if (IsDynamic && ProcessDynamicBuffers || !IsDynamic && ProcessNonDynamicBuffers)
586 {
587 if (IsDynamic)
588 {
589 #ifdef DILIGENT_DEBUG
590 if (pBuffToTransition->IsInKnownState())
591 {
592 VERIFY(pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER),
593 "Dynamic buffers must always have RESOURCE_STATE_CONSTANT_BUFFER state flag set");
594 }
595 #endif
596 }
597 else
598 {
599 if (TransitionStates)
600 {
601 if (pBuffToTransition->IsInKnownState() && !pBuffToTransition->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
602 {
603 CmdCtx.TransitionResource(pBuffToTransition, RESOURCE_STATE_CONSTANT_BUFFER);
604 }
605 }
606 #ifdef DILIGENT_DEVELOPMENT
607 else if (ValidateStates)
608 {
609
610 DvpVerifyResourceState(Res, D3D12_DESCRIPTOR_RANGE_TYPE_CBV);
611 }
612 #endif
613 }
614
615 if (CommitViews)
616 {
617 D3D12_GPU_VIRTUAL_ADDRESS CBVAddress = pBuffToTransition->GetGPUAddress(DeviceCtxId, pDeviceCtx);
618 if (IsCompute)
619 CmdCtx.GetCommandList()->SetComputeRootConstantBufferView(RootInd, CBVAddress);
620 else
621 CmdCtx.GetCommandList()->SetGraphicsRootConstantBufferView(RootInd, CBVAddress);
622 }
623 }
624 }
625 }
626 }
627
628
629 class LocalRootSignature
630 {
631 public:
632 LocalRootSignature(const char* pCBName, Uint32 ShaderRecordSize);
633
634 bool SetOrMerge(const D3DShaderResourceAttribs& CB);
105 bool IsShaderRecord(const D3DShaderResourceAttribs& CB);
635106
636107 ID3D12RootSignature* Create(ID3D12Device* pDevice);
637108
644115 CComPtr<ID3D12RootSignature> m_pd3d12RootSignature;
645116 };
646117
118
119
120 class RootSignatureCacheD3D12
121 {
122 public:
123 RootSignatureCacheD3D12(RenderDeviceD3D12Impl& DeviceD3D12Impl);
124
125 // clang-format off
126 RootSignatureCacheD3D12 (const RootSignatureCacheD3D12&) = delete;
127 RootSignatureCacheD3D12 (RootSignatureCacheD3D12&&) = delete;
128 RootSignatureCacheD3D12& operator = (const RootSignatureCacheD3D12&) = delete;
129 RootSignatureCacheD3D12& operator = (RootSignatureCacheD3D12&&) = delete;
130 // clang-format on
131
132 ~RootSignatureCacheD3D12();
133
134 RefCntAutoPtr<RootSignatureD3D12> GetRootSig(const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>* ppSignatures, Uint32 SignatureCount);
135
136 void OnDestroyRootSig(RootSignatureD3D12* pRootSig);
137
138 private:
139 struct RootSignatureHash
140 {
141 std::size_t operator()(const RootSignatureD3D12* Key) const noexcept
142 {
143 return Key->GetHash();
144 }
145 };
146
147 struct RootSignatureCompare
148 {
149 bool operator()(const RootSignatureD3D12* lhs, const RootSignatureD3D12* rhs) const noexcept;
150 };
151
152 private:
153 RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
154
155 std::mutex m_RootSigCacheGuard;
156
157 std::unordered_set<RootSignatureD3D12*, RootSignatureHash, RootSignatureCompare> m_RootSigCache;
158 };
159
647160 } // namespace Diligent
3333 #include "RenderDeviceD3D12.h"
3434 #include "ShaderResourceBindingBase.hpp"
3535 #include "ShaderResourceCacheD3D12.hpp"
36 #include "ShaderResourceLayoutD3D12.hpp"
3736 #include "ShaderVariableD3D12.hpp"
37 #include "PipelineResourceSignatureD3D12Impl.hpp"
3838
3939 namespace Diligent
4040 {
4141
42 class PipelineStateD3D12Impl;
43
4442 /// Implementation of the Diligent::IShaderResourceBindingD3D12 interface
4543 // sizeof(ShaderResourceBindingD3D12Impl) == 152 (x64, msvc, Release)
46 class ShaderResourceBindingD3D12Impl final : public ShaderResourceBindingBase<IShaderResourceBindingD3D12, PipelineStateD3D12Impl>
44 class ShaderResourceBindingD3D12Impl final : public ShaderResourceBindingBase<IShaderResourceBindingD3D12, PipelineResourceSignatureD3D12Impl>
4745 {
4846 public:
49 using TBase = ShaderResourceBindingBase<IShaderResourceBindingD3D12, PipelineStateD3D12Impl>;
47 using TBase = ShaderResourceBindingBase<IShaderResourceBindingD3D12, PipelineResourceSignatureD3D12Impl>;
5048
51 ShaderResourceBindingD3D12Impl(IReferenceCounters* pRefCounters,
52 PipelineStateD3D12Impl* pPSO,
53 bool IsPSOInternal);
49 ShaderResourceBindingD3D12Impl(IReferenceCounters* pRefCounters,
50 PipelineResourceSignatureD3D12Impl* pPRS,
51 bool IsDeviceInternal);
5452 ~ShaderResourceBindingD3D12Impl();
5553
5654 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderResourceBindingD3D12, TBase)
6563
6664 virtual void DILIGENT_CALL_TYPE InitializeStaticResources(const IPipelineState* pPipelineState) override final;
6765
66 virtual void DILIGENT_CALL_TYPE InitializeStaticResourcesWithSignature(const IPipelineResourceSignature* pResourceSignature) override final;
67
6868 ShaderResourceCacheD3D12& GetResourceCache() { return m_ShaderResourceCache; }
69
70 #ifdef DILIGENT_DEVELOPMENT
71 void dvpVerifyResourceBindings(const PipelineStateD3D12Impl* pPSO) const;
72 #endif
7369
7470 bool StaticResourcesInitialized() const
7571 {
8480
8581 // Resource layout index in m_ShaderResourceCache array for every shader stage,
8682 // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
87 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1};
83 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ShaderVarIndex = {-1, -1, -1, -1, -1, -1};
8884 static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
8985
9086 bool m_bStaticResourcesInitialized = false;
8383 //
8484
8585 #include "DescriptorHeap.hpp"
86 #include "PipelineResourceSignatureD3D12Impl.hpp"
8687
8788 namespace Diligent
8889 {
89
90 enum class CachedResourceType : Int32
91 {
92 Unknown = -1,
93 CBV = 0,
94 TexSRV,
95 BufSRV,
96 TexUAV,
97 BufUAV,
98 Sampler,
99 AccelStruct,
100 NumTypes
101 };
10290
10391 class ShaderResourceCacheD3D12
10492 {
10593 public:
106 // This enum is used for debug purposes only
107 enum DbgCacheContentType
108 {
109 StaticShaderResources,
110 SRBResources
111 };
112
113 explicit ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) noexcept
114 // clang-format off
115 #ifdef DILIGENT_DEBUG
116 : m_DbgContentType
117 {
118 dbgContentType
119 }
120 #endif
121 // clang-format on
122 {
123 }
94 using CacheContentType = PipelineResourceSignatureD3D12Impl::CacheContentType;
95
96 explicit ShaderResourceCacheD3D12(CacheContentType ContentType) noexcept :
97 m_ContentType{static_cast<Uint32>(ContentType)}
98 {}
12499
125100 ~ShaderResourceCacheD3D12();
126101
138113 {
139114 Resource() noexcept {}
140115
141 CachedResourceType Type = CachedResourceType::Unknown;
116 SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN;
142117 // CPU descriptor handle of a cached resource in CPU-only descriptor heap
143118 // Note that for dynamic resources, this is the only available CPU descriptor handle
144119 D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0};
162137 }
163138
164139 inline const Resource& GetResource(Uint32 OffsetFromTableStart,
165 const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType,
166 const SHADER_TYPE dbgRefShaderType) const
140 const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType) const
167141 {
168142 VERIFY(m_dbgHeapType == dbgDescriptorHeapType, "Incosistent descriptor heap type");
169 VERIFY(dbgRefShaderType == SHADER_TYPE_UNKNOWN || m_dbgShaderType == SHADER_TYPE_UNKNOWN || m_dbgShaderType == dbgRefShaderType, "Incosistent shader type");
143 //VERIFY(dbgRefShaderType == SHADER_TYPE_UNKNOWN || m_dbgShaderType == SHADER_TYPE_UNKNOWN || m_dbgShaderType == dbgRefShaderType, "Incosistent shader type");
170144
171145 VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart);
172146 return m_pResources[OffsetFromTableStart];
173147 }
174148 inline Resource& GetResource(Uint32 OffsetFromTableStart,
175 const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType,
176 const SHADER_TYPE dbgRefShaderType)
177 {
178 return const_cast<Resource&>(const_cast<const RootTable*>(this)->GetResource(OffsetFromTableStart, dbgDescriptorHeapType, dbgRefShaderType));
149 const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType)
150 {
151 return const_cast<Resource&>(const_cast<const RootTable*>(this)->GetResource(OffsetFromTableStart, dbgDescriptorHeapType));
179152 }
180153
181154 inline Uint32 GetSize() const { return m_NumResources; }
186159 #ifdef DILIGENT_DEBUG
187160 void SetDebugAttribs(Uint32 MaxOffset,
188161 const D3D12_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType,
189 const SHADER_TYPE dbgRefShaderType)
162 bool isDynamic)
190163 {
191164 VERIFY_EXPR(m_NumResources == MaxOffset);
192 m_dbgHeapType = dbgDescriptorHeapType;
193 m_dbgShaderType = dbgRefShaderType;
165 m_dbgHeapType = dbgDescriptorHeapType;
166 //m_dbgShaderType = dbgRefShaderType;
167 m_dbgIsDynamic = isDynamic;
194168 }
195169
196170 D3D12_DESCRIPTOR_HEAP_TYPE DbgGetHeapType() const { return m_dbgHeapType; }
171 bool IsDynamic() const { return m_dbgIsDynamic; }
197172 #endif
198173
199174 const Uint32 m_NumResources = 0;
200175
201176 private:
202177 #ifdef DILIGENT_DEBUG
203 D3D12_DESCRIPTOR_HEAP_TYPE m_dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
204 SHADER_TYPE m_dbgShaderType = SHADER_TYPE_UNKNOWN;
178 D3D12_DESCRIPTOR_HEAP_TYPE m_dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
179 //SHADER_TYPE m_dbgShaderType = SHADER_TYPE_UNKNOWN;
180 bool m_dbgIsDynamic = false;
205181 #endif
206182
207183 Resource* const m_pResources = nullptr;
319295 // Returns the number of dynamic constant buffers bound in the cache regardless of their variable types
320296 Uint32 GetNumDynamicCBsBound() const { return m_NumDynamicCBsBound; }
321297
298 CacheContentType GetContentType() const { return static_cast<CacheContentType>(m_ContentType); }
299
322300 #ifdef DILIGENT_DEBUG
323 // Only for debug purposes: indicates what types of resources are stored in the cache
324 DbgCacheContentType DbgGetContentType() const { return m_DbgContentType; }
325 void DbgVerifyBoundDynamicCBsCounter() const;
301 void DbgVerifyBoundDynamicCBsCounter() const;
326302 #endif
327303
328304 private:
345321 // The number of the dynamic buffers bound in the resource cache regardless of their variable type
346322 Uint32 m_NumDynamicCBsBound = 0;
347323
348 #ifdef DILIGENT_DEBUG
349 // Only for debug purposes: indicates what types of resources are stored in the cache
350 const DbgCacheContentType m_DbgContentType;
351 #endif
324 // Indicates what types of resources are stored in the cache
325 const Uint32 m_ContentType : 1;
352326 };
353327
354328 } // namespace Diligent
+0
-402
Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp less more
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Declaration of Diligent::ShaderResourceLayoutD3D12 class
31
32 // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout/
33
34 // All resources are stored in a single continuous chunk of memory using the following layout:
35 //
36 // m_ResourceBuffer
37 // | | |
38 // | D3D12Resource[0] ... | D3D12Resource[s] ... | D3D12Resource[s+m] ... | D3D12Resource[smd] ... | D3D12Resource[smd+s'] ... | D3D12Resource[smd+s'+m'] ... D3D12Resource[s+m+d+s'+m'+d'-1] ||
39 // | | | | | | ||
40 // | SRV/CBV/UAV - STATIC | SRV/CBV/UAV - MUTABLE | SRV/CBV/UAV - DYNAMIC | Samplers - STATIC | Samplers - MUTABLE | Samplers - DYNAMIC ||
41 // | | | |
42 //
43 // s == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_STATIC]
44 // m == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE]
45 // d == NumCbvSrvUav[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC]
46 // smd = s+m+d
47 //
48 // s' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_STATIC]
49 // m' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE]
50 // d' == NumSamplers[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC]
51 //
52 //
53 //
54 // ___________________________ ____________________________________________________________________________________________________________
55 // | | unique_ptr | | | | | | |
56 // | ShaderResourceLayoutD3D12 |--------------->| D3D12Resource[0] | D3D12Resource[1] | ... | D3D12Resource[smd] | D3D12Resource[smd+1] | ... |
57 // |___________________________| |__________________|__________________|_______________|____________________|______________________|__________|
58 // A A | A A
59 // | \ |______________\____SamplerId________________________|
60 // | \ \
61 // | Ref Ref
62 // | \ \_____
63 // | \ \
64 // ____________|_______________ ________\_______________________\__________________________________________
65 // | | | | | |
66 // | ShaderVariableManagerD3D12 |---------------->| ShaderVariableD3D12Impl[0] | ShaderVariableD3D12Impl[1] | ... |
67 // |____________________________| |____________________________|____________________________|_________________|
68 //
69 //
70 //
71 //
72 //
73 // One ShaderResourceLayoutD3D12 instance can be referenced by multiple objects
74 //
75 //
76 // ________________________ _<m_pShaderResourceLayouts>_ _____<m_pShaderVarMgrs>_____ ________________________________
77 // | | | | | | | |
78 // | PipelineStateD3D12Impl |========>| ShaderResourceLayoutD3D12 |<-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl |
79 // |________________________| |____________________________| |____________________________| |________________________________|
80 // A
81 // \
82 // \ _____<m_pShaderVarMgrs>_____ ________________________________
83 // \ | | | |
84 // '-------| ShaderVariableManagerD3D12 |<====| ShaderResourceBindingD3D12Impl |
85 // |____________________________| |________________________________|
86 //
87 //
88 //
89 // Resources in the resource cache are identified by the root index and offset in the descriptor table
90 //
91 //
92 // ShaderResourceLayoutD3D12 is used as follows:
93 // * Every pipeline state object (PipelineStateD3D12Impl) maintains shader resource layout for every active shader stage
94 // ** These resource layouts are used as reference layouts for shader resource binding objects
95 // ** All variable types are preserved
96 // ** Root indices and descriptor table offsets are assigned during the initialization
97 // * Every pipeline state object also contains shader resource layout that facilitates management of static shader resources
98 // ** The resource layout defines artificial layout where root index matches the resource type (CBV/SRV/UAV/SAM)
99 // ** Only static variables are referenced
100 //
101 // * Every shader resource binding object (ShaderResourceBindingD3D12Impl) encompasses shader variable
102 // manager (ShaderVariableManagerD3D12) for every active shader stage in the parent pipeline state that
103 // handles mutable and dynamic resources
104
105 #include <array>
106
107 #include "ShaderBase.hpp"
108 #include "ShaderResourceCacheD3D12.hpp"
109 #include "ShaderD3D12Impl.hpp"
110 #include "StringPool.hpp"
111 #include "D3DCommonTypeConversions.hpp"
112
113 namespace Diligent
114 {
115
116 /// Diligent::ShaderResourceLayoutD3D12 class
117 // sizeof(ShaderResourceLayoutD3D12) == 56 (MS compiler, x64)
118 class ShaderResourceLayoutD3D12 final
119 {
120 public:
121 ShaderResourceLayoutD3D12(IObject& Owner, ID3D12Device* pd3d12Device) noexcept :
122 m_Owner{Owner},
123 m_pd3d12Device{pd3d12Device}
124 {
125 #if defined(_MSC_VER) && defined(_WIN64)
126 static_assert(sizeof(*this) == 56, "Unexpected sizeof(ShaderResourceLayoutD3D12)");
127 #endif
128 }
129
130 // Initializes reference layouts that address all types of resources (static, mutable, dynamic).
131 // Root indices and descriptor table offsets are assigned during the initialization.
132 void Initialize(PIPELINE_TYPE PipelineType,
133 const PipelineResourceLayoutDesc& ResourceLayout,
134 const std::vector<ShaderD3D12Impl*>& Shaders,
135 IMemoryAllocator& LayoutDataAllocator,
136 class RootSignatureBuilder& RootSgnBldr,
137 class LocalRootSignature* pLocalRootSig);
138
139 // Copies static resources from the source layout and initializes the
140 // resource cache. Uses bind points from the source layout.
141 void InitializeStaticReourceLayout(const ShaderResourceLayoutD3D12& SrcLayout,
142 IMemoryAllocator& LayoutDataAllocator,
143 ShaderResourceCacheD3D12& ResourceCache);
144
145 // clang-format off
146 ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete;
147 ShaderResourceLayoutD3D12 (ShaderResourceLayoutD3D12&&) = delete;
148 ShaderResourceLayoutD3D12& operator =(const ShaderResourceLayoutD3D12&) = delete;
149 ShaderResourceLayoutD3D12& operator =(ShaderResourceLayoutD3D12&&) = delete;
150 // clang-format on
151
152 ~ShaderResourceLayoutD3D12();
153
154 // sizeof(D3D12Resource) == 32 (x64)
155 struct D3D12Resource final
156 {
157 // clang-format off
158 D3D12Resource (const D3D12Resource&) = delete;
159 D3D12Resource ( D3D12Resource&&) = delete;
160 D3D12Resource& operator=(const D3D12Resource&) = delete;
161 D3D12Resource& operator=( D3D12Resource&&) = delete;
162 // clang-format on
163
164 static constexpr Uint32 ResourceTypeBits = 3;
165 static constexpr Uint32 VariableTypeBits = 2;
166 static constexpr Uint32 RootIndexBits = 32 - ResourceTypeBits - VariableTypeBits;
167
168 static constexpr Uint32 InvalidRootIndex = (1U << RootIndexBits) - 1U;
169 static constexpr Uint32 MaxRootIndex = InvalidRootIndex - 1U;
170
171 static constexpr Uint32 InvalidOffset = static_cast<Uint32>(-1);
172
173 static_assert(SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES < (1 << VariableTypeBits), "Not enough bits to represent SHADER_RESOURCE_VARIABLE_TYPE");
174 static_assert(static_cast<int>(CachedResourceType::NumTypes) < (1 << ResourceTypeBits), "Not enough bits to represent CachedResourceType");
175
176 /* 0 */ const ShaderResourceLayoutD3D12& ParentResLayout;
177 /* 8 */ const D3DShaderResourceAttribs Attribs; // Copy of the attributes, potentially with some changes to bindings
178 /*24 */ const Uint32 OffsetFromTableStart;
179 /*28.0*/ const Uint32 ResourceType : ResourceTypeBits; // | 0 1 2 |
180 /*28.3*/ const Uint32 VariableType : VariableTypeBits; // | 3 4 |
181 /*28.5*/ const Uint32 RootIndex : RootIndexBits; // | 5 6 7 ... 15 |
182 /*32 */ // End of data
183
184 D3D12Resource(const ShaderResourceLayoutD3D12& _ParentLayout,
185 StringPool& _StringPool,
186 const D3DShaderResourceAttribs& _Attribs,
187 Uint32 _SamplerId,
188 SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
189 CachedResourceType _ResType,
190 Uint32 _BindPoint,
191 Uint32 _RootIndex,
192 Uint32 _OffsetFromTableStart) noexcept :
193 // clang-format off
194 ParentResLayout{_ParentLayout},
195 Attribs
196 {
197 _StringPool,
198 _Attribs,
199 _SamplerId,
200 _BindPoint
201 },
202 ResourceType {static_cast<Uint32>(_ResType) },
203 VariableType {static_cast<Uint32>(_VariableType)},
204 RootIndex {static_cast<Uint32>(_RootIndex) },
205 OffsetFromTableStart{ _OffsetFromTableStart }
206 // clang-format on
207 {
208 #if defined(_MSC_VER) && defined(_WIN64)
209 static_assert(sizeof(*this) == 32, "Unexpected sizeof(D3D12Resource)");
210 #endif
211
212 VERIFY(IsValidOffset(), "Offset must be valid");
213 VERIFY(IsValidRootIndex(), "Root index must be valid");
214 VERIFY(_RootIndex <= MaxRootIndex, "Root index (", _RootIndex, ") exceeds max allowed value (", MaxRootIndex, ")");
215 VERIFY(static_cast<Uint32>(_ResType) < (1 << ResourceTypeBits), "Resource type is out of representable range");
216 VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type is out of representable range");
217 }
218
219 bool IsBound(Uint32 ArrayIndex,
220 const ShaderResourceCacheD3D12& ResourceCache) const;
221
222 void BindResource(IDeviceObject* pObject,
223 Uint32 ArrayIndex,
224 ShaderResourceCacheD3D12& ResourceCache) const;
225
226 // clang-format off
227 bool IsValidRootIndex() const { return RootIndex != InvalidRootIndex; }
228 bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; }
229 // clang-format on
230
231 CachedResourceType GetResType() const { return static_cast<CachedResourceType>(ResourceType); }
232 SHADER_RESOURCE_VARIABLE_TYPE GetVariableType() const { return static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VariableType); }
233
234 private:
235 void CacheCB(IDeviceObject* pBuffer,
236 ShaderResourceCacheD3D12::Resource& DstRes,
237 Uint32 ArrayInd,
238 D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle,
239 Uint32& BoundDynamicCBsCounter) const;
240
241 template <typename TResourceViewType,
242 typename TViewTypeEnum,
243 typename TBindSamplerProcType>
244 void CacheResourceView(IDeviceObject* pView,
245 ShaderResourceCacheD3D12::Resource& DstRes,
246 Uint32 ArrayIndex,
247 D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle,
248 TViewTypeEnum dbgExpectedViewType,
249 TBindSamplerProcType BindSamplerProc) const;
250
251 void CacheSampler(IDeviceObject* pSampler,
252 ShaderResourceCacheD3D12::Resource& DstSam,
253 Uint32 ArrayIndex,
254 D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const;
255
256 void CacheAccelStruct(IDeviceObject* pTLAS,
257 ShaderResourceCacheD3D12::Resource& DstRes,
258 Uint32 ArrayIndex,
259 D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const;
260 };
261
262 void CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache,
263 const ShaderResourceLayoutD3D12& DstLayout,
264 ShaderResourceCacheD3D12& DstCache) const;
265
266 #ifdef DILIGENT_DEVELOPMENT
267 bool dvpVerifyBindings(const ShaderResourceCacheD3D12& ResourceCache) const;
268 #endif
269
270 IObject& GetOwner()
271 {
272 return m_Owner;
273 }
274
275 Uint32 GetCbvSrvUavCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
276 {
277 return m_CbvSrvUavOffsets[VarType + 1] - m_CbvSrvUavOffsets[VarType];
278 }
279 Uint32 GetSamplerCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
280 {
281 return m_SamplersOffsets[VarType + 1] - m_SamplersOffsets[VarType];
282 }
283 Uint32 GetTotalResourceCount() const
284 {
285 return m_SamplersOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES];
286 }
287
288 const D3D12Resource& GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
289 {
290 VERIFY_EXPR(r < GetCbvSrvUavCount(VarType));
291 return GetResource(GetSrvCbvUavOffset(VarType, r));
292 }
293 const D3D12Resource& GetSampler(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) const
294 {
295 VERIFY_EXPR(s < GetSamplerCount(VarType));
296 return GetResource(GetSamplerOffset(VarType, s));
297 }
298
299 const D3D12Resource& GetResource(Uint32 r) const
300 {
301 VERIFY_EXPR(r < GetTotalResourceCount());
302 const auto* Resources = reinterpret_cast<const D3D12Resource*>(m_ResourceBuffer.get());
303 return Resources[r];
304 }
305
306 const bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; }
307
308 SHADER_TYPE GetShaderType() const { return m_ShaderType; }
309
310 bool IsCompatibleWith(const ShaderResourceLayoutD3D12& ResLayout) const;
311
312 private:
313 const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv) const;
314 D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv);
315
316 Uint32 FindSamplerByName(const char* SamplerName) const;
317
318 const Char* GetShaderName() const
319 {
320 return GetStringPoolData();
321 }
322
323
324 Uint32 GetTotalSrvCbvUavCount() const
325 {
326 VERIFY_EXPR(m_CbvSrvUavOffsets[0] == 0);
327 return m_CbvSrvUavOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES];
328 }
329 Uint32 GetTotalSamplerCount() const
330 {
331 return m_SamplersOffsets[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES] - m_SamplersOffsets[0];
332 }
333
334 D3D12Resource& GetResource(Uint32 r)
335 {
336 VERIFY_EXPR(r < GetTotalResourceCount());
337 auto* Resources = reinterpret_cast<D3D12Resource*>(m_ResourceBuffer.get());
338 return Resources[r];
339 }
340
341 Uint32 GetSrvCbvUavOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
342 {
343 Uint32 Offset = m_CbvSrvUavOffsets[VarType] + r;
344 VERIFY_EXPR(Offset < m_CbvSrvUavOffsets[VarType + 1]);
345 return Offset;
346 }
347 D3D12Resource& GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r)
348 {
349 VERIFY_EXPR(r < GetCbvSrvUavCount(VarType));
350 return GetResource(GetSrvCbvUavOffset(VarType, r));
351 }
352 const D3D12Resource& GetSrvCbvUav(Uint32 r) const
353 {
354 VERIFY_EXPR(r < GetTotalSrvCbvUavCount());
355 return GetResource(m_CbvSrvUavOffsets[0] + r);
356 }
357
358
359 Uint32 GetSamplerOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s) const
360 {
361 auto Offset = m_SamplersOffsets[VarType] + s;
362 VERIFY_EXPR(Offset < m_SamplersOffsets[VarType + 1]);
363 return Offset;
364 }
365 D3D12Resource& GetSampler(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 s)
366 {
367 VERIFY_EXPR(s < GetSamplerCount(VarType));
368 return GetResource(GetSamplerOffset(VarType, s));
369 }
370 const D3D12Resource& GetSampler(Uint32 s) const
371 {
372 VERIFY_EXPR(s < GetTotalSamplerCount());
373 return GetResource(m_SamplersOffsets[0] + s);
374 }
375
376 const char* GetStringPoolData() const
377 {
378 const auto* Resources = reinterpret_cast<const D3D12Resource*>(m_ResourceBuffer.get());
379 return reinterpret_cast<const char*>(Resources + GetTotalResourceCount());
380 }
381
382 StringPool AllocateMemory(IMemoryAllocator& Allocator,
383 const std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>& CbvSrvUavCount,
384 const std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>& SamplerCount,
385 size_t StringPoolSize);
386 // clang-format off
387
388 /* 0 */ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
389 /* 16 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES + 1> m_CbvSrvUavOffsets = {};
390 /* 24 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES + 1> m_SamplersOffsets = {};
391
392 /* 32 */ IObject& m_Owner;
393 /* 40 */ CComPtr<ID3D12Device> m_pd3d12Device;
394 /* 48 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN;
395 /* */ bool m_IsUsingSeparateSamplers = false;
396 /* 56 */ // End of data
397
398 // clang-format on
399 };
400
401 } // namespace Diligent
6363 #include <memory>
6464
6565 #include "ShaderResourceVariableD3D.h"
66 #include "ShaderResourceLayoutD3D12.hpp"
6766 #include "ShaderResourceVariableBase.hpp"
67 #include "ShaderResourceCacheD3D12.hpp"
68 #include "PipelineResourceSignatureD3D12Impl.hpp"
6869
6970 namespace Diligent
7071 {
8182 m_ResourceCache{ResourceCache}
8283 {}
8384
84 void Initialize(const ShaderResourceLayoutD3D12& Layout,
85 IMemoryAllocator& Allocator,
86 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
87 Uint32 NumAllowedTypes);
85 void Initialize(const PipelineResourceSignatureD3D12Impl& Signature,
86 IMemoryAllocator& Allocator,
87 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
88 Uint32 NumAllowedTypes,
89 SHADER_TYPE ShaderType);
8890 ~ShaderVariableManagerD3D12();
8991
9092 void Destroy(IMemoryAllocator& Allocator);
9496
9597 void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags);
9698
97 static size_t GetRequiredMemorySize(const ShaderResourceLayoutD3D12& Layout,
98 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
99 Uint32 NumAllowedTypes,
100 Uint32& NumVariables);
99 static size_t GetRequiredMemorySize(const PipelineResourceSignatureD3D12Impl& Signature,
100 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
101 Uint32 NumAllowedTypes,
102 SHADER_TYPE ShaderType,
103 Uint32& NumVariables);
101104
102105 Uint32 GetVariableCount() const { return m_NumVariables; }
103106
104107 private:
105108 friend ShaderVariableD3D12Impl;
109 using ResourceAttribs = PipelineResourceSignatureD3D12Impl::ResourceAttribs;
106110
107111 Uint32 GetVariableIndex(const ShaderVariableD3D12Impl& Variable);
108112
109 // clang-format off
110
111 IObject& m_Owner;
113 const PipelineResourceDesc& GetResourceDesc(Uint32 Index) const
114 {
115 VERIFY_EXPR(m_pSignature);
116 return m_pSignature->GetResourceDesc(Index);
117 }
118 const ResourceAttribs& GetResourceAttribs(Uint32 Index) const
119 {
120 VERIFY_EXPR(m_pSignature);
121 return m_pSignature->GetResourceAttribs(Index);
122 }
123
124 private:
125 PipelineResourceSignatureD3D12Impl const* m_pSignature = nullptr;
126
127 IObject& m_Owner;
112128
113129 // Variable mgr is owned by either Pipeline state object (in which case m_ResourceCache references
114 // static resource cache owned by the same PSO object), or by SRB object (in which case
130 // static resource cache owned by the same PSO object), or by SRB object (in which case
115131 // m_ResourceCache references the cache in the SRB). Thus the cache and the resource layout
116132 // (which the variables reference) are guaranteed to be alive while the manager is alive.
117 ShaderResourceCacheD3D12& m_ResourceCache;
133 ShaderResourceCacheD3D12& m_ResourceCache;
118134
119135 // Memory is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block
120136 // memory allocator is used. This ensures that all resources from different shader resource bindings reside in
121137 // continuous memory. If allocation granularity == 1, raw allocator is used.
122 ShaderVariableD3D12Impl* m_pVariables = nullptr;
123 Uint32 m_NumVariables = 0;
138 ShaderVariableD3D12Impl* m_pVariables = nullptr;
139 Uint32 m_NumVariables = 0;
124140
125141 #ifdef DILIGENT_DEBUG
126 IMemoryAllocator* m_pDbgAllocator = nullptr;
142 IMemoryAllocator* m_pDbgAllocator = nullptr;
127143 #endif
128 // clang-format on
129144 };
130145
131146 // sizeof(ShaderVariableD3D12Impl) == 24 (x64)
132147 class ShaderVariableD3D12Impl final : public IShaderResourceVariableD3D
133148 {
134149 public:
135 ShaderVariableD3D12Impl(ShaderVariableManagerD3D12& ParentManager,
136 const ShaderResourceLayoutD3D12::D3D12Resource& Resource) :
150 ShaderVariableD3D12Impl(ShaderVariableManagerD3D12& ParentManager,
151 Uint32 ResIndex) :
137152 m_ParentManager{ParentManager},
138 m_Resource{Resource}
153 m_ResIndex{ResIndex}
139154 {}
140155
141156 // clang-format off
175190
176191 virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final
177192 {
178 return m_Resource.GetVariableType();
179 }
180
181 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final
182 {
183 m_Resource.BindResource(pObject, 0, m_ParentManager.m_ResourceCache);
184 }
185
186 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final
187 {
188 VerifyAndCorrectSetArrayArguments(m_Resource.Attribs.Name, m_Resource.Attribs.BindCount, FirstElement, NumElements);
189 for (Uint32 Elem = 0; Elem < NumElements; ++Elem)
190 m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache);
191 }
193 return GetDesc().VarType;
194 }
195
196 virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final;
197
198 virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final;
192199
193200 virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final
194201 {
195 ResourceDesc = GetHLSLResourceDesc();
196 }
202 const auto& Desc = GetDesc();
203 ResourceDesc.Name = Desc.Name;
204 ResourceDesc.Type = Desc.ResourceType;
205 ResourceDesc.ArraySize = Desc.ArraySize;
206 }
207
208 virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final
209 {
210 return m_ParentManager.GetVariableIndex(*this);
211 }
212
213 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final;
197214
198215 virtual HLSLShaderResourceDesc DILIGENT_CALL_TYPE GetHLSLResourceDesc() const override final
199216 {
200 return m_Resource.Attribs.GetHLSLResourceDesc();
201 }
202
203 virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final
204 {
205 return m_ParentManager.GetVariableIndex(*this);
206 }
207
208 virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
209 {
210 return m_Resource.IsBound(ArrayIndex, m_ParentManager.m_ResourceCache);
211 }
212
213 const ShaderResourceLayoutD3D12::D3D12Resource& GetResource() const
214 {
215 return m_Resource;
217 // AZ TODO
218 return {};
216219 }
217220
218221 private:
219222 friend ShaderVariableManagerD3D12;
220
221 ShaderVariableManagerD3D12& m_ParentManager;
222 const ShaderResourceLayoutD3D12::D3D12Resource& m_Resource;
223 using ResourceAttribs = PipelineResourceSignatureD3D12Impl::ResourceAttribs;
224
225 const PipelineResourceDesc& GetDesc() const { return m_ParentManager.GetResourceDesc(m_ResIndex); }
226 const ResourceAttribs& GetAttribs() const { return m_ParentManager.GetResourceAttribs(m_ResIndex); }
227
228 void BindResource(IDeviceObject* pObj, Uint32 ArrayIndex) const;
229
230 private:
231 ShaderVariableManagerD3D12& m_ParentManager;
232 const Uint32 m_ResIndex;
223233 };
224234
225235 } // namespace Diligent
4242 #include "CommandListD3D12Impl.hpp"
4343 #include "DXGITypeConversions.hpp"
4444 #include "ShaderBindingTableD3D12Impl.hpp"
45 #include "ShaderResourceBindingD3D12Impl.hpp"
4546
4647 namespace Diligent
4748 {
7374 bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : EngineCI.NumCommandsToFlushCmdList,
7475 bIsDeferred
7576 },
77 m_GraphicsResources{false},
78 m_ComputeResources {true },
7679 m_DynamicHeap
7780 {
7881 pDeviceD3D12Impl->GetDynamicMemoryManager(),
223226
224227 TDeviceContextBase::SetPipelineState(pPipelineStateD3D12, 0 /*Dummy*/);
225228
226 auto& CmdCtx = GetCmdContext();
229 auto& CmdCtx = GetCmdContext();
230 auto& RootInfo = GetRootTableInfo(PSODesc.PipelineType);
231 auto* pd3d12RootSig = pPipelineStateD3D12->GetRootSignature()->GetD3D12RootSignature();
232
233 if (RootInfo.pRootSig != pd3d12RootSig)
234 {
235 RootInfo.pRootSig = pd3d12RootSig;
236 RootInfo.bRootTablesCommited = false;
237 RootInfo.bRootViewsCommitted = false;
238 }
227239
228240 switch (PSODesc.PipelineType)
229241 {
234246 auto& GraphicsCtx = CmdCtx.AsGraphicsContext();
235247 auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState();
236248 GraphicsCtx.SetPipelineState(pd3d12PSO);
249 GraphicsCtx.SetGraphicsRootSignature(pd3d12RootSig);
237250
238251 if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS)
239252 {
261274 case PIPELINE_TYPE_COMPUTE:
262275 {
263276 auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState();
264 CmdCtx.AsComputeContext().SetPipelineState(pd3d12PSO);
277 auto& CompCtx = CmdCtx.AsComputeContext();
278 CompCtx.SetPipelineState(pd3d12PSO);
279 CompCtx.SetComputeRootSignature(pd3d12RootSig);
265280 break;
266281 }
267282 case PIPELINE_TYPE_RAY_TRACING:
268283 {
269284 auto* pd3d12SO = pPipelineStateD3D12->GetD3D12StateObject();
270 CmdCtx.AsGraphicsContext4().SetRayTracingPipelineState(pd3d12SO);
285 auto& RTCtx = CmdCtx.AsGraphicsContext4();
286 RTCtx.SetRayTracingPipelineState(pd3d12SO);
287 RTCtx.SetComputeRootSignature(pd3d12RootSig);
271288 break;
272289 }
273290 default:
274291 UNEXPECTED("unknown pipeline type");
275292 }
276
277 m_State.pCommittedResourceCache = nullptr;
278 m_State.bRootViewsCommitted = false;
293 }
294
295 void DeviceContextD3D12Impl::CommitRootTables(RootTableInfo& RootInfo)
296 {
297 const auto& RootSig = *m_pPipelineState->GetRootSignature();
298 auto& CmdCtx = GetCmdContext();
299
300 if (!RootInfo.bRootTablesCommited)
301 {
302 RootInfo.bRootTablesCommited = true;
303
304 for (Uint32 s = 0; s < RootSig.GetSignatureCount(); ++s)
305 {
306 auto* pSignature = RootSig.GetSignature(s);
307 auto* pSRB = RootInfo.SRBs[s];
308
309 if (pSignature == nullptr)
310 continue;
311
312 VERIFY_EXPR(pSRB != nullptr);
313 pSignature->CommitRootTables(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootInfo.IsCompute, RootSig.GetFirstRootIndex(s));
314 }
315 }
316
317 if (!RootInfo.bRootViewsCommitted)
318 {
319 RootInfo.bRootViewsCommitted = true;
320
321 for (Uint32 s = 0; s < RootSig.GetSignatureCount(); ++s)
322 {
323 auto* pSignature = RootSig.GetSignature(s);
324 auto* pSRB = RootInfo.SRBs[s];
325
326 if (pSignature == nullptr)
327 continue;
328
329 VERIFY_EXPR(pSRB != nullptr);
330 pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootInfo.IsCompute, RootSig.GetFirstRootIndex(s));
331 }
332 }
279333 }
280334
281335 void DeviceContextD3D12Impl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
287341 return;
288342 }
289343
290 auto& Ctx = GetCmdContext();
291
292 auto* pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pPipelineState);
293
294 PipelineStateD3D12Impl::CommitAndTransitionResourcesAttribs Attribs;
295 Attribs.CtxId = m_ContextId;
296 Attribs.pShaderResourceBinding = pShaderResourceBinding;
297 Attribs.CommitResources = false;
298 Attribs.TransitionResources = true;
299 Attribs.ValidateStates = false;
300 pPipelineStateD3D12->CommitAndTransitionShaderResources(this, Ctx, Attribs);
344 auto& CmdCtx = GetCmdContext();
345 auto* pResBindingD3D12Impl = ValidatedCast<ShaderResourceBindingD3D12Impl>(pShaderResourceBinding);
346 auto& ResourceCache = pResBindingD3D12Impl->GetResourceCache();
347
348 pResBindingD3D12Impl->GetSignature()->TransitionResources(ResourceCache, CmdCtx, true, false);
301349 }
302350
303351 void DeviceContextD3D12Impl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
305353 if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/))
306354 return;
307355
308 auto& Ctx = GetCmdContext();
309
310 PipelineStateD3D12Impl::CommitAndTransitionResourcesAttribs Attribs;
311 Attribs.CtxId = m_ContextId;
312 Attribs.pShaderResourceBinding = pShaderResourceBinding;
313 Attribs.CommitResources = true;
314 Attribs.TransitionResources = StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
315 Attribs.ValidateStates = StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY;
316 m_State.pCommittedResourceCache = m_pPipelineState->CommitAndTransitionShaderResources(this, Ctx, Attribs);
317 m_State.bRootViewsCommitted = false;
318 }
356 auto* pResBindingD3D12Impl = ValidatedCast<ShaderResourceBindingD3D12Impl>(pShaderResourceBinding);
357 auto& ResourceCache = pResBindingD3D12Impl->GetResourceCache();
358 auto& CmdCtx = GetCmdContext();
359 auto* pSignature = pResBindingD3D12Impl->GetSignature();
360
361 //if (pSignature->GetTotalRootCount() == 0)
362 //{
363 // Ignore SRBs that contain no resources
364 // return;
365 //}
366
367 #ifdef DILIGENT_DEBUG
368 //ResourceCache.DbgVerifyDynamicBuffersCounter();
369 #endif
370
371 if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
372 {
373 pSignature->TransitionResources(ResourceCache, CmdCtx, true, false);
374 }
375 #ifdef DILIGENT_DEVELOPMENT
376 else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
377 {
378 pSignature->TransitionResources(ResourceCache, CmdCtx, false, true);
379 }
380 #endif
381
382 auto& RootInfo = GetRootTableInfo(pSignature->GetPipelineType());
383
384 RootInfo.SRBs[pSignature->GetDesc().BindingIndex] = pResBindingD3D12Impl;
385
386 RootInfo.bRootTablesCommited = false;
387 RootInfo.bRootViewsCommitted = false;
388 }
389
390 DeviceContextD3D12Impl::RootTableInfo& DeviceContextD3D12Impl::GetRootTableInfo(PIPELINE_TYPE PipelineType)
391 {
392 return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH ?
393 m_GraphicsResources :
394 m_ComputeResources;
395 }
396
397 #ifdef DILIGENT_DEVELOPMENT
398 void DeviceContextD3D12Impl::DvpValidateCommittedShaderResources()
399 {
400 if (m_State.CommittedResourcesValidated)
401 return;
402
403 const auto& RootSig = *m_pPipelineState->GetRootSignature();
404 auto& RootInfo = GetRootTableInfo(m_pPipelineState->GetDesc().PipelineType);
405 const auto SignCount = RootSig.GetSignatureCount();
406
407 for (Uint32 i = 0; i < SignCount; ++i)
408 {
409 auto* pSignature = RootSig.GetSignature(i);
410 if (pSignature == nullptr)
411 continue;
412
413 if (pSignature->GetTotalRootCount() == 0)
414 {
415 // Skip signatures without any resources
416 continue;
417 }
418
419 const auto* pSRB = RootInfo.SRBs[i];
420 if (pSRB == nullptr)
421 {
422 LOG_ERROR_MESSAGE("Shader resource binding is not bound to index (", i, ").");
423 continue;
424 }
425
426 auto* pSRBSign = pSRB->GetSignature();
427 VERIFY_EXPR(pSRBSign != nullptr);
428
429 if (!pSignature->IsCompatibleWith(*pSRBSign))
430 {
431 LOG_ERROR_MESSAGE("Shader resource binding at index ", i, " with signature '", pSRBSign->GetDesc().Name,
432 "' is not compatible with pipeline layout in current pipeline '", m_pPipelineState->GetDesc().Name, "'.");
433 }
434 }
435
436 //m_pPipelineState->DvpVerifySRBResources(RootInfo.SRBs);
437
438 m_State.CommittedResourcesValidated = true;
439 }
440 #endif
319441
320442 void DeviceContextD3D12Impl::SetStencilRef(Uint32 StencilRef)
321443 {
455577 }
456578 #endif
457579
458 GraphCtx.SetGraphicsRootSignature(m_pPipelineState->GetD3D12RootSignature());
459
460 if (m_State.pCommittedResourceCache != nullptr)
461 {
462 if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0)
463 {
464 if (!m_State.bRootViewsCommitted || (Flags & DRAW_FLAG_DYNAMIC_RESOURCE_BUFFERS_INTACT) == 0)
465 {
466 // Only process dynamic buffers. Non-dynamic buffers are committed by CommitShaderResources
467 m_pPipelineState->GetRootSignature()
468 .CommitRootViews(*m_State.pCommittedResourceCache,
469 GraphCtx,
470 false, // IsCompute
471 m_ContextId,
472 this,
473 true, // CommitViews
474 true, // ProcessDynamicBuffers
475 false, // ProcessNonDynamicBuffers
476 false, // TransitionStates
477 false // ValidateStates
478 );
479 m_State.bRootViewsCommitted = true;
480 }
481 }
482 }
580 auto& RootInfo = GetRootTableInfo(PIPELINE_TYPE_GRAPHICS);
581 if (RootInfo.RequireUpdate(Flags & DRAW_FLAG_DYNAMIC_RESOURCE_BUFFERS_INTACT))
582 {
583 CommitRootTables(RootInfo);
584 }
585
483586 #ifdef DILIGENT_DEVELOPMENT
484 else
485 {
486 if (m_pPipelineState->ContainsShaderResources())
487 LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called with non-null SRB");
488 }
587 DvpValidateCommittedShaderResources();
489588 #endif
490589 }
491590
611710
612711 void DeviceContextD3D12Impl::PrepareForDispatchCompute(ComputeContext& ComputeCtx)
613712 {
614 ComputeCtx.SetComputeRootSignature(m_pPipelineState->GetD3D12RootSignature());
615 if (m_State.pCommittedResourceCache != nullptr)
616 {
617 if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0)
618 {
619 // Only process dynamic buffers. Non-dynamic buffers are committed by CommitShaderResources
620 m_pPipelineState->GetRootSignature()
621 .CommitRootViews(*m_State.pCommittedResourceCache,
622 ComputeCtx,
623 true, // IsCompute
624 m_ContextId,
625 this,
626 true, // CommitViews
627 true, // ProcessDynamicBuffers
628 false, // ProcessNonDynamicBuffers
629 false, // TransitionStates
630 false // ValidateStates
631 );
632 }
633 }
713 auto& RootInfo = GetRootTableInfo(PIPELINE_TYPE_COMPUTE);
714 if (RootInfo.RequireUpdate())
715 {
716 CommitRootTables(RootInfo);
717 }
718
634719 #ifdef DILIGENT_DEVELOPMENT
635 else
636 {
637 if (m_pPipelineState->ContainsShaderResources())
638 LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called with non-null SRB");
639 }
720 DvpValidateCommittedShaderResources();
640721 #endif
641722 }
642723
643724 void DeviceContextD3D12Impl::PrepareForDispatchRays(GraphicsContext& GraphCtx)
644725 {
645 GraphCtx.SetComputeRootSignature(m_pPipelineState->GetD3D12RootSignature());
646 if (m_State.pCommittedResourceCache != nullptr)
647 {
648 if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0)
649 {
650 // Only process dynamic buffers. Non-dynamic buffers are committed by CommitShaderResources
651 m_pPipelineState->GetRootSignature()
652 .CommitRootViews(*m_State.pCommittedResourceCache,
653 GraphCtx,
654 true, // IsCompute
655 m_ContextId,
656 this,
657 true, // CommitViews
658 true, // ProcessDynamicBuffers
659 false, // ProcessNonDynamicBuffers
660 false, // TransitionStates
661 false // ValidateStates
662 );
663 }
664 }
726 auto& RootInfo = GetRootTableInfo(PIPELINE_TYPE_RAY_TRACING);
727 if (RootInfo.RequireUpdate())
728 {
729 CommitRootTables(RootInfo);
730 }
731
665732 #ifdef DILIGENT_DEVELOPMENT
666 else
667 {
668 if (m_pPipelineState->ContainsShaderResources())
669 LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called with non-null SRB");
670 }
733 DvpValidateCommittedShaderResources();
671734 #endif
672735 }
673736
831894 RequestCommandContext(m_pDevice);
832895
833896 m_State = State{};
897
898 m_GraphicsResources = RootTableInfo{false};
899 m_ComputeResources = RootTableInfo{true};
834900
835901 // Setting pipeline state to null makes sure that render targets and other
836902 // states will be restored in the command list next time a PSO is bound.
0 /*
1 * Copyright 2019-2021 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #include "pch.h"
28 #include "PipelineResourceSignatureD3D12Impl.hpp"
29 #include "ShaderResourceCacheD3D12.hpp"
30 #include "ShaderVariableD3D12.hpp"
31 #include "RenderDeviceD3D12Impl.hpp"
32 #include "ShaderResourceBindingD3D12Impl.hpp"
33 #include "BufferD3D12Impl.hpp"
34 #include "BufferViewD3D12Impl.hpp"
35 #include "SamplerD3D12Impl.hpp"
36 #include "TextureD3D12Impl.hpp"
37 #include "TextureViewD3D12Impl.hpp"
38 #include "TopLevelASD3D12Impl.hpp"
39
40 namespace Diligent
41 {
42
43 PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
44 Uint32 RootIndex,
45 UINT Register,
46 UINT RegisterSpace,
47 D3D12_SHADER_VISIBILITY Visibility,
48 ROOT_TYPE RootType) noexcept :
49 // clang-format off
50 m_RootIndex{RootIndex},
51 m_RootType {RootType }
52 // clang-format on
53 {
54 VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, "Unexpected parameter type - verify argument list");
55 m_RootParam.ParameterType = ParameterType;
56 m_RootParam.ShaderVisibility = Visibility;
57 m_RootParam.Descriptor.ShaderRegister = Register;
58 m_RootParam.Descriptor.RegisterSpace = RegisterSpace;
59 }
60
61 PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
62 Uint32 RootIndex,
63 UINT Register,
64 UINT RegisterSpace,
65 UINT NumDwords,
66 D3D12_SHADER_VISIBILITY Visibility,
67 ROOT_TYPE RootType) noexcept :
68 // clang-format off
69 m_RootIndex{RootIndex},
70 m_RootType {RootType }
71 // clang-format on
72 {
73 VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, "Unexpected parameter type - verify argument list");
74 m_RootParam.ParameterType = ParameterType;
75 m_RootParam.ShaderVisibility = Visibility;
76 m_RootParam.Constants.Num32BitValues = NumDwords;
77 m_RootParam.Constants.ShaderRegister = Register;
78 m_RootParam.Constants.RegisterSpace = RegisterSpace;
79 }
80
81 PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType,
82 Uint32 RootIndex,
83 UINT NumRanges,
84 D3D12_DESCRIPTOR_RANGE* pRanges,
85 D3D12_SHADER_VISIBILITY Visibility,
86 ROOT_TYPE RootType) noexcept :
87 // clang-format off
88 m_RootIndex{RootIndex},
89 m_RootType {RootType }
90 // clang-format on
91 {
92 VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type - verify argument list");
93 VERIFY_EXPR(pRanges != nullptr);
94 m_RootParam.ParameterType = ParameterType;
95 m_RootParam.ShaderVisibility = Visibility;
96 m_RootParam.DescriptorTable.NumDescriptorRanges = NumRanges;
97 m_RootParam.DescriptorTable.pDescriptorRanges = pRanges;
98 #ifdef DILIGENT_DEBUG
99 for (Uint32 r = 0; r < NumRanges; ++r)
100 pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1);
101 #endif
102 }
103
104 PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(const RootParameter& RP) noexcept :
105 // clang-format off
106 m_RootParam {RP.m_RootParam },
107 m_DescriptorTableSize{RP.m_DescriptorTableSize},
108 m_RootType {RP.m_RootType },
109 m_RootIndex {RP.m_RootIndex }
110 // clang-format on
111 {
112 VERIFY(m_RootParam.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Use another constructor to copy descriptor table");
113 }
114
115 PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(const RootParameter& RP,
116 UINT NumRanges,
117 D3D12_DESCRIPTOR_RANGE* pRanges) noexcept :
118 // clang-format off
119 m_RootParam {RP.m_RootParam },
120 m_DescriptorTableSize{RP.m_DescriptorTableSize},
121 m_RootType {RP.m_RootType },
122 m_RootIndex {RP.m_RootIndex }
123 // clang-format on
124 {
125 VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table");
126 VERIFY(NumRanges >= m_RootParam.DescriptorTable.NumDescriptorRanges, "New table must be larger than source one");
127 auto& DstTbl = m_RootParam.DescriptorTable;
128 DstTbl.NumDescriptorRanges = NumRanges;
129 DstTbl.pDescriptorRanges = pRanges;
130 const auto& SrcTbl = RP.m_RootParam.DescriptorTable;
131 memcpy(pRanges, SrcTbl.pDescriptorRanges, SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE));
132 #ifdef DILIGENT_DEBUG
133 {
134 Uint32 dbgTableSize = 0;
135 for (Uint32 r = 0; r < SrcTbl.NumDescriptorRanges; ++r)
136 {
137 const auto& Range = SrcTbl.pDescriptorRanges[r];
138 dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors);
139 }
140 VERIFY(dbgTableSize == m_DescriptorTableSize, "Incorrect descriptor table size");
141
142 for (Uint32 r = SrcTbl.NumDescriptorRanges; r < DstTbl.NumDescriptorRanges; ++r)
143 pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1);
144 }
145 #endif
146 }
147
148 void PipelineResourceSignatureD3D12Impl::RootParameter::SetDescriptorRange(UINT RangeIndex,
149 D3D12_DESCRIPTOR_RANGE_TYPE Type,
150 UINT Register,
151 UINT RegisterSpace,
152 UINT Count,
153 UINT OffsetFromTableStart)
154 {
155 VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected");
156 auto& Tbl = m_RootParam.DescriptorTable;
157 VERIFY(RangeIndex < Tbl.NumDescriptorRanges, "Invalid descriptor range index");
158 D3D12_DESCRIPTOR_RANGE& range = const_cast<D3D12_DESCRIPTOR_RANGE&>(Tbl.pDescriptorRanges[RangeIndex]);
159 VERIFY(range.RangeType == static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1), "Descriptor range has already been initialized. m_DescriptorTableSize may be updated incorrectly");
160 range.RangeType = Type;
161 range.NumDescriptors = Count;
162 range.BaseShaderRegister = Register;
163 range.RegisterSpace = RegisterSpace;
164 range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart;
165 m_DescriptorTableSize = std::max(m_DescriptorTableSize, OffsetFromTableStart + Count);
166 }
167
168 Uint32 PipelineResourceSignatureD3D12Impl::RootParameter::GetDescriptorTableSize() const
169 {
170 VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected");
171 return m_DescriptorTableSize;
172 }
173
174 bool PipelineResourceSignatureD3D12Impl::RootParameter::operator==(const RootParameter& rhs) const
175 {
176 if (m_RootType != rhs.m_RootType ||
177 m_DescriptorTableSize != rhs.m_DescriptorTableSize ||
178 m_RootIndex != rhs.m_RootIndex)
179 return false;
180
181 if (m_RootParam.ParameterType != rhs.m_RootParam.ParameterType ||
182 m_RootParam.ShaderVisibility != rhs.m_RootParam.ShaderVisibility)
183 return false;
184
185 switch (m_RootParam.ParameterType)
186 {
187 case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
188 {
189 const auto& tbl0 = m_RootParam.DescriptorTable;
190 const auto& tbl1 = rhs.m_RootParam.DescriptorTable;
191 if (tbl0.NumDescriptorRanges != tbl1.NumDescriptorRanges)
192 return false;
193 for (UINT r = 0; r < tbl0.NumDescriptorRanges; ++r)
194 {
195 const auto& rng0 = tbl0.pDescriptorRanges[r];
196 const auto& rng1 = tbl1.pDescriptorRanges[r];
197 if (memcmp(&rng0, &rng1, sizeof(rng0)) != 0)
198 return false;
199 }
200 }
201 break;
202
203 case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
204 {
205 const auto& cnst0 = m_RootParam.Constants;
206 const auto& cnst1 = rhs.m_RootParam.Constants;
207 if (memcmp(&cnst0, &cnst1, sizeof(cnst0)) != 0)
208 return false;
209 }
210 break;
211
212 case D3D12_ROOT_PARAMETER_TYPE_CBV:
213 case D3D12_ROOT_PARAMETER_TYPE_SRV:
214 case D3D12_ROOT_PARAMETER_TYPE_UAV:
215 {
216 const auto& dscr0 = m_RootParam.Descriptor;
217 const auto& dscr1 = rhs.m_RootParam.Descriptor;
218 if (memcmp(&dscr0, &dscr1, sizeof(dscr0)) != 0)
219 return false;
220 }
221 break;
222
223 default: UNEXPECTED("Unexpected root parameter type");
224 }
225
226 return true;
227 }
228
229 size_t PipelineResourceSignatureD3D12Impl::RootParameter::GetHash() const
230 {
231 size_t hash = ComputeHash(m_RootType, m_DescriptorTableSize, m_RootIndex);
232 HashCombine(hash, m_RootParam.ParameterType, m_RootParam.ShaderVisibility);
233
234 switch (m_RootParam.ParameterType)
235 {
236 case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
237 {
238 const auto& tbl = m_RootParam.DescriptorTable;
239 HashCombine(hash, tbl.NumDescriptorRanges);
240 for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r)
241 {
242 const auto& rng = tbl.pDescriptorRanges[r];
243 HashCombine(hash, rng.BaseShaderRegister, rng.NumDescriptors, rng.OffsetInDescriptorsFromTableStart, rng.RangeType, rng.RegisterSpace);
244 }
245 }
246 break;
247
248 case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
249 {
250 const auto& cnst = m_RootParam.Constants;
251 HashCombine(hash, cnst.Num32BitValues, cnst.RegisterSpace, cnst.ShaderRegister);
252 }
253 break;
254
255 case D3D12_ROOT_PARAMETER_TYPE_CBV:
256 case D3D12_ROOT_PARAMETER_TYPE_SRV:
257 case D3D12_ROOT_PARAMETER_TYPE_UAV:
258 {
259 const auto& dscr = m_RootParam.Descriptor;
260 HashCombine(hash, dscr.RegisterSpace, dscr.ShaderRegister);
261 }
262 break;
263
264 default: UNEXPECTED("Unexpected root parameter type");
265 }
266
267 return hash;
268 }
269
270
271 PipelineResourceSignatureD3D12Impl::RootParamsManager::RootParamsManager(IMemoryAllocator& MemAllocator) :
272 m_MemAllocator{MemAllocator},
273 m_pMemory{nullptr, STDDeleter<void, IMemoryAllocator>(MemAllocator)}
274 {}
275
276 size_t PipelineResourceSignatureD3D12Impl::RootParamsManager::GetRequiredMemorySize(Uint32 NumExtraRootTables,
277 Uint32 NumExtraRootViews,
278 Uint32 NumExtraDescriptorRanges) const
279 {
280 return sizeof(RootParameter) * (m_NumRootTables + NumExtraRootTables + m_NumRootViews + NumExtraRootViews) + sizeof(D3D12_DESCRIPTOR_RANGE) * (m_TotalDescriptorRanges + NumExtraDescriptorRanges);
281 }
282
283 D3D12_DESCRIPTOR_RANGE* PipelineResourceSignatureD3D12Impl::RootParamsManager::Extend(Uint32 NumExtraRootTables,
284 Uint32 NumExtraRootViews,
285 Uint32 NumExtraDescriptorRanges,
286 Uint32 RootTableToAddRanges)
287 {
288 VERIFY(NumExtraRootTables > 0 || NumExtraRootViews > 0 || NumExtraDescriptorRanges > 0, "At least one root table, root view or descriptor range must be added");
289 auto MemorySize = GetRequiredMemorySize(NumExtraRootTables, NumExtraRootViews, NumExtraDescriptorRanges);
290 VERIFY_EXPR(MemorySize > 0);
291 auto* pNewMemory = ALLOCATE_RAW(m_MemAllocator, "Memory buffer for root tables, root views & descriptor ranges", MemorySize);
292 memset(pNewMemory, 0, MemorySize);
293
294 // Note: this order is more efficient than views->tables->ranges
295 auto* pNewRootTables = reinterpret_cast<RootParameter*>(pNewMemory);
296 auto* pNewRootViews = pNewRootTables + (m_NumRootTables + NumExtraRootTables);
297 auto* pCurrDescriptorRangePtr = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pNewRootViews + m_NumRootViews + NumExtraRootViews);
298
299 // Copy existing root tables to new memory
300 for (Uint32 rt = 0; rt < m_NumRootTables; ++rt)
301 {
302 const auto& SrcTbl = GetRootTable(rt);
303 auto& D3D12SrcTbl = static_cast<const D3D12_ROOT_PARAMETER&>(SrcTbl).DescriptorTable;
304 auto NumRanges = D3D12SrcTbl.NumDescriptorRanges;
305 if (rt == RootTableToAddRanges)
306 {
307 VERIFY(NumExtraRootTables == 0 || NumExtraRootTables == 1, "Up to one descriptor table can be extended at a time");
308 NumRanges += NumExtraDescriptorRanges;
309 }
310 new (pNewRootTables + rt) RootParameter(SrcTbl, NumRanges, pCurrDescriptorRangePtr);
311 pCurrDescriptorRangePtr += NumRanges;
312 }
313
314 // Copy existing root views to new memory
315 for (Uint32 rv = 0; rv < m_NumRootViews; ++rv)
316 {
317 const auto& SrcView = GetRootView(rv);
318 new (pNewRootViews + rv) RootParameter(SrcView);
319 }
320
321 m_pMemory.reset(pNewMemory);
322 m_NumRootTables += NumExtraRootTables;
323 m_NumRootViews += NumExtraRootViews;
324 m_TotalDescriptorRanges += NumExtraDescriptorRanges;
325 m_pRootTables = m_NumRootTables != 0 ? pNewRootTables : nullptr;
326 m_pRootViews = m_NumRootViews != 0 ? pNewRootViews : nullptr;
327
328 return pCurrDescriptorRangePtr;
329 }
330
331 void PipelineResourceSignatureD3D12Impl::RootParamsManager::AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType,
332 Uint32 RootIndex,
333 UINT Register,
334 UINT RegisterSpace,
335 D3D12_SHADER_VISIBILITY Visibility,
336 ROOT_TYPE RootType)
337 {
338 auto* pRangePtr = Extend(0, 1, 0);
339 VERIFY_EXPR((char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0));
340 new (m_pRootViews + m_NumRootViews - 1) RootParameter(ParameterType, RootIndex, Register, RegisterSpace, Visibility, RootType);
341 }
342
343 void PipelineResourceSignatureD3D12Impl::RootParamsManager::AddRootTable(Uint32 RootIndex,
344 D3D12_SHADER_VISIBILITY Visibility,
345 ROOT_TYPE RootType,
346 Uint32 NumRangesInNewTable)
347 {
348 auto* pRangePtr = Extend(1, 0, NumRangesInNewTable);
349 VERIFY_EXPR((char*)(pRangePtr + NumRangesInNewTable) == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0));
350 new (m_pRootTables + m_NumRootTables - 1) RootParameter(D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, RootIndex, NumRangesInNewTable, pRangePtr, Visibility, RootType);
351 }
352
353 void PipelineResourceSignatureD3D12Impl::RootParamsManager::AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges)
354 {
355 auto* pRangePtr = Extend(0, 0, NumExtraRanges, RootTableInd);
356 VERIFY_EXPR((char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0));
357 }
358
359 bool PipelineResourceSignatureD3D12Impl::RootParamsManager::operator==(const RootParamsManager& RootParams) const
360 {
361 if (m_NumRootTables != RootParams.m_NumRootTables ||
362 m_NumRootViews != RootParams.m_NumRootViews)
363 return false;
364
365 for (Uint32 rv = 0; rv < m_NumRootViews; ++rv)
366 {
367 const auto& RV0 = GetRootView(rv);
368 const auto& RV1 = RootParams.GetRootView(rv);
369 if (RV0 != RV1)
370 return false;
371 }
372
373 for (Uint32 rv = 0; rv < m_NumRootTables; ++rv)
374 {
375 const auto& RT0 = GetRootTable(rv);
376 const auto& RT1 = RootParams.GetRootTable(rv);
377 if (RT0 != RT1)
378 return false;
379 }
380
381 return true;
382 }
383
384 template <class TOperation>
385 __forceinline void PipelineResourceSignatureD3D12Impl::RootParamsManager::ProcessRootTables(TOperation Operation) const
386 {
387 for (Uint32 rt = 0; rt < m_NumRootTables; ++rt)
388 {
389 auto& RootTable = GetRootTable(rt);
390 auto RootInd = RootTable.GetLocalRootIndex();
391 const D3D12_ROOT_PARAMETER& D3D12Param = RootTable;
392
393 VERIFY_EXPR(D3D12Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE);
394
395 auto& d3d12Table = D3D12Param.DescriptorTable;
396 VERIFY(d3d12Table.NumDescriptorRanges > 0 && RootTable.GetDescriptorTableSize() > 0, "Unexepected empty descriptor table");
397 bool IsResourceTable = d3d12Table.pDescriptorRanges[0].RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
398 D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
399 #ifdef DILIGENT_DEBUG
400 dbgHeapType = IsResourceTable ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV : D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
401 #endif
402 Operation(RootInd, RootTable, D3D12Param, IsResourceTable, dbgHeapType);
403 }
404 }
405
406
407 namespace
408 {
409
410 D3D12_DESCRIPTOR_RANGE_TYPE GetDescriptorRangeType(SHADER_RESOURCE_TYPE ResType)
411 {
412 static_assert(SHADER_RESOURCE_TYPE_LAST == SHADER_RESOURCE_TYPE_ACCEL_STRUCT, "Please update the switch below to handle the new resource type");
413
414 switch (ResType)
415 {
416 // clang-format off
417 case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: return D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
418 case SHADER_RESOURCE_TYPE_TEXTURE_SRV: return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
419 case SHADER_RESOURCE_TYPE_BUFFER_SRV: return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
420 case SHADER_RESOURCE_TYPE_TEXTURE_UAV: return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
421 case SHADER_RESOURCE_TYPE_BUFFER_UAV: return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
422 case SHADER_RESOURCE_TYPE_SAMPLER: return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
423 case SHADER_RESOURCE_TYPE_ACCEL_STRUCT: return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
424 // clang-format on
425 case SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT:
426 default:
427 UNEXPECTED("Unknown resource type");
428 return static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(~0u);
429 }
430 }
431
432 void GetRootTableIndex(SHADER_TYPE ShaderType,
433 D3D12_SHADER_VISIBILITY& ShaderVisibility,
434 Uint32& RootTableIndex)
435 {
436 // Use VISIBILITY_ALL if used in many stages.
437 if (ShaderType & (ShaderType - 1))
438 {
439 RootTableIndex = 0;
440 ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
441 return;
442 }
443
444 // https://developer.nvidia.com/dx12-dos-and-donts#roots
445 // * Start with the entries for the pixel stage
446 // * Carry on with decreasing execution frequency of the shader stages
447 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
448 switch (ShaderType)
449 {
450 case SHADER_TYPE_PIXEL:
451 RootTableIndex = 1;
452 ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
453 break;
454
455 case SHADER_TYPE_VERTEX:
456 RootTableIndex = 2;
457 ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
458 break;
459
460